Android 自定义控件之开关按钮

本文为android学习笔记,由博主总结整理

效果图:
这里写图片描述

1.在 res/drawable 下添加资源文件。

2.新建一个继承view的MyToggleBtn类。

package finch.scu.cn.togglebtn;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

/** * Created by finch on 2015-12-14. */
public class MyToggleBtn extends View implements View.OnClickListener{

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

     private Bitmap backgroundBitmap;
     private Bitmap slideBtn;
     private Paint paint;

    //slideBtn的左边距,关 = 0 ,开 = backgroundBitmap宽度 - slideBtn宽度
     private float slideBtn_left;

    /** 在代码内创建对象时使用此构造方法 * @param context */
    public MyToggleBtn(Context context){
        super(context);
    }

    /** 在布局中申明的view,创建时由系统自动调用 * @param context * @param attrs */
    public MyToggleBtn(Context context, AttributeSet attrs){
        super(context,attrs);
        //初始化图片
        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);
    }


    /** 测量尺寸的回调方法 * @param widthMeasureSpec * @param heightMeasureSpec */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        //设置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);
    }

    //当前开关的状态
    private Boolean currState = false;

    @Override
    protected void onDraw(Canvas canvas) {
// super.onDraw(canvas);
        //绘制图片大小和背景大小一样,left和top都为0
        canvas.drawBitmap(backgroundBitmap,0,0,paint);

        //绘制可滑动按钮
        canvas.drawBitmap(slideBtn,slideBtn_left,0,paint);
    }



    /**只要有 down事件和up事件,系统就认为发生了click事件 * @param v */
    private Boolean isDrag = false;//判断是否发生拖动,发生了就不响应click事件
    @Override
    public void onClick(View v) {
        if(!isDrag){
            currState = !currState;
            if(currState){
                slideBtn_left = backgroundBitmap.getWidth() - slideBtn.getWidth();
            }else{
                slideBtn_left =0;
            }

            //刷新当前view,重新调用onDraw()的执行
            invalidate();
        }

    }

    /** 添加滑动事件的监听 * @param event * @return */
    private int firstX;
    private int lastX;
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);

        int maxLeft = backgroundBitmap.getWidth() - slideBtn.getWidth();

        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);

                lastX = (int) event.getX();
                //根据手指移动的距离,改变slideBtn_left的值
                slideBtn_left = slideBtn_left + dis;

                break;
            case MotionEvent.ACTION_UP:
                 if(isDrag){
                     //根据slideBtn_left的值来判断开关状态
                     if(slideBtn_left>maxLeft/2){
                         slideBtn_left = maxLeft;
                     }else{
                         slideBtn_left = 0;
                     }
                 }

                break;
        }

        //对slideBtn_left的值进行判断,确保它在合理的位置 0<maxLeft<maxLeft

        slideBtn_left = (slideBtn_left>0)?slideBtn_left:0;
        slideBtn_left = (slideBtn_left<maxLeft)?slideBtn_left:maxLeft;

        invalidate();
        return true;
    }
}

3.最后是activity_main.xml布局文件。

<?xml version="1.0" encoding="utf-8"?>
<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:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="finch.scu.cn.togglebtn.MainActivity">

    <finch.scu.cn.togglebtn.MyToggleBtn  android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" />
</RelativeLayout>

你可能感兴趣的:(android,自定义)