Desired functionality:
I have an Activity that has a value received from backend which indicates to use either one of two layouts. Let's call this value layoutType and let's assume for simplicity in this example code below that we don't care how it will be assigned. Thus, I have two layout xml files, let's call them layout1.xml & layout2.xml.
Implementation: I'd like to use View Binding. I've created a variable of type ViewBinding and I tried assigning to it either a Layout1Binding or a Layout2Binding. A summary of this logic in pseudocode is this:
private ViewBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(layoutType == 1){
binding = Layout1Binding.inflate(getLayoutInflater());
} else {
binding = Layout2Binding.inflate(getLayoutInflater());
}
setContentView(binding.getRoot());
}
Result: Of course, this doesn't work and variable binding appears to have no inner children that can be referenced. Also, of course if I convert the variable's type to Layout1Binding and layoutType equals 1, then I can use it correctly. Same goes if I use Layout2Binding and layoutType is not equal to 1. All these make sense, since ViewBinding is just an Interface implemented by the generated classes Layout1Binding & Layout2Binding.
Question: How can I achieve the above desired behaviour by using only one binding variable which can be assigned to two different generated classes? Is there any other alternative way?
Here's an example of how I used an adapter for a custom view that uses three layouts. In my case, most views in the different layout files had common IDs.
class MyCustomViewBindingAdapter(
b1: Layout1Binding?,
b2: Layout2Binding?,
b3: Layout3Binding?
) {
val text =
b1?.myTextView
?: b2?.myTextView
?: b3?.myTextView
val badgeText = b3?.myBadgeTextView
}
private lateinit var binding: MyCustomViewBindingAdapter
private fun getBinding(layoutType: Int): MyCustomViewBindingAdapter {
val inflater = LayoutInflater.from(context)
return when(layoutType) {
TEXT_ONLY -> {
val textBinding = Layout1Binding.inflate(inflater, this, true)
MyCustomViewBindingAdapter(textBinding, null, null)
}
IMAGE_AND_TEXT -> {
val imageTextBinding = Layout2Binding.inflate(inflater, this, true)
MyCustomViewBindingAdapter(null, imageTextBinding, null)
}
TEXT_AND_BADGE -> {
val textBadgeBinding = Layout3Binding.inflate(inflater, this, true)
MyCustomViewBindingAdapter(null, null, textBadgeBinding)
}
else -> throw IllegalArgumentException("Invalid view type")
}
}
binding = getBinding(layoutType)