圆形扫描自定义view随记

效果图

扫描白纸图

先定义又上往下扫描

public class ScanView extends View implements ValueAnimator.AnimatorUpdateListener{

    private static final int PLAY_STATE_PLAYING = 1;
    private static final int PLAY_STATE_PAUSE = 2;

    Drawable drawableLine;
//  Drawable drawableFrame;

    int linePaddingLeft;
    int linePaddingRight;
    int linePaddingTop;
    int linePaddingBottom;

    int framePaddingLeft;
    int framePaddingRight;
    int framePaddingTop;
    int framePaddingBottom;

    float lineHeight = 0.3f;

    private ValueAnimator animatorLine;
    private Interpolator interpolator;
    private int duration = 1500;
    int playState = PLAY_STATE_PLAYING;

    public ScanView(Context context) {
        super(context);
        init(context);
    }

    public ScanView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ScanView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initAttrs(context, attrs);
    }

    private void initAttrs(Context context, AttributeSet attrs){
        init(context);
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ScanView);
        drawableLine = typedArray.getDrawable(R.styleable.ScanView_scanLineDrawable);

//      drawableFrame = typedArray.getDrawable(R.styleable.ScanView_scanFrameDrawable);
        lineHeight = typedArray.getFloat(R.styleable.ScanView_lineHeight, lineHeight);

        framePaddingLeft = framePaddingRight = framePaddingTop = framePaddingBottom =
                typedArray.getDimensionPixelSize(R.styleable.ScanView_framePadding, 0);
        framePaddingLeft = typedArray.getDimensionPixelSize(R.styleable.ScanView_framePaddingLeft, framePaddingLeft);
        framePaddingRight = typedArray.getDimensionPixelSize(R.styleable.ScanView_framePaddingRight, framePaddingRight);
        framePaddingTop = typedArray.getDimensionPixelSize(R.styleable.ScanView_framePaddingTop, framePaddingTop);
        framePaddingBottom = typedArray.getDimensionPixelSize(R.styleable.ScanView_framePaddingBottom, framePaddingBottom);

        linePaddingLeft = linePaddingRight = linePaddingTop = linePaddingBottom =
                typedArray.getDimensionPixelSize(R.styleable.ScanView_linePadding, 0);
        linePaddingLeft = typedArray.getDimensionPixelSize(R.styleable.ScanView_linePaddingLeft, linePaddingLeft);
        linePaddingRight = typedArray.getDimensionPixelSize(R.styleable.ScanView_linePaddingRight, linePaddingRight);
        linePaddingBottom = typedArray.getDimensionPixelSize(R.styleable.ScanView_linePaddingBottom, linePaddingBottom);
        linePaddingTop = typedArray.getDimensionPixelSize(R.styleable.ScanView_linePaddingTop, linePaddingTop);

        duration = typedArray.getInt(R.styleable.ScanView_duration, duration);

        typedArray.recycle();
    }

    private void init(Context context){
        interpolator = new LinearInterpolator();
    }

    /**
     * 设定扫描条图片资源
     * @param drawable
     */
    public void setDrawableLine(Drawable drawable){
        this.drawableLine = drawable;
        setLinePadding(linePaddingLeft, linePaddingTop, linePaddingRight, linePaddingBottom);
    }

    /**
     * 设定扫描条图片资源
     * @param resId
     */
    public void setDrawableLine(int resId){
        setDrawableLine(getResources().getDrawable(resId));
    }

    /**
     * 设定扫描框图片资源
     * @param drawable
     */
    public void setDrawableFrame(Drawable drawable){
//      this.drawableFrame = drawable;
        setFramePadding(framePaddingLeft, framePaddingTop, framePaddingRight, framePaddingBottom);
    }

    /**
     * 设定扫描框图片资源
     * @param resId
     */
    public void setDrawableFrame(int resId){
        setDrawableFrame(getResources().getDrawable(resId));
    }

    /**
     * 扫描条完成一次扫描所用的时间
     * @param duration
     */
    public void setDuration(int duration) {
        this.duration = duration;
        if(animatorLine != null) {
            animatorLine.setDuration(duration);
        }
    }

    /**
     * 设定扫描条插值计算器
     * @param interpolator
     */
    public void setInterpolator(Interpolator interpolator) {
        this.interpolator = interpolator;
        if(animatorLine != null) {
            animatorLine.setInterpolator(this.interpolator);
        }
    }

    /**
     * 设定扫描条插值计算器
     * @param interpolatorId
     */
    public void setInterpolator(int interpolatorId) {
        setInterpolator( AnimationUtils.loadInterpolator(getContext(), interpolatorId));
    }

    /**
     * lineHeight 0-1.0:设定扫描线占据的ScanView控件的高度比例
     * lineHeight 大于1.0:设定扫描线指定相对应的像素高度
     * @param lineHeight
     */
    public void setLineHeight(float lineHeight) {
        this.lineHeight = lineHeight;
        setLinePadding(linePaddingLeft, linePaddingRight, linePaddingTop, linePaddingBottom);
    }

    public void setLinePadding(int paddingLeft, int paddingTop, int paddingRight, int paddingBottom) {
        this.linePaddingLeft = paddingLeft;
        this.linePaddingRight = paddingRight;
        this.linePaddingBottom = paddingBottom;
        this.linePaddingTop = paddingTop;

        if(drawableLine != null) {
            int lineHeight;
            if(this.lineHeight > 1){
                lineHeight = (int) this.lineHeight;
            }
            else {
                lineHeight = (int) (getMeasuredHeight() * this.lineHeight);
            }
            drawableLine.setBounds(new Rect(linePaddingLeft, linePaddingTop,
                    getMeasuredWidth() - linePaddingRight, lineHeight + linePaddingTop));
            if(animatorLine != null){
                animatorLine.setIntValues(
                        0, getMeasuredHeight() - linePaddingTop - linePaddingBottom + drawableLine.getBounds().height());
            }
        }
    }

    public void setFramePadding(int paddingLeft, int paddingTop, int paddingRight, int paddingBottom) {
        this.framePaddingLeft = paddingLeft;
        this.framePaddingRight = paddingRight;
        this.framePaddingBottom = paddingBottom;
        this.framePaddingTop = paddingTop;
//      if(drawableFrame != null) {
//          drawableFrame.setBounds(new Rect(framePaddingLeft, framePaddingTop,
//                  getMeasuredWidth() - framePaddingRight, getMeasuredHeight() - framePaddingBottom));
//      }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setLinePadding(linePaddingLeft, linePaddingRight, linePaddingTop, linePaddingBottom);
        setFramePadding(framePaddingLeft, framePaddingTop, framePaddingRight, framePaddingBottom);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);

        if(changed) {
            if (animatorLine != null) {
                animatorLine.cancel();
                animatorLine = null;
            }

            animatorLine = ValueAnimator.ofInt(
                    0, getMeasuredHeight() - linePaddingTop - linePaddingBottom + drawableLine.getBounds().height())
                    .setDuration(duration);
            animatorLine.setRepeatMode(ValueAnimator.RESTART);
            animatorLine.setRepeatCount(ValueAnimator.INFINITE);
            animatorLine.setInterpolator(interpolator);
            animatorLine.addUpdateListener(this);

            play();
        }
    }

    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        invalidate();
    }

    /**
     * 启动扫描
     */
    public void play() {
        startAnim();
        playState = PLAY_STATE_PLAYING;
    }

    private void startAnim() {
        if(animatorLine != null && !animatorLine.isRunning()){
            animatorLine.start();
        }
    }

    /**
     * 停止扫描
     */
    public void stop(){
        stopAnim();
        playState = PLAY_STATE_PAUSE;
    }

    private void stopAnim() {
        if(animatorLine != null){
            animatorLine.end();
        }
    }

    @Override
    protected void onWindowVisibilityChanged(int visibility) {
        super.onWindowVisibilityChanged(visibility);
        if(visibility == VISIBLE){
            if(playState == PLAY_STATE_PLAYING) {
                startAnim();
            }
        }
        else{
            stopAnim();
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if(drawableLine == null /*|| drawableFrame == null*/) return;
        canvas.save();
        int transDis = 0;
        if(animatorLine != null){
            transDis = (int) animatorLine.getAnimatedValue();
        }
        Rect drawableLineBounds = drawableLine.getBounds();
        canvas.clipRect(drawableLineBounds.left, drawableLineBounds.top, drawableLineBounds.right, getHeight() - drawableLineBounds.top);
        canvas.translate(0, transDis - drawableLineBounds.height());
        drawableLine.draw(canvas);
        canvas.restore();
//      drawableFrame.draw(canvas);
        super.onDraw(canvas);
    }

}

定义扫描的线face_scan_line.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >

    <gradient
        android:angle="270"
        android:centerX="0.5"
        android:centerY="0.5"
        android:endColor="#7723af9c"
        android:startColor="#00c9caca" />
</shape>

再次定义xml布局定义圆形扫描效果

 <android.support.v7.widget.CardView
        android:id="@+id/card_view"
        android:layout_width="wrap_content"
        app:cardCornerRadius="116dp"
        app:cardBackgroundColor="#00ffffff"
        app:cardUseCompatPadding="false"
        android:layout_marginTop="104dp"
        app:cardElevation="0dp"
        android:visibility="gone"
        android:layout_centerHorizontal="true"
        android:layout_height="wrap_content">
    <com.example.test.widget.ScanView
        android:id="@+id/scanview"
        android:layout_width="232dp"
        android:layout_height="232dp"
        android:background="#00ffffff"
        app:scanLineDrawable="@drawable/face_scan_line"
        app:lineHeight="0.25"
        app:duration="1500"
        />
    </android.support.v7.widget.CardView>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,481评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,019评论 4 62
  • 跟大家分享一本书《爱的五种语言》,作者是盖瑞·查普曼博士。 在我们的本性中都有被爱的深切渴望,婚姻就是被设计来满足...
    呆小五阅读 439评论 0 0
  • 5岁月长,衣衫薄 “春晓,我说你怎么一点也不紧张啊?明天可就要比赛了,这是我们拜入师傅门下的第一次正式比赛呢。”宋...
    往后只求己阅读 166评论 0 0
  • 我根本没有心思上课,才上午第四节课,就发生了那么多事。我用胳膊捅了捅完颜清,问道:“你刚才,你刚才怎么把我认做你娘...
    讼儿阅读 261评论 3 7