Android自定义View-倒计时控件(可自动继续,矫正时间)

需求

项目中需要用到倒计时View,因为需求需要,所以不能只依靠本地计时。还需要网络请求数据之后,矫正时间。

所以本文的目标如下:

  • 自定义字体
  • 依赖网络的倒计时
  • 时间矫正
  • 倒计时的自动更新

最终效果如下:
倒计时

分析

通过自定义控件去实现,然后通过HashMap存储对应奖期以及倒计时信息,然后通过定时的网络请求,去矫正计时。

因此本文设计控件继承自AppCompatTextView, 增加了设置初始时间,开始计时,更新计时,停止计时,取消计时,矫正计时,设置字体等若干方法。

实现

加载自定义字体

// 加载自定义字体
Typeface TEXT_TYPE;
try {
    TEXT_TYPE = Typeface.createFromAsset(context.getAssets(), "fonts/Quartz_Regular.ttf");
} catch (Exception e) {
    LogUtils.e("加载第三方字体失败。");
    TEXT_TYPE = null;
}

if (TEXT_TYPE != null) {
    setTypeface(TEXT_TYPE);
}

开始计时

开始计时,首先通过接口回调,对外暴露方法,方便进行开始前的准备工作。需要传入期次和结束时间两个参数。

更新时间通过handler去实现。

    public void start(final int term_no, final long end_time) {
        timeListener.timeStart();

        contine_tag = true;
        this.end_time = end_time;
        this.term_no = term_no;
        if (mTimerMap.get(term_no) == null) {
            Timer timer = new Timer();
            Term_view_bean term_view_bean = new Term_view_bean(timer, term_no, end_time);
            mTimerMap.put(term_no, term_view_bean);
            mTimerMap.get(term_no).getTimer().schedule(new TimerTask() {
                @Override
                public void run() {
                    if (contine_tag) {
                        if (is_over) {
                            this.cancel();
                            return;
                        }
                        mHandler.sendEmptyMessage(ticket_mode);
                    }
                }
            }, 0, 1000);
        }
    }

结束

结束计时,共分为2种,取消指定期次,和取消全部期次。

取消全部期次计时: 当不需要页面倒计时的时候调用,因为倒计时是采用Timer进行维护的,所以需要手动释放,以避免内存泄露相关事宜。

public void stopAll() {
        try {
            Iterator it = mTimerMap.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry entry = (Map.Entry) it.next();
                int key = (int) entry.getKey();
                Term_view_bean bean = (Term_view_bean) entry.getValue();
                bean.getTimer().cancel();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        contine_tag = false;
        is_over = true;
    }
   

取消指定期次计时: 某一个期次奖期结束,根据期次号或者存储的值进行停止

   
public void stop(int position_term_no) {
        if (mTimerMap.get(position_term_no) != null) {
            mTimerMap.get(position_term_no).getTimer().cancel();
    }
}

public void stopSaveValue(int value) {
    Iterator it = mTimerMap.entrySet().iterator();
    while (it.hasNext()) {
        Map.Entry entry = (Map.Entry) it.next();
        int key = (int) entry.getKey();
        if (key != value) {
            Term_view_bean bean = (Term_view_bean) entry.getValue();
            bean.getTimer().cancel();
        }
    }
}

时间显示格式化

/**
 * 时间显示格式化
 *
 * @param second
 * @return
 */
private String second2TimeSecond(long second) {

    long days = second / (3600 * 24);
    long hours = (second / 3600) % 24;
    long minutes = (second % 3600) / 60;
    long seconds = second % 60;

    String showTime = "";
    if (days > 0) {
        showTime = days + "天 ";
    }
    if (hours > 0) {
        if (hours < 10) {
            showTime += "0" + hours + "时 ";
        } else {
            showTime += hours + "时 ";
        }
    }
    if (minutes < 10) {
        showTime += "0" + minutes + ":";
    } else {
        showTime += "" + minutes + ":";
    }
    if (seconds < 10) {
        showTime += "0" + seconds;
    } else {
        showTime += "" + seconds;
    }
    return showTime;
}

修正倒计时

    /**
     * 修正当前倒计时信息
     */
    public void updateTimer(final int term_no, final long end_time) {
        this.end_time = end_time;
        this.term_no = term_no;
        if (mTimerMap.get(term_no) == null) {
            start(term_no, end_time);
        } else {
            mTimerMap.get(term_no).setEnd_time(end_time);
        }
    }

使用

使用的时候,首先初始化,传入handler,然后定时进行网络请求即可呈现效果。

完整代码

完整代码如下:

public class CountdownTextView extends android.support.v7.widget.AppCompatTextView {
    public static final int what_count_down_k3 = 1;

    Map<Integer, Term_view_bean> mTimerMap;
    private int term_no;
    private int ticket_mode;
    private TimeListener timeListener;
    private long end_time = 0;
    private boolean contine_tag = true;
    private boolean is_over = false;
    private Handler mHandler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            switch (msg.what) {
                case what_count_down_k3:// 10 分钟一期
					if (end_time - TimeManager.getInstance().getServiceTime() <= Config.K3_R006_Time_End_sale * 1000) {                 
                        timeListener.buyDown();
                    }
                    if (end_time - TimeManager.getInstance().getServiceTime() <= 0) {
                        timeListener.timedown();
                        while (end_time - TimeManager.getInstance().getServiceTime() <= 0) {
                            term_no++;
                            end_time += 10 * 60 * 1000;
                        }
                        setTimeText();
                        try {
                            stopSaveValue(term_no);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        start(term_no, end_time);
                    } else {
                        setTimeText();
                    }
                    break;
            }
        }
    };

    public CountdownTextView(Context context) {
        super(context);
        initTextType(context);
    }

    public CountdownTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initTextType(context);
    }

    public CountdownTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initTextType(context);
    }

    private void setTimeText() {
        setText(second2TimeSecond((end_time - TimeManager.getInstance().getServiceTime()) / 1000));
    }

    private void initTextType(Context context) {
        // 加载自定义字体
        Typeface TEXT_TYPE;
        try {
            TEXT_TYPE = Typeface.createFromAsset(context.getAssets(), "fonts/Quartz_Regular.ttf");
        } catch (Exception e) {
            LogUtils.e("加载第三方字体失败。");
            TEXT_TYPE = null;
        }

        if (TEXT_TYPE != null) {
            setTypeface(TEXT_TYPE);
        }
    }

    public void init(int ticket_mode, TimeListener timeListener) {
        mTimerMap = new HashMap<>();
        this.timeListener = timeListener;
        this.ticket_mode = ticket_mode;
    }

    public void start(final int term_no, final long end_time) {
        timeListener.timeStart();

        contine_tag = true;
        this.end_time = end_time;
        this.term_no = term_no;
        if (mTimerMap.get(term_no) == null) {
            Timer timer = new Timer();
            Term_view_bean term_view_bean = new Term_view_bean(timer, term_no, end_time);
            mTimerMap.put(term_no, term_view_bean);
            mTimerMap.get(term_no).getTimer().schedule(new TimerTask() {
                @Override
                public void run() {
                    if (contine_tag) {
                        if (is_over) {
                            this.cancel();
                            return;
                        }
                        mHandler.sendEmptyMessage(ticket_mode);
                    }
                }
            }, 0, 1000);
        }
    }

    public void stop(int position_term_no) {
        if (mTimerMap.get(position_term_no) != null) {
            mTimerMap.get(position_term_no).getTimer().cancel();
        }
    }

    public void stopAll() {
        try {
            Iterator it = mTimerMap.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry entry = (Map.Entry) it.next();
                int key = (int) entry.getKey();
                Term_view_bean bean = (Term_view_bean) entry.getValue();
                bean.getTimer().cancel();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        contine_tag = false;
        is_over = true;
    }

    public void stopSaveValue(int value) {
        Iterator it = mTimerMap.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            int key = (int) entry.getKey();
            if (key != value) {
                Term_view_bean bean = (Term_view_bean) entry.getValue();
                bean.getTimer().cancel();
            }
        }
    }

    /**
     * 格式化
     *
     * @param second
     * @return
     */
    private String second2TimeSecond(long second) {

        long days = second / (3600 * 24);
        long hours = (second / 3600) % 24;
        long minutes = (second % 3600) / 60;
        long seconds = second % 60;

        String showTime = "";
        if (days > 0) {
            showTime = days + "天 ";
        }
        if (hours > 0) {
            if (hours < 10) {
                showTime += "0" + hours + "时 ";
            } else {
                showTime += hours + "时 ";
            }
        }
        if (minutes < 10) {
            showTime += "0" + minutes + ":";
        } else {
            showTime += "" + minutes + ":";
        }
        if (seconds < 10) {
            showTime += "0" + seconds;
        } else {
            showTime += "" + seconds;
        }
        return showTime;
    }

    /**
     * 获取当前奖期
     *
     * @return
     */
    public int getTerm_no() {
        return term_no;
    }

    /**
     * 修正当前倒计时信息
     */
    public void updateTimer(final int term_no, final long end_time) {
        this.end_time = end_time;
        this.term_no = term_no;
        if (mTimerMap.get(term_no) == null) {
            start(term_no, end_time);
        } else {
            mTimerMap.get(term_no).setEnd_time(end_time);
        }
    }

    public interface TimeListener {
        void timedown();

        void buyDown();

        void timeStart();
    }

    private class Term_view_bean {
        private Timer timer;// 定时器
        private int integer;// 奖期
        private long end_time;// 结束时间

        public Term_view_bean() {
        }

        public Term_view_bean(Timer timer, int integer, long end_time) {
            this.timer = timer;
            this.integer = integer;
            this.end_time = end_time;
        }

        public Timer getTimer() {
            return timer;
        }

        public void setTimer(Timer timer) {
            this.timer = timer;
        }

        public int getInteger() {
            return integer;
        }

        public void setInteger(int integer) {
            this.integer = integer;
        }

        public long getEnd_time() {
            return end_time;
        }

        public void setEnd_time(long end_time) {
            this.end_time = end_time;
        }
    }
}
发布了70 篇原创文章 · 获赞 176 · 访问量 31万+

猜你喜欢

转载自blog.csdn.net/zheng_weichao/article/details/87625140