Tiroir de navigation avec en-têtes / sections
Je voudrais savoir si il existe un moyen pour que je puisse ajouter des en-têtes/articles à la navigation de tiroir. J'ai réussi à ajouter quelque chose comme ça, mais il ne s'affiche en haut de la liste, parce que addHeaderView doit être appelée avant setAdapter et si j'essaie d'ajouter plus d'éléments après setAdapter ils vont réécrire les premiers éléments.
Grâce.
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:
J'ai trouvé une bonne solution en combinant des solutions à partir de différentes sources, ce sont les principales classes que j'ai utilisé:
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;
}
}
Élément
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);
}
}
Mais j'ai un petit problème: les sections prendre position dans la liste et la sélection de fragments, c'est foiré.
source d'informationauteur Ionut Negru
Vous devez vous connecter pour publier un commentaire.
Vous ajouter des en-têtes/sections à une
ListView
pour une utilisation dans unDrawerLayout
de la même façon que vous ajoutez des en-têtes/sections à uneListView
pour une utilisation n'importe où ailleurs à l'intérieur de Android.Au niveau bas, ce qui implique une
ListAdapter
que:Remplace
getViewTypeCount()
pour indiquer le nombre de types distincts de lignes (par exemple, 2, l'un pour les en-têtes et un programme régulier de lignes)Remplace
getItemViewType()
à indiquer le type de ligne à utiliser pour unposition
Assure que
getView()
(ounewView()
/bindView()
d'unCursorAdapter
) est conscient de la multiplicité des types de ligne et les traite en conséquenceÀ un niveau supérieur, vous pouvez essayer d'utiliser des choses comme mon
MergeAdapter
ou divers autres bibliothèques de tiers, pour aider à simplifier cette.Dans le Tiroir de Navigation dans la liste des éléments peut être affiché à l'aide d'une liste de sorte que vous pouvez avoir un adaptateur de classe et met en œuvre votre logique.
Ainsi, vous pouvez ajouter des sections, les en-têtes et ainsi de suite.
Ici, vous avez un exemple complet de Navigation Tiroir à l'aide des en-têtes/sections
C'est le résultat
Si la liste de vos éléments sont fixes(non variable), un petit "hack" serait d'inclure un interrupteur cas pour la "position" de votre adaptateur getView() la méthode et gonfler un headerlayout.xml à ces positions fixes. Votre régulière inflation va par défaut dans le cadre de l'interrupteur cas. C'est sale et pas recommandé, mais efficace.
Je suggère d'étendre
EntryItem
par l'ajout d'une balise membre de vous indique quel type de fragment de créer. Ensuite, il suffit de cocher la balise dans votreonItemClick
gestionnaire pour créer le bon type de fragment. De cette façon, vous n'êtes pas dépendant de la position, qui peut changer à mesure que vous ajoutez/supprimer des éléments dans les sections.Vous avez besoin d'ajouter cela à la EntryAdapter classe:
avec qui, et:
Sections de ne pas prendre position sur la liste.
Une bonne solution que j'ai lu était de placer un en-tête TextView à l'intérieur de votre ligne fichier de mise en page et sa visibilité est définie à
GONE
.Puis dans votre carte
getView
à une certaine logique qui dit: Est-ce que le premier élément de la liste (position 0), OU est le type de ce point différents que le type d'une position au-dessus d'elle? Si donc, tournez la têteTextView's
de la visibilité àVISIBLE
.De cette façon est préféré parce que lorsque vous souhaitez utiliser
getItemAtPosition
vous n'avez pas à comprendre comment esquiver vos en-têtes de section, ils seraient à prendre une position si vous avez implémenté le chemin de l'OP et d'autres ont suggéré.