I would like to know if there is any way that I can add headers/sections to the navigation drawer. I managed to add something like that, but it is only displayed at the top of the list, because addHeaderView needs to be called before setAdapter and if I try to add more elements after setAdapter they will rewrite the first elements.
Thanks.
Edit:
public class MenuListAdapter extends BaseAdapter {
// Declare Variables
Context context;
String[] mTitle;
String[] mSubTitle;
int[] mIcon;
LayoutInflater inflater;
public MenuListAdapter(Context context, String[] title, String[] subtitle,
int[] icon) {
this.context = context;
this.mTitle = title;
this.mSubTitle = subtitle;
this.mIcon = icon;
inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getViewTypeCount() {
return super.getViewTypeCount();
}
@Override
public int getItemViewType(int position) {
return super.getItemViewType(position);
}
@Override
public int getCount() {
return mTitle.length;
}
@Override
public Object getItem(int position) {
return mTitle[position];
}
@Override
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
// Declare Variables
TextView txtTitle;
TextView txtSubTitle;
ImageView imgIcon;
View itemView = inflater.inflate(R.layout.drawer_list_item, parent,
false);
// Locate the TextViews in drawer_list_item.xml
txtTitle = (TextView) itemView.findViewById(R.id.title);
txtSubTitle = (TextView) itemView.findViewById(R.id.subtitle);
// Locate the ImageView in drawer_list_item.xml
imgIcon = (ImageView) itemView.findViewById(R.id.icon);
// Set the results into TextViews
txtTitle.setText(mTitle[position]);
txtSubTitle.setText(mSubTitle[position]);
// Set the results into ImageView
imgIcon.setImageResource(mIcon[position]);
return itemView;
}
}
EDIT:
I found a good solution by combining solutions from different sources, this are the main classes that I used:
EntryAdapter
import java.util.ArrayList;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import com.androidbegin.sidemenututorial.R;
public class EntryAdapter extends ArrayAdapter<Item> {
private enum RowType {
LIST_ITEM, HEADER_ITEM
}
private Context context;
private ArrayList<Item> items;
private LayoutInflater vi;
public EntryAdapter(Context context, ArrayList<Item> items) {
super(context,0, items);
this.context = context;
this.items = items;
vi = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public int getViewTypeCount() { //Returns the number of types of Views that will be created by getView(int, View, ViewGroup).
return RowType.values().length;
}
@Override
public int getItemViewType(int position) { //framework calls getItemViewType for row n, the row it is about to display.
//Get the type of View that will be created by getView(int, View, ViewGroup) for the specified item.
Log.i("LIST", "item at " + position + " is "
+ ((getItem(position).isSection() ? 0 : 1) == 0 ? "section" : "normal item"));
return getItem(position).isSection() ? 0 : 1; // get position passes (n) and accertain is its a header or not
}
@Override
public boolean isEnabled(int position) {
return !getItem(position).isSection();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
final Item i = items.get(position);
if (i != null) {
if(i.isSection()){
SectionItem si = (SectionItem) i;
v = vi.inflate(R.layout.list_item_section, null);
v.setOnClickListener(null);
v.setOnLongClickListener(null);
v.setLongClickable(false);
final TextView sectionView = (TextView) v.findViewById(R.id.list_item_section_text);
sectionView.setText(si.getTitle());
}else{
EntryItem ei = (EntryItem) i;
v = vi.inflate(R.layout.list_item_entry, null);
final TextView title = (TextView)v.findViewById(R.id.list_item_entry_title);
final TextView subtitle = (TextView)v.findViewById(R.id.list_item_entry_summary);
if (title != null)
title.setText(ei.title);
if(subtitle != null)
subtitle.setText(ei.subtitle);
}
}
return v;
}
}
EntryItem
public class EntryItem implements Item{
public final String title;
public final String subtitle;
public EntryItem(String title, String subtitle) {
this.title = title;
this.subtitle = subtitle;
}
@Override
public boolean isSection() {
return false;
}
}
Item
public interface Item {
public boolean isSection();
}
SectionItem
public class SectionItem implements Item{
private final String title;
public SectionItem(String title) {
this.title = title;
}
public String getTitle(){
return title;
}
@Override
public boolean isSection() {
return true;
}
}
MainActivity
import java.util.ArrayList;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
import com.androidbegin.item.EntryAdapter;
import com.androidbegin.item.EntryItem;
import com.androidbegin.item.Item;
import com.androidbegin.item.SectionItem;
public class MainActivity extends SherlockFragmentActivity {
// Declare Variable
DrawerLayout mDrawerLayout;
ListView mDrawerList;
ActionBarDrawerToggle mDrawerToggle;
MenuListAdapter mMenuAdapter;
String[] title;
String[] subtitle;
int[] icon;
Fragment fragment1 = new Fragment1();
Fragment fragment2 = new Fragment2();
Fragment fragment3 = new Fragment3();
Context context;
ArrayList<Item> items = new ArrayList<Item>();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.drawer_main);
this.context = this;
// Generate title
title = new String[] { "Title Fragment 1", "Title Fragment 2",
"Title Fragment 3" };
// Generate subtitle
subtitle = new String[] { "Subtitle Fragment 1", "Subtitle Fragment 2",
"Subtitle Fragment 3" };
// Generate icon
icon = new int[] { R.drawable.action_about, R.drawable.action_settings,
R.drawable.collections_cloud };
// Locate DrawerLayout in drawer_main.xml
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
// Locate ListView in drawer_main.xml
mDrawerList = (ListView) findViewById(R.id.left_drawer);
// Set a custom shadow that overlays the main content when the drawer
// opens
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow,
GravityCompat.START);
// Pass results to MenuListAdapter Class
// mMenuAdapter = new MenuListAdapter(this, title, subtitle, icon);
// Set the MenuListAdapter to the ListView
// mDrawerList.setAdapter(mMenuAdapter);
items.add(new SectionItem("Category 1"));
items.add(new EntryItem("Item 1", "This is item 1.1"));
items.add(new EntryItem("Item 2", "This is item 1.2"));
items.add(new EntryItem("Item 3", "This is item 1.3"));
items.add(new SectionItem("Category 2"));
items.add(new EntryItem("Item 4", "This is item 2.1"));
items.add(new EntryItem("Item 5", "This is item 2.2"));
items.add(new EntryItem("Item 6", "This is item 2.3"));
items.add(new EntryItem("Item 7", "This is item 2.4"));
items.add(new SectionItem("Category 3"));
items.add(new EntryItem("Item 8", "This is item 3.1"));
items.add(new EntryItem("Item 9", "This is item 3.2"));
items.add(new EntryItem("Item 10", "This is item 3.3"));
items.add(new EntryItem("Item 11", "This is item 3.4"));
items.add(new EntryItem("Item 12", "This is item 3.5"));
EntryAdapter adapter = new EntryAdapter(this, items);
mDrawerList.setAdapter(adapter);
// Capture button clicks on side menu
mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
// Enable ActionBar app icon to behave as action to toggle nav drawer
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// ActionBarDrawerToggle ties together the the proper interactions
// between the sliding drawer and the action bar app icon
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
R.drawable.ic_drawer, R.string.drawer_open,
R.string.drawer_close) {
public void onDrawerClosed(View view) {
// TODO Auto-generated method stub
super.onDrawerClosed(view);
}
public void onDrawerOpened(View drawerView) {
// TODO Auto-generated method stub
super.onDrawerOpened(drawerView);
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
if (savedInstanceState == null) {
selectItem(0);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getSupportMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
if (mDrawerLayout.isDrawerOpen(mDrawerList)) {
mDrawerLayout.closeDrawer(mDrawerList);
} else {
mDrawerLayout.openDrawer(mDrawerList);
}
}
return super.onOptionsItemSelected(item);
}
// The click listener for ListView in the navigation drawer
private class DrawerItemClickListener implements
ListView.OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
Log.i("LIST", "item position = " + Integer.toString(position)
+ "\nitem id = " + String.valueOf(id));
if (!items.get(position).isSection()) {
EntryItem item = (EntryItem)items.get(position);
Toast.makeText(context, "You clicked " + item.title , Toast.LENGTH_SHORT).show();
selectItem(position);
}
// selectItem(position);
}
}
private void selectItem(int position) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
// Locate Position
switch (position) {
case 0:
ft.replace(R.id.content_frame, fragment1);
break;
case 1:
ft.replace(R.id.content_frame, fragment2);
break;
case 2:
ft.replace(R.id.content_frame, fragment3);
break;
}
ft.commit();
mDrawerList.setItemChecked(position, true);
// Close drawer
mDrawerLayout.closeDrawer(mDrawerList);
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
mDrawerToggle.syncState();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Pass any configuration change to the drawer toggles
mDrawerToggle.onConfigurationChanged(newConfig);
}
}
But I have a little problem: the sections take a position in the list and the selection of fragments is messed up.
The navigation drawer is a UI panel that shows your app's main navigation menu. The drawer appears when the user touches the drawer icon in the app bar or when the user swipes a finger from the left edge of the screen.
You add headers/sections to a ListView
for use in a DrawerLayout
the same way that you add headers/sections to a ListView
for use anywhere else inside of Android.
At the low level, this involves a ListAdapter
that:
Overrides getViewTypeCount()
to indicate how many distinct types of rows there are (e.g., 2, one for headers and one for regular rows)
Overrides getItemViewType()
to indicate which row type to use for a given position
Ensures that getView()
(or newView()
/bindView()
of a CursorAdapter
) is aware of the multiple row types and processes them accordingly
At a higher level, you can try to use things like my MergeAdapter
, or various other third-party libraries, to help simplify this.
In the Navigation Drawer the item list can be displayed using a ListView so you can have a class adapter and implements your logic. So you can add sections, headers and so on.
Here you have a complete example of Navigation Drawer using headers/sections
This is the result
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With