自定义开关

2018-10-02  本文已影响9人  GeekGray

阅读原文

自定义开关

自定义一个类继承View

/**
 * 
 * @author: Hashub.NG
 * @description: 
 * @update: 2018年7月26日 上午8:59:25
 * 一个视图从创建到显示过程中的主要方法
 * //1.构造方法实例化类
 * //2.测量-measure(int,int)-->onMeasure();
 * 如果当前View是一个ViewGroup,还有义务测量孩子
 * 孩子有建议权
 * //3.指定位置-layout()-->onLayout();
 * 指定控件的位置,一般View不用写这个方法,ViewGroup的时候才需要,一般View不需要重写该方法
 * //4.绘制视图--draw()-->onDraw(canvas)
 * 根据上面两个方法参数,进入绘制
 */
public class MyToggleButton extends View implements View.OnClickListener
{

    private Bitmap backgroundBitmap;
    private Bitmap slidingBitmap;
    
    /**
     * 距离左边最大距离
     */
    private int slidLeftMax;
    private Paint paint;
    private int slideLeft;
    
    private float startX;
    private float lastX;
    
    private boolean isOpen=false;
    
    /**
     * 如果我们在布局文件使用该类,将会用这个构造方法实例该类,如果没有就崩溃
     * @param context
     * @param attrs
     */
    public MyToggleButton(Context context)
    {
        super(context);
        initView();
    }

    .......
}

实例化控件

//创建两个Bitmap,这样才能绘制
private Bitmap backgroundBitmap;
private Bitmap slidingBitmap;

private void initView()
    {
        paint=new Paint();
        paint.setAntiAlias(true);//设置抗锯齿,光滑

        backgroundBitmap=BitmapFactory.decodeResource(getResources(), R.drawable.switch_background);//从资源文件获取
        slidingBitmap=BitmapFactory.decodeResource(getResources(), R.drawable.slide_button);
        
        //背景宽度-遮盖部分的宽度
        slidLeftMax=backgroundBitmap.getWidth()-slidingBitmap.getWidth();
        
        setOnClickListener(this);//设置点击事件
    }

重写onMeasure()测量方法

     /**
     * 视图的测量
     * @param widthMeasureSpec
     * @param heightMeasureSpec
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        //super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        
        //保存测量结果
        setMeasuredDimension(backgroundBitmap.getWidth(), backgroundBitmap.getHeight());
    }

绘制

    /**
     * 绘制
     * @param canvas
     */
    @Override
    protected void onDraw(Canvas canvas)
    {
        //super.onDraw(canvas);

        canvas.drawBitmap(backgroundBitmap, 0, 0,paint);//绘制Bitmap
        canvas.drawBitmap(slidingBitmap, slideLeft,0, paint);
    }

开关的点击事件

    /**
     * true:点击事件生效,滑动事件不生效
     * false:点击事件不生效,滑动事件生效
     */
    private boolean isEnableClick=true;
    
    @Override
    public void onClick(View v)
    {
        if(isEnableClick)
        {
            isOpen=!isOpen;
            flushView();
        }
    }

    private void flushView()
    {
        if(isOpen)
        {
            slideLeft=slidLeftMax;
        }
        else
        {
            slideLeft=0;
        }
        invalidate();//会导致onDraw()执行
    }

开关的滑动事件(ACTION_DOWN,ACTION_MOVE,ACTION_UP)

滑动在Y轴上无变化,记录X轴的坐标即可

event.getX()和event.getRawX()的区别

    private float startX;//记录按下的横坐标
    private float lastX;//记录原始值,该值只记录一次

    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
         super.onTouchEvent(event);//执行父类的方法

         switch (event.getAction())
        {
        case MotionEvent.ACTION_DOWN:

             //1.记录按下的坐标
            lastX=startX=event.getX();

            isEnableClick=true;
            break;

        case MotionEvent.ACTION_MOVE:

             //2.计算结束值
            float endX=event.getX();

             //3.计算偏移量
            float distanceX=endX-startX;
//          slideLeft = (int) (slideLeft + distanceX);//动态改变
            slideLeft+=distanceX;

              //4.有可能越界,屏蔽非法值
            if(slideLeft<0)
            {
                slideLeft=0;
            }
            else if(slideLeft>slidLeftMax)
            {
                slideLeft=slidLeftMax;
            }

            //5.刷新
            invalidate();
            
             //6.数据还原,startX重新赋值
            startX=event.getX();
            
            if(Math.abs(endX-lastX)>5)
            {
                //滑动
                isEnableClick=false;
            }
            break;
            
        case MotionEvent.ACTION_UP://根据距离松开回弹
            if(!isEnableClick)
            {
                if(slideLeft>slidLeftMax/2)
                {
                    //显示按钮开
                    isOpen=true;
                }
                else
                {
                    isOpen=false;
                }
                flushView();
            }
            break;
        }
         return true;//处理触摸事件
    }

解决事件的冲突

    /**
     * true:点击事件生效,滑动事件不生效
     * false:点击事件不生效,滑动事件生效
     */
    private boolean isEnableClick=true;

最后的值-原始值如果大于5个px,就认为是滑动,点击事件不生效,滑动事件生效

if(Math.abs(endX-lastX)>5)
            {
                //滑动
                isEnableClick=false;
            }
上一篇下一篇

猜你喜欢

热点阅读