Android自定义一个带缩放动画的倒计时View

为了方便修改字体样式,于是我继承了TextView。这个自定义的倒计时View,于是就是一个特别一点的TextView,用法和TextView一样。

以下是全部代码。需要注意的是,存在多个倒计时View时,应将Handler和TimeTask分离出来,重写代码。只使用一个线程进行倒计时,分发消息通知多个view更新时间文字。

import android.content.Context;
import android.graphics.Canvas;
import android.os.Build.VERSION_CODES;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.ScaleAnimation;
import android.widget.TextView;

import java.util.Timer;
import java.util.TimerTask;

/**
 * Created by Yue on 2017/7/18.
 */

public class TimeDownView extends TextView {
    private Timer timer;
    private DownTimerTask downTimerTask;
    private int downCount;
    private int lastDown;
    private long intervalMills;
    private long delayMills;
    private AnimationSet animationSet;

    public TimeDownView(Context context) {
        this(context, null);
    }

    public TimeDownView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public TimeDownView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @RequiresApi(api = VERSION_CODES.LOLLIPOP)
    public TimeDownView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    private void init() {
        if (timer == null) {
            timer = new Timer();
        }
        if (animationSet == null) {
            animationSet = new AnimationSet(true);
        }
        if (downHandler == null){
            downHandler = new DownHandler();
        }
       setGravity(Gravity.CENTER);
    }

    /**
     * 开始计时
     *
     * @param seconds
     */
    public void downSecond(int seconds) {
        downTime(seconds, 0, 0, 1000);
    }

    /**
     * 倒计时开启方法
     *
     * @param downCount     倒计时总数
     * @param lastDown      显示的倒计时的最后一个数
     * @param delayMills    延迟启动倒计时(毫秒数)
     * @param intervalMills 倒计时间隔时间(毫秒数)
     */
    public void downTime(int downCount, int lastDown, long delayMills, long intervalMills) {
        this.downCount = downCount;
        this.lastDown = lastDown;
        this.delayMills = delayMills;
        this.intervalMills = intervalMills;
        initDefaultAnimate();

        if (downTimerTask == null) {
            downTimerTask = new DownTimerTask();
        }
        timer.schedule(downTimerTask, delayMills, intervalMills);

    }

    @Override
    public void setVisibility(int visibility) {
        super.setVisibility(visibility);
        if (View.GONE == visibility) {
            timer.cancel();
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (drawTextFlag == DRAW_TEXT_NO) {
            return;
        }
        super.onDraw(canvas);
    }

    /**
     * 取消
     */
    public void cancel() {
        timer.cancel();
    }

    private class DownTimerTask extends TimerTask {

        @Override
        public void run() {
            if (downCount >= (lastDown - 1)) {
                Message msg = Message.obtain();
                msg.what = 1;
                downHandler.sendMessage(msg);
            }
        }
    }

    public interface DownTimeWatcher {
        void onTime(int num);

        void onLastTime(int num);

        void onLastTimeFinish(int num);
    }

    private DownTimeWatcher downTimeWatcher = null;

    /**
     * 监听倒计时的变化
     *
     * @param downTimeWatcher
     */
    public void setOnTimeDownListener(DownTimeWatcher downTimeWatcher) {
        this.downTimeWatcher = downTimeWatcher;
    }
    private DownHandler downHandler;

    private class DownHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == 1) {
                if (downTimeWatcher != null) {
                    downTimeWatcher.onTime(downCount);
                }
                if (downCount >= (lastDown - 1)) {
                    drawTextFlag = DRAW_TEXT_YES;//默认绘制

                    //未到结束时
                    if (downCount >= lastDown) {
                        setText(downCount + "");
                        startDefaultAnimate();
                        if (downCount == lastDown && downTimeWatcher != null) {
                            downTimeWatcher.onLastTime(downCount);
                        }
                    }

                    //到结束时
                    else if (downCount == (lastDown - 1)) {// 若lastDown为0,downCount == -1时是倒计时真正结束之时。
                        if (downTimeWatcher != null) {
                            downTimeWatcher.onLastTimeFinish(downCount);
                        }
                        //倒计时结束,虽然setText()方法触发onDraw,但重写使之不进行绘制
                        //设置不绘制标记
                        if (afterDownDimissFlag == AFTER_LAST_TIME_DIMISS) {
                            drawTextFlag = DRAW_TEXT_NO;
                        }
                        invalidate();//刷新一下
                        timer.cancel();
                    }
                    downCount--;
                }
                //
            }
        }
    }
    private final int DRAW_TEXT_YES = 1;
    private final int DRAW_TEXT_NO = 0;
    /**
     * 是否执行onDraw的标识,默认绘制
     */
    private int drawTextFlag = DRAW_TEXT_YES;

    private final int AFTER_LAST_TIME_DIMISS = 1;
    private final int AFTER_LAST_TIME_NODIMISS = 0;
    /**
     * 在倒计时结束之后文字是否消失的标志,默认消失
     */
    private int afterDownDimissFlag = AFTER_LAST_TIME_DIMISS;

    /**
     * 设置倒计时结束后文字不消失
     */
    public void setAfterDownNoDimiss() {
        afterDownDimissFlag = AFTER_LAST_TIME_NODIMISS;
    }

    /**
     * 设置倒计时结束后文字消失
     */
    public void setAferDownDimiss() {
        afterDownDimissFlag = AFTER_LAST_TIME_DIMISS;
    }

    private boolean startDefaultAnimFlag = true;

    //关闭默认动画
    public void closeDefaultAnimate() {
        animationSet.reset();
        startDefaultAnimFlag = false;
    }
    //开启默认动画
    private void startDefaultAnimate() {
        if (startDefaultAnimFlag) {
            animationSet.startNow();
        }
    }

    private void initDefaultAnimate() {
        if (animationSet == null) {
            animationSet = new AnimationSet(true);
        }

        ScaleAnimation scaleAnimation = new ScaleAnimation(1f, 0.5f, 1f, 0.5f, Animation.RESTART, 0.5f, Animation.RESTART, 0.5f);
        scaleAnimation.setDuration(intervalMills);

        AlphaAnimation alphaAnimation = new AlphaAnimation(1f, 0.3f);
        alphaAnimation.setDuration(intervalMills);
        //将AlphaAnimation这个已经设置好的动画添加到 AnimationSet中
        animationSet.addAnimation(scaleAnimation);
        animationSet.addAnimation(alphaAnimation);
        animationSet.setInterpolator(new AccelerateInterpolator());
        setAnimation(animationSet);
    }

}

使用方式:


TimeDownView tdvDownTime = (TimeDownView)findViewById(R.id.xxx);
tdvDownTime.downSecond(10);//从10开始倒计时,一秒倒一次

如果要定义倒计时间隔时间,使用:

tdvDownTime.downTime(10, 0, 500, 1000);//从10开始倒计时, 到0结束;延迟500毫秒才开始倒计时,每1000毫秒倒一次。

如果要监听倒计时的变化,使用:

tdvDownTime.setOnTimeDownListener(new DownTimeWatcher() {
        void onTime(int num){
        }

        void onLastTime(int num){
        }

        void onLastTimeFinish(int num){
        }
    }

);

缩放动画是默认开启的,可以关闭它:

    tdvDownTime.closeDefaultAnimate();

——end

发布了105 篇原创文章 · 获赞 70 · 访问量 34万+

猜你喜欢

转载自blog.csdn.net/Mingyueyixi/article/details/75670328