2013-06-18 27 views
11

Vorrei sapere se c'è un modo che io possa aggiungere intestazioni/sezioni per il cassetto di navigazione. Sono riuscito ad aggiungere qualcosa del genere, ma è visualizzato solo in cima alla lista, perché addHeaderView deve essere chiamato prima di setAdapter e se provo ad aggiungere più elementi dopo setAdapter, essi riscriveranno i primi elementi.navigazione cassetto con le intestazioni/Sezioni

Grazie.

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:

ho trovato una buona soluzione combinando soluzioni provenienti da fonti diverse, questo sono le principali classi che ho usato:

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; 
    } 

} 

Articolo

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; 
    } 

} 

Mai nActivity

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); 
    } 
} 

Ma ho un piccolo problema: sezioni prendono una posizione nella lista e la selezione dei frammenti è incasinato.

risposta

1

nel cassetto di navigazione l'elenco delle voci possono essere visualizzate utilizzando un ListView in modo da poter disporre di una scheda di classe e implementa la logica. Quindi puoi aggiungere sezioni, intestazioni e così via.

+0

E come posso raggiungere questo obiettivo? Ho già un BaseAdapter che compila l'elenco (perché ho aggiunto l'immagine e il sottotitolo per la lista)? Ho aggiunto l'adattatore nel post principale. –

+0

Basta implementare un adattatore personalizzato e sovrascrivere i metodi come getView e così via. – FrancescoAzzola

+0

Come potete vedere, lo faccio già, ma come si consiglia di aggiungere intestazioni all'elenco del cassetto di navigazione? –

6

si aggiunge intestazioni/sezioni per un ListView per l'uso in un DrawerLayout stesso modo in cui si aggiungono le intestazioni/sezioni per un ListView per l'utilizzo in qualsiasi altro luogo all'interno di Android.

A livello basso, questo comporta una ListAdapter che:

  • Sostituzioni getViewTypeCount() per indicare quanti distinti tipi di righe esistono (ad esempio, 2, uno per le intestazioni e uno per file regolari)

  • Sostituzioni getItemViewType() per indicare quale tipo di riga da utilizzare per un determinato position

  • Assicura che getView() (o newView()/bindView() di un CursorAdapter) è consapevole i molteplici tipi di riga e li elabora di conseguenza

a un livello superiore, si può provare ad usare cose come my MergeAdapter, o varie altre librerie di terze parti, per aiutare semplificare questo

+0

Grazie, proverò con la tua libreria, anche se sembra molto lavoro per qualcosa che ritiene che dovrebbe esserci di default lì. Se conoscete altri tutorial su come ciò possa essere realizzato, vi sarò molto grato. –

+1

@IonutNegru: una semplice ricerca su 'intestazioni di sezioni android listview' nel tuo motore di ricerca preferito mostrerà molte pagine, incluse le librerie (come http://code.google.com/p/android-amazing-listview/), Domande StackOverflow (come http://stackoverflow.com/questions/7943802/how-to-draw-a-section-header-in-android-listview-just-like-the-ioss-uitableview), tutorial/ricette (come http://androidcookbook.com/Recipe.seam?recipeId=992) e altro ancora. – CommonsWare

0

Se le voci dell'elenco sono fisse (non modificabili), un "trucco" rapido consiste nell'includere un interruttore per "posizione" nel metodo getView() dell'adattatore e gonfiare un headerlayout.xml in quelle posizioni fisse. La tua inflazione regolare andrà nella parte predefinita del caso switch. È sporco e non raccomandato ma efficace.

+0

Vorrei evitare questo tipo di hack perché sarà difficile modificarlo in futuro (se sarà necessario). Ma grazie per il suggerimento. –

0

Suggerirei di estendere EntryItem aggiungendo un membro tag che indica quale tipo di frammento creare. Quindi è sufficiente controllare il tag nel gestore onItemClick per creare il tipo corretto di frammento. In questo modo non sei dipendente dalla posizione, che può cambiare man mano che aggiungi/rimuovi elementi nelle sezioni.

0

È necessario aggiungere questo alla classe EntryAdapter:

@Override 
public boolean areAllItemsEnabled() { 
    return false; 
} 

con quello, e:

@Override 
public boolean isEnabled(int position) { 
    return !getItem(position).isSection(); 
} 

sezioni non devono assumere una posizione sul ListView.

0

Una buona soluzione che ho letto è stata posizionare un'intestazione TextView all'interno del file di layout di riga e impostarne la visibilità su GONE.

Quindi nell'adattatore getView, è presente una logica che dice: È questo il primo elemento nell'elenco (posizione 0), O il tipo di questa voce è diverso dal tipo una posizione sopra di esso? In tal caso, attivare la visibilità dell'intestazione TextView's su VISIBLE.

In questo modo viene preferito perché quando si desidera utilizzare getItemAtPosition, non c'è bisogno di capire come schivare le vostre intestazioni di sezione come avrebbero preso un intero posizione se li implementato il modo in cui l'OP e altri suggerito .

1

Ecco una complete example di navigazione cassetto usando intestazioni/sezioni

Questo è il risultato

enter image description here

Problemi correlati