Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use ViewBindings for mutiple layouts

I'm migrating from kotlinx.android.synthetic to ViewBindings.

I have two layouts(for phones and tablets) with the same set of ids:

class GameActivity: AppCompatActivity() {
    lateinit var binding: ViewBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        if (AppData.instance.isTablet)
            binding=ActivityGameTabletBinding.inflate(layoutInflater)
        else
            binding=ActivityGamePhoneBinding.inflate(layoutInflater)
        setContentView(binding.root)
        val btn=binding.menuBtn //no such property
    }
    ...

}

The problem is binding contains only one property which is root.

Thus I'm forced to fallback to old getViewById. Is there way to have viewBinding features for different layouts?

like image 720
undefined Avatar asked Jan 22 '26 12:01

undefined


2 Answers

You cannot have a variable have binded to 2 different views instead you can create 2 variables and initialize both of them and use them accordingly.

Here is an example.

private lateinit var phoneBinding : ActivityGamePhoneBinding
private lateinit var tabletBinding : ActivityGameTabletBinding

Then initialize both of them.

phoneBinding = ActivityGamePhoneBinding.inflate(layoutInflater)
tabletBinding = ActivityGameTabletBinding.inflate(layoutInflater)

  if (AppData.instance.isTablet){
       val btn = tabletBinding.button
       //Do rest of your tablet code
  } else {
       val btn = phoneBinding.button
       //Do rest of your phone code
  }

If you are doing common things you should create a function and call the same function in both scenarios.

phoneBinding = ActivityGamePhoneBinding.inflate(layoutInflater)
tabletBinding = ActivityGameTabletBinding.inflate(layoutInflater)

  if (AppData.instance.isTablet){
       val btn = tabletBinding.button
       onButtonClick(btn)
  } else {
       val btn = phoneBinding.button
       onButtonClick(btn)
  }

  fun onButtonClick(button : Button){
   button.setOnclickListner{
    //rest of you code.
   }
  }
like image 77
Jayanta Sarkar Avatar answered Jan 25 '26 01:01

Jayanta Sarkar


For those who might facing the same problem. I found two solutions:

Method 1: Use kotlin-reflection library to get properties by it's string name:

private inline fun <T>getViewByName(name:String):T{
        val prop= binding::class.memberProperties.find { it.name==name }
        val view=prop?.call(binding) as T
        if (view!=null) {
            return view
        } else
            throw Exception("view not found")
    }

I find this method quite hacky, so I sticked to the second one:

class GameActivityBinding(private val binding:ViewBinding) {
  val menuBtn:ImageButton
        get() {
            return when (binding) {
                is ActivityGameTabletBinding -> {
                    binding.menuBtn
                }

                is ActivityGamePhoneBinding -> {
                    binding.menuBtn
                }
                else -> throw Exception("incorrect layout")
            }
        }
    // rest of the views
}

No need to litter code with dozens of if-else's

like image 36
undefined Avatar answered Jan 25 '26 03:01

undefined



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!