Android自定义控件—滑动开关

来源:互联网 发布:mysql集群原理 编辑:程序博客网 时间:2024/05/16 14:04

在IM即时通讯的项目中,我用过了滑动开关,那时候,还不会现在这种通过继承View自定义的方式,那时候,我用了两个ImageView通过setVisibility方法去控制的。感觉也挺方便的。(Android4.0有Switch控件,一样的效果)


定义一个类继承自View,并实现他的有两个构造函数的方法。执行初始化:

public class MyToggleButton extends View implements OnClickListener{/** * 做为背景的图片 */private Bitmap backgroundBitmap;/** * 可以滑动的图片 */private Bitmap slideBtn;private Paint paint;/** * 滑动按钮的左边届 */private float slideBtn_left;/** * 在代码里面创建对象的时候,使用此构造方法 */public MyToggleButton(Context context) {super(context);// TODO Auto-generated constructor stub}/** * 在布局文件中声名的view,创建时由系统自动调用。 * @param context上下文对象 * @param attrs属性集 */public MyToggleButton(Context context, AttributeSet attrs) {super(context, attrs);initView();}
初始化图片资源和画笔:

/** * 初始化 */private void initView() {//初始化图片backgroundBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.switch_background);slideBtn = BitmapFactory.decodeResource(getResources(), R.drawable.slide_button);//初始化 画笔paint = new Paint();paint.setAntiAlias(true); // 打开抗矩齿//添加onclick事件监听setOnClickListener(this);}

 view 对象显示的屏幕上,有几个重要步骤:
* 1、构造方法 创建 对象。
* 2、测量view的大小。onMeasure(int,int);
* 3、确定view的位置 ,view自身有一些建议权,决定权在 父view手中。  onLayout();
* 4、绘制 view 的内容 。 onDraw(Canvas)

测量view的大小:

@Override/** * 测量尺寸时的回调方法  */protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {//super.onMeasure(widthMeasureSpec, heightMeasureSpec);/** * 设置当前view的大小 * width  :view的宽度 * height :view的高度   (单位:像素) */setMeasuredDimension(backgroundBitmap.getWidth(),backgroundBitmap.getHeight());}//确定位置的时候调用此方法//自定义view的时候,作用不大//@Override//protected void onLayout(boolean changed, int left, int top, int right,//int bottom) {//super.onLayout(changed, left, top, right, bottom);//}

绘制:

/** * 当前开关的状态 *  true 为开 */private boolean currState = false;/** * 绘制当前view的内容 */protected void onDraw(Canvas canvas) {//super.onDraw(canvas);// 绘制 背景/* * backgroundBitmap要绘制的图片 * left图片的左边届 * top图片的上边届 * paint 绘制图片要使用的画笔 */canvas.drawBitmap(backgroundBitmap, 0, 0, paint);//绘制 可滑动的按钮canvas.drawBitmap(slideBtn, slideBtn_left, 0, paint);}

点击的时候状态发生改变:

/** * 判断是否发生拖动, * 如果拖动了,就不再响应 onclick 事件 *  */private boolean isDrag = false;@Override/** * onclick 事件在View.onTouchEvent 中被解析。 * 系统对onclick 事件的解析,过于简陋,只要有down 事件  up 事件,系统即认为 发生了click 事件 *  */public void onClick(View v) {/* * 如果没有拖动,才执行改变状态的动作 */if(!isDrag){currState = !currState;flushState();}}

上面必须在不拖动的时候;

刷新:

/** * 刷新当前状态 */private void flushState() {if(currState){slideBtn_left = backgroundBitmap.getWidth()-slideBtn.getWidth();}else{slideBtn_left = 0;}flushView(); }/** * 刷新当前视力 */private void flushView() {/* * 对 slideBtn_left  的值进行判断 ,确保其在合理的位置 即       0<=slideBtn_left <=  maxLeft *  */int maxLeft = backgroundBitmap.getWidth()-slideBtn.getWidth();//slideBtn 左边届最大值//确保 slideBtn_left >= 0slideBtn_left = (slideBtn_left>0)?slideBtn_left:0;//确保 slideBtn_left <=maxLeftslideBtn_left = (slideBtn_left<maxLeft)?slideBtn_left:maxLeft;/* * 刷新当前视图  导致 执行onDraw执行 */invalidate();}


onTouchDown事件:

/** * down 事件时的x值 */private int firstX;/** * touch 事件的上一个x值 */private int lastX;@Overridepublic boolean onTouchEvent(MotionEvent event) {super.onTouchEvent(event);switch (event.getAction()) {case MotionEvent.ACTION_DOWN:firstX = lastX =(int) event.getX();isDrag = false;break;case MotionEvent.ACTION_MOVE://判断是否发生拖动if(Math.abs(event.getX()-firstX)>5){isDrag = true;}//计算 手指在屏幕上移动的距离int dis = (int) (event.getX() - lastX);//将本次的位置 设置给lastXlastX = (int) event.getX();//根据手指移动的距离,改变slideBtn_left 的值slideBtn_left = slideBtn_left+dis;break;case MotionEvent.ACTION_UP://在发生拖动的情况下,根据最后的位置,判断当前开关的状态if (isDrag) {int maxLeft = backgroundBitmap.getWidth() - slideBtn.getWidth(); // slideBtn// 左边届最大值/* * 根据 slideBtn_left 判断,当前应是什么状态 */if (slideBtn_left > maxLeft / 2) { // 此时应为 打开的状态currState = true;} else {currState = false;}flushState();}break;}flushView();return true; }


方法消费了该事件。

0 0
原创粉丝点击