Android 自定義仿SeekBar滑動(dòng)驗(yàn)證

最近在項(xiàng)目中遇到一個(gè)需要滑動(dòng)驗(yàn)證的功能,樣式如下:


????????? 在未滑動(dòng)時(shí)滑塊為箭頭形式,滑動(dòng)到末端后變?yōu)閷?duì)勾樣式,滑動(dòng)過的路徑變?yōu)榧t色,遇到問題當(dāng)然是先百度一番啦,沒有對(duì)象,只能面向百度編程了,結(jié)果弄了半天都沒找到合適的,大部分都是通過SeekBar來做的,但動(dòng)態(tài)設(shè)置thumb的時(shí)候滑到首尾上面的thumb總是被覆蓋掉一半,然后找了半天也沒得到解決,沒想到這東西資料這么少,沒辦法,只能自己來了,先看一下效果:




效果大概就是這個(gè)樣子,不是很完美,勉強(qiáng)夠用,沒滑到底松開會(huì)自動(dòng)回到起點(diǎn),

下面來說一下具體實(shí)現(xiàn):

1. 自定義VerifiSeekBar(就這個(gè)控件)繼承自View。

2.畫背景灰色圓角矩形,畫上方紅色圓角矩形,畫初始狀態(tài)滑塊(帶箭頭),畫結(jié)束狀態(tài)滑塊。

3.TouchEvent監(jiān)聽手勢,主要是X軸位置,根據(jù)屏幕上的坐標(biāo)動(dòng)態(tài)畫紅色矩形和滑塊

4.監(jiān)聽滑動(dòng)距離是否到最后,到最后后畫完成狀態(tài)滑塊(對(duì)勾)

思路就是這個(gè)樣子咯,思路對(duì)了的話,代碼就很好寫了,下面貼一下代碼,寫得不是很好,有啥不對(duì)的地方歡迎大家指教。

```

public class VerifiSeekBar extends View {

private Contextcontext;

? ? private Paintpaint;

? ? private int movex;

? ? private RectFbgRect;

? ? private RectFupRect;

? ? private BitmapinBitmap;

? ? private BitmapoutBitmap;

? ? private int bitmapWidth;

? ? private int bitmapHeight;

? ? //防止多次調(diào)用

? ? private boolean isNewdown =true;

? ? private OnSeekbarCompleListenneronSeekbarCompleListenner;

? ? public VerifiSeekBar(Context context) {

super(context);

? ? ? ? this.context = context;

? ? ? ? initView();

? ? }

public VerifiSeekBar(Context context, @Nullable AttributeSet attrs) {

super(context, attrs);

? ? ? ? this.context = context;

? ? ? ? initView();

? ? }

public VerifiSeekBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

? ? ? ? this.context = context;

? ? ? ? initView();

? ? }

public void setProgress(int progress) {

movex = progress;

? ? ? ? invalidate();

? ? }

@Override

? ? protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

? ? ? ? paint.setColor(ContextCompat.getColor(context, R.color.seekbar_notclick));

? ? ? ? bgRect.set(0, 0, getWidth(), bitmapHeight + SizeUtils.dp2px(6));

? ? ? ? canvas.drawRoundRect(bgRect, SizeUtils.dp2px(5), SizeUtils.dp2px(5), paint);

? ? ? ? if (movex > getWidth()) {

movex = getWidth();

? ? ? ? }

if (movex <=0) {

movex =0;

? ? ? ? }

upRect.set(0, 0, movex, bitmapHeight + SizeUtils.dp2px(6));

? ? ? ? paint.setColor(ContextCompat.getColor(context, R.color.red));

? ? ? ? canvas.drawRoundRect(upRect, SizeUtils.dp2px(5), SizeUtils.dp2px(5), paint);

? ? ? ? if (movex == getWidth()) {

getParent().requestDisallowInterceptTouchEvent(false);


? ? ? ? ? canvas.drawBitmap(outBitmap, movex -bitmapWidth <0 ?

SizeUtils.dp2px(3) :movex - (bitmapWidth + SizeUtils.dp2px(3)),

SizeUtils.dp2px(3), paint);

? ? ? ? ? ? if (onSeekbarCompleListenner !=null) {

if (isNewdown) {

onSeekbarCompleListenner.comple();

? ? ? ? ? ? ? ? ? ? isNewdown =false;

? ? ? ? ? ? ? ? }

}

}else {

canvas.drawBitmap(inBitmap, movex -bitmapWidth <0 ? SizeUtils.dp2px(3) :movex -bitmapWidth, SizeUtils.dp2px(3), paint);

? ? ? ? ? ? if (onSeekbarCompleListenner !=null) {

onSeekbarCompleListenner.uncomple();

? ? ? ? ? ? }

}

}

private void initView() {

paint =new Paint();

? ? ? ? paint.setStyle(Paint.Style.FILL);

? ? ? ? paint.setColor(ContextCompat.getColor(context, R.color.red));

? ? ? ? paint.setStrokeWidth(2);

? ? ? ? bgRect =new RectF();

? ? ? ? upRect =new RectF();

? ? ? ? inBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.login_move);

? ? ? ? outBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.login_ok);

? ? ? ? bitmapWidth =inBitmap.getWidth();

? ? ? ? bitmapHeight =inBitmap.getHeight();

? ? }

@Override

? ? public boolean onTouchEvent(MotionEvent event) {

switch (event.getAction()) {

case MotionEvent.ACTION_DOWN:

isNewdown =true;

? ? ? ? ? ? ? ? movex =bitmapWidth + SizeUtils.dp2px(3);

? ? ? ? ? ? case MotionEvent.ACTION_MOVE:

movex = (int) event.getX();

? ? ? ? ? ? ? ? invalidate();

break;

? ? ? ? ? ? case MotionEvent.ACTION_UP:

if (movex < getWidth()) {

movex =0;

? ? ? ? ? ? ? ? }

invalidate();

break;

? ? ? ? ? ? default:

break;

? ? ? ? }

return true;

? ? }

public void setOnSeekbarCompleListenner(OnSeekbarCompleListenner onSeekbarCompleListenner) {

this.onSeekbarCompleListenner = onSeekbarCompleListenner;

? ? }

public interface OnSeekbarCompleListenner {

void comple();

? ? ? ? void uncomple();

? ? }

}

```

里面用到的工具類:

```

public final class SizeUtils {

private SizeUtils() {

throw new UnsupportedOperationException("u can't instantiate me...");

? ? }

/**

* Value of dp to value of px.

*

? ?? * @param dpValue The value of dp.

? ?? * @return value of px

*/

? ? public static int dp2px(final float dpValue) {

final float scale = Resources.getSystem().getDisplayMetrics().density;

? ? ? ? return (int) (dpValue * scale +0.5f);

? ? }

/**

* Value of px to value of dp.

*

? ?? * @param pxValue The value of px.

? ?? * @return value of dp

*/

? ? public static int px2dp(final float pxValue) {

final float scale = Resources.getSystem().getDisplayMetrics().density;

? ? ? ? return (int) (pxValue / scale +0.5f);

? ? }

/**

* Value of sp to value of px.

*

? ?? * @param spValue The value of sp.

? ?? * @return value of px

*/

? ? public static int sp2px(final float spValue) {

final float fontScale = Resources.getSystem().getDisplayMetrics().scaledDensity;

? ? ? ? return (int) (spValue * fontScale +0.5f);

? ? }

/**

* Value of px to value of sp.

*

? ?? * @param pxValue The value of px.

? ?? * @return value of sp

*/

? ? public static int px2sp(final float pxValue) {

final float fontScale = Resources.getSystem().getDisplayMetrics().scaledDensity;

? ? ? ? return (int) (pxValue / fontScale +0.5f);

? ? }

/**

* Converts an unpacked complex data value holding a dimension to its final floating

? ?? * point value. The two parameters <var>unit</var> and <var>value

? ?? * are as in {@link TypedValue#TYPE_DIMENSION}.

*

? ?? * @param value The value to apply the unit to.

? ?? * @param unit? The unit to convert from.

? ?? * @return The complex floating point value multiplied by the appropriate

* metrics depending on its unit.

*/

? ? public static float applyDimension(final float value, final int unit) {

DisplayMetrics metrics = Utils.getApp().getResources().getDisplayMetrics();

? ? ? ? switch (unit) {

case TypedValue.COMPLEX_UNIT_PX:

return value;

? ? ? ? ? ? case TypedValue.COMPLEX_UNIT_DIP:

return value * metrics.density;

? ? ? ? ? ? case TypedValue.COMPLEX_UNIT_SP:

return value * metrics.scaledDensity;

? ? ? ? ? ? case TypedValue.COMPLEX_UNIT_PT:

return value * metrics.xdpi * (1.0f /72);

? ? ? ? ? ? case TypedValue.COMPLEX_UNIT_IN:

return value * metrics.xdpi;

? ? ? ? ? ? case TypedValue.COMPLEX_UNIT_MM:

return value * metrics.xdpi * (1.0f /25.4f);

? ? ? ? }

return 0;

? ? }

/**

* Force get the size of view.

? ?? * <p>e.g.

? ?? *

? ?? * SizeUtils.forceGetViewSize(view, new SizeUtils.onGetSizeListener() {

*? ?? Override

*? ?? public void onGetSize(final View view) {

*? ? ? ?? view.getWidth();

*? ?? }

* });

? ?? *

? ?? *

? ?? * @param view? ?? The view.

? ?? * @param listener The get size listener.

*/

? ? public static void forceGetViewSize(final View view, final onGetSizeListener listener) {

view.post(new Runnable() {

@Override

? ? ? ? ? ? public void run() {

if (listener !=null) {

listener.onGetSize(view);

? ? ? ? ? ? ? ? }

}

});

? ? }

/**

* Return the width of view.

*

? ?? * @param view The view.

? ?? * @return the width of view

*/

? ? public static int getMeasuredWidth(final View view) {

return measureView(view)[0];

? ? }

/**

* Return the height of view.

*

? ?? * @param view The view.

? ?? * @return the height of view

*/

? ? public static int getMeasuredHeight(final View view) {

return measureView(view)[1];

? ? }

/**

* Measure the view.

*

? ?? * @param view The view.

? ?? * @return arr[0]: view's width, arr[1]: view's height

*/

? ? public static int[]measureView(final View view) {

ViewGroup.LayoutParams lp = view.getLayoutParams();

? ? ? ? if (lp ==null) {

lp =new ViewGroup.LayoutParams(

ViewGroup.LayoutParams.MATCH_PARENT,

? ? ? ? ? ? ? ? ? ? ViewGroup.LayoutParams.WRAP_CONTENT

? ? ? ? ? ? );

? ? ? ? }

int widthSpec = ViewGroup.getChildMeasureSpec(0, 0, lp.width);

? ? ? ? int lpHeight = lp.height;

? ? ? ? int heightSpec;

? ? ? ? if (lpHeight >0) {

heightSpec = View.MeasureSpec.makeMeasureSpec(lpHeight, View.MeasureSpec.EXACTLY);

? ? ? ? }else {

heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);

? ? ? ? }

view.measure(widthSpec, heightSpec);

? ? ? ? return new int[]{view.getMeasuredWidth(), view.getMeasuredHeight()};

? ? }

///////////////////////////////////////////////////////////////////////////

// interface

///////////////////////////////////////////////////////////////////////////

? ? public interface onGetSizeListener {

void onGetSize(View view);

? ? }

}

```

這就是整個(gè)的代碼啦,代碼不多,有需要的直接拷過去用就行了,替換一下圖片,顏色,也可以做一下優(yōu)化。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容