文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Android如何自定View实现滑动验证效果

2023-06-22 05:09

关注

本篇内容主要讲解“Android如何自定View实现滑动验证效果”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Android如何自定View实现滑动验证效果”吧!

效果图

Android如何自定View实现滑动验证效果

自定义属性代码

<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="MyCheckView">        <attr name="m_blockBg" format="reference" /><!--滑块背景图片-->        <attr name="m_blockColor" format="color" /><!--滑块颜色-->        <attr name="m_blockShadowLayer" format="color" /><!--滑块阴影颜色-->        <attr name="m_proColor" format="color" /><!--进度条颜色-->        <attr name="m_recColor" format="color" /><!--矩形背景色-->        <attr name="m_circleSize" format="integer" /><!--圆角角度值-->    </declare-styleable></resources>

自定义View代码

public class MyCheckView extends View {    private boolean isBlockArea = false;    private boolean isMove = false;    private boolean isFinish = false;    private boolean isDown = false;    private int mRight;    private int startX = 0;        private final int blockSize = SizeUtils.dp2px(5);        private int m_blockColor = Color.WHITE;//默认滑块颜色    private int m_blockShadowLayer = Color.parseColor("#D8D8D8");//默认滑块阴影色    private int m_proColor = Color.parseColor("#ff3159");//默认进度条颜色    private int m_recColor = Color.parseColor("#D8D8D8");//默认矩形颜色    private int blockDrawableId;//默认滑块背景图        private final Paint recPaint = new Paint();        private final Paint proPaint = new Paint();        private final Paint blockPaint = new Paint();        private int circleSize = SizeUtils.dp2px(20);        private float parentWidth = 0f;        private int proHeight;        private final int DEFAULT_HEIGHT = SizeUtils.dp2px(45);        private final int blockWidth = SizeUtils.dp2px(60);        private int dX;        private int mX;        private FinishListener finishListener;    public void setFinishListener(FinishListener finishListener) {        this.finishListener = finishListener;    }    public MyCheckView(@NonNull Context context) {        super(context);        init();    }    public MyCheckView(@NonNull Context context, @Nullable AttributeSet attrs) {        super(context, attrs);        initParams(context, attrs);        init();    }    public MyCheckView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        initParams(context, attrs);        init();    }        private void initParams(Context context, AttributeSet attrs) {        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyCheckView);        if (typedArray != null) {            //获取滑块背景图片            blockDrawableId = typedArray.getResourceId(R.styleable.MyCheckView_m_blockBg, -1);            //获取滑块颜色            m_blockColor = typedArray.getColor(R.styleable.MyCheckView_m_blockColor, m_blockColor);            //滑块阴影色            m_blockShadowLayer = typedArray.getColor(R.styleable.MyCheckView_m_blockColor, m_blockShadowLayer);            //进度条颜色            m_proColor = typedArray.getColor(R.styleable.MyCheckView_m_blockColor, m_proColor);            //矩形颜色            m_recColor = typedArray.getColor(R.styleable.MyCheckView_m_blockColor, m_recColor);            //圆角角度值            circleSize = typedArray.getInt(R.styleable.MyCheckView_m_blockColor, circleSize);            typedArray.recycle();        }    }        private void init() {        //设置矩形背景色        recPaint.setColor(m_recColor);        recPaint.setStyle(Paint.Style.FILL);        recPaint.setAntiAlias(true);        //设置进度条背景色        proPaint.setColor(m_proColor);        proPaint.setStyle(Paint.Style.FILL);        recPaint.setAntiAlias(true);        //判断是否使用了背景图        if (blockDrawableId != -1) {            //设置滑块背景色            blockPaint.setColor(m_blockColor);            blockPaint.setStyle(Paint.Style.FILL_AND_STROKE);            blockPaint.setAntiAlias(true);            //给滑块添加阴影            blockPaint.setShadowLayer(35, 1, 1, m_blockShadowLayer);        } else {            blockPaint.setStyle(Paint.Style.FILL_AND_STROKE);            blockPaint.setAntiAlias(true);        }    }    public void blockReset() {        mX = 0;        reset(startX);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        parentWidth = getMyWSize(widthMeasureSpec);        proHeight = getMyHSize(heightMeasureSpec);        setMeasuredDimension((int) parentWidth, proHeight);    }    @SuppressLint("DrawAllocation")    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        //绘制矩形        RectF rectF = new RectF();        rectF.left = 1;        rectF.right = parentWidth - 1;        rectF.top = 1;        rectF.bottom = proHeight - 1;        //绘制圆角矩形        canvas.drawRoundRect(rectF, circleSize, circleSize, recPaint);        if (isMove || isDown) {            //绘制进度条            RectF rectP = new RectF();            rectP.left = 1;            rectP.right = blockWidth + blockSize + mX;            rectP.top = 1;            rectP.bottom = proHeight - 1;            canvas.drawRoundRect(rectP, circleSize, circleSize, proPaint);        }        //绘制滑块        RectF rectB = new RectF();        rectB.left = blockSize + mX;        rectB.right = blockWidth + mX;        rectB.top = blockSize;        rectB.bottom = proHeight - blockSize;        mRight = (int) rectB.right;        //判断是否使用了背景图        if (blockDrawableId != -1) {            //绘制背景图            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), blockDrawableId);            Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());            canvas.drawBitmap(bitmap, rect, rectB, blockPaint);        } else {            //绘制滑块            canvas.drawRoundRect(rectB, circleSize, circleSize, blockPaint);        }    }    @SuppressLint("ClickableViewAccessibility")    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                dX = (int) event.getX();                int dY = (int) event.getY();                int top = getTop();                int bottom = getBottom();                //判断区域是否为滑块                if (dX > blockSize && dX < blockWidth && dY > blockSize && dY < (bottom - top)) {                    isBlockArea = true;                }                return true;            case MotionEvent.ACTION_MOVE:                if (isBlockArea) {                    mX = (int) event.getX() - dX;                    //设置范围                    if ((blockWidth + blockSize + mX) < parentWidth && (blockSize + mX) >= blockSize) {                        //计算偏移量                        invalidate();                        startX = (int) event.getX() - blockWidth / 2;                    } else if ((blockSize + mX) >= blockSize) {                        //超出复位                        mX = (int) parentWidth - blockWidth - blockSize;                        invalidate();                    }                    isMove = true;                }                return true;            case MotionEvent.ACTION_UP:            case MotionEvent.ACTION_CANCEL:                isBlockArea = false;                isFinish = mRight == parentWidth - blockSize;                if (isFinish) {                    //监听回调                    if (finishListener != null) {                        finishListener.finish();                    }                }                if (!isFinish && isMove) {                    reset(startX);                }                break;        }        return super.onTouchEvent(event);    }        private void reset(int start) {        ValueAnimator valueAnimator = ValueAnimator.ofInt(start, 0);        valueAnimator.setDuration(500);        valueAnimator.start();        valueAnimator.addUpdateListener(animation -> {            mX = (int) animation.getAnimatedValue();            //刷新            invalidate();        });        valueAnimator.addListener(new AnimatorListenerAdapter() {            @Override            public void onAnimationEnd(Animator animation) {                isMove = false;                isFinish = false;                startX = 0;            }        });    }        private int getMyWSize(int measureSpec) {        int result;        int specMode = MeasureSpec.getMode(measureSpec);        int specSize = MeasureSpec.getSize(measureSpec);        if (specMode == MeasureSpec.EXACTLY) {            result = specSize;//确切大小,所以将得到的尺寸给view        } else if (specMode == MeasureSpec.AT_MOST) {            result = Math.min(getScreenWidth() - 20, specSize);        } else {            result = getScreenWidth() - 20;        }        return result;    }        private int getMyHSize(int measureSpec) {        int result;        int specMode = MeasureSpec.getMode(measureSpec);        int specSize = MeasureSpec.getSize(measureSpec);        if (specMode == MeasureSpec.EXACTLY) {            result = specSize;//确切大小,所以将得到的尺寸给view        } else if (specMode == MeasureSpec.AT_MOST) {            result = Math.min(DEFAULT_HEIGHT, specSize);        } else {            result = DEFAULT_HEIGHT - 20;        }        return result;    }        private int getScreenWidth() {        WindowManager windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);        DisplayMetrics displayMetrics = new DisplayMetrics();        windowManager.getDefaultDisplay().getMetrics(displayMetrics);        return displayMetrics.widthPixels;    }        public interface FinishListener {        void finish();    }}

使用方法

<com.guanwei.globe.view.MyCheckView        android:id="@+id/checkView"        android:layout_width="200dp"        android:layout_height="wrap_content"        android:layout_marginLeft="20dp"        android:layout_marginRight="20dp"        app:layout_constraintLeft_toLeftOf="parent"        app:layout_constraintRight_toRightOf="parent"        app:layout_constraintBottom_toBottomOf="parent"        app:layout_constraintTop_toTopOf="parent"        app:m_blockBg="@mipmap/block" />

到此,相信大家对“Android如何自定View实现滑动验证效果”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯