导航抽屉:在列表视图中添加标题

15

我已经使用新的导航抽屉对象创建了一个项目。

我想自定义菜单布局,添加另一个对象,如TextView、ImageView等。首先,我想修改默认布局,该布局仅由一个ListView组成,通过在ListView中添加2或3个标题来进行修改。

今天,我尝试使用"addHeaderView",但我认为只能将其用于添加一个标题。

如何添加头文件并真正自定义我的布局菜单?因为从开发者API来看,似乎在"android.support.v4.widget.DrawerLayout"下只允许两个子元素。

这是我今天布局的截图:

Navigation Drawer Headers in listview

这是我想创建的截图:

Navigation Drawer Headers in listview

这是我的MainActivity代码片段:

public class MainActivity extends Activity {
private DrawerLayout mDrawerLayout;
private ListView mDrawerList;
private ActionBarDrawerToggle mDrawerToggle;

private CharSequence mDrawerTitle;
private CharSequence mTitle;
private String[] mPlanetTitles;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mTitle = mDrawerTitle = getTitle();
    mPlanetTitles = getResources().getStringArray(R.array.planets_array);
    mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);

    // Declaration of the 2 listview's 
    mDrawerList = (ListView) findViewById(R.id.dernieres_news);

    LayoutInflater inflater = getLayoutInflater();

    // Add header news title
    ViewGroup header_news = (ViewGroup)inflater.inflate(R.layout.header_dernieres_news, mDrawerList, false);
    mDrawerList.addHeaderView(header_news, null, false);

    // set a custom shadow that overlays the main content when the drawer opens
    mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);

    String[] names=new String[]{"Title 1", "Title 2", "Title 3", "Title 4", "Title 5"};

    /*Array of Images*/
    int[] image = new int[] {R.drawable.ic_action_feed, R.drawable.ic_action_feed, R.drawable.ic_action_feed, R.drawable.ic_action_feed, R.drawable.ic_action_feed};

    List<HashMap<String, String>> listinfo = new ArrayList<HashMap<String, String>>();
    listinfo.clear();
    for(int i=0;i<5;i++){
        HashMap<String, String> hm = new HashMap<String, String>();
        hm.put("name", names[i]);
        hm.put("image", Integer.toString(image[i]));
        listinfo.add(hm);
    }

    // Keys used in Hashmap
    String[] from = { "image", "name" };
    int[] to = { R.id.img, R.id.txt };
    SimpleAdapter adapter = new SimpleAdapter(getBaseContext(), listinfo, R.layout.drawer_list_item, from, to);
    mDrawerList.setAdapter(adapter);

    mDrawerList.setOnItemClickListener(new DrawerItemClickListener());

    // enable ActionBar app icon to behave as action to toggle nav drawer
    getActionBar().setDisplayHomeAsUpEnabled(true);
    getActionBar().setHomeButtonEnabled(true);

    // ActionBarDrawerToggle ties together the the proper interactions
    // between the sliding drawer and the action bar app icon
    mDrawerToggle = new ActionBarDrawerToggle(
            this,                  /* host Activity */
            mDrawerLayout,         /* DrawerLayout object */
            R.drawable.ic_drawer,  /* nav drawer image to replace 'Up' caret */
            R.string.drawer_open,  /* "open drawer" description for accessibility */
            R.string.drawer_close  /* "close drawer" description for accessibility */
            ) {
        public void onDrawerClosed(View view) {
            getActionBar().setTitle(mTitle);
            invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
        }

        public void onDrawerOpened(View drawerView) {
            getActionBar().setTitle(mDrawerTitle);
            invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
        }
    };
    mDrawerLayout.setDrawerListener(mDrawerToggle);

    if (savedInstanceState == null) {
        selectItem(0);
    }
}

以及 activity_main.xml 的代码:

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<FrameLayout
    android:id="@+id/content_frame"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />


    <ListView
        android:id="@+id/dernieres_news"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="#F3F3F4"
        android:choiceMode="singleChoice"
        android:divider="#E3E9E3"
        android:dividerHeight="1dp" />

int[] to = { R.id.img, R.id.txt }; 这个定义在哪里了? - DroidLearner
3个回答

8
您可以像在任何其他的ListView中添加标题一样来完成这个操作,通过让您的ListAdapter返回标题行和详细信息行。在低层次上,这涉及到重写您的ListAdapter中的方法,例如getViewTypeCount()getItemViewType(),并且getView()需要知道行类型的区别。或者,使用现有的高级实现,例如https://github.com/emilsjolander/StickyListHeadershttp://code.google.com/p/android-amazing-listview/,或任何在搜索android listview headers时找到的其他库。

那么你不能使用除了ListView之外的其他东西吗?(比如一个带有3个按钮的布局) - Thomas Decaux
@ThomasDecaux:那会违反设计指南。虽然SurfaceView可能会有问题,但没有任何阻止您在其中放置任何内容的限制。 - CommonsWare

8
其他回答是正确的。我找到了一个非常好的示例,可以自定义视图以包含两种类型的项:菜单部分和菜单项。当然,您可以根据需要更改它。该示例还包含一个抽象活动类的实现,每个拥有导航抽屉的活动都会从这个类继承。请查看http://www.michenux.net/android-navigation-drawer-748.html

1
您需要子类化BaseAdapter并在ListView中使用它,而不是SimpleAdapter。
您需要向适配器提供填充数据,其中额外的数据是标题。标题和列表项本身将成为同一个公共类的成员。然后,在适配器中,根据数据项决定实际视图是标题还是项目,并相应地膨胀它。
更新:
这里有一个很好的例子: http://w2davids.wordpress.com/android-sectioned-headers-in-listviews/ 这实际上将标题与数据项分开,并正确使用了convertView,与我之前应用程序中使用的解决方案不同。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接