Android如何自定View实现滑动验证效果
发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,本篇内容主要讲解"Android如何自定View实现滑动验证效果",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"Android如何自定View实现滑动验证效
千家信息网最后更新 2026年11月03日Android如何自定View实现滑动验证效果
本篇内容主要讲解"Android如何自定View实现滑动验证效果",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"Android如何自定View实现滑动验证效果"吧!
效果图
自定义属性代码
自定义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(); } /** * 初始化自定义属性 * * @param context 上下文 * @param attrs 属性参数 */ 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(); }}使用方法
到此,相信大家对"Android如何自定View实现滑动验证效果"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
背景
矩形
颜色
效果
进度
大小
属性
画笔
自定
验证
圆角
宽度
方法
阴影
代码
内容
尺寸
接口
角度
高度
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
互联网是第几次科技革命的成果
广州百单互联网科技有限公司
猪兼强互联网科技
互联网科技公司怎么样
互联网金融科技创新
中国互联网有什么科技含量
阿里互联网科技公司
互联网5g黑科技有哪些
广西互联网科技孵化中心
东莞新华互联网科技学校
2021互联网科技公司排名
每天都有哪些好的互联网科技
电子商务与互联网科技的关系
黑云互联网科技有限公司
互联网科技收购价值
北京天晋互联网科技有限公司
互联网时代高科技布局
安徽九吞吴互联网科技有限公司
互联网的黑科技实验室
知域互联网科技有限公司官网
科技信息互联网
华中科技大学互联网
壕鑫互联网络科技
现代互联网科技股
互联网科技与管理
中和天地互联网科技有限公司
宁波跨境商互联网科技有限公司
国产互联网科技公司
版纳互联网科技选哪家
云南互联网科技学费