Android如何自定View实现滑动验证效果
发表于:2025-01-25 作者:千家信息网编辑
千家信息网最后更新 2025年01月25日,本篇内容主要讲解"Android如何自定View实现滑动验证效果",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"Android如何自定View实现滑动验证效
千家信息网最后更新 2025年01月25日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安全错误
数据库的锁怎样保障安全
js数据库引擎
车内异构网络安全防护
数据云存储服务器
数据库有哪几个模式
数据库技术讲解视频
广西网络安全基地
怎么才能保持网络安全
提供网络安全服务器
pqdt数据库网址
数据库系统基础教程原书第3版
软件开发需要什么技能
图像处理 服务器要求
饿了吗 网络技术团队
服务器调优
服务器磁盘管理无法分配盘符
机械网络技术概念设计
比亚迪做软件开发
论坛服务器软件开发厂家
网络安全英文小短文
数据库逻辑结构图实例
如何拷贝sybase数据库
公网如何访问私有服务器
网络技术安全维护
上海贡新互联网科技有限公司
2022数据库系统工程师考点
web缓存服务器软件
led屏服务器
超市数据库安全要求
海底勘探软件开发
网络服务器的知识