Search code examples
androidandroid-layoutviewandroid-custom-view

Creating Custom Views that accept other layouts in xml attributes


I have an open question on here that I am trying to solve, and I might have found a possible solution that is less error-prone; however, I don't know how to code up the solution.

The solution would be very similar to how android.support.design.widget.NavigationView handles the header view in XML!! The only problem is that I have tried to search for the source code for NavigationView, but I cannot seem to find it. I can find other Android Source code easily - except for the newer Design Library.

If I can find the Source code from Google, then I can implement something similar.

Code

<android.support.design.widget.NavigationView
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:menu="@menu/drawer"
        app:headerLayout="@layout/drawer_header"  />

See that last line? I want to be able to do something like that for my own customView to insert another view inside it.

So my question is:

  • Where is the source code for the Design Library's NavigationView?

    OR

  • Is there another custom view that allows you to insert layouts inside of it that has code posted online?

    OR

  • If there is nothing online, then how would a person go about doing that? It is possible. The NavigationView does it.


Solution

  • Here is an exmaple how you might do it:
    In your resources.xml:

    <declare-styleable name="MyCustomView">
       <attr name="child_view" format="reference" />
    </declare-styleable>
    

    In your MyCustomView.java:

    public class MyCustomView extends ViewGroup {
    
        public MyCustomView(Context context, AttributeSet attrs) {
            super(context, attrs);
    
            TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MyCustomView, 0, 0);
    
            int childView = a.getResourceId(R.styleable.MyCustomView_child_view, R.layout.default_child_view);
            a.recycle();
    
            LayoutInflater.from(context).inflate(childView, this, true);
        }
    }
    

    In your layout file:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                  xmlns:custom_view="http://schemas.android.com/apk/res-auto"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent">
    
    <your.package.MyCustomView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            custom_view:child_view="@layout/some_layout" />
    
    </LinearLayout>