Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NavigationDrawer fragment with ListView and custom Header

I'm having a problem and I can not solve it. In my app I have a navigation drawer defined as below:

activity_main.xml

<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<!-- As the main content view, the view below consumes the entire
     space available using match_parent in both dimensions. -->
<FrameLayout
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

<!-- android:layout_gravity="start" tells DrawerLayout to treat
     this as a sliding drawer on the left side for left-to-right
     languages and on the right side for right-to-left languages.
     If you're not building against API 17 or higher, use
     android:layout_gravity="left" instead. -->
<!-- The drawer is given a fixed width in dp and extends the full height of
     the container. -->
<fragment android:id="@+id/navigation_drawer"
    android:layout_width="@dimen/navigation_drawer_width"
    android:layout_height="match_parent"
    android:layout_gravity="start"  />

On the MainActivity class, I normally setContentView passing this xml: MainActivity.java

setContentView(R.layout.activity_main);

    mNavigationDrawerFragment = (NavigationDrawerFragment)
        getSupportFragmentManager().findFragmentById(R.id.navigation_drawer);

On my NavigationDrawerFragment onCreateView I normally inflate its xml with this:

NavigationDrawerFragment.java

public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View root = (View)inflater.inflate(R.layout.fragment_navigation_drawer,null,false);
    mDrawerListView = (ListView)root.findViewById(R.id.drawer_list_view);

    mDrawerListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            selectItem(position);
        }
    });

And this is fragment_navigation_drawer.xml: fragment_navigation_drawer.xml

<LinearLayout
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:android="http://schemas.android.com/apk/res/android">

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:padding="10dp">

    <ImageView
            android:id="@+id/profile_picture"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_alignParentLeft="true"/>

    <TextView
            android:id="@+id/user_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10dp"
            android:layout_toRightOf="@id/profile_picture"
            android:textStyle="bold"
            android:textSize="15sp" />

    <TextView
            android:id="@+id/user_mail"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/user_name"
            android:layout_alignLeft="@id/user_name"
            android:fontFamily="sans-serif-light" />


    <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:src="@android:drawable/ic_menu_close_clear_cancel"/>

</RelativeLayout>

<ListView xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:choiceMode="singleChoice"
          android:id="@+id/drawer_list_view"
          android:dividerHeight="0dp"
          android:background="@color/navigation_drawer_background" />

When I run the code, I get an exception on the setContentView of MainActivity saying:

Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

I think there is something wrong with the NavigationDrawer layout. What am I doing wrong?

EDIT: I changed my layout to:

<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
<!-- The main content view -->
<FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
<!-- The navigation drawer -->
<FrameLayout
        android:id="@+id/left_drawer_frame"
        android:layout_width="@dimen/navigation_drawer_dimension"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="@android:color/white"/>

So with a FrameLayout, in my activity I use:

mFragment = new Fragment();
        getSupportFragmentManager()
            .beginTransaction()
            .replace(R.id.content_frame, mFragment)
            .commit();

And i Inflate the fragment with this:

View root = inflater.inflate(R.layout.fragment_main, container, false);

It all seems working

like image 855
edoardotognoni Avatar asked Mar 21 '14 08:03

edoardotognoni


1 Answers

Better late than never.

Looking at your code (variable names, layout structure etc.) I presume that you are using Android Studio and you created the project using the "Navigation Drawer" template provided by the Android Studio "Create Project" wizard.

If the above assumption is true, then your problem resides in the onCreateView of NavigationDrawerFragment. You must return the inflated view from onCreateView and what you should return in this particular case is root not mDrawerListView

public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View root = (View)inflater.inflate(R.layout.fragment_navigation_drawer,null,false);
    mDrawerListView = (ListView)root.findViewById(R.id.drawer_list_view);

    mDrawerListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            selectItem(position);
        }
    });

    return root;

    // This is wrong
    // return mDrawerListView;
}

It's a common mistake that happen when we edit the IDE generated code.

Hope this helps.

like image 126
gnuanu Avatar answered Nov 08 '22 03:11

gnuanu