自定义控件一般的几个步骤: 1.初始化相关背景图片,布局文件,自定义属性 2.设置控件宽高OnMeasure() 3.布局或者排版OnLayout() 4.绘制控件OnDraw() 5.处理触摸事件OnTouchEvent()
1 public class SwitchView extends View implements View.OnTouchListener { 2 3 //开关状态图片 4 private Bitmap mSwitch_on, mSwitch_off, mSwitch_circle; 5 6 //开关状态 默认关闭 7 private boolean mCurrentState = false; 8 9 //开关切换回调接口 10 private OnSwitchChangedListener mOnSwitchChangedListener; 11 12 //X轴按下坐标 13 private int downX; 14 //X轴移动时触点坐标 15 private int moveX; 16 //X轴偏移量 17 private int left = 0; 18 //最大可移动距离 19 private int max; 20 21 public SwitchView(Context context) { 22 super(context); 23 init(); 24 } 25 26 public SwitchView(Context context, AttributeSet attrs) { 27 super(context, attrs); 28 init(); 29 } 30 31 public SwitchView(Context context, AttributeSet attrs, int defStyle) { 32 super(context, attrs, defStyle); 33 init(); 34 } 35 36 //1 初始化图片(加载) 37 private void init() { 38 Resources resr = getResources(); 39 mSwitch_on = BitmapFactory.decodeResource(resr, R.mipmap.switch_on); 40 mSwitch_off = BitmapFactory.decodeResource(resr, R.mipmap.switch_off); 41 mSwitch_circle = BitmapFactory.decodeResource(resr, R.mipmap.switch_circle); 42 setOnTouchListener(this); 43 } 44 45 //2 设置控件宽高(测量) 46 @Override 47 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 48 int widthSize = mSwitch_off.getWidth(); 49 int heightSize = mSwitch_off.getHeight(); 50 max = mSwitch_off.getWidth() - mSwitch_circle.getWidth(); 51 setMeasuredDimension(widthSize, heightSize); 52 } 53 54 //3 布局(排版) 55 @Override 56 protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 57 super.onLayout(changed, left, top, right, bottom); 58 } 59 60 //4 最后绘制控件 61 @Override 62 protected void onDraw(Canvas canvas) { 63 super.onDraw(canvas); 64 Matrix m = new Matrix(); 65 Paint p = new Paint(); 66 if (mCurrentState) { 67 canvas.drawBitmap(mSwitch_on, m, p); 68 } else { 69 canvas.drawBitmap(mSwitch_off, m, p); 70 } 71 canvas.drawBitmap(mSwitch_circle, left, 0, p); 72 } 73 74 //5 触摸事件 75 @Override 76 public boolean onTouch(View v, MotionEvent event) { 77 switch (event.getAction()) { 78 case MotionEvent.ACTION_DOWN: 79 downX = (int) event.getX();//初始X轴按下坐标 80 break; 81 case MotionEvent.ACTION_MOVE: 82 moveX = (int) event.getX(); 83 left = moveX - downX; 84 if (!mCurrentState) { 85 //关闭状态边界处理 86 if (left < 0) { 87 left = 0; 88 } else if (left > max) { 89 left = max; 90 } 91 } else { 92 //开启状态边界处理 93 left = moveX - downX; 94 if (left > 0) { //向右滑 95 left = max; 96 } else if (Math.abs(left) > max) { 97 left = 0; 98 } else { 99 left = max - Math.abs(left);100 }101 }102 break;103 case MotionEvent.ACTION_UP:104 case MotionEvent.ACTION_CANCEL://抬起时的判断105 int upX = (int) event.getX();106 boolean state = false; //滑动是否成功107 //1 关闭状态108 if (!mCurrentState) {109 //滑动是否成功110 //a 移动距离超过 1/2 的滑动宽度111 //b 触摸点在滑动区域,开启按钮112 state = (moveX - downX) >= max / 2 || upX >= max;113 if (state) {114 left = max;115 mCurrentState = true;116 } else {117 left = 0;118 }119 } else {120 //2 开启状态,判断滑动是否成功121 //a 移动距离超过 1/2 的滑动宽度122 //b 触摸点在滑动区域,关闭按钮123 state = (downX - moveX) >= max / 2 || upX <= max;124 if (state) {125 left = 0;126 mCurrentState = false;127 } else {128 left = max;129 }130 }131 //滑动成功 且 回调接口不能空 触发回调方法132 if (state && null != mOnSwitchChangedListener) {133 mOnSwitchChangedListener.onSwitchChanged(mCurrentState);134 }135 break;136 }137 invalidate();138 return true;139 }140 141 //开关切换回调接口142 public interface OnSwitchChangedListener {143 void onSwitchChanged(boolean isOpen);144 }145 146 public void setOnSwitchChangedListener(OnSwitchChangedListener listener) {147 this.mOnSwitchChangedListener = listener;148 }149 150 public void setCurrentState(boolean isOpen) {151 mCurrentState = isOpen;152 left = isOpen ? max : 0;153 invalidate();154 }155 156 }