Toggle Button in Navigation Drawer
Asked Answered
S

1

8

I am trying to implement a toggle button into the Navigation Drawer Project, that Android Studio can automatically generate. In the end I want to have something like this ("Downloaded only"-Button):

enter image description here

Unfortunately I don't understand how to add a toggle button to the ListView of the NavDrawer. I could probably use one of the "Custom NavDrawer Libs" out there but I would like to understand the way Google proposes it with the auto generated example.

Any ideas on how to implement this into the default NavDrawer Project?

Smaragdite answered 22/3, 2015 at 19:31 Comment(1)
Same question with simpler, more canonical, answer: https://mcmap.net/q/841755/-switch-in-navigation-drawer-item-with-design-support-library-on-android/671393Hubblebubble
J
5

I would do something like this: instead of using a listview I would use an RecyclerView. Then I create three different layout definitions for the label with icon, the divider and the label with optional switch. Your RecyclerView Adapter should extend Form RecyclerView.Adapter. For each of those three layouts you should create an own implementation of ViewHolder. Now you have to create several classes for the list items and one superclass for all of them. In your Adapter you have to override the getViewType method. Tomorrow when I'm at work I could post some demo code for you.

Edit:

activity_main.xml

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

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="de.devhew.navigationdrawerexample.MainActivity">

    <android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/toolbar_main"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/colorPrimary"
        android:minHeight="?attr/actionBarSize"
        app:popupTheme="@style/AppTheme.Toolbar.Overflow"
        app:theme="@style/AppTheme.Toolbar" />

    <FrameLayout
        android:id="@+id/main_content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>

<fragment
    android:id="@+id/fragment_navigation_drawer"
    android:name="de.devhew.navigationdrawerexample.drawer.NavigationDrawerFragment"
    android:layout_width="280dp"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    app:layout="@layout/fragment_navigation_drawer"
    tools:layout="@layout/fragment_navigation_drawer" />

MainActivity.java

public class MainActivity extends ActionBarActivity {

private Toolbar toolbar;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    toolbar = (Toolbar) findViewById(R.id.toolbar_main);
    setSupportActionBar(toolbar);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

    List<NavDrawerEntry> drawerEntries = new ArrayList<>();
    drawerEntries.add(new NavDrawerItemWithIcon("Home", R.drawable.app_generic));
    drawerEntries.add(new NavDrawerItemWithIcon("People", R.drawable.app_generic));
    drawerEntries.add(new NavDrawerItemWithIcon("Stuff", R.drawable.app_generic));
    drawerEntries.add(new NavDrawerDivider());
    drawerEntries.add(new NavDrawerItem("Settings"));
    drawerEntries.add(new NavDrawerToggle("Wifi only"));

    NavigationDrawerFragment drawerFragment = (NavigationDrawerFragment) getSupportFragmentManager().findFragmentById(R.id.fragment_navigation_drawer);
    drawerFragment.init((android.support.v4.widget.DrawerLayout) findViewById(R.id.drawer_layout),
            toolbar, drawerEntries);
}}

NavigationDrawerFragment.java

public class NavigationDrawerFragment extends Fragment {

private View root;
private ActionBarDrawerToggle mDrawerToggle;
private DrawerLayout mDrawerLayout;
private RecyclerView mRecyclerView;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    root = inflater.inflate(R.layout.fragment_navigation_drawer, container, false);
    return root;
}

public void init(DrawerLayout drawerLayout, final Toolbar toolbar, List<NavDrawerEntry> drawerEntries) {
    mDrawerLayout = drawerLayout;
    mDrawerToggle = new ActionBarDrawerToggle(getActivity(),
            drawerLayout, toolbar, R.string.drawer_open, R.string.drawer_close) {
        @Override
        public void onDrawerOpened(View drawerView) {
            super.onDrawerOpened(drawerView);
            getActivity().invalidateOptionsMenu();
        }

        @Override
        public void onDrawerClosed(View drawerView) {
            super.onDrawerClosed(drawerView);
            getActivity().invalidateOptionsMenu();
        }
    };

    mDrawerLayout.setDrawerListener(mDrawerToggle);
    mDrawerLayout.post(new Runnable() {
        @Override
        public void run() {
            mDrawerToggle.syncState();
        }
    });

    mRecyclerView = (RecyclerView) root.findViewById(R.id.nav_list);
    mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
    mRecyclerView.setHasFixedSize(true);

    NavigationDrawerAdapter adapter = new NavigationDrawerAdapter(getActivity(), drawerEntries);
    mRecyclerView.setAdapter(adapter);
}}

NavigationDrawerAdapter.java

public class NavigationDrawerAdapter
    extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

private List<NavDrawerEntry> data;
private LayoutInflater inflater;

public NavigationDrawerAdapter(Context context, List<NavDrawerEntry> data) {
    this.data = data;
    this.inflater = LayoutInflater.from(context);
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {

    View itemLayoutView;
    switch (viewType) {
        case 0:
            itemLayoutView = inflater.inflate(R.layout.layout_nav_drawer_item_with_icon, viewGroup, false);
            ItemWithIconVH holder = new ItemWithIconVH(itemLayoutView);
            return holder;
        case 1:
            itemLayoutView = inflater.inflate(R.layout.layout_nav_drawer_divider, viewGroup, false);
            DividerVH dividerViewHolder = new DividerVH(itemLayoutView);
            return dividerViewHolder;
        case 2:
            itemLayoutView = inflater.inflate(R.layout.layout_nav_drawer_item, viewGroup, false);
            ItemVH itemViewHolder = new ItemVH(itemLayoutView);
            return itemViewHolder;
        case 3:
            itemLayoutView = inflater.inflate(R.layout.layout_nav_drawer_toggle, viewGroup, false);
            ToggleVH toggleViewHolder = new ToggleVH(itemLayoutView);
            return toggleViewHolder;
    }
    return null;
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
    final NavDrawerEntry item = data.get(position);

    if (item instanceof NavDrawerItemWithIcon) {
        ItemWithIconVH viewHolder = (ItemWithIconVH) holder;
        viewHolder.mTitle.setText(((NavDrawerItemWithIcon) item).getTitle());
        viewHolder.mImageView.setImageResource(((NavDrawerItemWithIcon) item).getIconId());
    }

    if (item instanceof NavDrawerItem) {
        ItemVH viewHolder = (ItemVH) holder;
        viewHolder.mTitle.setText(((NavDrawerItem) item).getTitle());
    }

    if (item instanceof NavDrawerToggle) {
        ToggleVH viewHolder = (ToggleVH) holder;
        viewHolder.mTitle.setText(((NavDrawerToggle) item).getTitle());
        viewHolder.mSwitch.setChecked(((NavDrawerToggle) item).isChecked());
    }
}

@Override
public int getItemViewType(int position) {
    if (data.get(position) instanceof NavDrawerItemWithIcon)
        return 0;

    if (data.get(position) instanceof NavDrawerDivider)
        return 1;

    if (data.get(position) instanceof NavDrawerItem)
        return 2;

    if (data.get(position) instanceof NavDrawerToggle)
        return 3;

    return -1;
}

@Override
public int getItemCount() {
    return data.size();
}

class ItemWithIconVH extends RecyclerView.ViewHolder {
    final TextView mTitle;
    final ImageView mImageView;

    public ItemWithIconVH(View itemView) {
        super(itemView);
        mTitle = (TextView) itemView.findViewById(R.id.nav_item_title);
        mImageView = (ImageView) itemView.findViewById(R.id.nav_item_image);
    }
}

class DividerVH extends RecyclerView.ViewHolder {
    public DividerVH(View itemView) {
        super(itemView);
    }
}

class ItemVH extends RecyclerView.ViewHolder {
    final TextView mTitle;

    public ItemVH(View itemView) {
        super(itemView);
        mTitle = (TextView) itemView.findViewById(R.id.nav_item_title);
    }
}

class ToggleVH extends RecyclerView.ViewHolder {
    final TextView mTitle;
    final Switch mSwitch;

    public ToggleVH(View itemView) {
        super(itemView);
        mTitle = (TextView) itemView.findViewById(R.id.nav_item_title);
        mSwitch = (Switch) itemView.findViewById(R.id.nav_switch);
    }
}}

Superclass for all NavDrawer Items:

public class NavDrawerEntry {}

Item without icon:

public class NavDrawerItem extends NavDrawerEntry {
private String title;

public NavDrawerItem(String title) {
    this.setTitle(title);
}

public String getTitle() {
    return title;
}

private void setTitle(String title) {
    this.title = title;
}}

Item with icon:

public class NavDrawerItemWithIcon extends NavDrawerEntry {
private String title;
private int iconId;

public NavDrawerItemWithIcon(String title, int iconId) {
    this.setTitle(title);
    this.setIconId(iconId);
}

public int getIconId() {
    return iconId;
}

private void setIconId(int iconId) {
    this.iconId = iconId;
}

public String getTitle() {
    return title;
}

private void setTitle(String title) {
    this.title = title;
}}

Divider:

public class NavDrawerDivider extends NavDrawerEntry {}

Item with Switch:

public class NavDrawerToggle extends NavDrawerEntry {
private String title;
private boolean checked;

public NavDrawerToggle(String title) {
    this.setTitle(title);
}

public boolean isChecked() {
    return checked;
}

public void setChecked(boolean checked) {
    this.checked = checked;
}

public String getTitle() {
    return title;
}

private void setTitle(String title) {
    this.title = title;
}}

layout_nav_drawer_item.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="60dp"
android:clickable="true"
android:orientation="horizontal">

<TextView
    android:id="@+id/nav_item_title"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerVertical="true"
    android:layout_gravity="center_vertical"
    android:layout_marginLeft="16dp"
    android:fontFamily="sans-serif"
    android:textColor="#000"
    android:textSize="16sp" /></LinearLayout>

layout_nav_drawer_item_with_icon.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="60dp"
android:clickable="true"
android:orientation="horizontal">

<ImageView
    android:id="@+id/nav_item_image"
    android:layout_width="30dp"
    android:layout_height="30dp"
    android:layout_gravity="center_vertical"
    android:layout_marginLeft="16dp"
    android:src="@drawable/app_generic" />

<TextView
    android:id="@+id/nav_item_title"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerVertical="true"
    android:layout_gravity="center_vertical"
    android:layout_marginLeft="16dp"
    android:fontFamily="sans-serif"
    android:text="Verbundene Geräte"
    android:textColor="#000"
    android:textSize="16sp" /></LinearLayout>

layout_nav_drawer_divider.xml

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

<View
    android:layout_width="match_parent"
    android:layout_height="1dp"
    android:background="#ddd"
    android:layout_marginBottom="8dp"
    android:layout_marginTop="8dp" /></LinearLayout>

layout_nav_drawer_toggle.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="60dp"
android:clickable="true">

<TextView
    android:id="@+id/nav_item_title"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerVertical="true"
    android:layout_gravity="center_vertical"
    android:layout_marginLeft="16dp"
    android:fontFamily="sans-serif"
    android:text="Verbundene Geräte"
    android:textColor="#000"
    android:textSize="16sp" />

<Switch
    android:id="@+id/nav_switch"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentRight="true"
    android:layout_centerVertical="true"
    android:layout_marginRight="16dp" /></RelativeLayout>

fragment_navigation_drawer.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="280dp"
android:layout_height="match_parent"
android:background="#eee"
tools:context="de.vacom.hew.materialdemo.NavigationDrawerFragment">

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="120dp"
        android:background="@color/primaryColor"
        android:elevation="3dp"
        android:orientation="horizontal">

        <ImageView
            android:id="@+id/nav_app_icon"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_marginLeft="16dp"
            android:layout_marginTop="55dp"
            android:src="@drawable/app_generic" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="8dp"
            android:layout_marginTop="64dp"
            android:fontFamily="sans-serif-medium"
            android:text="Demo App"
            android:textColor="#eee"
            android:textSize="18sp" />

    </LinearLayout>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/nav_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout></FrameLayout>
Jenette answered 22/3, 2015 at 21:31 Comment(5)
That would be awesome, thank you! EDIT: I've tried for several hours to get the L&F of the material design rules and finally ended up in using this: github.com/mikepenz/MaterialDrawer If you could base your modifications on this example, I would be really grateful. :-)Smaragdite
My code is my own implementation of diffrent items iside the navDrawer. Sorry i seen yout Edit to late for changes. Try my example, maybe it will help you.Jenette
Thanks a lot, I will have a look at your really extensive edit. If it is not too much asked, could you maybe zip your code and upload it somewhere? I tried to copy everything in a project but still get plenty of errors...Smaragdite
Sure. Here's the Link. Its a Android-Studio project using gradle. drive.google.com/…Jenette
Thank you very much, I'll try to merge your solution with the drawer I mentioned in my edit. It is not based on fragments, but hopefully I will manage to patch it together. Herzlichen Dank ;-)Smaragdite

© 2022 - 2024 — McMap. All rights reserved.