自定义控件练习——滑动解锁

本文介绍了一个自定义的Android锁屏滑块View组件的实现细节,包括如何响应触摸事件来控制滑块的移动,如何通过Scroller实现平滑滚动效果等。该组件能够根据用户的手势操作来解锁,并提供了回调接口以便于外部监听解锁事件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

public class LockView extends View {

    private Bitmap button;
    private int buttonHeight;
    private Paint paint;
    private int buttonWidth;
    private float downX;
    private int viewW;
    private Scroller scroller;//帮助scroll的工具类
    private OnLockListener onLockListener;

    public LockView(Context context) {
        this(context, null);
    }

    public LockView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public LockView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //加载滑块的图片
        button = BitmapFactory.decodeResource(getResources(), R.drawable.switch_button);
        buttonHeight = button.getHeight();
        buttonWidth = button.getWidth();
        //创建画笔
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        //1.创建scroller
        scroller = new Scroller(context);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //手动设置当前view的高度为滑块的高度
        setMeasuredDimension(widthMeasureSpec, buttonHeight);
        //获取当前view测量的宽度
//        int measuredWidth = getMeasuredWidth();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //画滑块按钮
        canvas.drawBitmap(button, 0, 0, paint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downX = event.getX();
                //滑块需要移动的距离
                float offsetX = -(downX - buttonWidth / 2);
                //当点击在button之外时 不处理手势事件
                if (downX > buttonWidth) {
                    return false;
                }
                //只有在手指触摸到button宽度一半之后才进行处理
                if (downX >= buttonWidth / 2) {
                    //将滑块移动到制定位置
                    scrollTo((int) offsetX, 0);
                }
                break;
            case MotionEvent.ACTION_MOVE:
                //获取当前x
                float moveX = event.getX();
                //scrollby
//                float moveOffsetX = moveX- downX;
                //滑动偏移
                float scrollX = -(moveX - buttonWidth / 2);
                //判断左边界是否出界
                if (moveX < buttonWidth / 2) {
                    scrollX = 0;
                } else if (moveX > viewW - buttonWidth / 2) {//判断右边是否越界
                    scrollX = -(viewW - buttonWidth);
                }
                scrollTo((int) scrollX, 0);
                break;
            case MotionEvent.ACTION_UP:
                float upX = event.getX();
                int thresX = viewW - buttonWidth / 2;
                if (upX < thresX) {
                    //复位
//                    scrollTo(0,0);
                    int startX = getScrollX();//获取x方向上的偏移
                    int startY = 0;//在y方向上的偏移
                    int dx = -startX;
                    int dy=0;
                    //2.开始滑动 只是做了各个时间点需要滑动到的位置
                    scroller.startScroll(startX,startY,dx,dy);
                    //3.
                    invalidate();//重新绘制
                } else {
                    //解锁
                    if(onLockListener!=null){
                        onLockListener.onLock();
                    }
                }
                break;
        }
        return true;//消费掉事件
    }
    //4.使用scroller需要复写这个方法
    @Override
    public void computeScroll() {
        super.computeScroll();
        //判断当前还需不需要继续滑动  true 需要  false 不需要
        if(scroller.computeScrollOffset()){
            scrollTo(scroller.getCurrX(),0);//scroller.getCurrX()当前需要滑动到的位置偏移
            invalidate();//继续进行滑动
//            ViewCompat.postInvalidateOnAnimation(this);//invalidate在有些模拟器上的兼容
        }
    }

    /**
     * view布局改变后执行  layout-setFrame-sizechanged-onSizechanged
     *
     * @param w
     * @param h
     * @param oldw
     * @param oldh
     */
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        viewW = w;
    }
    public interface OnLockListener{
        void onLock();
    }
    public void setOnLockListener(OnLockListener onLockListener){
        this.onLockListener = onLockListener;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值