> Android在线手册 > 【Android 界面效果33】二级listview列表

今天来实现以下大众点评客户端的横向listview二级列表,先看一下样式。

【Android 界面效果33】二级listview列表

这种横向的listview二级列表在手机软件上还不太常见,但是使用过平板的都应该知道,在平板上市比较常见的。可能是因为平板屏幕比较大,而且也能展现更多的内容。

下面来看一下我的实现步骤。

首先自定义一个listview,代码如下:

[HTML] view plaincopy
  1. public class MyListView extends ListView implements Runnable {
  2. private float mLastDownY = 0f;
  3. private int mDistance = 0;
  4. private int mStep = 10;
  5. private boolean mPositive = false;
  6. public MyListView (Context context, AttributeSet attrs) {
  7. super(context, attrs);
  8. }
  9. public MyListView (Context context, AttributeSet attrs, int defStyle) {
  10. super(context, attrs, defStyle);
  11. }
  12. public MyListView (Context context) {
  13. super(context);
  14. }
  15. @Override
  16. public boolean onTouchEvent(MotionEvent event) {
  17. switch (event.getAction()) {
  18. case MotionEvent.ACTION_DOWN:
  19. if (mLastDownY == 0f && mDistance == 0) {
  20. mLastDownY = event.getY();
  21. return true;
  22. }
  23. break;
  24. case MotionEvent.ACTION_CANCEL:
  25. break;
  26. case MotionEvent.ACTION_UP:
  27. if (mDistance != 0) {
  28. mStep = 1;
  29. mPositive = (mDistance >= 0);
  30. this.post(this);
  31. return true;
  32. }
  33. mLastDownY = 0f;
  34. mDistance = 0;
  35. break;
  36. case MotionEvent.ACTION_MOVE:
  37. if (mLastDownY != 0f) {
  38. mDistance = (int) (mLastDownY - event.getY());
  39. if ((mDistance < 0 && getFirstVisiblePosition() == 0 && getChildAt(0).getTop() == 0) || (mDistance > 0 && getLastVisiblePosition() == getCount() - 1)) {
  40. mDistance /= 2;
  41. scrollTo(0, mDistance);
  42. return true;
  43. }
  44. }
  45. mDistance = 0;
  46. break;
  47. }
  48. return super.onTouchEvent(event);
  49. }
  50. public void run() {
  51. mDistance += mDistance > 0 ? -mStep : mStep;
  52. scrollTo(0, mDistance);
  53. if ((mPositive && mDistance <= 0) || (!mPositive && mDistance >= 0)) {
  54. scrollTo(0, 0);
  55. mDistance = 0;
  56. mLastDownY = 0f;
  57. return;
  58. }
  59. mStep += 1;
  60. this.postDelayed(this, 10);
  61. }
  62. }

然后看一下xml的布局:

[html] view plaincopy
  1. <LinearLayout xmlns:android="Http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:orientation="horizontal"
  4. android:layout_width="fill_parent"
  5. android:layout_height="fill_parent" >
  6. <com.example.multilistview.MyListView
  7. android:id="@+id/listView"
  8. android:layout_width="wrap_content"
  9. android:layout_height="wrap_content"
  10. android:layout_weight="1"
  11. android:choiceMode="singleChoice"
  12. android:scrollbars="none"
  13. android:divider="@drawable/listitem_divide"
  14. android:listSelector="#00000000"
  15. android:background="#e4e3De"
  16. >
  17. </com.example.multilistview.MyListView>
  18. <com.example.multilistview.MyListView
  19. android:id="@+id/subListView"
  20. android:layout_width="wrap_content"
  21. android:layout_height="wrap_content"
  22. android:layout_weight="1"
  23. android:background="#e4e3de"
  24. >
  25. </com.example.multilistview.MyListView>
  26. </LinearLayout>


两个自定义的listview 横向布局,然后是父listview的适配器

[html] view plaincopy
  1. public class MyAdapter extends BaseAdapter {
  2. Context context;
  3. LayoutInflater inflater;
  4. String [] foods;
  5. int last_item;
  6. int [] images;
  7. private int selectedPosition = -1;
  8. public MyAdapter(Context context,String [] foods,int[] images){
  9. this.context = context;
  10. this.foods = foods;
  11. this.images = images;
  12. inflater=LayoutInflater.from(context);
  13. }
  14. @Override
  15. public int getCount() {
  16. // TODO Auto-generated method stub
  17. return foods.length;
  18. }
  19. @Override
  20. public Object getItem(int position) {
  21. // TODO Auto-generated method stub
  22. return position;
  23. }
  24. @Override
  25. public long getItemId(int position) {
  26. // TODO Auto-generated method stub
  27. return position;
  28. }
  29. @Override
  30. public View getView(int position, View convertView, ViewGroup parent) {
  31. // TODO Auto-generated method stub
  32. ViewHolder holder = null;
  33. if(convertView==null){
  34. convertView = inflater.inflate(R.layout.mylist_item, null);
  35. holder = new ViewHolder();
  36. holder.textView =(TextView)convertView.findViewById(R.id.textview);
  37. holder.imageView =(ImageView)convertView.findViewById(R.id.imageview);
  38. holder.layout=(LinearLayout)convertView.findViewById(R.id.colorlayout);
  39. convertView.setTag(holder);
  40. }
  41. else{
  42. holder=(ViewHolder)convertView.getTag();
  43. }
  44. // 设置选中效果
  45. if(selectedPosition == position)
  46. {
  47. holder.textView.setTextColor(Color.BLUE);
  48. holder.layout.setBackgroundColor(Color.LTGRAY);
  49. } else {
  50. holder.textView.setTextColor(Color.WHITE);
  51. holder.layout.setBackgroundColor(Color.TRANSPARENT);
  52. }
  53. holder.textView.setText(foods[position]);
  54. holder.textView.setTextColor(Color.BLACK);
  55. holder.imageView.setBackgroundResource(images[position]);
  56. return convertView;
  57. }
  58. public static class ViewHolder{
  59. public TextView textView;
  60. public ImageView imageView;
  61. public LinearLayout layout;
  62. }
  63. public void setSelectedPosition(int position) {
  64. selectedPosition = position;
  65. }
  66. }

对应的 item布局:

[html] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:id="@+id/colorlayout"
  4. android:layout_width="fill_parent"
  5. android:layout_height="fill_parent" >
  6. <ImageView
  7. android:id="@+id/imageview"
  8. android:layout_width="wrap_content"
  9. android:layout_height="wrap_content"
  10. android:layout_marginLeft="10dip"
  11. android:layout_marginTop="5dip"
  12. />
  13. <TextView
  14. android:id="@+id/textview"
  15. android:layout_width="wrap_content"
  16. android:layout_height="wrap_content"
  17. android:text=""
  18. android:textSize="16dip"
  19. android:layout_marginTop="8dip"
  20. android:layout_marginLeft="8dip"
  21. android:layout_marginBottom="8dip"/>
  22. <!-- android:background="@drawable/selector" 自定义listview 样式-->
  23. </LinearLayout>


然后是子适配器代码:

[html] view plaincopy
  1. public class SubAdapter extends BaseAdapter {
  2. Context context;
  3. LayoutInflater layoutInflater;
  4. String[][] cities;
  5. public int foodpoition;
  6. public SubAdapter(Context context, String[][] cities,int position) {
  7. this.context = context;
  8. this.cities = cities;
  9. layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  10. this.foodpoition = position;
  11. }
  12. @Override
  13. public int getCount() {
  14. // TODO Auto-generated method stub
  15. return cities.length;
  16. }
  17. @Override
  18. public Object getItem(int position) {
  19. // TODO Auto-generated method stub
  20. return getItem(position);
  21. }
  22. @Override
  23. public long getItemId(int position) {
  24. // TODO Auto-generated method stub
  25. return position;
  26. }
  27. @Override
  28. public View getView(int position, View convertView, ViewGroup parent) {
  29. // TODO Auto-generated method stub
  30. ViewHolder viewHolder = null;
  31. final int location=position;
  32. if (convertView == null) {
  33. convertView = layoutInflater.inflate(R.layout.sublist_item, null);
  34. viewHolder = new ViewHolder();
  35. viewHolder.textView = (TextView) convertView
  36. .findViewById(R.id.textview1);
  37. convertView.setTag(viewHolder);
  38. } else {
  39. viewHolder = (ViewHolder) convertView.getTag();
  40. }
  41. viewHolder.textView.setText(cities[foodpoition][position]);
  42. viewHolder.textView.setTextColor(Color.BLACK);
  43. return convertView;
  44. }
  45. public static class ViewHolder {
  46. public TextView textView;
  47. }
  48. }


对应的xml布局:

[html] view plaincopy
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="wrap_content"
  4. android:layout_height="wrap_content"
  5. >
  6. <TextView
  7. android:id="@+id/textview1"
  8. android:layout_width="wrap_content"
  9. android:layout_height="wrap_content"
  10. android:text="aaaaa"
  11. android:textSize="16dip"
  12. android:layout_marginTop="10dip"
  13. android:layout_marginLeft="8dip"
  14. android:layout_marginBottom="8dip"/>
  15. </LinearLayout>


最后看下主activity的实现代码

[html] view plaincopy
  1. public class MainActivity extends Activity {
  2. private MyListView listView;
  3. private MyListView subListView;
  4. private MyAdapter myAdapter;
  5. private SubAdapter subAdapter;
  6. String cities[][] = new String[][] {
  7. new String[] {"全部美食", "本帮江浙菜", "川菜", "粤菜", "湘菜","东北菜","台湾菜","新疆/清真","素菜","火锅","自助餐","小吃快餐","日本","韩国料理",
  8. "东南亚菜","西餐","面包甜点","其他"},
  9. new String[] {"全部休闲娱乐","咖啡厅","酒吧","茶馆","KTV","电影院","游乐游艺","公园","景点/郊游","洗浴","足浴按摩","文化艺术",
  10. "DIY手工坊","桌球馆","桌面游戏","更多休闲娱乐"},
  11. new String[] {"全部购物", "综合商场", "服饰鞋包", "运动户外","珠宝饰品","化妆品","数码家电","亲子购物","家居建材"
  12. ,"书店","书店","眼镜店","特色集市","更多购物场所","食品茶酒","超市/便利店","药店"},
  13. new String[] {"全部休闲娱乐","咖啡厅","酒吧","茶馆","KTV","电影院","游乐游艺","公园","景点/郊游","洗浴","足浴按摩","文化艺术",
  14. "DIY手工坊","桌球馆","桌面游戏","更多休闲娱乐"},
  15. new String[] {"全","咖啡厅","酒吧","茶馆","KTV","游乐游艺","公园","景点/郊游","洗浴","足浴按摩","文化艺术",
  16. "DIY手工坊","桌球馆","桌面游戏","更多休闲娱乐"},
  17. new String[] {"全部","咖啡厅","酒吧","茶馆","电影院","游乐游艺","公园","景点/郊游","洗浴","足浴按摩","文化艺术",
  18. "DIY手工坊","桌球馆","桌面游戏","更多休闲娱乐"},
  19. new String[] {"全部休","咖啡厅","酒吧","茶馆","KTV","电影院","游乐游艺","公园","景点/郊游","洗浴","足浴按摩","文化艺术",
  20. "DIY手工坊","桌球馆","桌面游戏","更多休闲娱乐"},
  21. new String[] {"全部休闲","咖啡厅","酒吧","茶馆","KTV","电影院","游乐游艺","公园","景点/郊游","洗浴","足浴按摩","文化艺术",
  22. "DIY手工坊","桌球馆","桌面游戏","更多休闲娱乐"},
  23. new String[] {"全部休闲娱","咖啡厅","酒吧","茶馆","KTV","电影院","游乐游艺","公园","景点/郊游","洗浴","足浴按摩","文化艺术",
  24. "DIY手工坊","桌球馆","桌面游戏"},
  25. new String[] {"全部休闲娱乐","咖啡厅","酒吧","茶馆","KTV","电影院","游乐游艺","公园","景点/郊游","洗浴","足浴按摩","文化艺术",
  26. "DIY手工坊","桌球馆","桌面游戏","更多休闲娱乐"},
  27. new String[] {"全部休闲aaa","咖啡厅","酒吧","茶馆","KTV","电影院","游乐游艺","公园","景点/郊游","洗浴","足浴按摩","文化艺术",
  28. "DIY手工坊","桌球馆","桌面游戏"},
  29. };
  30. String foods[] =new String []{"全部频道","美食","休闲娱乐","购物","酒店","丽人","运动健身","结婚","亲子","爱车","生活服务"};
  31. int images[] = new int[]{R.drawable.ic_category_0,R.drawable.ic_category_10,R.drawable.ic_category_30,R.drawable.ic_category_20
  32. ,R.drawable.ic_category_60,R.drawable.ic_category_50,R.drawable.ic_category_45,R.drawable.ic_category_50,R.drawable.ic_category_70,
  33. R.drawable.ic_category_65,R.drawable.ic_category_80};
  34. @Override
  35. public void onCreate(Bundle savedInstanceState) {
  36. super.onCreate(savedInstanceState);
  37. setContentView(R.layout.activity_main);
  38. init();
  39. myAdapter=new MyAdapter(getApplicationContext(), foods, images);
  40. listView.setAdapter(myAdapter);
  41. selectDefult();
  42. listView.setOnItemClickListener(new OnItemClickListener() {
  43. @Override
  44. public void onItemClick(AdapterView<?> arg0, View arg1, int position,
  45. long arg3) {
  46. // TODO Auto-generated method stub
  47. final int location=position;
  48. myAdapter.setSelectedPosition(position);
  49. myAdapter.notifyDataSetInvalidated();
  50. subAdapter=new SubAdapter(getApplicationContext(), cities, position);
  51. subListView.setAdapter(subAdapter);
  52. subListView.setOnItemClickListener(new OnItemClickListener() {
  53. @Override
  54. public void onItemClick(AdapterView<?> arg0, View arg1,
  55. int position, long arg3) {
  56. // TODO Auto-generated method stub
  57. Toast.makeText(getApplicationContext(), cities[location][position], Toast.LENGTH_SHORT).show();
  58. }
  59. });
  60. }
  61. });
  62. }
  63. private void init(){
  64. listView=(MyListView) findViewById(R.id.listView);
  65. subListView=(MyListView) findViewById(R.id.subListView);
  66. }
  67. private void selectDefult(){
  68. final int location=0;
  69. myAdapter.setSelectedPosition(0);
  70. myAdapter.notifyDataSetInvalidated();
  71. subAdapter=new SubAdapter(getApplicationContext(), cities, 0);
  72. subListView.setAdapter(subAdapter);
  73. subListView.setOnItemClickListener(new OnItemClickListener() {
  74. @Override
  75. public void onItemClick(AdapterView<?> arg0, View arg1,
  76. int position, long arg3) {
  77. // TODO Auto-generated method stub
  78. Toast.makeText(getApplicationContext(), cities[location][position], Toast.LENGTH_SHORT).show();
  79. }
  80. });
  81. }
  82. }


默认我选中了第0个,下面看一下运行效果:

【Android 界面效果33】二级listview列表



代码下载地址:点击打开链接