Search code examples
javaandroidmergeincludefindviewbyid

findViewById for view inside an included merge root-element


I want to use a view in multiple activities. In my case it's a FloatingActionButton. The moment I am searching for the view via findViewById the program throws a NullPointerException. How do I get access to the FloatingActionButton?


As the button should always be the same, I created a XML Layout only including the FloatingActionButton inside a mergeroot element to reduce overhead when using ìnclude.

floating_button.xml

<merge xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/include_merge" >

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/addBloodDonation"/>

</merge>

To use this in my other XML Layouts I use the include tag

XML Activitiy Layouts that should include the FloatingActionButton

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

That works so far.

To have the same functionality in all my Activities, I created a BaseActivity which my other classes inherit from, e.g. my MainActivity.

BaseActivity

public abstract class BaseActivity extends AppCompatActivity {
    public FloatingActionButton fab;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        View include_merge = findViewById(R.id.include_merge);
        fab = include_merge.findViewById(R.id.addBloodDonation);
    }
}

MainActivity (exemplarily)

public class MainActivity extends BaseActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

When starting the application I receive a NullPointerException in BaseActivity for trying to find the inner element as the View variable include_merge is null.

As I read here the include tag and the root element should have the same android:id. Is there a difference when using a merge as root element? And is it even possible to convert a merge tag into a View.

Do I need to make use of setContentView in the BaseActivity as its onCreate method is called before the one of MainActivity?


Edit:

Added setContentView(R.layout.activity_main); to BaseActivity as mentioned in the comments which still does not fix it.


Solution

  • You don't have to set an id to the <include> or <merge> tag. Just remove it as well as findViewById(R.id.include_merge). The <merge> tag indicates that all its views are added to the container of the <include> tag. Thus there's no View with the id you've set to it. But you can directly find the FAB.

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        fab = include_merge.findViewById(R.id.addBloodDonation);
    }