findViewById not working for an include?

Android

Android Problem Overview


I have an include like:

<include
    android:id="@+id/placeHolder"
    layout="@layout/test" />

The include layout looks like (test.xml):

<?xml version="1.0" encoding="utf-8"?>

<FrameLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/outer"
    ... >

    <ImageView
        android:id="@+id/inner"
        ... />
</FrameLayout>

I can't seem to find the inner ImageView with id="inner" at runtime:

ImageView iv = (ImageView)findViewById(R.id.inner);
if (iv == null) {
    Log.e(TAG, "Not found!");
}

Should I be able to find it? It seems like since it's using an "include", the normal findViewById method does not work.

---------- Update ----------------

So I can find the id assigned to the include:

View view = findViewById(R.id.placeHolder); // ok

but I can't find any of its children by id like:

view.findViewById(R.id.outer); // nope
view.findViewById(R.id.inner); // nope

same as the original if I try searching for them directly like:

findViewById(R.id.outer); // nope
findViewById(R.id.inner); // nope

Do ids just get stripped off of elements at runtime maybe?

Thanks

Android Solutions


Solution 1 - Android

Try retrieving the <include /> and then searching within that

Make sure your root has the same ID as the root element in the included XML file.. ex

<include
    android:id="@+id/outer"
    layout="@layout/test" />

Then retrieve your "inner" content using:

FrameLayout outer = (FrameLayout)findViewById(R.id.outer);

ImageView iv = (ImageView)outer.findViewById(R.id.inner);
if (iv == null) {
    Log.e(TAG, "Not found!");
}

Solution 2 - Android

I just wanted to add to this for future Googlers, I had kind of the opposite problem where the root layout of the included xml (in this case outer), was null when calling findViewById(), but the children of outer were not null.

The problem was solved for me by removing the id property of the include 'view' (in this case placeHolder). When that was gone, I could find outer but it's id :)

If you need a an id assigned to the include item, I think it's better to wrap it in another viewgroup.

Solution 3 - Android

Don't give your included layout an ID

<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:layout_constraintTop_toBottomOf="@id/twitterItem"
    android:id="@+id/item1">

    <include
        layout="@layout/item_common_layout"/>

</FrameLayout>

item_common_layout

<FrameLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    ... >

    <ImageView
        android:id="@+id/inner"
        ... />
</FrameLayout>

now you could find inner Views:

ImageView iv = (ImageView) view.findViewById(R.id.inner); // works fine!

Solution 4 - Android

Can you try then finding the outer parent (lets call it op) and then try op.findViewById()?

Solution 5 - Android

I had the same problem. I found out that I used a wrong function with the same name with 2 parameters as following:

public void onCreate(@Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentState) {
    super.onCreate(savedInstanceState, persistentState);
    setContentView(R.layout.activity_ble_connecting);
    //findViewByid() => wrong
} 

correct function with only one parameters:

    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_ble_connecting);
        //findViewByid() => correct
    }

Solution 6 - Android

Future researchers: https://stackoverflow.com/a/1760010/2790016 when you add an id to it overwrites the id from the outer tag from the "real layout"

Given that most constraint layouts need an id to positions items, removing the id from include is not an ideal answer.

Solution 7 - Android

If you have given the id to the include element and you have only single view in the included layout (not in any ViewGroup), in my case AdView, then use the id of include element instead of included view.

<?xml version="1.0" encoding="utf-8"?>
<!--adview.xml-->
<com.google.android.gms.ads.AdView
        xmlns:ads="http://schemas.android.com/apk/res-auto"
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/adView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true"
        ads:adSize="BANNER"
        ads:adUnitId="@string/admob_banner_id">
</com.google.android.gms.ads.AdView>

activity_main.xml

<include
        layout="@layout/adview"
        android:id="@+id/adsLayout"
  />

In activity

AdView nullAdView=findViewById(R.id.adView); //this will give null
AdView adView = findViewById(R.id.adsLayout);  //this will be AdView

If you do not give id to include element then it is ok to use view id. Also if your view is inside any ViewGroup like FrameLayout then it is ok to use view id.

Solution 8 - Android

I found the answer to this problem.

This problem arises when we set both the Incloud ID and the first inner layer.

I used merge to solve the problem.

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

and in layout_stories

<merge>
<LinearLayout
android:id="@+id/llItem">
 ...
</LinearLayout>
<merge>

Solution 9 - Android

I followed Daniel Wilson's answer and got the solution. I was using the same layout multiple times in same screen and wanted to refer them using different id. So, instead of assigning id to the include tag, I simply wrapped them in another viewGroup (I used FrameLayout) and id'ed the frameLayout to access the inner children. That worked succesfully. Example:

In my main.xml:

<!--    ITEM 1-->
<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:layout_constraintTop_toBottomOf="@id/twitterItem"
    android:id="@+id/item1">

    <include
        layout="@layout/item_common_layout"/>

</FrameLayout>

<!--    ITEM 2-->
<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:layout_constraintTop_toBottomOf="@id/item1"
    android:id="@+id/item2">

    <include
        layout="@layout/item_common_layout"/>

</FrameLayout>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser291701View Question on Stackoverflow
Solution 1 - AndroiddymmehView Answer on Stackoverflow
Solution 2 - AndroidDaniel WilsonView Answer on Stackoverflow
Solution 3 - AndroidMohamed AbdelraZekView Answer on Stackoverflow
Solution 4 - AndroidFelipe CaldasView Answer on Stackoverflow
Solution 5 - AndroidHungNM2View Answer on Stackoverflow
Solution 6 - AndroidBetoView Answer on Stackoverflow
Solution 7 - Androiduser5459652View Answer on Stackoverflow
Solution 8 - AndroidsaeedmptView Answer on Stackoverflow
Solution 9 - AndroidRishabh KamdarView Answer on Stackoverflow