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(); } /** * 初始化自定義屬性 * * @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實現滑動驗證效果的文章就介紹到這瞭,更多相關Android自定View滑動驗證內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Android View實現圓形進度條
- Android實現微信朋友圈圖片和視頻播放
- Android實現梯形TextView效果
- Android自定義View實現隨機數驗證碼
- Android自定義view之太極圖的實現教程