Reputation: 4698
I've two layouts for a screen. Activity works fine while setting a layout for Mobile device but it's causing error while setting layout for tablet device. The main issue is:
Caused by: java.lang.RuntimeException: view must have a tag at com.mypackage.DataBinderMapperImpl.getDataBinder(DataBinderMapperImpl.java:941)
Though, I don't face the problem when I install app on mobile device.
This way I'm setting layout on activity:
val resetPasswordActivityBinding = DataBindingUtil.setContentView<ResetPasswordActivityBinding>(this,
R.layout.reset_password_activity)
resetPasswordActivityBinding.resetPasswordViewModel = resetPasswordViewModel
Here is my XML layout for tablet screen:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="resetPasswordViewModel"
type="com.bhi.salesarchitect.user.password.reset.ResetPasswordViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
android:id="@+id/toolbar"
layout="@layout/app_toolbar_layout"
app:appTheme="@{resetPasswordViewModel.appTheme}"
app:appToolbar="@{resetPasswordViewModel.appToolbar}" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg_splash"
android:contentDescription="@null"
android:scaleType="centerCrop" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<ImageView
android:id="@+id/imv_builder_logo_change_pswd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_135"
android:layout_marginBottom="@dimen/space_xxlarge"
android:layout_weight=".5"
android:contentDescription="@null"
android:src="@drawable/ic_logo" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginEnd="@dimen/dp_80"
android:layout_weight=".4">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/space_normal"
android:layout_marginEnd="@dimen/space_normal"
android:contentDescription="@null"
android:scaleType="fitXY"
android:src="@drawable/bg_white_shadow" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingStart="@dimen/space_xxxlarge"
android:paddingEnd="@dimen/space_xxxlarge">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_55"
android:layout_marginBottom="@dimen/space_small"
android:gravity="center"
android:text="@string/a_one_time_password_reset_code_has_been_sent_to_your_email"
android:textColor="@color/blue_dark_main"
android:textSize="@dimen/text_size_normal" />
<EditText
android:id="@+id/et_otp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/space_normal"
android:background="@drawable/shape_rounded_white"
android:drawablePadding="@dimen/space_small"
android:hint="@string/password_reset_code"
android:inputType="textPersonName"
android:paddingStart="@dimen/space_small"
android:paddingTop="@dimen/space_xsmall"
android:paddingEnd="@dimen/space_xxsmall"
android:paddingBottom="@dimen/space_xsmall"
android:textColor="@android:color/black"
android:textSize="@dimen/sp_15" />
<EditText
android:id="@+id/et_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/space_small"
android:background="@drawable/shape_rounded_white"
android:drawableStart="@drawable/ic_password"
android:drawablePadding="@dimen/space_small"
android:hint="@string/new_password"
android:inputType="textPassword"
android:maxLength="@integer/max_password_length"
android:paddingStart="@dimen/space_small"
android:paddingTop="@dimen/space_xsmall"
android:paddingEnd="@dimen/space_xxsmall"
android:paddingBottom="@dimen/space_xsmall"
android:textColor="@android:color/black"
android:textSize="@dimen/sp_15" />
<EditText
android:id="@+id/et_confirm_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/space_small"
android:background="@drawable/shape_rounded_white"
android:drawableStart="@drawable/ic_password"
android:drawablePadding="@dimen/space_small"
android:hint="@string/confirm_new_password"
android:imeOptions="actionDone"
android:inputType="textPassword"
android:maxLength="@integer/max_password_length"
android:paddingStart="@dimen/space_small"
android:paddingTop="@dimen/space_xsmall"
android:paddingEnd="@dimen/space_xxsmall"
android:paddingBottom="@dimen/space_xsmall"
android:textColor="@android:color/black"
android:textSize="@dimen/sp_15" />
<Button
android:id="@+id/bt_submit"
style="@style/ButtonNormal"
android:layout_marginTop="@dimen/space_normal"
android:backgroundTint="@color/blue_dark_main"
android:onClick="@{()-> resetPasswordViewModel.onSubmitClick()}"
android:text="@string/submit"
android:textColor="@android:color/white" />
</LinearLayout>
</FrameLayout>
</LinearLayout>
</FrameLayout>
</LinearLayout>
</layout>
Upvotes: 30
Views: 23938
Reputation: 11
If you are using multiple modules and just incase both modules have same layout names, and you're using one of them with data/view binding then this type of problem occurred. So to solve this you have to rename one of the layout to some other name.
Upvotes: 1
Reputation: 51
In my case worked this code to set content view with data binding.
binding = GenericItemDetailsListBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
Upvotes: 0
Reputation: 1614
I encounter this problem, the root case is there are duplicate layout resource file in different module. delete the redundant one to resolve the issue.
Upvotes: 0
Reputation: 19824
I had this error trying to bind separately as my view is inflated within a library but I supply the layout.
The doc says you can do this:
val binding: MyLayoutBinding = MyLayoutBinding.bind(viewRoot)
The viewRoot I was passing was derived from the custom class but ended up being a parent of my layout file (the one that included the layout tag). So I had to specify the view as the root of my layout file via findViewById
Upvotes: 0
Reputation: 6407
Using viewStub with databinding:
class MyFragment {
lateinit var binding: MyFragmentBinding
lateinit var viewStubBinding: MyViewStubBinding
private fun setViewStub() {
binding.myViewStub.setOnInflateListener { viewStub, view ->
viewStubBinding = binding.myViewStub.binding as MyViewStubBinding // property viewStubBinding is finally inflated
}
binding.myViewStub.viewStub?.inflate() // inflate viewStub with defined layout file in XML
}
}
When I tried to use MyViewStubBinding.bind(view / viewStub)
it crash on View must have a tag. This happen because ViewStubProxy try to inflate binding class by itself, so when I try to call bind()
by myself on same Binding class, it was already bound and crashed with this error.
Upvotes: 5
Reputation: 2028
if you already use layout tag in your xml file, and you still give error, just rename your layout file name and clean/rebuild the project again it will fix
Upvotes: 0
Reputation: 1760
I just needed to clean and rebuild after deleting a resource file.
Upvotes: 0
Reputation: 101
i was facing similar error so my work around was
DataBindingUtil.bind(holder.itemView)?.apply { item = items[position] }
Upvotes: 1
Reputation: 8510
I was having this problem when using an array adapter, having a crash due to a missing tag on convertView. In my getView(), I was doing:
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
if (convertView == null) {
DataBindingUtil.inflate<ItemSpinnerDropDownWorkPackageFilterBinding>(
LayoutInflater.from(parent.context),
R.layout.item_spinner_drop_down_work_package_filter,
parent,
false
)
} else {
binding = ItemSpinnerDropDownWorkPackageFilterBinding.bind(convertView)
binding.text1.setText(getItem(position))
setDividerVisibility(binding.divider, position)
return convertView
}
}
Which was crashing. The solution was to set the tag on the first run through getView:
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val binding = if (convertView == null) {
DataBindingUtil.inflate<ItemSpinnerDropDownWorkPackageFilterBinding>(
LayoutInflater.from(parent.context),
R.layout.item_spinner_drop_down_work_package_filter,
parent,
false
)
} else {
convertView.tag as ItemSpinnerDropDownWorkPackageFilterBinding
}
binding.text1.setText(getItem(position))
setDividerVisibility(binding.divider, position)
binding.root.tag = binding
return binding.root
}
Upvotes: 8
Reputation: 4698
Keeping two layouts, one with layout tag of data-binding and another without it, is the common cause of this issue.
I got stuck when I renamed my two normal layout files with same name (/layout and /layout-sw720dp) and used tag. Then, it worked for mobile device but not for tablet. So, after cleaning project, it all started working.
Upvotes: 25
Reputation: 455
You must have <layout>
tag into your all XML views (portrait, landscape, tablet, etc.). Even you have to include <layout>
tag into included views ("@layout/app_toolbar_layout
").
Upvotes: 2
Reputation: 1006539
I ran into this when I had:
<layout>
element), but the app module's edition of that layout resource was notIn my case, the app module's layout was left over from when I created the project. Removing it cleared up the problem.
Upvotes: 43
Reputation: 227
You need to add layout tag at start of your app_toolbar_layout layout file
Upvotes: 3