Home > database >  [Kotlin][Android] Clicking 2 Views in order
[Kotlin][Android] Clicking 2 Views in order

Time:09-07

Hello I am trying to make a user to click the textView in order based on a keylist.

var keylist = arrayListOf("word1","word2")

val View1 = createTextView("word1")
View1.y = 83F*0

val View2 = createTextView("word2")
View2.y = 83F*4

if (View1.text == keylist[0]) {
    View1.setOnClickListener() {
       keylist.removeAt(0)
       frame.removeView(View1)
       }
}
else{
    View1.setOnClickListener() {
       outOfOrder(View1)
       }
}


if (View2.text == keylist[0]) {
   View2.setOnClickListener() {
      frame.removeView(View2)
      }
}
else{
    View2.setOnClickListener() {
       outOfOrder(View2)
     }
}

When I tried my program on the emulator, I successfully remove the word1. However, no matter what I tried I cannot remove word2. The output is always outOfOrder(View2) when I clicked word2.

Any suggestion what I did wrong?

CodePudding user response:

Check the conditions inside the setOnClickListener{} in each view because as you are doing now, the conditions are checked only when the code executes, but after that when you click the View1 it will not check any conditions out of View1.setOnClickListsener{} and so for the View2

CodePudding user response:

I think you're misunderstanding how the click listeners work. You want them to act dynamically, right? You want to click View2, and have it check if its text matches the current first word in the list, and then decide how to respond.

That decision logic needs to run inside the listener, at the moment it's clicked, because your list's state changes over time. But here's what you're doing:

if (View2.text == keylist[0]) {
   View2.setOnClickListener() {
      frame.removeView(View2)
      }
}
else{
    View2.setOnClickListener() {
       outOfOrder(View2)
     }
}

You're running that decision logic during setup, and assigning a click listener that only ever does one thing. So this setup only ever happens once - and because at setup time keylist[0] does not match View2.text, the click listener you attach always calls outOfOrder. It will never do anything else, and you never assign a different click listener to it.


Makes sense, right? So your checking needs to happen when you click the thing, like this:

// your variables should always start with a lowercase letter,
// a capitalised one looks like a class or companion object - can get confusing!
view2.setOnClickListener {
    if (view2.text == keylist[0]) frame.removeView(view2)
    else outOfOrder(view2)
}

So during setup, you assign a click listener that will do the necessary checks when it's clicked, and perform the correct action. And that's it! You've given it the behaviour it needs and that never needs to change.


By the way, in case it helps going forward, you can make a function that does all this stuff - it's the same code in both listeners, right? The only difference is which View they're checking. So if you pass the current View to the function, it can check if it's the correct one:

fun handleClick(view: TextView) {
    if (view.text == keylist[0]) frame.removeView(view)
    else outOfOrder(view) 
}

This way whichever TextView you pass in, if it matches the required key then it gets removed, otherwise it calls outOfOrder.

Now you can set up a simple click listener on each, that calls that function:

// make a convenient list of all the TextViews you have
val allTextViews = listOf(view1, view2)
// set up the listeners
allTextViews.forEach { textView ->
    textView.setOnClickListener { handleClick(textView) }
}

(There's a neater way to do this but I don't want to go too far here)

And you're done! A little more work, but if you're planning on having more than these two TextViews, this kind of organisation can save you a lot of repeated code, and avoid bugs from typos and inconsistent changes.

Also making that list of your TextViews is handy for doing all kinds of things. Like you can create a list or array of all the text content with:

// take your list of TextViews, and transform each into its 'text' value
val keyList = allTextViews.map { it.text }

Lots of ways to make your life easier! Just stuff to keep in mind as you go

  • Related