Android自定View實(shí)現(xiàn)滑動(dòng)驗(yàn)證效果的代碼
效果圖

自定義屬性代碼
<?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" /><!--進(jìn)度條顏色-->
<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);
/**
* 相關(guān)屬性
*/
private int m_blockColor = Color.WHITE;//默認(rèn)滑塊顏色
private int m_blockShadowLayer = Color.parseColor("#D8D8D8");//默認(rèn)滑塊陰影色
private int m_proColor = Color.parseColor("#ff3159");//默認(rèn)進(jìn)度條顏色
private int m_recColor = Color.parseColor("#D8D8D8");//默認(rèn)矩形顏色
private int blockDrawableId;//默認(rèn)滑塊背景圖
/**
* 矩形畫筆
*/
private final Paint recPaint = new Paint();
/**
* 進(jìn)度條畫筆
*/
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;
/**
* 默認(rèn)高度
*/
private final int DEFAULT_HEIGHT = SizeUtils.dp2px(45);
/**
* 滑塊寬度
*/
private final int blockWidth = SizeUtils.dp2px(60);
/**
* 手指落下位置
*/
private int dX;
/**
* 偏移距離
*/
private int mX;
/**
* 接口回調(diào)
*/
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);
//進(jìn)度條顏色
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() {
//設(shè)置矩形背景色
recPaint.setColor(m_recColor);
recPaint.setStyle(Paint.Style.FILL);
recPaint.setAntiAlias(true);
//設(shè)置進(jìn)度條背景色
proPaint.setColor(m_proColor);
proPaint.setStyle(Paint.Style.FILL);
recPaint.setAntiAlias(true);
//判斷是否使用了背景圖
if (blockDrawableId != -1) {
//設(shè)置滑塊背景色
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) {
//繪制進(jìn)度條
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;
//設(shè)置范圍
if ((blockWidth + blockSize + mX) < parentWidth && (blockSize + mX) >= blockSize) {
//計(jì)算偏移量
invalidate();
startX = (int) event.getX() - blockWidth / 2;
} else if ((blockSize + mX) >= blockSize) {
//超出復(fù)位
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)聽回調(diào)
if (finishListener != null) {
finishListener.finish();
}
}
if (!isFinish && isMove) {
reset(startX);
}
break;
}
return super.onTouchEvent(event);
}
/**
* 松手回彈動(dòng)畫效果
*/
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;
}
});
}
/**
* 獲取測(cè)量大小
*/
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;
}
/**
* 獲取測(cè)量大小
*/
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;
}
/**
* 接口回調(diào)方法
*/
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" />
到此這篇關(guān)于Android自定View實(shí)現(xiàn)滑動(dòng)驗(yàn)證效果的文章就介紹到這了,更多相關(guān)Android自定View滑動(dòng)驗(yàn)證內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Flutter實(shí)戰(zhàn)之自定義日志打印組件詳解
這篇文章主要介紹了Flutter實(shí)戰(zhàn)之自定義日志打印組件詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-03-03
Android點(diǎn)擊事件的實(shí)現(xiàn)方式
這篇文章主要為大家詳細(xì)介紹了Android點(diǎn)擊事件的實(shí)現(xiàn)方式,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-12-12
Android 自定義View實(shí)現(xiàn)任意布局的RadioGroup效果
這篇文章主要介紹了Android 自定義View實(shí)現(xiàn)任意布局的RadioGroup,需要的朋友可以參考下2018-11-11
Android設(shè)置PreferenceCategory背景顏色的方法
這篇文章主要介紹了Android設(shè)置PreferenceCategory背景顏色的方法,涉及Android設(shè)置背景色的技巧,需要的朋友可以參考下2015-05-05
Android獲取手機(jī)型號(hào)/系統(tǒng)版本號(hào)/App版本號(hào)等信息實(shí)例講解
本示例獲得手機(jī)型號(hào),系統(tǒng)版本,App版本號(hào)等信息,具體實(shí)現(xiàn)如下,感興趣的朋友可以參考下哈2013-06-06
Android和iOS 測(cè)試五個(gè)最好的開源自動(dòng)化工具
本文主要介紹Android和iOS 五個(gè)最好的開源自動(dòng)化工具,這里整理了相關(guān)資料,希望能幫助測(cè)試軟件的朋友,有需要的看下2016-09-09
Android中快速便捷的實(shí)現(xiàn)圓角按鈕方法詳解
圓角按鈕在我們現(xiàn)在的界面中常常會(huì)用到,最近在開發(fā)中就又遇到了,所以想著有沒有更快速更便捷的實(shí)現(xiàn)方法呢,所以就有了這篇文章,本文主要給大家介紹了關(guān)于Android中如何快速便捷的實(shí)現(xiàn)圓角按鈕的相關(guān)資料,需要的朋友可以參考下。2017-05-05

