标签:
先上效果图:
实现思路:
1.先说右边标题:
首先,右边的数据源集合中的Javabean中含有三个属性name,type,title,而每个条目中会默认含有一个标题.
如果这是第一个条目,就让标题显示出来,再如果这个条目的类型和上一个条目的类型不一样,就让这个条目的标题显示出来,否则,就隐藏标题, 这样我们就做到了每种类型只有第一个数据标题显示出来
接着,在Listview的外层(也就是MainActivity的布局文件中),默认放一个标题(下面都称作是主标题)
最后,设置右边Listview的滚动监听事件 在onScroll方法中,我们要做两件事:
第一件事是每当前第一个可见条目的类型和当前左边Listview选择的类型(红色字体的类型) 不一样时,需要将主标题的内容改变
第二件事 同时切换左边Listview的选中状态
2.再说左边的Listview
左边的Listview需要设置条目点击事件,在点击事件中需要干三件事:
第一 将左边点击条目的字体颜色改变
第二 将右边Listview滚动至左边Listview所选择类型相同的区域
第三 改变主标题的内容
说到这,大家可能还是云里雾里的,还是不知道左边的类型和右边的类型是怎么关联起来的?没关系,在下面的代码解析中你就会明白!下边是具体的实现步骤:
一.写布局
1.在MainActivity的布局文件中 添加应有的控件
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布局文件
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
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
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
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.初始化数据
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的注解
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的滚动监听事件
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的点击事件
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方法
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.csdn.net/detail/jeff169/9520261
PS:要是使用网络解析的数据, 可以再加点代码;
首先创建一个数组:
private ArrayList<Object> data=new ArrayList<Object>();
再添加一个更新数据源的代码:
public void updateData(ArrayList<Object> data){
this.data.clear();
this.data.addAll(data);
notifyDatasetChanged();
}
最后在需要更新数据的时候调适配器的updateData这个方法。
注意里边的Object改成你解析的实体类!
仿美团外卖,饿了吗 两个ListView联动,左边点击切换右边,右边滑动切换左边
标签:
原文地址:http://www.cnblogs.com/huolongluo/p/5797776.html