0

I am trying to pass a "@string" and "@stringarray" to my viewstub databinding via xml, but it does not work. I get the following error message:

C:\Users\censored\AndroidStudioProjects\example\app\build\generated\source\kapt\debug\com\example\app\databinding\AppStandardContactFormBindingImpl.java:943: error: cannot find symbol
            if (this.appDefaultCompanyNameEt.isInflated()) this.appDefaultCompanyNameEt.getBinding().setVariable(BR.hint, appDefaultCompanyNameEt.getResources().getString(R.string.app_contact_form_company_name));
                                                                                                                                                 ^
  symbol:   method getResources()
  location: variable appDefaultCompanyNameEt of type ViewStubProxy

ViewStub inflated layout

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>
        <variable
            name="vBility"
            type="Boolean" />
        <variable
            name="vForm"
            type="String" />
        <variable
            name="hint"
            type="String" />
        <variable
            name="iType"
            type="Integer" />
        <variable
            name="mText"
            type="String" />
    </data>


    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="@{vBility}">

        <com.example.app.presentation.util.view.FixedInputTextLayout
            android:id="@+id/app_default_et"
            style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
            android:layout_width="@dimen/wrapContent"
            android:layout_height="wrap_content"
            android:hint="@{hint}"
            android:visibility="@{vBility}"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:validate_form="@{vForm}">

            <com.google.android.material.textfield.TextInputEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:inputType="@{iType}"
                android:text="@={mText}"
                android:textSize="@dimen/font_text_large" />

        </com.example.app.presentation.util.view.FixedInputTextLayout>

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

Using Layout inside viewstub

<ViewStub
    android:id="@+id/app_default_company_name_et"
    android:layout_width="@dimen/wrapContent"
    android:layout_height="wrap_content"
    android:layout_marginTop="8dp"
    android:layout_marginEnd="8dp"
    android:inflatedId="@+id/app_default_company_name_et"
    android:layout="@layout/app_standard_textinputlayout"
    android:visibility="@{cValidator.companySwitchState}"
    app:vBility="@{cValidator.companySwitchState}"
    app:vForm="@{cValidator.etCompanyNameEM}"
    app:hint="@{@string/app_contact_form_company_name}" <!-- THIS IS GIVING ME THE ERROR -->
    app:iType="@{0x00000001}"
    app:mText="@{cValidator.etCompanyName}"
    app:layout_constraintEnd_toStartOf="@+id/app_default_company_ust_et"
    app:layout_constraintHorizontal_bias="0.5"
    app:layout_constraintStart_toStartOf="@+id/margin_left"
    app:layout_constraintTop_toBottomOf="@+id/calibrate_user_data_company_text" />

When I change app:hint="@{@string/app_contact_form_company_name}" with app:hint="@{someClass.someString}" it works. Does that mean, that I can't directly pass any string to my databinding if it is a viewstub?

Andrew
  • 4,264
  • 1
  • 21
  • 65

1 Answers1

1

This is the short answer to why you are having trouble passing a string resource into a ViewStub: In the code that you posted, the part that is causing a problem is appDefaultCompanyNameEt.getResources(). Here appDefaultCompanyNameEt is a ViewStubProxy which is not a View, so it doesn't have associated resources. As a result, appDefaultCompanyNameEt.getResources() fails. The message is a little cryptic, but this is what it means.

if (this.appDefaultCompanyNameEt.isInflated()) this.appDefaultCompanyNameEt.getBinding()
    .setVariable(BR.hint, appDefaultCompanyNameEt.getResources()  // fails!
    .getString(R.string.app_contact_form_company_name));

I believe that this can be considered a bug. So what is a work-around?

It seems that greater care was taken in providing a bound data link to included files. See this Stack Overflow answer from George Mount.

So, what we can do is place the contents of the ViewStub in an included file like this:

view_stub.xml

<layout>

    <data>

        <variable
            name="myData"
            type="String" />

    </data>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="A hint"
        android:text="@{myData}"
        android:textSize="36sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</layout>

and reference it in a layout file that will be included in the main layout:

included_layout.xml

<layout>

    <data>

        <variable
            name="myData"
            type="String" />

    </data>

    <FrameLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <ViewStub
            android:id="@+id/viewStub"
            android:layout_width="300dp"
            android:layout_height="wrap_content"
            android:inflatedId="@+id/inflatedViewStub"
            android:layout="@layout/view_stub"
            app:myData="@{myData}" />
    </FrameLayout>
</layout>

Finally, the main layout:

activity_main.xml

<layout>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/topLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <include
            android:id="@+id/included"
            layout="@layout/included_layout"
            app:myData="@{@string/myStringData}" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

If we define a string resource as follows:

<string name="myStringData">My string data.</string>

Then this layout will display

enter image description here

This works because the initial include does a good translation of the string resource. The included file just sees the string which it handles OK.

This is a little complicated. I would be interested to know if there is an easier way.

Cheticamp
  • 61,413
  • 10
  • 78
  • 131
  • The easiest way to do this, is instead of using "@string/bla_bla_bla" to create another variable inside your class and then get the string from there. So @{myClass.myString}. I will post my solution tomorrow – Andrew Sep 19 '21 at 18:00
  • @Andrew I agree that would be easier, but it seems to me that you were looking to pass the string resource directly into the _ViewStub_. In any case, you turned up a bug. I will look for your answer. – Cheticamp Sep 19 '21 at 18:29