trying to iteratively change the location of a button on screen – kotlin android studio

I have a button object that I want to make it move on the screen once an activation button is pushed. code:

override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)
  setContentView(R.layout.activity_main)
  val target: Button = findViewById(R.id.target)
  val text: TextView = findViewById(R.id.textView)
  val start: Button = findViewById(R.id.start_rec)
  start.setOnClickListener{
     var i:Float =1F
     while (i<360){
            target.x = new_x_position(i)
            target.y = new_y_position(i)
            text.setText = (target.x.toString()+','+target.y.toString())
            handler().postDelayed({movingDot.displayData()}, 1300)
            i += 3
           }
        }
     }

problem is the button only moves one single change in position and stays there. the “text” object also shows only first change and does not change when “i” is changing every iterations

Answer

Your “while” loop is running all at once and stacking up code to be executed that will all execute, one-after-another, in 1.3 seconds. Although everything you expect to execute does execute, the timing is off. You may also have other issues with changing the position of the view.

Here is a template that shows how to change the contents of a TextView every 250 milliseconds. Each execution of the Runnable makes a change to the TextView, checks the limit and, if the limit has not been reached, reposts itself to the message queue to execute after 250 milliseconds.

You should be able to use this code as a template for what you need to do.

val start: Button = findViewById(R.id.start_rec)

start.setOnClickListener {
    val changingView = findViewById<TextView>(R.id.changingView)
    object : Runnable {
        private var i = 0
        override fun run() {
            if (++i <= 10) {
                changingView.text = "$i"
                Handler(Looper.getMainLooper()).postDelayed(this, 250)
            }
        }
    }.run()
}

The foregoing works but I was wondering if there might be a more idiomatic Kotlin way to do this. The important aspect is the self reference to the runnable. I found a way here.

private lateinit var runnable: Runnable

init {
    var i = 0
    runnable = Runnable {
        val changingView = findViewById<TextView>(R.id.changingView)
        if (++i <= 10) {
            changingView.text = "$i"
            Handler(Looper.getMainLooper()).postDelayed(runnable, 250)
        }
    }
}

start.setOnClickListener {
    runnable.run()
}