首页 » 软件编程 » Android

安卓自定View实现滑动验证效果

Android 2021-12-25

效果图

安卓自定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(); } /**
     * 初始化自定义属性
     *
     * @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(); } } 

使用方法

<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实现圆形进度条下一篇:音视频录制基础原理概念
程序园_程序员的世界 Copyright © 2020- www.580doc.com. Some Rights Reserved.