android仿IOS选择(switch)开关

来源:互联网 发布:行知职业学校 编辑:程序博客网 时间:2024/05/12 06:05


       最近看见很多应用用这种仿IOS的开关控件,最近项目组也有要用到这个控件的需要,实际上最简单的方法是,直接让UI提供两张图片就可以了,分别代表打开和关闭的状态,但是UI实在是不给力,图片迟迟不到,所以,作为一个勤奋好学,自力更生的android程序员来说,好吧,果断自己自定义一个。

    其实,要实现这个功能,也不是很难,可以说非常easy。就是通过canvas画一个底层椭圆形的矩形,然后上面画一个开关的小圆圈,底层颜色和小圆圈所处位置根据开关状态不同显示。好了,先上图。



最后效果图就是这样的。代码如下:

package com.lyq.customSwitch;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.RectF;import android.util.AttributeSet;import android.view.View;import android.view.View.OnClickListener;/** * 仿IOS选择开关 * @author mufeng * */public class Switch extends View implements OnClickListener{private Context mContext;private Paint mPaint;private float width,height;private boolean isOpen=true;private RectF oval;public Switch(Context context) {super(context);init(context);}public Switch(Context context, AttributeSet attrs) {super(context, attrs);init(context);}public Switch(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context);}public Switch(Context context, AttributeSet attrs, int defStyleAttr,int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);init(context);}private void init(Context context) {mContext=context;//设置宽高 width=DensityUtils.dip2px(mContext, 80);height=width/2;mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);setOnClickListener(this);oval = new RectF(0, 0, width, height);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//根据控件当前状态设置画笔颜色if(isOpen){mPaint.setColor(getResources().getColor(R.color.select));}else{mPaint.setColor(Color.GRAY);}mPaint.setStyle(Paint.Style.FILL);// 充满//画底层圆角矩形canvas.drawRoundRect(oval,height/2 , width/4, mPaint);// 第二个参数是x半径,第三个参数是y半径//画开关圆圈 将画笔颜色设为白色 mPaint.setColor(Color.WHITE);//根据控件当前状态判断将圆圈画在左边还是右边if(isOpen){canvas.drawCircle(width/4*3, height/2, height/2-DensityUtils.dip2px(mContext, 2), mPaint);}else{canvas.drawCircle(width/4, height/2, height/2-DensityUtils.dip2px(mContext, 2), mPaint);}}@Override      protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {          //重新测量控件的大小,主要在控件宽高属性设置为wrap_content时,将控件大小设置为实际大小setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));      }    //测量宽度    private int measureWidth(int measureSpec) {          int result = 0;          int specMode = MeasureSpec.getMode(measureSpec);          int specSize = MeasureSpec.getSize(measureSpec);            if (specMode == MeasureSpec.EXACTLY) {              result = specSize;          } else {              result = (int) DensityUtils.dip2px(mContext, 80) + getPaddingLeft() + getPaddingRight();              if (specMode == MeasureSpec.AT_MOST) {                  result = Math.min(result, specSize);              }          }            return result;      }        //测量高度    private int measureHeight(int measureSpec) {          int result = 0;          int specMode = MeasureSpec.getMode(measureSpec);          int specSize = MeasureSpec.getSize(measureSpec);            if (specMode == MeasureSpec.EXACTLY) {              result = specSize;          } else {              result = (int) DensityUtils.dip2px(mContext, 80)/2 + getPaddingTop() + getPaddingBottom();              if (specMode == MeasureSpec.AT_MOST) {                  result = Math.min(result, specSize);              }          }        return result;      }      /**     * 点击切换isOpen值,调用postInvalidate重绘view,可用于异步线程     */@Overridepublic void onClick(View view) {isOpen=!isOpen;postInvalidate();}/** * 打开控件开关 */public void open(){if(!isOpen){isOpen=true;postInvalidate();}}/** * 关闭控件开关 */public void close(){if(isOpen){isOpen=false;postInvalidate();}}/** * 获取控件状态 * @return  */public boolean isOpen(){return isOpen;}}

代码中各个方法都注释的比较详细,具体的我就不介绍了。最后附上项目源码。

0 0