自定义View之添加银行卡动画(一)

作者: MrAllRight_Liu | 来源:发表于2017-08-16 11:04 被阅读880次

    本系列主要是记录一下项目中添加银行卡的动画,先来看一下要实现的效果


    添加银行卡

    本篇主要实现的是第一个动画,星星坠落动画,观察发现,总共16颗星星,我们让15颗星星坠落,最后保留一颗星星(TextView)来显示我们的卡号,而这16颗星星如果在xml里面写16个textview,然后在分别给其做位移动画实在比较麻烦,所以我们写一个自定义的view来处理这部分动画,我们命名为StarView,让其继承LinearLayout,代码如下:

    public class StarView extends LinearLayout {
        TranslateAnimation tvTranslation;//位移动画
        final int[] count = new int[2];//记录子view的个数
        private boolean isDone = false;//记录动画是否执行过
        Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                if (count[0] > 0) {
                    getChildAt(count[0]).startAnimation(tvTranslation);
                }
            }
        };
    
        public StarView(Context context) {
            this(context, null);
        }
    
        public StarView(Context context, AttributeSet attrs) {
            this(context, attrs, -1);
        }
    
        public StarView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }
    
        //首先是添加16个textview,然后每各4个加一个padding(银行卡显示效果)
        private void init() {
            for (int i = 0; i < 16; i++) {
                TextView tv = new TextView(getContext());
                tv.setTextColor(getResources().getColor(R.color.white));
                if (i % 4 == 0)
                    tv.setPadding(10, 0, 0, 0);
                tv.setText("*");
                tv.setTextSize(20);
                addView(tv);
            }
    
        }
    
        //星星坠落的动画
        public void startAnim() {
            if (isDone) return;//执行过不在执行
            isDone = true;
            count[0] = getChildCount();
            final Timer time = new Timer();
            TimerTask task = new TimerTask() {
                @Override
                public void run() {
                    tvTranslation = new TranslateAnimation(0, 0, 0, 500);
                    tvTranslation.setDuration(500);
                    tvTranslation.setFillAfter(true);
                    count[0]--;
                    handler.sendEmptyMessage(0);
                }
            };
            time.schedule(task, 0, 50);//添加定时器,间隔50毫秒对textview执行坠落动画,
        }
    
        public void setText(String s) {
            ((TextView) getChildAt(0)).setText(s);
        }//用第一个textview显示卡号
    }
    

    代码很少,也比较简单,初始化的时候添加16个textview,内容为*,然后每隔4个加一个padding,这样看起来像银行卡的格式,然后写一个开启动画的方法,主要是用一个定时器,依次对后面的15个textview执行位移动画,好了这个时候我们添加activity进行调用。首先我们自定义了一个BandCardEditText(https://github.com/smuyyh/BankCardFormat),继承EditText,主要是让其能按照银行卡格式显示输入效果,代码如下:

    public class BandCardEditText extends EditText {
    
        private boolean shouldStopChange = false;
        private final String WHITE_SPACE = " ";
        private BandCardEditTextListen listener;
        public BandCardEditText(Context context) {
            this(context, null);
        }
    
        public BandCardEditText(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public BandCardEditText(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init();
        }
    
        private void init() {
            format(getText());
            shouldStopChange = false;
            setFocusable(true);
            setEnabled(true);
            setFocusableInTouchMode(true);
            addTextChangedListener(new CardTextWatcher());
        }
    
        class CardTextWatcher implements TextWatcher {
    
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
              if(listener!=null)listener.beforeTextChanged(s,start,count,after);
            }
    
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
    
            }
    
            @Override
            public void afterTextChanged(Editable editable) {
                format(editable);
                if(listener!=null)listener.afterTextChanged(editable);
            }
        }
    
        private void format(Editable editable) {
            if (shouldStopChange) {
                shouldStopChange = false;
                return;
            }
    
            shouldStopChange = true;
    
            String str = editable.toString().trim().replaceAll(WHITE_SPACE, "");
            int len = str.length();
            int courPos;
    
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < len; i++) {
                builder.append(str.charAt(i));
                if (i == 3 || i == 7 || i == 11 || i == 15) {
                    if (i != len - 1)
                        builder.append(WHITE_SPACE);
                }
            }
            courPos = builder.length();
            setText(builder.toString());
            setSelection(courPos);
    
        }
    
        public String getBankCardText() {
            return getText().toString().trim().replaceAll(" ", "");
        }
        public interface BandCardEditTextListen{
            void beforeTextChanged(CharSequence s, int start, int count, int after);
            void afterTextChanged(Editable editable);
        }
    
        public void setListener(BandCardEditTextListen listener) {
            this.listener = listener;
        }
    }
    

    然后我们在activity中对这个EditText设置Listener,代码如下

      etInput.setListener(new BandCardEditText.BandCardEditTextListen() {
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                    starView.startAnim();//开始输入卡号的时候,执行星星坠落动画
                }
    
                @Override
                public void afterTextChanged(Editable editable) {
                 starView.setText(etInput.getText().toString());//将EditText的内容显示到第一个星星(TextView)上
                }
            });
    

    好了,到此这个星星坠落的动画已经实现,其余动画我们会在接下来慢慢实现。
    全部代码已经上传至github:https://github.com/MrAllRight/BezierView

    相关文章

      网友评论

      • IT烟酒僧:作者大大有没有研究过新版天猫首页标题栏的那个动画效果
      • e4e672d98fe6:线程开启后未关闭,浪费资源,handle发送信息时应该发送当前的count值,接收时收到msg.what来赋值动画。否则会出现后面几个星星不会掉的情况
        MrAllRight_Liu:@616707902 好的,多谢,我看一下
        e4e672d98fe6:@MrAllRight_Liu 在部分手机上会出现后面的几颗星星未消失,或者是中间会有几颗星星未消失,这是因为子线程在一直运行,而handle收到信息时,count已经是下一个值了。这只是在部分机型上出现,昨天亲测。
        MrAllRight_Liu:谢谢提醒,确实是需要关闭,不过count值是在线程中递减的,不用发送,你直接取就可以了

      本文标题:自定义View之添加银行卡动画(一)

      本文链接:https://www.haomeiwen.com/subject/nzzbrxtx.html