Android Navigation Drawer ExpandableListView
Solution 1
If you want to achieve above behavior to your NavigationDrawer you can follow below steps:
1) You have to add Expandable listview to your NavigationView.
2) Create Header View
3) Create Child View.
4) Extend BaseExpandableListAdapter
5) Set Adapter in MainActivity
There are few solutions available. You can follow this tutorial or this. For basic knowledge about creating Navigation drawer, you can go here. I got helped by these tutorials and they are very easy to apply.
Hope this helps.
Solution 2
Download source code from here (Navigation drawer with expandablelistview in android)
MainActivity.java
package com.deepshikha.navigationdrawer;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
ArrayList<Model_country> al_main = new ArrayList<>();
ExpandableListView ev_list;
CountryAdapter obj_adapter;
String TAG = "MainActivity";
private DrawerLayout mDrawerLayout;
HomeFragment fragment;
TextView tv_name;
RelativeLayout rl_menu;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fn_data();
init();
}
private void init() {
getSupportActionBar().hide();
ev_list = (ExpandableListView) findViewById(R.id.ev_menu);
tv_name = (TextView) findViewById(R.id.tv_name);
rl_menu = (RelativeLayout) findViewById(R.id.rl_menu);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
obj_adapter = new CountryAdapter(MainActivity.this, al_main);
ev_list.setAdapter(obj_adapter);
ev_list.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
@Override
public boolean onGroupClick(ExpandableListView parent, View v,
int groupPosition, long id) {
setListViewHeight(parent, groupPosition);
return false;
}
});
setExpandableListViewHeightBasedOnChildren(ev_list);
fragment = new HomeFragment();
Bundle bundle = new Bundle();
bundle.putString("name", al_main.get(0).getStr_country());
bundle.putString("des", al_main.get(0).getAl_state().get(0).getStr_description());
bundle.putString("dish", al_main.get(0).getAl_state().get(0).getStr_name());
bundle.putString("image", al_main.get(0).getAl_state().get(0).getStr_image());
tv_name.setText(al_main.get(0).getStr_country());
fragment.setArguments(bundle);
getSupportFragmentManager().beginTransaction().replace(R.id.content_frame, fragment, "HomeFragment").addToBackStack("null").commit();
rl_menu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mDrawerLayout.openDrawer(Gravity.LEFT);
}
});
}
private void setListViewHeight(ExpandableListView listView, int group) {
ExpandableListAdapter listAdapter = (ExpandableListAdapter) listView.getExpandableListAdapter();
int totalHeight = 0;
int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(),
View.MeasureSpec.EXACTLY);
for (int i = 0; i < listAdapter.getGroupCount(); i++) {
View groupItem = listAdapter.getGroupView(i, false, null, listView);
groupItem.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
totalHeight += groupItem.getMeasuredHeight();
if (((listView.isGroupExpanded(i)) && (i != group))
|| ((!listView.isGroupExpanded(i)) && (i == group))) {
for (int j = 0; j < listAdapter.getChildrenCount(i); j++) {
View listItem = listAdapter.getChildView(i, j, false, null,
listView);
listItem.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED);
totalHeight += listItem.getMeasuredHeight();
}
}
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
int height = totalHeight
+ (listView.getDividerHeight() * (listAdapter.getGroupCount() - 1));
/* if (height < 10)
height = 200;*/
params.height = height;
listView.setLayoutParams(params);
listView.requestLayout();
}
private void fn_data() {
String str_data = loadJSONFromAsset();
try {
JSONObject jsonObject_country = new JSONObject(str_data);
JSONArray jsonArray_country = jsonObject_country.getJSONArray("country");
al_main = new ArrayList<>();
for (int i = 0; i < jsonArray_country.length(); i++) {
Model_country obj_country = new Model_country();
JSONObject jsonObject = jsonArray_country.getJSONObject(i);
JSONArray jsonArray_dishes = jsonObject.getJSONArray("dishes");
ArrayList<Model_Dish> al_dishes = new ArrayList<>();
for (int j = 0; j < jsonArray_dishes.length(); j++) {
JSONObject jsonObject_dishes = jsonArray_dishes.getJSONObject(j);
Model_Dish obj_dish = new Model_Dish();
obj_dish.setStr_name(jsonObject_dishes.getString("dishname"));
obj_dish.setStr_description(jsonObject_dishes.getString("description"));
obj_dish.setStr_image(jsonObject_dishes.getString("image"));
al_dishes.add(obj_dish);
}
obj_country.setAl_state(al_dishes);
obj_country.setStr_country(jsonObject.getString("name"));
al_main.add(obj_country);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
public static void setExpandableListViewHeightBasedOnChildren(ExpandableListView expandableListView) {
CountryAdapter adapter = (CountryAdapter) expandableListView.getExpandableListAdapter();
if (adapter == null) {
return;
}
int totalHeight = expandableListView.getPaddingTop() + expandableListView.getPaddingBottom();
for (int i = 0; i < adapter.getGroupCount(); i++) {
View groupItem = adapter.getGroupView(i, false, null, expandableListView);
groupItem.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
totalHeight += groupItem.getMeasuredHeight();
if (expandableListView.isGroupExpanded(i)) {
for (int j = 0; j < adapter.getChildrenCount(i); j++) {
View listItem = adapter.getChildView(i, j, false, null, expandableListView);
listItem.setLayoutParams(new ViewGroup.LayoutParams(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED));
listItem.measure(View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED), View.MeasureSpec
.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
totalHeight += listItem.getMeasuredHeight();
}
}
}
ViewGroup.LayoutParams params = expandableListView.getLayoutParams();
int height = totalHeight + expandableListView.getDividerHeight() * (adapter.getGroupCount() - 1);
if (height < 10)
height = 100;
params.height = height;
expandableListView.setLayoutParams(params);
expandableListView.requestLayout();
}
public String loadJSONFromAsset() {
String json = null;
try {
InputStream is = getAssets().open("dishes.json");
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
json = new String(buffer, "UTF-8");
} catch (IOException ex) {
ex.printStackTrace();
return null;
}
Log.e(TAG, "Json response " + json);
return json;
}
public void fn_selectedPosition(int group, int child) {
fragment = new HomeFragment();
Bundle bundle = new Bundle();
bundle.putString("name", al_main.get(group).getStr_country());
bundle.putString("des", al_main.get(group).getAl_state().get(child).getStr_description());
bundle.putString("dish", al_main.get(group).getAl_state().get(child).getStr_name());
bundle.putString("image", al_main.get(group).getAl_state().get(child).getStr_image());
fragment.setArguments(bundle);
getSupportFragmentManager().beginTransaction().replace(R.id.content_frame, fragment, "HomeFragment").addToBackStack("null").commit();
mDrawerLayout.closeDrawer(Gravity.LEFT);
tv_name.setText(al_main.get(group).getStr_country());
}
@Override
public void onBackPressed() {
super.onBackPressed();
finish();
}
}
CountryAdapter.java
package com.deepshikha.navigationdrawer;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.TextView;
import java.util.ArrayList;
/**
* Created by deepshikha on 12/7/17.
*/
public class CountryAdapter extends BaseExpandableListAdapter {
Context context;
ArrayList<Model_country> al_country;
public CountryAdapter(Context context, ArrayList<Model_country> al_country) {
this.context = context;
this.al_country = al_country;
}
@Override
public int getGroupCount() {
return al_country.size();
}
@Override
public int getChildrenCount(int i) {
return al_country.get(i).getAl_state().size();
}
@Override
public Object getGroup(int i) {
return al_country.get(i);
}
@Override
public Object getChild(int i, int i1) {
return al_country.get(i).getAl_state().get(i1);
}
@Override
public long getGroupId(int i) {
return i;
}
@Override
public long getChildId(int i, int i1) {
return i1;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public View getGroupView(int i, boolean b, View view, ViewGroup viewGroup) {
if (view==null){
LayoutInflater layoutInflater = (LayoutInflater) this.context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = layoutInflater.inflate(R.layout.adapter_header, null);
}
TextView tv_state = (TextView)view.findViewById(R.id.tv_name);
tv_state.setText(al_country.get(i).getStr_country());
return view;
}
@Override
public View getChildView(final int i, final int i1, boolean b, View view, ViewGroup viewGroup) {
if (view==null){
LayoutInflater layoutInflater = (LayoutInflater) this.context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = layoutInflater.inflate(R.layout.adapter_childview, null);
}
TextView tv_state = (TextView)view.findViewById(R.id.tv_name);
tv_state.setText(al_country.get(i).getAl_state().get(i1).getStr_name());
tv_state.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
((MainActivity)context).fn_selectedPosition(i,i1);
}
});
return view;
}
@Override
public boolean isChildSelectable(int i, int i1) {
return false;
}
}
Thanks!
Devil's Dream
Updated on October 15, 2021Comments
-
Devil's Dream over 2 years
I am trying to implement SubMenu under Navigation Drawer Menu. There will be only One group menu. See the following image what I want to do. Currently I have only added the main menu from a xml menu list. How to add an ExpandableListView to a Menu as SubMenu to get the following type of interface.
Here the code I used to open/close navigation drawer and start activity on drawer menu click
navigationView = (NavigationView) findViewById(R.id.navigation_view); drawerLayout = (DrawerLayout) findViewById(R.id.drawer); //Setting Navigation View Item Selected Listener to handle the item click of the navigation menu navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() { // This method will trigger on item Click of navigation menu @Override public boolean onNavigationItemSelected(MenuItem item) { Intent intent; int id = item.getItemId(); //Check to see which item was being clicked and perform appropriate action if (id == R.id.favorites) { Intent favoritesIntent = new Intent(MainActivity.this, Favorites.class); startActivity(favoritesIntent); } else if (id == R.id.settings) { Intent settingsIntent = new Intent(MainActivity.this, Settings.class); startActivity(settingsIntent); } drawerLayout.closeDrawer(GravityCompat.START); return true; } }); // Initializing Drawer Layout and ActionBarToggle ActionBarDrawerToggle actionBarDrawerToggle = new ActionBarDrawerToggle(this,drawerLayout,toolbar,R.string.openDrawer, R.string.closeDrawer){ @Override public void onDrawerClosed(View drawerView) { // Code here will be triggered once the drawer closes as we dont want anything to happen so we leave this blank super.onDrawerClosed(drawerView); } @Override public void onDrawerOpened(View drawerView) { // Code here will be triggered once the drawer open as we dont want anything to happen so we leave this blank super.onDrawerOpened(drawerView); } }; actionBarDrawerToggle.setDrawerIndicatorEnabled(false); ImageView titleLogo = (ImageView) findViewById(R.id.titleLogo); titleLogo.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { drawerLayout.openDrawer(GravityCompat.START); } }); ..... @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; }
Here is the XML I used
<android.support.design.widget.NavigationView android:id="@+id/navigation_view" android:layout_height="match_parent" android:layout_width="wrap_content" android:layout_gravity="start" app:itemTextColor="@color/white" app:itemIconTint="@color/white" app:headerLayout="@layout/header" app:menu="@menu/drawer" android:background="@color/colorPrimary" > </android.support.design.widget.NavigationView>
Here is the drawer.xml for menu list
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <group android:checkableBehavior="single"> <item android:id="@+id/favorites" android:checked="false" android:icon="@drawable/favorites" android:title="@string/favorites" /> <item android:id="@+id/services" android:checked="false" android:icon="@drawable/services" android:title="@string/services" /> <item android:id="@+id/settings" android:checked="false" android:icon="@drawable/settings" android:title="@string/settings" /> </group> </menu>