簡體   English   中英

如何在啟用 Button 的同時顯示/開始倒計時?

[英]How do I make a CountDown show/start at the same moment my Button gets enabled?

“如何在啟用 Button 的同時進行 CountDown 顯示?”

關於按鈕的附加信息:按鈕作業是通過 Textview 中顯示的字符串數組單擊 5 次,然后禁用 5 秒鍾以再次執行相同的任務。

所以..我想要一個倒計時來直觀地顯示那些 5 秒(按鈕啟用的時間)倒計時供用戶查看。

遺憾的是,我不知道如何將我的 Button 與 CountDown 連接起來,讓它知道它應該在啟用 Button 的特定時間倒計時。

此外,我希望每次啟用按鈕時都開始倒計時。

我查看了https://developer.android.com/reference/android/os/CountDownTimer但它似乎沒有針對該特定情況的解決方案。

這就是我現在的按鈕代碼:

next_button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            if (currentnumber == list.length) {
                currentnumber = 0;
            }
            if (Curclicks == mod - 1) {
                next_button.setEnabled(false);
                display.setText(list[currentnumber]);
                currentnumber++;


                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        //the button will unlock after the delay specified
                        next_button.setEnabled(true);
                        Curclicks = 0;

                    }
                }, delay);

            } else {
                display.setText(list[currentnumber]);
                currentnumber++;

            }
            Curclicks++;

        }

    });

UI Thread 代碼可以解決嗎?

  private void runThread() {

            new Thread() {
                public void run() {
                    while (delay == 5000) { //delay = 5000 ( 5 secs)
                        try {
                            runOnUiThread(new Runnable() {

                                @Override
                                public void run() {
                                    timer.setText("" + delay);//timer=TxtView
                                }
                            });
                            Thread.sleep(300);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }.start();

這個函數應該做你想做的,只需將它調用到 OnClickListener 中

public void countDown(Button yourBtn) {
    new Thread() {
        public void run() {
            try {
                int second = 10;
                for (int i = second; i >= 1; i--) {
                    int finalI = i;
                    yourBtn.post(new Runnable() {
                        @Override
                        public void run() {
                            yourBtn.setText(String.valueOf(finalI))
                        }
                    });
                    Thread.sleep(1000); // Change text every 1s
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }.start();
}

下面是一個示例,說明如何使用HandlerpostDelayed()方法創建倒計時。 我特意把代碼留得有點冗長,這樣你就可以一步一步地瀏覽它,看看發生了什么。

創建一些類變量和常量。

private static final long COUNT_DOWN_TICKS = 100l;
private static final long COUNT_DOWN_FINISH = 5000l;
private long countdownElapsed = 0l;
private Handler mCountDownHandler = new Handler();

COUNT_DOWN_FINISH設置為 5000 --> 5 秒。 但可以更改為您需要的任何內容。 我還使用COUNT_DOWN_TICKS設置為 100 --> 0.1 秒,以防萬一您想顯示更精確的倒計時。

從您的OnClick()方法只需調用startCountDown()即可開始倒計時。

private void startCountDown() {
    try {
        countdownElapsed = 0l;
        next_button.setEnabled(false);
        displayCountDown();
        mCountDownHandler.postDelayed(mCountDownRunnable, COUNT_DOWN_TICKS);
    }
    catch (Exception ex){
        Log.e(TAG, ex.getMessage());
    }
}

private Runnable mCountDownRunnable = new Runnable() {
    @Override
    public void run() {
        countdownElapsed = countdownElapsed + COUNT_DOWN_TICKS;

        if(countdownElapsed >= COUNT_DOWN_FINISH){
            releaseCountDownHandler();
            next_button.setEnabled(true);
        }
        else{
            mCountDownHandler.postDelayed(mCountDownRunnable, COUNT_DOWN_TICKS);
        }

        long secFull = countdownElapsed % 1000;
        if(secFull == 0){
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    displayCountDown();
                }
            });
        }
    }
};

private void releaseCountDownHandler() {
    try {
        if(mCountDownRunnable != null) {
            mCountDownHandler.removeCallbacks(mCountDownRunnable);
        }
    }
    catch (Exception ex){
        Log.e(TAG, ex.getMessage());
    }
}


private void displayCountDown(){
    long t = (COUNT_DOWN_FINISH - countdownElapsed)/1000;
    String myTime = String.valueOf(t);
    timer.setText(myTime);
}

為了正確處理Runnable ,您需要從onPause()方法調用releaseCountDownHandler() 這只是一個短期運行的Thread ,但它仍然不應被忽略。

Thread.sleep()方法postDelay()我更喜歡帶有postDelay()方法的Handler ——讓任何線程進入睡眠狀態的事情令人不安。 另請注意,根據實現(例如,您使用SystemClock.elapsedRealtime()代替),習慣於使用 ">=" 而不是 "==" 檢查經過時間條件是一個好主意,該條件可能會錯過確切的價值!


編輯


在您的Activity類定義下的某處(在本例中,我將其稱為MainActivity ),您需要聲明一些變量。 由於它們是在類內部而不是在方法內部定義的,因此它們被稱為“類變量”,並且在定義為“私有”時具有整個類的范圍。

public class MainActivity extends AppCompatActivity {

    //class variables
    private static final long COUNT_DOWN_TICKS = 100l;
    private static final long COUNT_DOWN_FINISH = 5000l;
    private long countdownElapsed = 0l;
    private Handler mCountDownHandler = new Handler();
    private Button next_button;
    private TextView timer;


....    

}

您可能已經在MainActivity類的onCreate()方法中聲明了onClick()方法。 所以只需添加以下代碼:

next_button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
    startCountDown();
}

我提供的所有其他方法都是MainActivity類中的方法……而不是任何其他方法中的方法。 所以在onCreate()方法下面添加我之前發布的所有方法。

它看起來像這樣:

public class MainActivity extends AppCompatActivity {

    private static final String TAG = MainActivity.class.getSimpleName();

    //class variables
    private static final long COUNT_DOWN_TICKS = 100l;
    private static final long COUNT_DOWN_FINISH = 5000l;
    private long countdownElapsed = 0l;
    private Handler mCountDownHandler = new Handler();
    private Button next_button;
    private TextView timer;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // you must compensate for the actual layout for your activity
        setContentView(R.layout.activity_main);


        // you must compensate for the actual id of the TextView
        timer = findViewById(R.id.tvTimer);

        // you must compensate for the actual id of the Button
        next_button = findViewById(R.id.btnNext);
        next_button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startCountDown();
            }
        });
    }

    private void startCountDown() {
        try {
            countdownElapsed = 0l;
            next_button.setEnabled(false);
            displayCountDown();
            mCountDownHandler.postDelayed(mCountDownRunnable, COUNT_DOWN_TICKS);
        }
        catch (Exception ex){
            Log.e(TAG, ex.getMessage());
        }
    }

    private Runnable mCountDownRunnable = new Runnable() {
        @Override
        public void run() {
            countdownElapsed = countdownElapsed + COUNT_DOWN_TICKS;

            if(countdownElapsed >= COUNT_DOWN_FINISH){
                releaseCountDownHandler();
                next_button.setEnabled(true);
            }
            else{
                mCountDownHandler.postDelayed(mCountDownRunnable, COUNT_DOWN_TICKS);
            }

            long secFull = countdownElapsed % 1000;
            if(secFull == 0){
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        displayCountDown();
                    }
                });
            }
        }
    };

    private void releaseCountDownHandler() {
        try {
            if(mCountDownRunnable != null) {
                mCountDownHandler.removeCallbacks(mCountDownRunnable);
            }
        }
        catch (Exception ex){
            Log.e(TAG, ex.getMessage());
        }
    }


    private void displayCountDown(){
        long t = (COUNT_DOWN_FINISH - countdownElapsed)/1000;
        String myTime = String.valueOf(t);
        timer.setText(myTime); 
    }   

}

這段代碼就像我上面的代碼,除了這段代碼引入了一個“點擊計數器”。 我引入了一個新的類變量來跟蹤按鈕被點擊的次數。 我還引入了一個名為“NUMBER_OF_BUTTON_CLICKS”的新常量,它作為點擊次數的上限。

用戶現在可以點擊按鈕(在本例中)5 次。 在第五次單擊時,滿足觸發startCountDown方法的條件並且按鈕被禁用 5 秒。

public class MainActivity extends AppCompatActivity {
    //Constant values    
    private static final String TAG = MainActivity.class.getSimpleName();
    private static final int NUMBER_OF_BUTTON_CLICKS = 5;
    private static final long COUNT_DOWN_TICKS = 100l;
    private static final long COUNT_DOWN_FINISH = 5000l;

    //class variables
    private int howManyClicks = 0;
    private long countdownElapsed = 0l;
    private Handler mCountDownHandler = new Handler();
    private Button next_button;
    private TextView timer;
    private TextView clicks;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // you must compensate for the actual layout for your activity
        setContentView(R.layout.activity_main);


        // you must compensate for the actual id of the TextView
        timer = findViewById(R.id.tvTimer);

        // Use this only if you want to display the number of clicks 
        // you might need to add this TextView if you want to display the number of clicks
        clicks = findViewById(R.id.tvClicks);

        // you must compensate for the actual id of the Button
        next_button = findViewById(R.id.btnNext);
        next_button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                howManyClicks++;
                if(howManyClicks >= NUMBER_OF_BUTTON_CLICKS){
                    startCountDown();
                }

                //Add this only if you want to see how many clicks were made
                String myClicks = String.valueOf(howManyClicks);
                clicks.setText(myClicks)
            }
        });
    }

    private void startCountDown() {
        try {
            countdownElapsed = 0l;
            next_button.setEnabled(false);
            displayCountDown();
            mCountDownHandler.postDelayed(mCountDownRunnable, COUNT_DOWN_TICKS);
        }
        catch (Exception ex){
            Log.e(TAG, ex.getMessage());
        }
    }

    private Runnable mCountDownRunnable = new Runnable() {
        @Override
        public void run() {
            countdownElapsed = countdownElapsed + COUNT_DOWN_TICKS;

            if(countdownElapsed >= COUNT_DOWN_FINISH){
                releaseCountDownHandler();
                next_button.setEnabled(true);
                // reset the clicks counter
                howManyClicks = 0;
            }
            else{
                mCountDownHandler.postDelayed(mCountDownRunnable, COUNT_DOWN_TICKS);
            }

            long secFull = countdownElapsed % 1000;
            if(secFull == 0){
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        displayCountDown();
                    }
                });
            }
        }
    };

    private void releaseCountDownHandler() {
        try {
            if(mCountDownRunnable != null) {
                mCountDownHandler.removeCallbacks(mCountDownRunnable);
            }
        }
        catch (Exception ex){
            Log.e(TAG, ex.getMessage());
        }
    }


    private void displayCountDown(){
        long t = (COUNT_DOWN_FINISH - countdownElapsed)/1000;
        String myTime = String.valueOf(t);
        timer.setText(myTime);

        //Add this only if you want to see how many clicks were made
        String myClicks = String.valueOf(howManyClicks);
        clicks.setText(myClicks)
    }   

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM