skip to Main Content

I have a button such as

                <com.google.android.material.button.MaterialButton
                    android:id="@+id/button"
                    style="@style/Widget.MaterialComponents.Button.OutlinedButton.Icon"
                    android:layout_width="150dp"
                    android:layout_height="50dp"
                    android:text="@string/lightning"
                    android:textColor="#FFFFFF"
                    android:textSize="14sp"
                    app:icon="@drawable/ic_baseline_flash_on_24"
                    app:iconTint="@color/white"
                    app:layout_constraintBottom_toBottomOf="parent"
                    app:layout_constraintEnd_toEndOf="parent"
                    app:layout_constraintHorizontal_bias="0.061"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintTop_toTopOf="parent"
                    app:layout_constraintVertical_bias="0.239"
                    app:strokeColor="@color/white"
                    app:strokeWidth="1dp" />

I have created a setOnClickListener method and inside their is a loop.

        val btnClickMe1 = findViewById<Button>(R.id.button)
        btnClickMe1.setOnClickListener {
                
               //do something here 20 times
        }

This method works fine, however, I have created a .apk file. When I click the button the function runs. I want to know how I can exit the loop by clicking the same button. Regardless of whether or not the loop has finished.

2

Answers


  1. Create a variable that allows you to know the state of the operation, executing or not executing, and performs said operation if the variable is executing.

    When you press the button, the variable will change to its negative, when it is false,
    the next iteration in the loop will detect if it is still active, if not it will skip the loop.

    private val isButtonLoopActive: Boolean = false
    
    btn.setOnClickListener {
        isButtonLoopActive = !isButtonLoopActive 
        for (i in 1..20) {
            if (isButtonLoopActive) {
                //TODO
            } else {
                break
            }
        }
        isButtonLoopActive = false
    }
    
    Login or Signup to reply.
  2. You haven’t posted what your actual code is, but if your loop just runs inside the click listener, then execution won’t finish (and the thread won’t be able to do anything else, including respond to button clicks) until that loop has finished and you exit the listener function.

    You need to set that loop running asynchronously somehow (delayed Runnable events, a coroutine, a worker thread) so it can do its thing without blocking the thread, and the rest of the app can run as normal. And then your click listener needs to check if that task is currently running – if not, start it, if so then stop it.

    Here’s a way you could do it with coroutines:

    // a reference to the currently running task (if any)
    private var job: Job? = null
    
    // kick off a new task, and store a reference to it
    private fun startTask() {
        // you'll have to use the appropriate scope and 'launchWhen' function
        // to keep it running/paused the way you want - depends what you're doing
        job = viewLifecycleOwner.lifecycleScope.launchWhenCreated {
            repeat(20) {
                // the actual thing you're doing!
                binding.text.isVisible = !binding.text.isVisible
                delay(500)
            }
        }
    }
    
    // stop any running task and discard it, so the next click will start a new one
    private fun endTask() {
        job?.cancel()
        job = null
    }
    

    Then your click listener can be:

    binding.button.setOnClickListener {
        // check if there's a running job -
        // if so, the click means stop, otherwise it means start
        if (job?.isActive == true) endTask() else startTask()
    }
    

    That’s just one way – another typical one is having a Runnable that calls postDelayed on a Handler or View, so it does an action and then posts itself to run again in the future (or doesn’t, if some completed condition is met). You’d need to have some running boolean somewhere, and use that to see if the posting should start or if the Runnable should give up next time it runs. And it would need to be stopped when the app goes to the background or whatever – again, depends what you’re doing

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search