【Android】自定义控件实现可滑动的开关(switch)

~转载请注明来源:

介绍

昨天晚上写了一个Android的滑动开关,, 即SlideSwitch。效果如下:

实现

实现的思路其实很简单,监听控件上的touch事件,并不断刷新,让滑块在手指的位置上绘出,达到滑块跟着手指滑动的显示效果。 先看一下代码: SlideSwitch.java (7月3日有修改:在touch事件里调用onStateChangedListener前增加判空)

package com.incell.view;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;{private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); //抗锯齿boolean isOn = false;float curX = 0;float centerY; //y固定float viewWidth;float radius;lineWidth;final int SCALE = 4; // 控件长度为滑动的圆的半径的倍数OnStateChangedListener onStateChangedListener;public SlideSwitch(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}public SlideSwitch(Context context, AttributeSet attrs) {super(context, attrs);}public SlideSwitch(Context context) {super(context);}(MotionEvent event) {// TODO Auto-generated method stubcurX = event.getX();if(event.getAction() == MotionEvent.ACTION_UP){if(curX > viewWidth / 2){curX = lineEnd;if(false == isOn){//只有状态发生改变才调用回调函数, 下同if(null != onStateChangedListener){onStateChangedListener.onStateChanged(true);}isOn = true;}}else{curX = lineStart;if(true == isOn){if(null != onStateChangedListener){onStateChangedListener.onStateChanged(false);}isOn = false;}}}/*通过刷新调用onDraw*/this.postInvalidate();return true;}(int widthMeasureSpec, int heightMeasureSpec) {// TODO Auto-generated method stubsuper.onMeasure(widthMeasureSpec, heightMeasureSpec);/*保持宽是高的SCALE / 2倍, 即圆的直径*/this.setMeasuredDimension(this.getMeasuredWidth(), this.getMeasuredWidth() * 2 / SCALE);viewWidth = this.getMeasuredWidth();radius = viewWidth / SCALE;lineWidth = radius * 2f; //直线宽度等于滑块直径curX = radius;centerY = this.getMeasuredWidth() / SCALE; //centerY为高度的一半lineStart = radius;lineEnd = (SCALE – 1) * radius;}(Canvas canvas) {// TODO Auto-generated method stubsuper.onDraw(canvas);/*限制滑动范围*/curX = curX > lineEnd?lineEnd:curX;curX = curX < lineStart?lineStart:curX;/*划线*/mPaint.setStyle(Paint.Style.STROKE);mPaint.setStrokeWidth(lineWidth);/*左边部分的线,绿色*/mPaint.setColor(Color.BLUE);canvas.drawLine(lineStart, centerY, curX, centerY, mPaint);/*右边部分的线,灰色*/mPaint.setColor(Color.GRAY);canvas.drawLine(curX, centerY, lineEnd, centerY, mPaint);/*画圆*//*画最左和最右的圆,直径为直线段宽度, 即在直线段两边分别再加上一个半圆*/mPaint.setStyle(Paint.Style.FILL);mPaint.setColor(Color.GRAY);canvas.drawCircle(lineEnd, centerY, lineWidth / 2, mPaint);mPaint.setColor(Color.BLUE);canvas.drawCircle(lineStart, centerY, lineWidth / 2, mPaint);/*圆形滑块*/mPaint.setColor(Color.LTGRAY);canvas.drawCircle(curX, centerY, radius , mPaint);}(OnStateChangedListener o){this.onStateChangedListener = o;}{(boolean state);}}

注释应该很详细了。主要有以下几点。 1、重写了onMeasure方法,使控件高度依赖于控件的宽度。这样不论在布局文件中如何设置,总能保证控件的宽高比。 2、控制好滑块的活动范围 3、定义内部接口OnStateChangedListener,并在自定义控件里定义了其对象以及从外部赋值的方法setOnStateChangedListener,以便对开关状态更改事件进行监听并调用回调。

使用及Demo

在布局文件中添加该控件即可使用。Demo效果为动图展示效果(demo里颜色为绿色,动图为蓝色是因为绿色会导致截取gif时出问题,临时更改的)。 Demo中布局文件如下: activity_main.xml:

<RelativeLayout xmlns:android=”http://schemas.android.com/apk/res/android”xmlns:tools=”http://schemas.android.com/tools”android:layout_width=”match_parent”android:layout_height=”match_parent” ><android:id=”@+id/slide_switch”android:layout_width=”200dp”android:layout_height=”wrap_content”android:layout_centerInParent=”true”/></RelativeLayout>对于旅行,从来都记忆模糊。记不得都去了哪些地方,

【Android】自定义控件实现可滑动的开关(switch)

相关文章:

你感兴趣的文章:

标签云: