编程实践view

Android 自定义仿SeekBar滑动验证

2019-12-06  本文已影响0人  小白彡

最近在项目中遇到一个需要滑动验证的功能,样式如下:

          在未滑动时滑块为箭头形式,滑动到末端后变为对勾样式,滑动过的路径变为红色,遇到问题当然是先百度一番啦,没有对象,只能面向百度编程了,结果弄了半天都没找到合适的,大部分都是通过SeekBar来做的,但动态设置thumb的时候滑到首尾上面的thumb总是被覆盖掉一半,然后找了半天也没得到解决,没想到这东西资料这么少,没办法,只能自己来了,先看一下效果:

效果大概就是这个样子,不是很完美,勉强够用,没滑到底松开会自动回到起点,

下面来说一下具体实现:

1. 自定义VerifiSeekBar(就这个控件)继承自View。

2.画背景灰色圆角矩形,画上方红色圆角矩形,画初始状态滑块(带箭头),画结束状态滑块。

3.TouchEvent监听手势,主要是X轴位置,根据屏幕上的坐标动态画红色矩形和滑块

4.监听滑动距离是否到最后,到最后后画完成状态滑块(对勾)

思路就是这个样子咯,思路对了的话,代码就很好写了,下面贴一下代码,写得不是很好,有啥不对的地方欢迎大家指教。

```

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;

    //防止多次调用

    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);

    }

}

```

这就是整个的代码啦,代码不多,有需要的直接拷过去用就行了,替换一下图片,颜色,也可以做一下优化。

上一篇下一篇

猜你喜欢

热点阅读