Android Countdown Custom Control (for Shop Secondary Kill)

Posted by markduce on Sat, 12 Feb 2022 03:03:48 +0100

(1) Preface
Android actually provides a countdown control called CountDownTimer, which is easy to use, but it's cumbersome to follow the desired countdown style. For example, we want the countdown to show HH:MM:SS or HH-MM-SS in the style we want, or we want to show it as follows:

The work to be done is tedious, not impossible, but expensive, so if we make it a custom view, we can show the countdown style according to the style passed in by the user (Note: The code in this article does not do the function of these styles, but it is easy to do this based on the code in this article). Let's take a look at the countdown custom control I implemented.
(Note: This code can not be used directly in the project, if it needs to be used in the project, it also needs to be processed, such as fixed time to display width, or skip and display incomplete pairs will occur when display time, such as "00:00:00" can be measured Setting the width of the display to set the view, or the way the reader can choose to solve it, and whether or not the font margins need to be removed when displaying, requires the reader to decide for himself. Removing the margins is easy, just setIncludeFontPadding(false), a method of TextView.
(2) Effect display
This countdown is accurate to milliseconds, but it can also be modified to suit your needs. Simply change the format from "HH:MM:SS SSS" to "HH:MM:SS"

(3) Ideas for implementation
The idea is actually simple, inherited from a TextView, referring to the countdown control of the system to make an encapsulation.
First initialize the countdown time:

 public void init(long timeInFuture, long timeInterval){
        mTimeInFuture = timeInFuture;
        mTimeInterval = timeInterval;
        mStopTimeInFuture = SystemClock.elapsedRealtime() + mTimeInFuture;
        updateText(mStopTimeInFuture);
    }

timeInFuture represents the length of time you want to count down, such as 10 seconds, 3 days, 5 days, etc. timeInterval represents the time interval, that is, how much time each countdown decreases, which can be one second, two seconds, three seconds..., elapsedRealtime represents the amount of time elapsed since the boot of the device, and by adding our length of time, it is ready to start counting down.

  public  void start() {
        mStarted = true;
        updateTimer();
    }

When the user calls the start() function, the updateTimer() function is called, which executes the logic of the countdown:

private void updateTimer() {
        boolean running = mVisible && mStarted && isShown();
        if(running != mRunning){
            if(running) {
                doCountDownTimer();
            }else{
                removeCallbacks(mTickRunnable);
            }
            mRunning = running;
        }

    }

As you can see from the code, a countdown is only made if the control is visible and mStarted. The countdown execution function doCountDownTimer is as follows:

 private void doCountDownTimer() {
        final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime();
        if(millisLeft <= 0){
            onFinish();
        }else{
            long lastUpdateTextStart = SystemClock.elapsedRealtime();
            updateText(millisLeft);
            // take into account updateText() take time to execute
            long lastUpdateTextDuration = SystemClock.elapsedRealtime() - lastUpdateTextStart;
            long delay;

            if(millisLeft < mTimeInterval){
                delay = millisLeft - lastUpdateTextDuration;

                if(delay < 0) {
                    delay = 0;
                }
            } else {
                delay = mTimeInterval - lastUpdateTextDuration;
                while (delay < 0) {
                    delay += mTimeInterval;
                }
            }
            postDelayed(mTickRunnable,delay);
        }
    }

The code is easy to understand, so here's a special note. Our countdown uses the view's postDelayed method. Last UpdateTextDuration is a variable that records the time taken by the last update of the countdown text. Taking this time into account will make the countdown more precise, because demo adds two buttons for demonstration purposes. At second kill time, The accuracy of this time is still required and will affect the user experience if the difference is too large.

At the beginning of the article, it says that time can display all kinds of styles. In fact, it is to separate each character of time so that you can define styles separately:

 private String formatTime(long now) {
        String split = " : ";
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss SSS", Locale.CHINA);
        String time = sdf.format(now).replace(" ",":");
        Log.d(TAG,"zhongxj: " + time);
        String[] time_arr = time.split(":");
        int hour = Integer.parseInt(time_arr[0]);
        Log.d(TAG,"zhongxj: before transform " + hour);
        hour-=8;
        Log.d(TAG,"zhongxj: " + hour);
        if(hour<10){
            time_arr[0] = "0"+hour;
        }else{
            time_arr[0] = "" + hour;
        }

        return time_arr[0] + split + time_arr[1] + split
                +time_arr[2] + split + time_arr[3];
    }

If you need to add style, you can design a style and fill in the style with the split characters!!!

The logic of countdown actually refers to the system countdown, here is a custom control trick, when we receive demand, don't rush to Baidu first, because large companies often design the control Baidu hard to find even if they find it may not meet the requirements, there may be hidden bug s. You can then refer to how the Android system implements similar controls, referring to the system's controls to make custom controls, the effect and performance will be better. First of all, so many questions are welcome to discuss.

(3) Code address
Code repository uses gitee in China, we recommend you use it!!!!
https://gitee.com/zhong-walt/count-down-timer.git

Topics: Java Android Apache