2013-06-18 157 views
11

我想知道是否有任何方法,我可以添加标题/部分导航抽屉。我设法添加类似的东西,但它只显示在列表顶部,因为addHeaderView需要在setAdapter之前调用,如果我尝试在setAdapter之后添加更多元素,它们将重写第一个元素。导航抽屉与标题/部分

谢谢。

编辑:

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

}

编辑:

我找到了一个很好的解决方案从不同的源相结合的解决方案,这是我使用的主要类型:

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

} 

项目

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

} 

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

但我有一个小问题:部分接受职位列表和片段的选择搞砸。

回答

1

在Navigation Drawer中,可以使用ListView显示项目列表,以便您可以拥有类适配器并实现您的逻辑。 所以你可以添加节,标题等。

+0

我怎样才能做到这一点抽屉式导航的complete example?我已经有一个BaseAdapter来填充列表(因为我为列表添加了图像和副标题)? 我在主帖中添加了适配器。 –

+0

只需实现一个自定义适配器并重写像getView等方法。 – FrancescoAzzola

+0

正如你所见,我已经这样做了,但你如何建议将标题添加到导航抽屉的列表? –

6

您将标头/节添加到ListView以便在DrawerLayout中使用,就像您将标头/节添加到ListView以用于Android内部其他任何位置一样。

在低的水平,这涉及一个ListAdapter在于:

  • 重写getViewTypeCount()从而指出有多少不同类型的行有(例如2,一个用于报头,一个用于定期行)

  • 重写getItemViewType()以指示要用于给定position

  • 哪一行型确保了CursorAdaptergetView()(或newView()/bindView())知道的多行类型和他们相应

处理在一个较高的水平,你可以尝试使用之类的东西my MergeAdapter,或其他各种第三方库,以帮助简化这一点。

+0

谢谢,我会试试你的图书馆,尽管对于那些认为它应该是默认设置的东西似乎有很多工作。 如果您知道其他教程如何实现这一目标,我将非常感激。 –

+1

@IonutNegru:在您最喜爱的搜索引擎中对“android listview section headers”的简单搜索会打开许多​​页面,包括库(如http://code.google.com/p/android-amazing-listview/), StackOverflow的问题(如http://stackoverflow.com/questions/7943802/how-to-draw-a-section-header-in-android-listview-just-like-the-ioss-uitableview),教程/食谱(如http://androidcookbook.com/Recipe.seam?recipeId=992)等。 – CommonsWare

0

如果您的列表项是固定的(不变),那么一个快速的“黑客攻击”就是在适配器的getView()方法中包含一个用于“位置”的开关盒,并在这些固定位置膨胀headerlayout.xml。您的定期通货膨胀将进入开关柜的默认部分。它很脏,不推荐,但有效。

+0

我想避免这种黑客攻击,因为将来很难进行修改(如果需要的话)。但谢谢你的提示。 –

0

我建议通过添加一个标记成员来告诉你要创建什么类型的片段来扩展EntryItem。然后只需检查onItemClick处理程序中的标记以创建正确类型的片段。这样,您不依赖于位置,可以在添加/删除部分中的项目时更改位置。

0

您需要将它添加到EntryAdapter类:

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

了,并且:

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

节不应该承担ListView控件的位置。

0

我读过的一个很好的解决方案是在您的行布局文件中放置一个标题TextView,并将其可见性设置为GONE

然后在你的适配器的getView,有一些逻辑说:这是列表中的第一个项目(位置0),OR是这个项目的类型不同于它上面的类型一个位置?如果是这样,将标题TextView's的可见性转到VISIBLE

这种方式是首选,因为当你想要使用getItemAtPosition时,你不必弄清楚如何避开部分标题,因为它们将占据整个位置,如果你按照OP和其他人的建议。

1

在这里,你可以选择使用页眉/段

这是结果

enter image description here