自定义控件:滑动开关按钮_第1张图片

 1 <RelativeLayout  2 xmlns:android="http://schemas.android.com/apk/res/android"  3  xmlns:tools="http://schemas.android.com/tools"  4  android:layout_width="match_parent"  5  android:layout_height="match_parent" >  6  7 <com.example.testdemo.MyToggleButton  8 android:id="@+id/my_toggle_btn"  9  android:layout_width="wrap_content" 10  android:layout_height="wrap_content" 11  android:layout_centerHorizontal="true" 12  android:layout_centerVertical="true" /> 13 14 </RelativeLayout>
  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  @Override 101 /** 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  @Override 119 /** 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  @Override 133 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 // 将本次的位置 设置给lastX 153 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 <= maxLeft 203 */ 205 int maxLeft = backgroundBitmap.getWidth() - slideBtn.getWidth(); 207 208 // 确保 slideBtn_left >= 0 209 slideBtn_left = (slideBtn_left > 0) ? slideBtn_left : 0; 210 211 // 确保 slideBtn_left <=maxLeft 212 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

更多相关文章

  1. android处理大图片内存溢出的简单办法
  2. android:ImageView选择本地图片并显示
  3. android获取图片和视频的缩略图
  4. Android:TextView与EditText中插入表情图片
  5. android设置背景图片,去除背景图片
  6. Android四种点击事件和五中存储方式
  7. Android 图片处理工具类封装
  8. Android 打开相机和图库获取图片并裁剪

随机推荐

  1. 实例详解php中empty、isset、isnull三者
  2. php实现获取数组中相同/不相同的元素
  3. php利用ZipArchive类实现文件压缩与解压
  4. jQuery+PHP实现购物商城常用的星级评分效
  5. PHP-FPM与Swoole的比较
  6. Docker+LNMP+Jenkins+码云实现 PHP 代码
  7. 详解php soap实现web service接口服务
  8. 关于php中匿名函数与回调函数的详解
  9. php中异步执行的四种方式
  10. php实现队列的详细步骤