Search code examples
androidbuttonlabel

Is it possible to keep a button's label alternating between values until it is clicked?


For example, a button would be labeled with digits from 0 to 9, one at a time and changing at a given rate (say, each half a second). When clicked, the label would stop changing and be set to the value showing at the time. Is there any way to do this?


Solution

  • Yes, this is possible. You could use a Handler (Java) or a coroutine (Kotlin) to do this. Here are some examples:

    Kotlin

    With Kotlin, you can start a coroutine that has a loop with a delay, and when the button is clicked it exits the loop and stops updating the button text and stored number.

    private lateinit var binding: ActivityMainBinding
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
    
        binding.timedBtn.setOnClickListener { incrementing = false }
        startNumbers()
    }
    
    private var incrementing = true
    private var num = 0
    private val delayMillisecond = 500L
    
    private fun startNumbers() {
        incrementing = true
        lifecycleScope.launch {
            while(incrementing) {
                num = (num + 1) % 10
                binding.timedBtn.text = "$num"
                delay(delayMillisecond)
            }
        }
    }
    

    Java

    With Java you can use a handler and postDelayed to keep posting future updates to the button text, and when the button is pressed cancel all the handler tasks so it stops updating the button text and stored number.

    private ActivityMainBinding binding;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());
        
        binding.timedBtn.setOnClickListener(v -> handler.removeCallbacksAndMessages(null));
        startNumbers();
    }
    
    private final Handler handler = new Handler();
    private int num = 0;
    private final long delay_ms = 500;
    
    private void startNumbers() {
        handler.post(new Runnable() {
            @Override
            public void run() {
                num = (num + 1) % 10;
                binding.timedBtn.setText(String.valueOf(num));
                handler.postDelayed(this, delay_ms);
            }
        });
    }