仿美团外卖,饿了吗 两个ListView联动,左边点击切换右边,右边滑动切换左边

先上效果图:

仿美团外卖,饿了吗 两个ListView联动,左边点击切换右边,右边滑动切换左边


仿美团外卖,饿了吗 两个ListView联动,左边点击切换右边,右边滑动切换左边

实现思路:

1.先说右边标题:

首先,右边的数据源集合中的Javabean中含有三个属性name,type,title,而每个条目中会默认含有一个标题.

如果这是第一个条目,就让标题显示出来,再如果这个条目的类型和上一个条目的类型不一样,就让这个条目的标题显示出来,否则,就隐藏标题,  这样我们就做到了每种类型只有第一个数据标题显示出来

接着,在Listview的外层(也就是MainActivity的布局文件中),默认放一个标题(下面都称作是主标题)

最后,设置右边Listview的滚动监听事件    在onScroll方法中,我们要做两件事:

     第一件事是每当前第一个可见条目的类型和当前左边Listview选择的类型(红色字体的类型) 不一样时,需要将主标题的内容改变

     第二件事  同时切换左边Listview的选中状态

2.再说左边的Listview

左边的Listview需要设置条目点击事件,在点击事件中需要干三件事:

第一  将左边点击条目的字体颜色改变

第二   将右边Listview滚动至左边Listview所选择类型相同的区域

第三  改变主标题的内容


说到这,大家可能还是云里雾里的,还是不知道左边的类型和右边的类型是怎么关联起来的?没关系,在下面的代码解析中你就会明白!下边是具体的实现步骤:

一.写布局

1.在MainActivity的布局文件中    添加应有的控件

[html] view plain copy
  1. <span style="font-size:14px;"><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:orientation="horizontal"  
  6.     tools:context=".MainActivity" >  
  7.   
  8.     <ListView  
  9.         android:id="@+id/lv_left"  
  10.         android:layout_width="0dp"  
  11.         android:layout_height="match_parent"  
  12.         android:layout_weight="1" >  
  13.     </ListView>  
  14.   
  15.     <RelativeLayout  
  16.         android:layout_width="0dp"  
  17.         android:layout_height="match_parent"  
  18.         android:layout_weight="3" >  
  19.   
  20.         <ListView  
  21.             android:id="@+id/lv_Right"  
  22.             android:layout_width="match_parent"  
  23.             android:layout_height="match_parent" >  
  24.         </ListView>  
  25.   
  26.         <TextView  
  27.             android:id="@+id/tv_title"  
  28.             android:layout_width="match_parent"  
  29.             android:layout_height="wrap_content"  
  30.             android:background="#9f9f9f"  
  31.             android:gravity="center"  
  32.             android:padding="5dp"  
  33.             android:textColor="#000000"  
  34.             android:textSize="18sp" />  
  35.     </RelativeLayout>  
  36.   
  37. </LinearLayout></span>  


注意   这里边将Listview和主标题textView放在一个相对布局中,并且先放Listview,后放textView,目的是将主标题放在Listview的空间的上方


2.左边Listview的Item布局文件

[html] view plain copy
  1. <span style="font-size:14px;"><?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="50dp"  
  5.     android:background="#f9f9f9"  
  6.     android:gravity="center"  
  7.     android:orientation="vertical" >  
  8.   
  9.     <TextView  
  10.         android:id="@+id/tv_left"  
  11.         android:layout_width="wrap_content"  
  12.         android:layout_height="wrap_content"  
  13.         android:text="左边条目"  
  14.         android:textColor="#000000"  
  15.         android:textSize="18sp" />  
  16.   
  17. </LinearLayout></span>  
  18.   
  19. <span style="font-size:18px;">3.右边Listview的Item布局文件</span>  
  20.   
  21. <span style="font-size:14px;"><?xml version="1.0" encoding="utf-8"?>  
  22. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  23.     android:layout_width="match_parent"  
  24.     android:layout_height="wrap_content"  
  25.     android:background="#f9f9f9"  
  26.     android:gravity="center"  
  27.     android:orientation="vertical" >  
  28.   
  29.     <TextView  
  30.         android:id="@+id/tv_right"  
  31.         android:layout_width="match_parent"  
  32.         android:layout_height="wrap_content"  
  33.         android:background="#9f9f9f"  
  34.         android:gravity="center"  
  35.         android:padding="5dp"  
  36.         android:text="右边条目"  
  37.         android:textColor="#000000"  
  38.         android:textSize="18sp" />  
  39.   
  40.     <LinearLayout  
  41.         android:layout_width="match_parent"  
  42.         android:layout_height="90dp"  
  43.         android:gravity="center_vertical"  
  44.         android:orientation="horizontal" >  
  45.   
  46.         <ImageView  
  47.             android:layout_width="80dp"  
  48.             android:layout_height="80dp"  
  49.             android:background="@drawable/jipai" />  
  50.   
  51.         <TextView  
  52.             android:id="@+id/tv_content"  
  53.             android:layout_width="wrap_content"  
  54.             android:layout_height="wrap_content"  
  55.             android:layout_marginLeft="50dp"  
  56.             android:text="左边条目"  
  57.             android:textColor="#000000"  
  58.             android:textSize="18sp" />  
  59.     </LinearLayout>  
  60.   
  61. </LinearLayout></span>  


二.创建Javabean

[java] view plain copy
  1. <span style="font-size:14px;">public class BaseData {  
  2.     private String name;  
  3.     private int type;// 类型 后边要根据类型显示标题  
  4.     private String title;//  
  5.   
  6.     public BaseData(String name, int type, String title) {  
  7.         super();  
  8.         this.name = name;  
  9.         this.type = type;  
  10.         this.title = title;  
  11.     }  
  12.   
  13.     public BaseData() {  
  14.         super();  
  15.     }  
  16.   
  17.     public String getTitle() {  
  18.         return title;  
  19.     }  
  20.   
  21.     public void setTitle(String title) {  
  22.         this.title = title;  
  23.     }  
  24.   
  25.     public String getName() {  
  26.         return name;  
  27.     }  
  28.   
  29.     public void setName(String name) {  
  30.         this.name = name;  
  31.     }  
  32.   
  33.     public int getType() {  
  34.         return type;  
  35.     }  
  36.   
  37.     public void setType(int type) {  
  38.         this.type = type;  
  39.     }  
  40.   
  41. }</span>  

三.创建两个adapter

1.左边Listview的adapter

[java] view plain copy
  1. <span style="font-size:14px;">/** 
  2.  * 左边的adapter   注意要给textview设置tag 
  3.  * @author HaiPeng 
  4.  * 
  5.  */  
  6. public class LeftAdapter extends BaseAdapter {  
  7.   
  8.     private Context context;  
  9.     String data[]={"蔬菜1","水果1","姓氏1","蔬菜2","水果2","姓氏2","蔬菜3","水果3","姓氏3"};  
  10.   
  11.     public LeftAdapter(Context context) {  
  12.         super();  
  13.         this.context = context;  
  14.     }  
  15.   
  16.     @Override  
  17.     public int getCount() {  
  18.         return data.length;  
  19.     }  
  20.   
  21.     @Override  
  22.     public Object getItem(int position) {  
  23.         return null;  
  24.     }  
  25.   
  26.     @Override  
  27.     public long getItemId(int position) {  
  28.         return 0;  
  29.     }  
  30.   
  31.     @Override  
  32.     public View getView(final int position, View convertView, ViewGroup parent) {  
  33.         ViewHold vh = null;  
  34.         if (convertView == null) {  
  35.             convertView = View.inflate(context, R.layout.item_left, null);  
  36.             vh = new ViewHold();  
  37.             convertView.setTag(vh);  
  38.             vh.tv_left = (TextView) convertView.findViewById(R.id.tv_left);  
  39.         } else {  
  40.             vh = (ViewHold) convertView.getTag();  
  41.         }  
  42.         vh.tv_left.setTag(position);  
  43.         vh.tv_left.setText(data[position]);  
  44.         return convertView;  
  45.     }  
  46.   
  47.     public class ViewHold {  
  48.         TextView tv_left;  
  49.           
  50.     }  
  51. }</span>  

2.右边Listview的adapter

[java] view plain copy
  1. <span style="font-size:14px;">/** 
  2.  * 右边listview的adapter 
  3.  * 
  4.  * @author HaiPeng 
  5.  * 
  6.  */  
  7. public class RightAdapter extends BaseAdapter {  
  8.     private Context context;  
  9.     private ArrayList<BaseData> data = new ArrayList<BaseData>();  
  10.   
  11.     public RightAdapter(Context context) {  
  12.         super();  
  13.         this.context = context;  
  14.     }  
  15.   
  16.     /** 
  17.      * 这个方法是用来更新数据源 
  18.      * 
  19.      * @param context 
  20.      */  
  21.   
  22.     public void updateData(ArrayList<BaseData> lists) {  
  23.         data.clear();  
  24.         data.addAll(lists);  
  25.         this.notifyDataSetChanged();  
  26.     }  
  27.   
  28.     @Override  
  29.     public int getCount() {  
  30.         // TODO Auto-generated method stub  
  31.         return data.size();  
  32.     }  
  33.   
  34.     @Override  
  35.     public Object getItem(int position) {  
  36.   
  37.         return null;  
  38.     }  
  39.   
  40.     @Override  
  41.     public long getItemId(int position) {  
  42.         // TODO Auto-generated method stub  
  43.         return 0;  
  44.     }  
  45.   
  46.     @Override  
  47.     public View getView(int position, View convertView, ViewGroup parent) {  
  48.         ViewHold vh = null;  
  49.         if (convertView == null) {  
  50.             convertView = View.inflate(context, R.layout.item_right, null);  
  51.             vh = new ViewHold();  
  52.             convertView.setTag(vh);  
  53.             vh.tv_content = (TextView) convertView  
  54.                     .findViewById(R.id.tv_content);  
  55.             vh.tv_right = (TextView) convertView.findViewById(R.id.tv_right);  
  56.         } else {  
  57.             vh = (ViewHold) convertView.getTag();  
  58.         }  
  59.         vh.tv_content.setText(data.get(position).getName());  
  60.         if (position == 0) {//如果是第一个  需要显示标题  
  61.             vh.tv_right.setVisibility(View.VISIBLE);  
  62.             vh.tv_right.setText(data.get(position).getTitle());  
  63.         } else if (!TextUtils.equals(data.get(position).getTitle(),  
  64.                 data.get(position - 1).getTitle())) {//如果这个标题和上一个不一样   也需要将标题显示出来  
  65.             vh.tv_right.setVisibility(View.VISIBLE);  
  66.             vh.tv_right.setText(data.get(position).getTitle());  
  67.         } else {  
  68.             vh.tv_right.setVisibility(View.GONE);  
  69.         }  
  70.         return convertView;  
  71.     }  
  72.   
  73.     public class ViewHold {  
  74.         TextView tv_content;  
  75.         TextView tv_right;  
  76.     }  
  77.   
  78. }</span>  


四.MainActivity中操作

1.初始化数据

[java] view plain copy
  1. <span style="font-size:14px;">private void initData() {  
  2.         lists = new ArrayList<BaseData>();  
  3.         String title[] = { "蔬菜1""水果1""姓氏1""蔬菜2""水果2""姓氏2""蔬菜3",  
  4.                 "水果3""姓氏3" };  
  5.         String name1[] = { "萝卜""大葱""茄子""大蒜""生姜""萝卜""大葱""茄子",  
  6.                 "大蒜""生姜""萝卜""大葱" };  
  7.         String name2[] = { "苹果""梨""香蕉""西瓜""橘子""大枣""菠萝""红提""葡萄",  
  8.                 "樱桃""椰子" };  
  9.         String name3[] = { "郑""王""伊""荆""汤""王""孙""李""钱""赵",  
  10.                 "祁""韦""宏" };  
  11.         for (int i = 0; i < name1.length; i++) {  
  12.             lists.add(new BaseData(name1[i] + 1, i, title[0]));  
  13.         }  
  14.         for (int i = 0; i < name2.length; i++) {  
  15.             lists.add(new BaseData(name2[i] + 1, i, title[1]));  
  16.         }  
  17.         for (int i = 0; i < name3.length; i++) {  
  18.             lists.add(new BaseData(name3[i] + 1, i, title[2]));  
  19.         }  
  20.         for (int i = 0; i < name1.length; i++) {  
  21.             lists.add(new BaseData(name1[i] + 2, i, title[3]));  
  22.         }  
  23.         for (int i = 0; i < name2.length; i++) {  
  24.             lists.add(new BaseData(name2[i] + 2, i, title[4]));  
  25.         }  
  26.         for (int i = 0; i < name3.length; i++) {  
  27.             lists.add(new BaseData(name3[i] + 2, i, title[5]));  
  28.         }  
  29.         for (int i = 0; i < name1.length; i++) {  
  30.             lists.add(new BaseData(name1[i] + 3, i, title[6]));  
  31.         }  
  32.         for (int i = 0; i < name2.length; i++) {  
  33.             lists.add(new BaseData(name2[i] + 3, i, title[7]));  
  34.         }  
  35.         for (int i = 0; i < name3.length; i++) {  
  36.             lists.add(new BaseData(name3[i] + 3, i, title[8]));  
  37.         }  
  38.   
  39. //假数据创建的方式比较low,大家不喜勿喷  
  40.   
  41. //看下边这个集合,这个集合是右边所有要显示标题的条目的position  
  42.   
  43.       ArrayList<String>  showTitle = new ArrayList<String>();  
  44.         for (int i = 0; i < lists.size(); i++) {  
  45.             if (i == 0) {//第一个必须显示  
  46.                 showTitle.add(i + "");  
  47.             } else if (!TextUtils.equals(lists.get(i).getTitle(),  
  48.                     lists.get(i - 1).getTitle())) {//如果跟上一个条目的type不一样就必须显示  
  49.                 showTitle.add(i + "");  
  50.             }  
  51.         }  
  52.     }  
  53.   
  54. //这个集合也就是就是左边和右边类型联系的桥梁</span>  


2.初始化布局,我用的xutils的注解

  

[java] view plain copy
  1. <span style="font-size:14px;"@ViewInject(R.id.lv_left)  
  2.     private ListView lv_left;  
  3.   
  4.     @ViewInject(R.id.lv_Right)  
  5.     private ListView lv_Right;  
  6.   
  7.     @ViewInject(R.id.tv_title)  
  8.     private TextView tv_title;  
  9.   
  10. //但不要忘记在onCreate方法ViewUtils.inject(this);  
  11.   
  12.         leftAdapter = new LeftAdapter(context);  
  13.         lv_left.setAdapter(leftAdapter);  
  14.   
  15.         rightAdapter = new RightAdapter(context);  
  16.         lv_Right.setAdapter(rightAdapter);  
  17.         rightAdapter.updateData(lists);// 将数据源传递给Listview  
  18.   
  19.         tv_title.setText(lists.get(0).getTitle());// 主标题栏设置默认初始值</span>  


3.先看右边的Listview的滚动监听事件

[java] view plain copy
  1. <span style="font-size:14px;">lv_Right.setOnScrollListener(new OnScrollListener() {  
  2.   
  3.             @Override  
  4.             public void onScroll(AbsListView view, int firstVisibleItem,  
  5.                     int visibleItemCount, int totalItemCount) {  
  6.                 int currentPosition = showTitle.indexOf(firstVisibleItem + "");//当前选中的一级条目的position    
  7.   
  8.                               //firstVisibleItem是右边Listview当前第一个可见条目的position   根据//showTitle.indexOf(firstVisibleItem + "")可以得到这个数字在showTitle集合中的排序(是第几个),而这个排序刚好就是  
  9.   
  10. //左边Listview当前所选中的条目的position 这样我们就能根据左边的类型判断右边的类型了  
  11.   
  12.             //  updateLeftListview(firstVisibleItem, currentPosition);//这个方法下面会说  是一个抽出来的方法   左边//Listview的点击事件也会用到  
  13.   
  14.             }  
  15.   
  16.             @Override  
  17.             public void onScrollStateChanged(AbsListView view, int scrollState) {  
  18.             }  
  19.   
  20.         });</span>  


4.左边Listview的点击事件

[java] view plain copy
  1. <span style="font-size:14px;">lv_left.setOnItemClickListener(new OnItemClickListener() {  
  2.   
  3.             @Override  
  4.             public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,  
  5.                     long arg3) {  
  6.                 int firstVisibleItem = lv_Right.getFirstVisiblePosition();     
  7.  //右边Listview当前第一个可见条目的position  
  8.                 updateLeftListview(firstVisibleItem, arg2);   
  9.                 lv_Right.setSelection(Integer.parseInt(showTitle.get(arg2)));   
  10. //arg2是点击(选择)左边条目的第几个     
  11. //根据这个数字我们就能通过Integer.parseInt(showTitle.get(arg2))得到在点击左边后应该跳转到右边第几个条目      
  12.  //  通过etSelection方法跳转     
  13.             }  
  14.         });</span>  


5.updateLeftListview方法


[java] view plain copy
  1.  <span style="font-size:14px;">   /** 
  2.      * 更新左边Listview字体颜色  并且更改主标题的内容 
  3.      * 
  4.      * @param firstVisibleItem 
  5.      *            右边当前第一个可见的条目position 
  6.      * @param currentPosition 
  7.      *            左边listview当前被点击或者要显示为红色的条目position 
  8.      */  
  9.     private void updateLeftListview(int firstVisibleItem, int currentPosition) {  
  10.         if (showTitle.contains(firstVisibleItem + "")) {//右边的Listview滑动到这firstVisibleItem这个条目时   
  11. // 而showTitle中包含firstVisibleItem  那么这个时候我们就需要将主标题的内容修改和firstVisibleItem的标题一样      
  12. // 并且左边Listview需要更改颜色的条目(点击需要更改或者右边滑动应该改变的textView)的字体颜色改变掉  
  13.   
  14.            tv_title.setText(lists.get(firstVisibleItem).getTitle());//将主标题的内容修改和firstVisibleItem的标题一样  
  15.             TextView lasTextView = (TextView) lv_left  
  16.                     .findViewWithTag(lastPosition);  
  17.             if (lasTextView != null) {//在右边Listview第一次加载过程中会一直调用监听中的onscroll  这时的textView可能为空  
  18.                 lasTextView.setTextColor(Color.BLACK);//先将上一个textView字体的颜色改成黑色  
  19.             }  
  20.             TextView currenTextView = (TextView) lv_left  
  21.                     .findViewWithTag(currentPosition);  
  22.             if (currenTextView != null) {//再将当前要改变的extView字体的颜色改成红色  
  23.                 currenTextView.setTextColor(Color.RED);  
  24.             }  
  25.             lastPosition = currentPosition;  
  26.   
  27.         }  
  28.     }</span>  


到这大家应该大概明白左边点击切换右边,右边滑动切换左边是怎么实现的了吧

  这里是源码的下载地址http://download.****.net/detail/jeff169/9520261