16 7 13 14
1 package com.example.testdemo; 2 3 import android.content.Context; 4 import android.graphics.Bitmap; 5 import android.graphics.BitmapFactory; 6 import android.graphics.Canvas; 7 import android.graphics.Paint; 8 import android.util.AttributeSet; 9 import android.view.MotionEvent; 10 import android.view.View; 11 import android.view.View.OnClickListener; 12 13 public class MyToggleButton extends View implements OnClickListener { 14 15 // 做为背景的图片 16 private Bitmap backgroundBitmap; 17 // 可以滑动的图片 18 private Bitmap slideBtn; 19 private Paint paint; 20 // 滑动按钮的左边届 21 private float slideBtn_left; 22 // down 事件时的x值 23 private int firstX; 24 // touch 事件的上一个x值 25 private int lastX; 26 // 当前开关的状态 true 为开 27 private boolean currState = false; 28 // 判断是否发生拖动, 如果拖动了,就不再响应 onclick 事件 29 private boolean isDrag = false; 30 31 /** 32 * 在代码里面创建对象的时候,使用此构造方法 33 */ 34 public MyToggleButton(Context context) { 35 super(context); 36 // TODO Auto-generated constructor stub 37 } 38 39 /** 40 * 在布局文件中声名的view,创建时由系统自动调用。 41 * 42 * @param context 43 * 上下文对象 44 * @param attrs 45 * 属性集 46 */ 47 public MyToggleButton(Context context, AttributeSet attrs) { 48 super(context, attrs); 49 50 initView(); 51 } 52 53 /** 54 * 初始化 55 */ 56 private void initView() { 57 58 // 初始化图片 59 backgroundBitmap = BitmapFactory.decodeResource(getResources(), 60 R.drawable.switch_background); 61 slideBtn = BitmapFactory.decodeResource(getResources(), 62 R.drawable.slide_button); 63 64 // 初始化 画笔 65 paint = new Paint(); 66 paint.setAntiAlias(true); // 打开抗矩齿 67 68 // 添加onclick事件监听 69 setOnClickListener(this); 70 } 71 72 /* 73 * view 对象显示的屏幕上,有几个重要步骤: 74 * 1、构造方法 创建 对象。 75 * 2、测量view的大小。 onMeasure(int,int); 76 * 3、确定view的位置 ,view自身有一些建议权,决定权在 父view手中。 onLayout(); 77 * 4、绘制 view 的内容 。 78 * onDraw(Canvas) 79 */ 80 81 @Override 82 /** 83 * 测量尺寸时的回调方法 84 */ 85 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 86 // super.onMeasure(widthMeasureSpec, heightMeasureSpec); 87 // 设置当前view的大小 width :view的宽度 height :view的高度 (单位:像素) 88 setMeasuredDimension(backgroundBitmap.getWidth(), 89 backgroundBitmap.getHeight()); 90 } 91 92 // 确定位置的时候调用此方法 93 // 自定义view的时候,作用不大 94 // @Override 95 // protected void onLayout(boolean changed, int left, int top, int right, 96 // int bottom) { 97 // super.onLayout(changed, left, top, right, bottom); 98 // } 99 100 @Override101 /**102 * 绘制当前view的内容103 */104 protected void onDraw(Canvas canvas) {105 // super.onDraw(canvas);106 107 // 绘制 背景108 /*109 * backgroundBitmap 要绘制的图片 left 图片的左边届 top 图片的上边届 paint 绘制图片要使用的画笔110 */111 canvas.drawBitmap(backgroundBitmap, 0, 0, paint);112 113 // 绘制 可滑动的按钮114 canvas.drawBitmap(slideBtn, slideBtn_left, 0, paint);115 }116 117 118 @Override119 /**120 * onclick 事件在View.onTouchEvent 中被解析。121 * 系统对onclick 事件的解析,过于简陋,只要有down 事件 up 事件,122 * 系统即认为 发生了click 事件123 */124 public void onClick(View v) {125 // 如果没有拖动,才执行改变状态的动作126 if (!isDrag) {127 currState = !currState;128 flushState();129 }130 }131 132 @Override133 public boolean onTouchEvent(MotionEvent event) {134 super.onTouchEvent(event);135 136 switch (event.getAction()) {137 case MotionEvent.ACTION_DOWN:138 firstX = lastX = (int) event.getX();139 isDrag = false;140 141 break;142 case MotionEvent.ACTION_MOVE:143 144 // 判断是否发生拖动145 if (Math.abs(event.getX() - firstX) > 5) {146 isDrag = true;147 }148 149 // 计算 手指在屏幕上移动的距离150 int dis = (int) (event.getX() - lastX);151 152 // 将本次的位置 设置给lastX153 lastX = (int) event.getX();154 155 // 根据手指移动的距离,改变slideBtn_left 的值156 slideBtn_left = slideBtn_left + dis;157 break;158 case MotionEvent.ACTION_UP:160 // 在发生拖动的情况下,根据最后的位置,判断当前开关的状态161 if (isDrag) {162 // alideBtn 左边界最大值163 int maxLeft = backgroundBitmap.getWidth() - slideBtn.getWidth();165 /*166 * 根据 slideBtn_left 判断,当前应是什么状态167 */168 if (slideBtn_left > maxLeft / 2) { // 此时应为 打开的状态169 currState = true;170 } else {171 currState = false;172 }174 flushState();175 }176 break;177 }179 flushView();181 return true;182 }183 184 /**185 * 刷新当前状态186 */187 private void flushState() {188 if (currState) {189 slideBtn_left = backgroundBitmap.getWidth() - slideBtn.getWidth();190 } else {191 slideBtn_left = 0;192 }194 flushView();195 }196 197 /**198 * 刷新当前视力199 */200 private void flushView() {201 /*202 * 对 slideBtn_left 的值进行判断 ,确保其在合理的位置 即 0<=slideBtn_left <= maxLeft203 */205 int maxLeft = backgroundBitmap.getWidth() - slideBtn.getWidth(); 207 208 // 确保 slideBtn_left >= 0209 slideBtn_left = (slideBtn_left > 0) ? slideBtn_left : 0;210 211 // 确保 slideBtn_left <=maxLeft212 slideBtn_left = (slideBtn_left < maxLeft) ? slideBtn_left : maxLeft;213 214 /*215 * 刷新当前视图 导致 执行onDraw执行216 */217 invalidate();218 }219 220 }
DEMO下载地址:http://pan.baidu.com/s/1qWjXEhQ