Android自定View實現(xiàn)滑動驗證效果的代碼
更新時間:2021年12月25日 14:45:22 作者:NoNullPoint
這篇文章主要介紹了Android自定View實現(xiàn)滑動驗證效果,代碼分為自定義屬性代碼和自定義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 屬性參數(shù)
*/
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();
//判斷區(qū)域是否為滑塊
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) {
//監(jiān)聽回調
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實現(xiàn)滑動驗證效果的文章就介紹到這了,更多相關Android自定View滑動驗證內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Android LocationManager獲取經度與緯度等地理信息
這篇文章主要介紹了Android LocationManager獲取經度與緯度等地理信息的相關資料,希望通過本站大家能掌握這樣的知識,需要的朋友可以參考下2017-09-09
Android仿zaker用手向上推動的特效開發(fā)【推動門效果】(附demo源碼下載)
這篇文章主要介紹了Android仿zaker用手向上推動的特效,結合完整實例形式分析了Android滑動切換效果的實現(xiàn)步驟與相關技巧,具有一定參考借鑒價值,需要的朋友可以參考下2016-07-07
Android 使用Vitamio打造自己的萬能播放器(4)——本地播放(快捷搜索、數(shù)據(jù)存儲)
本文主要介紹android Vitamio 本地播放功能(快捷搜索,數(shù)據(jù)存儲),這里提供實例代碼和效果圖,有需要的小伙伴可以參考下2016-07-07

