自定义滑动开关
2016-08-16 23:02
183 查看
1.布局文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:health="http://schemas.android.com/apk/res/com.health.myswitch"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.health.myswitch.MySwith
android:id="@+id/MySwith"
android:layout_centerInParent="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
health:isOpen = "false"
health:slideSrc = "@drawable/ic_launcher"
/>
</RelativeLayout>
2.写一个类继承 MySwith extends View
package com.health.myswitch;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class MySwith extends View {
private int bitmapHeight;
private Bitmap bitmap;
private Paint paint;
private int bitmapWidth; // 开关的
private Bitmap slideBitmap; // 滑块的宽度
private int mMaxLeft; // 距离左边的最大距离 即为右滑的最大距离
private int mCurrentLeft; // 距离左边的当前距离
private boolean isOpen;
private boolean isClick ;
private float totaldx;
private static final String namespace ="http://schemas.android.com/apk/res/com.health.myswitch";
public MySwith(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initData();
// 两种方式
isOpen = attrs.getAttributeBooleanValue(namespace, "isOpen", false);
slideSrc = attrs.getAttributeResourceValue(namespace, "slideSrc", 0);
System.out.println("isOpen=" + isOpen + ",slideSrc=" + slideSrc);
}
// 在布局文件中使用MySwitch,在系统加载布局文件的时候,会调用此方法生成一个MySwitch的对象
// Attribute : 属性,特性
public MySwith(Context context, AttributeSet attrs) {
this(context, attrs, -1);
}
// 直接在java代码中new出这个控件的时候,会使用
public MySwith(Context context) {
this(context, null);
}
private void initData() {
// 画笔
paint = new Paint();
// 将画笔的颜色设置为红色
paint.setColor(Color.BLUE);
// 初始化图片 decode : 翻译
bitmap = BitmapFactory.decodeResource(getResources(), //slideSrc);
R.drawable.switch_background);
bitmapWidth = bitmap.getWidth();
bitmapHeight = bitmap.getHeight();
slideBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.slide_button);
int slideBitmapWidth = slideBitmap.getWidth();
// 滑块可以向右滑动的最大距离
mMaxLeft = bitmapWidth - slideBitmapWidth;
setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (isClick) {
System.out.println("MySwitch.onClick"+isClick);
if (isOpen) {
// 关闭
mCurrentLeft = 0;
isOpen = false;
} else {
// 打开
mCurrentLeft = mMaxLeft;
isOpen = true;
}
// 刷新界面 促发onDraw方法的调用
invalidate();
// 接受 观察者的通知
notifyStatus();
}
}
});
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// 背景图片有多大,控件就有多大
setMeasuredDimension(bitmapWidth, bitmapHeight);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 绘制开关图片
canvas.drawBitmap(bitmap, 0, 0, paint);
// 绘制滑块的图片
canvas.drawBitmap(slideBitmap, mCurrentLeft, 0, paint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
startX = event.getX();
totaldx = 0;
break;
case MotionEvent.ACTION_MOVE:
float moveX = event.getX();
float dx = moveX - startX;
totaldx = totaldx + Math.abs(dx);
mCurrentLeft = (int) (mCurrentLeft + dx);
if (mCurrentLeft < 0) {
mCurrentLeft = 0;
} else if (mCurrentLeft > mMaxLeft) {
mCurrentLeft = mMaxLeft;
}
invalidate(); // 刷新界面 必须刷新,否则没有效果
startX = moveX;
break;
case MotionEvent.ACTION_UP:
if (totaldx > 3) {
isClick = false;
} else {
isClick = true;
}
if (!isClick) {
if (mCurrentLeft > mMaxLeft / 2) {
// 自动打开
mCurrentLeft = mMaxLeft;
isOpen = true;
} else {
mCurrentLeft = 0;
isOpen = false;
}
invalidate();
notifyStatus();
}
break;
}
return super.onTouchEvent(event);// 消耗掉事件;
}
// 观察者模式 五步
// 1. 找到被观察者 Myswith
// 2.定义观察者,(定义接口)
public interface OnStatusChangeLister {
public void OnStatusChange(Boolean isOpen);
}
// 3.在被观察者中 保存观察者的对象
private OnStatusChangeLister mLister;
private float startX;
private int slideSrc;
public void setOnStatusChangeLister(OnStatusChangeLister Lister) {
this.mLister = Lister;
}
// 4.通知观察者
public void notifyStatus() {
if (mLister != null) {
mLister.OnStatusChange(isOpen);
// System.out.println("开关的状态为:" + isOpen);
}
}
}
3.在MainActivity中引入
package com.health.myswitch;
import android.app.Activity;
import android.os.Bundle;
import android.widget.Toast;
import com.health.myswitch.MySwith.OnStatusChangeLister;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MySwith mySwith = (MySwith) findViewById(R.id.MySwith);
//设置背景 滑动开关
mySwith.setBackgroundResource(R.drawable.switch_background);
//设置开关默认状态
mySwith.setOnStatusChangeLister(new OnStatusChangeLister() {
@Override
public void OnStatusChange(Boolean isOpen) {
// 按压状态 的变化 监听不了触摸的状态
Toast.makeText(MainActivity.this, "开关的状态为:"+isOpen, 0).show();
//System.out.println("开关的状态为:"+isOpen);
}
});
}
}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:health="http://schemas.android.com/apk/res/com.health.myswitch"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.health.myswitch.MySwith
android:id="@+id/MySwith"
android:layout_centerInParent="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
health:isOpen = "false"
health:slideSrc = "@drawable/ic_launcher"
/>
</RelativeLayout>
2.写一个类继承 MySwith extends View
package com.health.myswitch;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class MySwith extends View {
private int bitmapHeight;
private Bitmap bitmap;
private Paint paint;
private int bitmapWidth; // 开关的
private Bitmap slideBitmap; // 滑块的宽度
private int mMaxLeft; // 距离左边的最大距离 即为右滑的最大距离
private int mCurrentLeft; // 距离左边的当前距离
private boolean isOpen;
private boolean isClick ;
private float totaldx;
private static final String namespace ="http://schemas.android.com/apk/res/com.health.myswitch";
public MySwith(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initData();
// 两种方式
isOpen = attrs.getAttributeBooleanValue(namespace, "isOpen", false);
slideSrc = attrs.getAttributeResourceValue(namespace, "slideSrc", 0);
System.out.println("isOpen=" + isOpen + ",slideSrc=" + slideSrc);
}
// 在布局文件中使用MySwitch,在系统加载布局文件的时候,会调用此方法生成一个MySwitch的对象
// Attribute : 属性,特性
public MySwith(Context context, AttributeSet attrs) {
this(context, attrs, -1);
}
// 直接在java代码中new出这个控件的时候,会使用
public MySwith(Context context) {
this(context, null);
}
private void initData() {
// 画笔
paint = new Paint();
// 将画笔的颜色设置为红色
paint.setColor(Color.BLUE);
// 初始化图片 decode : 翻译
bitmap = BitmapFactory.decodeResource(getResources(), //slideSrc);
R.drawable.switch_background);
bitmapWidth = bitmap.getWidth();
bitmapHeight = bitmap.getHeight();
slideBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.slide_button);
int slideBitmapWidth = slideBitmap.getWidth();
// 滑块可以向右滑动的最大距离
mMaxLeft = bitmapWidth - slideBitmapWidth;
setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (isClick) {
System.out.println("MySwitch.onClick"+isClick);
if (isOpen) {
// 关闭
mCurrentLeft = 0;
isOpen = false;
} else {
// 打开
mCurrentLeft = mMaxLeft;
isOpen = true;
}
// 刷新界面 促发onDraw方法的调用
invalidate();
// 接受 观察者的通知
notifyStatus();
}
}
});
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// 背景图片有多大,控件就有多大
setMeasuredDimension(bitmapWidth, bitmapHeight);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 绘制开关图片
canvas.drawBitmap(bitmap, 0, 0, paint);
// 绘制滑块的图片
canvas.drawBitmap(slideBitmap, mCurrentLeft, 0, paint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
startX = event.getX();
totaldx = 0;
break;
case MotionEvent.ACTION_MOVE:
float moveX = event.getX();
float dx = moveX - startX;
totaldx = totaldx + Math.abs(dx);
mCurrentLeft = (int) (mCurrentLeft + dx);
if (mCurrentLeft < 0) {
mCurrentLeft = 0;
} else if (mCurrentLeft > mMaxLeft) {
mCurrentLeft = mMaxLeft;
}
invalidate(); // 刷新界面 必须刷新,否则没有效果
startX = moveX;
break;
case MotionEvent.ACTION_UP:
if (totaldx > 3) {
isClick = false;
} else {
isClick = true;
}
if (!isClick) {
if (mCurrentLeft > mMaxLeft / 2) {
// 自动打开
mCurrentLeft = mMaxLeft;
isOpen = true;
} else {
mCurrentLeft = 0;
isOpen = false;
}
invalidate();
notifyStatus();
}
break;
}
return super.onTouchEvent(event);// 消耗掉事件;
}
// 观察者模式 五步
// 1. 找到被观察者 Myswith
// 2.定义观察者,(定义接口)
public interface OnStatusChangeLister {
public void OnStatusChange(Boolean isOpen);
}
// 3.在被观察者中 保存观察者的对象
private OnStatusChangeLister mLister;
private float startX;
private int slideSrc;
public void setOnStatusChangeLister(OnStatusChangeLister Lister) {
this.mLister = Lister;
}
// 4.通知观察者
public void notifyStatus() {
if (mLister != null) {
mLister.OnStatusChange(isOpen);
// System.out.println("开关的状态为:" + isOpen);
}
}
}
3.在MainActivity中引入
package com.health.myswitch;
import android.app.Activity;
import android.os.Bundle;
import android.widget.Toast;
import com.health.myswitch.MySwith.OnStatusChangeLister;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MySwith mySwith = (MySwith) findViewById(R.id.MySwith);
//设置背景 滑动开关
mySwith.setBackgroundResource(R.drawable.switch_background);
//设置开关默认状态
mySwith.setOnStatusChangeLister(new OnStatusChangeLister() {
@Override
public void OnStatusChange(Boolean isOpen) {
// 按压状态 的变化 监听不了触摸的状态
Toast.makeText(MainActivity.this, "开关的状态为:"+isOpen, 0).show();
//System.out.println("开关的状态为:"+isOpen);
}
});
}
}
相关文章推荐
- Android 三档自定义滑动开关,禁止点击功能的实现,用默认的seekbar组件实现
- Android自定义View-------IOS风格的滑动开关
- Android_自定义滑动开关
- android三档自定义滑动开关,禁止点击功能的实现,用默认的seekbar组件实现
- 自定义的可滑动的开关按钮
- 自定义开关(不带有滑动,只具有点击切换开关功能)
- android三档自定义滑动开关,禁止点击功能的实现,用默认的seekbar组件实现
- android自定义View之滑动开关SlideButton
- 自定义滑动开关-SwitchButton
- 自定义滑动开关按钮-SwitchButton-进阶
- android自定义滑动开关控件,适合所有的android系统
- 自定义可滑动、可点击的开关
- 自定义滑动开关按钮-SwitchButton-进阶
- Android自定义开关(可滑动,点击)
- Android进阶自定义控件之滑动开关
- QT自定义滑动开关
- 自定义开关控件 点击和滑动效果
- 【视图控件篇】自定义Android控件之IOS滑动开关模拟详解
- android自定义滑动开关控件,适合所有的android系统 《转载》
- Android自定义控件之旅(一)滑动开关