-3

I have 26 buttons which all have an id like button_0 button_1 etc.

I've saw that findviewbyid is deprecated and I don't want to have to call all those 26 button line by line. So my first idea was to make an array of them, but there is still the same problem I need to write them all at least one time. I didn't find a way to achieve that with view binding or by calling the button with a string and need help. Thanks!

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
  • perhaps useful to you https://stackoverflow.com/questions/4809834/how-to-iterate-through-a-views-elements – a_local_nobody Apr 08 '22 at 11:46
  • 3
    "I've saw that findviewbyid is deprecated" -- `findViewById()` is not deprecated. – CommonsWare Apr 08 '22 at 12:14
  • kotlin-android-extensions is needed for it to work and kotlin-android-extensions is deprecated – Virgil Nauleau Apr 08 '22 at 12:27
  • and you're sure you need `kotlin-android-extensions` for findViewById ? – a_local_nobody Apr 08 '22 at 13:12
  • Doesn't work for me and when I searched why it was because kotlin-android-extensions is needed and have been removed from auto import in app creation because it is deprecated and they advice to use view binding. https://antonioleiva.com/kotlin-android-extensions/ – Virgil Nauleau Apr 08 '22 at 13:18
  • The extensions negated the need to use ``findViewById`` at all, because they magically looked up each ID in the layout and created a variable in the Activity with the same name. View binding is just a more explicit and less messy way of doing that, where the views are looked up and those variables are created on a ``ViewBinding`` object instead. ``findViewById`` is the basic, standard way to find a view in a hierarchy, it's not deprecated (and it probably won't ever be, or at least there'll always be something like it) – cactustictacs Apr 08 '22 at 19:34

2 Answers2

2
  1. Wrap your buttons inside ViewGroup (constraintLayout, LinearLayout, etc), give it an Id
  2. call findViewById to the ViewGroup , not the button
  3. get ViewGroup children by using children method
// just an example
val buttonContainer = findviewbyid<LinearLayout>()
val buttons = buttonContainer.children //return Sequence<View>

buttons.forEach { btn ->
  if(btn is Button){
    // do something
  } 
}

Muhammad Rio
  • 759
  • 5
  • 6
  • It was what I was trying to achieve with what gave me Papa Yev thanks ! I used binding.buttonsContainer instead of findviewbyid() then everything worked ! thanks ! – Virgil Nauleau Apr 08 '22 at 16:25
  • @VirgilNauleau that would be better , `findviewbyid` is expensive call , you should avoid it as much as you can – Muhammad Rio Apr 08 '22 at 16:28
  • On internet it is also said that it's deprecated like i said in the comment on my post – Virgil Nauleau Apr 08 '22 at 17:09
  • 1
    You can do ``buttonContainer.children.filterIsInstance – cactustictacs Apr 08 '22 at 19:38
0

In the app level build.gradle file, just add viewBinding.

buildFeatures {
    viewBinding true
}

In your activity create a variable for the binding of your activity layout. The binding will be camel notation in reverse.

lateinit var bindingActivity: ActivityMainBinding

Then add this to the onCreate() method.

bindingActivity = ActivityMainBinding.inflate(layoutInflater)
    setContentView(bindingActivity.root)

After you have that in place, you can access your views by just writing binding.viewId and it’s the equivalent of you using find view by id. If you want to access more than one view at the same time using Kotlin just use apply.

// access single view
val text = binding.textTitle.text

// access multiple views without calling binding each time
binding.apply {
textTitle.text = “hello”
val data = inputText.text.toString()
}
Papa Yev
  • 618
  • 7
  • 10
  • I don't want to make binding.Button_0, binding.Button_1 binding.Button_2 that what I wanted to not do , also apply will do it for everything no ? I just want my button to have the modification @Papa_Yev – Virgil Nauleau Apr 08 '22 at 12:20
  • Binding work like this: once you inflate the binding it means now you can use the views that you gave ids to in your xml file as if they are already initialized and are able to be interacted with. “Apply” is a Kotlin function. Apply means to continue doing something with this object. So instead of saying I want to access just button1 from binding, I’m able to now access everything from binding. So I can call button2, button3 without placing binding in front of each one. It’s kind of like for example Class.name, Class.age, but Class.apply { name, age}. You are to access all the properties. – Papa Yev Apr 08 '22 at 12:39
  • but there is no way to do something like for(i in 0..25){ binding.button+i.setOnClickListener } ? I wanted to make less text to not poluate my file with it – Virgil Nauleau Apr 08 '22 at 12:48
  • I mean there isn't something like that, but you can still get id from views that are bound. You can also get all the children of a particular layout and getViewById, then call onClickListener. binding.rootConstraintLayout.children.find { it.id == R.id.textTitle } binding.root.findViewById(R.id.textTitle)?.setOnClickListener { } – Papa Yev Apr 08 '22 at 13:21
  • Instead of viewBinding you can use dataBinding, this way you can call onClick() directly in the xml layout. – Papa Yev Apr 08 '22 at 13:23
  • I tried to call it in the xml but It can only use function that are present in the Main Activity so I can't access my fragment activity, I'll try the one with children thanks ! – Virgil Nauleau Apr 08 '22 at 13:50
  • For dataBinding you have to convert your layout to use data binding. Simple. Just right click on the top layout tag, then press "Show Context Action", then press "convert to data binding layout" and that's it. Then try using onClick again! – Papa Yev Apr 08 '22 at 13:57