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

论坛 期权论坛 脚本     
匿名技术用户   2021-1-2 15:05   11   0

先上效果图:


实现思路:

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. <ListView
  8. android:id="@+id/lv_left"
  9. android:layout_width="0dp"
  10. android:layout_height="match_parent"
  11. android:layout_weight="1" >
  12. </ListView>
  13. <RelativeLayout
  14. android:layout_width="0dp"
  15. android:layout_height="match_parent"
  16. android:layout_weight="3" >
  17. <ListView
  18. android:id="@+id/lv_Right"
  19. android:layout_width="match_parent"
  20. android:layout_height="match_parent" >
  21. </ListView>
  22. <TextView
  23. android:id="@+id/tv_title"
  24. android:layout_width="match_parent"
  25. android:layout_height="wrap_content"
  26. android:background="#9f9f9f"
  27. android:gravity="center"
  28. android:padding="5dp"
  29. android:textColor="#000000"
  30. android:textSize="18sp" />
  31. </RelativeLayout>
  32. </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. <TextView
  9. android:id="@+id/tv_left"
  10. android:layout_width="wrap_content"
  11. android:layout_height="wrap_content"
  12. android:text="左边条目"
  13. android:textColor="#000000"
  14. android:textSize="18sp" />
  15. </LinearLayout></span>
  16. <span style="font-size:18px;">3.右边Listview的Item布局文件</span>
  17. <span style="font-size:14px;"><?xml version="1.0" encoding="utf-8"?>
  18. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  19. android:layout_width="match_parent"
  20. android:layout_height="wrap_content"
  21. android:background="#f9f9f9"
  22. android:gravity="center"
  23. android:orientation="vertical" >
  24. <TextView
  25. android:id="@+id/tv_right"
  26. android:layout_width="match_parent"
  27. android:layout_height="wrap_content"
  28. android:background="#9f9f9f"
  29. android:gravity="center"
  30. android:padding="5dp"
  31. android:text="右边条目"
  32. android:textColor="#000000"
  33. android:textSize="18sp" />
  34. <LinearLayout
  35. android:layout_width="match_parent"
  36. android:layout_height="90dp"
  37. android:gravity="center_vertical"
  38. android:orientation="horizontal" >
  39. <ImageView
  40. android:layout_width="80dp"
  41. android:layout_height="80dp"
  42. android:background="@drawable/jipai" />
  43. <TextView
  44. android:id="@+id/tv_content"
  45. android:layout_width="wrap_content"
  46. android:layout_height="wrap_content"
  47. android:layout_marginLeft="50dp"
  48. android:text="左边条目"
  49. android:textColor="#000000"
  50. android:textSize="18sp" />
  51. </LinearLayout>
  52. </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. public BaseData(String name, int type, String title) {
  6. super();
  7. this.name = name;
  8. this.type = type;
  9. this.title = title;
  10. }
  11. public BaseData() {
  12. super();
  13. }
  14. public String getTitle() {
  15. return title;
  16. }
  17. public void setTitle(String title) {
  18. this.title = title;
  19. }
  20. public String getName() {
  21. return name;
  22. }
  23. public void setName(String name) {
  24. this.name = name;
  25. }
  26. public int getType() {
  27. return type;
  28. }
  29. public void setType(int type) {
  30. this.type = type;
  31. }
  32. }</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. private Context context;
  8. String data[]={"蔬菜1","水果1","姓氏1","蔬菜2","水果2","姓氏2","蔬菜3","水果3","姓氏3"};
  9. public LeftAdapter(Context context) {
  10. super();
  11. this.context = context;
  12. }
  13. @Override
  14. public int getCount() {
  15. return data.length;
  16. }
  17. @Override
  18. public Object getItem(int position) {
  19. return null;
  20. }
  21. @Override
  22. public long getItemId(int position) {
  23. return 0;
  24. }
  25. @Override
  26. public View getView(final int position, View convertView, ViewGroup parent) {
  27. ViewHold vh = null;
  28. if (convertView == null) {
  29. convertView = View.inflate(context, R.layout.item_left, null);
  30. vh = new ViewHold();
  31. convertView.setTag(vh);
  32. vh.tv_left = (TextView) convertView.findViewById(R.id.tv_left);
  33. } else {
  34. vh = (ViewHold) convertView.getTag();
  35. }
  36. vh.tv_left.setTag(position);
  37. vh.tv_left.setText(data[position]);
  38. return convertView;
  39. }
  40. public class ViewHold {
  41. TextView tv_left;
  42. }
  43. }</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. public RightAdapter(Context context) {
  11. super();
  12. this.context = context;
  13. }
  14. /**
  15. * 这个方法是用来更新数据源
  16. *
  17. * @param context
  18. */
  19. public void updateData(ArrayList<BaseData> lists) {
  20. data.clear();
  21. data.addAll(lists);
  22. this.notifyDataSetChanged();
  23. }
  24. @Override
  25. public int getCount() {
  26. // TODO Auto-generated method stub
  27. return data.size();
  28. }
  29. @Override
  30. public Object getItem(int position) {
  31. return null;
  32. }
  33. @Override
  34. public long getItemId(int position) {
  35. // TODO Auto-generated method stub
  36. return 0;
  37. }
  38. @Override
  39. public View getView(int position, View convertView, ViewGroup parent) {
  40. ViewHold vh = null;
  41. if (convertView == null) {
  42. convertView = View.inflate(context, R.layout.item_right, null);
  43. vh = new ViewHold();
  44. convertView.setTag(vh);
  45. vh.tv_content = (TextView) convertView
  46. .findViewById(R.id.tv_content);
  47. vh.tv_right = (TextView) convertView.findViewById(R.id.tv_right);
  48. } else {
  49. vh = (ViewHold) convertView.getTag();
  50. }
  51. vh.tv_content.setText(data.get(position).getName());
  52. if (position == 0) {//如果是第一个 需要显示标题
  53. vh.tv_right.setVisibility(View.VISIBLE);
  54. vh.tv_right.setText(data.get(position).getTitle());
  55. } else if (!TextUtils.equals(data.get(position).getTitle(),
  56. data.get(position - 1).getTitle())) {//如果这个标题和上一个不一样 也需要将标题显示出来
  57. vh.tv_right.setVisibility(View.VISIBLE);
  58. vh.tv_right.setText(data.get(position).getTitle());
  59. } else {
  60. vh.tv_right.setVisibility(View.GONE);
  61. }
  62. return convertView;
  63. }
  64. public class ViewHold {
  65. TextView tv_content;
  66. TextView tv_right;
  67. }
  68. }</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. //假数据创建的方式比较low,大家不喜勿喷
  39. //看下边这个集合,这个集合是右边所有要显示标题的条目的position
  40. ArrayList<String> showTitle = new ArrayList<String>();
  41. for (int i = 0; i < lists.size(); i++) {
  42. if (i == 0) {//第一个必须显示
  43. showTitle.add(i + "");
  44. } else if (!TextUtils.equals(lists.get(i).getTitle(),
  45. lists.get(i - 1).getTitle())) {//如果跟上一个条目的type不一样就必须显示
  46. showTitle.add(i + "");
  47. }
  48. }
  49. }
  50. //这个集合也就是就是左边和右边类型联系的桥梁</span>


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

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


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

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


4.左边Listview的点击事件

  1. <span style="font-size:14px;">lv_left.setOnItemClickListener(new OnItemClickListener() {
  2. @Override
  3. public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
  4. long arg3) {
  5. int firstVisibleItem = lv_Right.getFirstVisiblePosition();
  6. //右边Listview当前第一个可见条目的position
  7. updateLeftListview(firstVisibleItem, arg2);
  8. lv_Right.setSelection(Integer.parseInt(showTitle.get(arg2)));
  9. //arg2是点击(选择)左边条目的第几个
  10. //根据这个数字我们就能通过Integer.parseInt(showTitle.get(arg2))得到在点击左边后应该跳转到右边第几个条目
  11. // 通过etSelection方法跳转
  12. }
  13. });</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. tv_title.setText(lists.get(firstVisibleItem).getTitle());//将主标题的内容修改和firstVisibleItem的标题一样
  14. TextView lasTextView = (TextView) lv_left
  15. .findViewWithTag(lastPosition);
  16. if (lasTextView != null) {//在右边Listview第一次加载过程中会一直调用监听中的onscroll 这时的textView可能为空
  17. lasTextView.setTextColor(Color.BLACK);//先将上一个textView字体的颜色改成黑色
  18. }
  19. TextView currenTextView = (TextView) lv_left
  20. .findViewWithTag(currentPosition);
  21. if (currenTextView != null) {//再将当前要改变的extView字体的颜色改成红色
  22. currenTextView.setTextColor(Color.RED);
  23. }
  24. lastPosition = currentPosition;
  25. }
  26. }</span>


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

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


分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:7942463
帖子:1588486
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP