2

I am trying to convert an existing project with findViewByIds over to ViewBinding. All of the view IDs outside of the ScrollView are available in Android Studio for use with "binding.viewId..." The problem is none of the views with IDs that are within the ScrollView are available for use with "binding.viewID..." So I am not able to access ImageViews that are within two <include layouts that are within a ViewFlipper in the layout. The simple ViewFlipper toggles between an up arrow ImageView and a down arrow ImageView. The ViewFlipper has an <include layout for the up ImageView and a second <include layout for the down ImageView. The ViewFlipper is inside a LinearLayout and the LinearLayout is inside the ScrollView.

//Activity
private ActivityEditBinding binding;

protected void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    binding = ActivityEditBinding.inflate(getLayoutInflater());
    View view = binding.getRoot();
    setContentView(view);

// activity_edit.xml
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFFFFF"
    android:focusableInTouchMode="true"
    tools:context=".AddorUpdateCardActivity">
 ...
 <RelativeLayout
    android:id="@+id/secondLinearLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_below="@+id/toolbar"  >

<ScrollView
    android:id="@+id/ScrollView1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_below="@+id/secondLinearLayout"
    ...  >        
<LinearLayout
    android:id="@+id/lowerVFRow"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingRight="5dp"
    android:paddingEnd="5dp"
    android:orientation="horizontal"  >

    <ViewFlipper
        android:id="@+id/expandVF"
        android:layout_width="wrap_content"
        android:layout_height="44dp"
        android:layout_marginBottom="5dp"  >

        <include layout="@layout/expand_more_act_edit"
            android:id="@+id/expandMore"  />

        <include layout="@layout/expand_less_act_edit"
            android:id="@+id/expandLess"  />

     </ViewFlipper>

</LinearLayout>
</ScrollView>
</RelativeLayout>

// expand_more_act_edit.xml
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"

android:id="@+id/downArrow"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:contentDescription="sd"
android:clickable="true"
android:focusable="true"
android:src="@drawable/ic_expand_more"  />

<!-- the down arrow -->

I confirmed that the autogenerated ViewBinding classes have been created. Below is where I am trying to attach a ClickListener to the downArrow but I can't access the downArrow reference. What am I missing here?

***Android Studio says "Cannot resolve symbol 'expandMore'***
binding.expandMore.downArrow.setOnClickListener(v -> {
        
    // change the down arrow to the up arrow and show the 1-20 EditText lines.
    expandVF.setDisplayedChild(expandVF.indexOfChild(findViewById(R.id.expandLess)));
    moreViewStub.setVisibility(View.VISIBLE);
});

Does ViewBinding not work within a ScrollView? What am I missing here?

AJW
  • 1,578
  • 3
  • 36
  • 77
  • "I confirmed that the autogenerated ViewBinding classes have been created" -- have you looked at what they contain? I have used view binding with `` successfully, so I am uncertain why `expandMore` would not be in your binding. – CommonsWare May 31 '21 at 19:32
  • I looked in the class, it contains: "@NonNull public final ExpandMoreActEditBinding expandMore;" and "@NonNull public final ViewFlipper expandVF;" and "this.expandVF = expandVF;" and "this.expandMore = expandMore;" So appears to be good. – AJW May 31 '21 at 20:32
  • @CommonsWare So in the Activity, I am able to access all of the view IDs using "binding.viewID..." except for the the IDs that are inside a . And the expandVF and expandMore are inside of a and that is inside the ScrollView. The ScrollView and the LinearLayout look correct in the autogenerated binding class. Any thoughts on how to fix? – AJW May 31 '21 at 20:49
  • "except for the the IDs that are inside a . And the expandVF and expandMore are inside of a and that is inside the ScrollView" -- that seems to conflict with what you wrote in [your first comment](https://stackoverflow.com/questions/67779226/android-how-to-access-include-layout-in-a-viewflipper-with-viewbinding?noredirect=1#comment119803763_67779226). So, I am uncertain what to tell you. – CommonsWare May 31 '21 at 21:10
  • @CommonsWare All of the views appear to be set up correctly in the autogenerated binding class. But when I try to add "binding.viewID..." in the Activity for an ID that is contained within the ScrollView, that ID text does not automatically appear. And that is when Studio shows the 'Cannot resolve symbol error' and the ID text is colored red. – AJW May 31 '21 at 21:17

6 Answers6

3

View binding will generate camelCase id from id that you have provided in your layout.If your view id is already in camelCase(expandVF) in your layout,sometimes android studio won't recognize that because layout view id and binding class view id are same.that may produce 'Cannot resolve symbol error'.

so instead of expandVF,expandMore,expandLess use expand_vf,expand_more,expand_less.Rebuild and run,may work.

androidLearner
  • 1,654
  • 1
  • 7
  • 13
  • Ah, interesting. I will change and then rebuild based on your feedback! – AJW Jun 03 '21 at 15:55
  • okay.let me know whether it's works or not.@AJW – androidLearner Jun 03 '21 at 19:04
  • No luck. I changed the IDs to your suggestions and re-built the project. I am still not able to access any of the layout IDs in the ScrollView when I am in the Activity and I type "binding.someIDInsideOfTheScrollView". Any ideas on how to fix? – AJW Jun 06 '21 at 20:48
  • everything working as expected when i run your code.So split the layout and Try to find issue like first add Relative layout and scrollview without anything into it ,then check scrollview binding class id in activity then add viewFlipper only without include tag then find it in activity after all run your relative layout (secondLinearLayout)as root layout .in this way you can find issue.@AJW – androidLearner Jun 07 '21 at 14:17
  • 1
    I changed the layout IDs as you suggested and deleted all other layout views and kept just the ScrollView section. I deleted the previous autogenerated java class. Then I commented out all previous "...findViewById()". Then cleaned and re-built the project, synced the project with gradle files and then invalidate caches/restart. Voila! I was able to finally access the IDs inside the ScrollView and the ViewFlipper . Haven't rebuilt the entire xml yet but hope to have enough to keep adding to the initial ScrollView section. Thx, answer upvoted and bounty awarded. – AJW Jun 09 '21 at 02:46
2

You need to use binding.expandVF instead of directly using expandVF and to use id of layout which have been included, you need to use binding.expandLess.ID_YOU_WANT_TO_USE

Kamal Nayan
  • 1,635
  • 1
  • 5
  • 19
  • The error is on the code line to set the OnClickListener. binding.expandVF or binding.expandMore are not working. – AJW May 31 '21 at 19:26
  • Yes because you are trying to directly access the id ... I think you just need to write binding before that...if are you using viewBinding – Kamal Nayan May 31 '21 at 19:28
  • I tried binding.expandVF and I tried binding.expandMore. See above. Neither one is working. – AJW May 31 '21 at 19:30
  • You need to make as the parent if you want to use viewBinding – Kamal Nayan May 31 '21 at 19:31
  • HERE_YOUR_LAYOUT_SHOULD_BE – Kamal Nayan May 31 '21 at 19:32
  • That is for DataBinding. I just want to use ViewBinding. – AJW May 31 '21 at 19:34
  • have you enabled view binding by doing this -> buildFeatures { viewBinding = true } – Kamal Nayan May 31 '21 at 19:35
  • Yes, I mentioned above that all of the autogenerated binding java classes have been created. – AJW May 31 '21 at 19:36
  • Nice then inflating layout in onCreateView like this -> private var _binding: ResultProfileBinding? = null // This property is only valid between onCreateView and // onDestroyView. private val binding get() = _binding!! override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { _binding = ResultProfileBinding.inflate(inflater, container, false) val view = binding.root return view } – Kamal Nayan May 31 '21 at 19:37
  • Reference -> https://developer.android.com/topic/libraries/view-binding – Kamal Nayan May 31 '21 at 19:38
  • I read android developer reference thanks. And you provide Kotlin. My question is for Android code. – AJW May 31 '21 at 19:39
  • could you please share your java code, so that I can help you with the exact answer? – Kamal Nayan May 31 '21 at 19:41
  • I put all of the code above in the question. – AJW May 31 '21 at 19:42
1

for databinding

in activity.java

private ActivityEditBinding binding;

protected void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
binding= DataBindingUtil.setContentView(this, R.layout.activity_edit);
    
}

in activity_edit.xml

<layout  xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto">
<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFFFFF"
    android:focusableInTouchMode="true"
    tools:context=".AddorUpdateCardActivity">//...
<ScrollView
<LinearLayout
    android:id="@+id/lowerVFRow"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingRight="5dp"
    android:paddingEnd="5dp"
    android:orientation="horizontal"  >

    <ViewFlipper
        android:id="@+id/expandVF"
        android:layout_width="wrap_content"
        android:layout_height="44dp"
        android:layout_marginBottom="5dp"  >

        <include layout="@layout/expand_more_act_edit"
            android:id="@+id/expandMore"  />

        <include layout="@layout/expand_less_act_edit"
            android:id="@+id/expandLess"  />

</LinearLayout>
</ScrollView>
</RelativeLayout>
</layout>

now

binding.expandMore.downArrow.setOnClickListener(v -> {
        
});

for ViewBinding here

Elango
  • 406
  • 3
  • 11
1

In your case, I don't see the problem in the code so I'm guessing maybe the Android build tool version is quite old - ViewBinding doesn't work very well

Try to update the build tools to the latest version 4.2.0 in build.gradle of project

dependencies {
   // At least it should be from 4.0.0 
   classpath 'com.android.tools.build:gradle:4.2.0'
}

And distributionUrl in gradle-wrapper.properties

# tools.build 4.2.0 requruired gradle distribution at least 6.7.1+
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-bin.zip

Change the viewBinding declaration if it is different from the code below:

buildFeatures{
    viewBinding = true
}

Then Clean-Rebuild your project.

Check out Compatibility Android Gradle plugin - Release Notes

Wilson Tran
  • 4,050
  • 3
  • 22
  • 31
  • Thanks for ideas. I had relatively new build tool, wrapper.properties and had the viewBinding declaration. Will include those in future posts. – AJW Jun 09 '21 at 23:35
1

convert your activity_edit.xml, expand_less_act_edit.xml, and expand_more_act_edit.xml layout into data binding by wrapping into layout tag.

your activity_edit.xml will look like

 <layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFFFFF"
    android:focusableInTouchMode="true"
    tools:context=".AddorUpdateCardActivity">

    <ScrollView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    >
    <LinearLayout
    android:id="@+id/lowerVFRow"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingRight="5dp"
    android:paddingEnd="5dp"
    android:orientation="horizontal"  >

    <ViewFlipper
    android:id="@+id/expandVF"
    android:layout_width="wrap_content"
    android:layout_height="44dp"
    android:layout_marginBottom="5dp"  >

        <include layout="@layout/expand_more_act_edit"
            android:id="@+id/expandMore"  />

        <include layout="@layout/expand_less_act_edit"
            android:id="@+id/expandLess"  />

    </LinearLayout>
    </ScrollView>
    </RelativeLayout>
    </layout>

your expand_more_act_edit.xml will look like

<layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <ImageView  
    android:id="@+id/downArrow"
    android:layout_width="45dp"
    android:layout_height="45dp"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:contentDescription="sd"
    android:clickable="true"
    android:focusable="true"
    android:src="@drawable/ic_expand_more"  />
</layout>

your main class to access the ImageView will be.

private ActivityEditBinding binding;

protected void onCreate(final Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
binding= DataBindingUtil.setContentView(this, R.layout.activity_edit);
//binding.expandMore.downArrow this is how you will gonna access the view. now do what ever you want with this.
    
}
  • Hi, I'm not interested in using data binding. I specifically used ViewBinding. – AJW Jun 06 '21 at 21:39
  • then just remove the layout tag from all xmls. rest would be same. instead of using util use ActivityEditBinding class to inflate the view and hold binding instance. – Muhammad Ali Jun 07 '21 at 21:55
  • I don't have a layout tag in my xmls. – AJW Jun 08 '21 at 02:15
  • Yes, I know. I was talking about the solution that I gave for your problem. The rest is Simple just follow the java code. – Muhammad Ali Jun 08 '21 at 19:55
1

It looks like you have missed ViewFlipper closing tag and there are other layout issues in xml. Check if that is the issue.

<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFFFF"
android:focusableInTouchMode="true"
tools:context=".AddorUpdateCardActivity">
<RelativeLayout
    android:id="@+id/secondLinearLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_below="@+id/toolbar"  >

    <ScrollView
        android:id="@+id/ScrollView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/secondLinearLayout">
    <LinearLayout
        android:id="@+id/lowerVFRow"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingRight="5dp"
        android:paddingEnd="5dp"
        android:orientation="horizontal"  >

        <ViewFlipper
            android:id="@+id/expandVF"
            android:layout_width="wrap_content"
            android:layout_height="44dp"
            android:layout_marginBottom="5dp"  >

        <include layout="@layout/expand_more_act_edit"
            android:id="@+id/expandMore"  />

        <include layout="@layout/expand_less_act_edit"
            android:id="@+id/expandLess"  />
        </ViewFlipper>

    </LinearLayout>
</ScrollView>

I've corrected some but not sure since I don't know the whole layout. Since there are some ellipses in the layout you have provided. Other than that ViewBinding has no issues with ScrollView AFAIK.

Saikrishna Rajaraman
  • 3,205
  • 2
  • 16
  • 29