Rahul Rastogi
Rahul Rastogi

Reputation: 4698

View must have a tag error in android data binding

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

Answers (14)

Abdullah shah
Abdullah shah

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

amsuredev
amsuredev

Reputation: 51

In my case worked this code to set content view with data binding.

binding = GenericItemDetailsListBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());

Upvotes: 0

Maximillian
Maximillian

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

Daniel Wilson
Daniel Wilson

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

mtrakal
mtrakal

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

Mahdi Zareei
Mahdi Zareei

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

Night
Night

Reputation: 11

May be you have multiple xml layout files.

Upvotes: 0

Alberto M
Alberto M

Reputation: 1760

I just needed to clean and rebuild after deleting a resource file.

Upvotes: 0

Waqar Afzal
Waqar Afzal

Reputation: 101

i was facing similar error so my work around was

DataBindingUtil.bind(holder.itemView)?.apply { item = items[position] }

Upvotes: 1

Kristy Welsh
Kristy Welsh

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

Rahul Rastogi
Rahul Rastogi

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

Abu Noman
Abu Noman

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

CommonsWare
CommonsWare

Reputation: 1006539

I ran into this when I had:

  • A library module defining a layout resource
  • An app module that depended upon that library module defining the same layout resource
  • The library layout resource was set up for data binding (e.g., root <layout> element), but the app module's edition of that layout resource was not

In my case, the app module's layout was left over from when I created the project. Removing it cleared up the problem.

Upvotes: 43

Mohammed Daoud
Mohammed Daoud

Reputation: 227

You need to add layout tag at start of your app_toolbar_layout layout file

Upvotes: 3

Related Questions