先上效果图:

实现思路:

1.先说右边标题:

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

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

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

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

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

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

2.再说左边的Listview

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

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

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

第三  改变主标题的内容

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

一.写布局

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

 <span style="font-size:14px;"><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
tools:context=".MainActivity" > <ListView
android:id="@+id/lv_left"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" >
</ListView> <RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3" > <ListView
android:id="@+id/lv_Right"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</ListView> <TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#9f9f9f"
android:gravity="center"
android:padding="5dp"
android:textColor="#000000"
android:textSize="18sp" />
</RelativeLayout> </LinearLayout></span>

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

2.左边Listview的Item布局文件

     <span style="font-size:14px;"><?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#f9f9f9"
android:gravity="center"
android:orientation="vertical" > <TextView
android:id="@+id/tv_left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="左边条目"
android:textColor="#000000"
android:textSize="18sp" /> </LinearLayout></span> <span style="font-size:18px;">3.右边Listview的Item布局文件</span> <span style="font-size:14px;"><?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#f9f9f9"
android:gravity="center"
android:orientation="vertical" > <TextView
android:id="@+id/tv_right"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#9f9f9f"
android:gravity="center"
android:padding="5dp"
android:text="右边条目"
android:textColor="#000000"
android:textSize="18sp" /> <LinearLayout
android:layout_width="match_parent"
android:layout_height="90dp"
android:gravity="center_vertical"
android:orientation="horizontal" > <ImageView
android:layout_width="80dp"
android:layout_height="80dp"
android:background="@drawable/jipai" /> <TextView
android:id="@+id/tv_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="50dp"
android:text="左边条目"
android:textColor="#000000"
android:textSize="18sp" />
</LinearLayout> </LinearLayout></span>

二.创建Javabean

     <span style="font-size:14px;">public class BaseData {
private String name;
private int type;// 类型 后边要根据类型显示标题
private String title;// public BaseData(String name, int type, String title) {
super();
this.name = name;
this.type = type;
this.title = title;
} public BaseData() {
super();
} public String getTitle() {
return title;
} public void setTitle(String title) {
this.title = title;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getType() {
return type;
} public void setType(int type) {
this.type = type;
} }</span>

三.创建两个adapter

1.左边Listview的adapter

     <span style="font-size:14px;">/**
* 左边的adapter 注意要给textview设置tag
* @author HaiPeng
*
*/
public class LeftAdapter extends BaseAdapter { private Context context;
String data[]={"蔬菜1","水果1","姓氏1","蔬菜2","水果2","姓氏2","蔬菜3","水果3","姓氏3"}; public LeftAdapter(Context context) {
super();
this.context = context;
} @Override
public int getCount() {
return data.length;
} @Override
public Object getItem(int position) {
return null;
} @Override
public long getItemId(int position) {
return 0;
} @Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHold vh = null;
if (convertView == null) {
convertView = View.inflate(context, R.layout.item_left, null);
vh = new ViewHold();
convertView.setTag(vh);
vh.tv_left = (TextView) convertView.findViewById(R.id.tv_left);
} else {
vh = (ViewHold) convertView.getTag();
}
vh.tv_left.setTag(position);
vh.tv_left.setText(data[position]);
return convertView;
} public class ViewHold {
TextView tv_left; }
}</span>

2.右边Listview的adapter

     <span style="font-size:14px;">/**
* 右边listview的adapter
*
* @author HaiPeng
*
*/
public class RightAdapter extends BaseAdapter {
private Context context;
private ArrayList<BaseData> data = new ArrayList<BaseData>(); public RightAdapter(Context context) {
super();
this.context = context;
} /**
* 这个方法是用来更新数据源
*
* @param context
*/ public void updateData(ArrayList<BaseData> lists) {
data.clear();
data.addAll(lists);
this.notifyDataSetChanged();
} @Override
public int getCount() {
// TODO Auto-generated method stub
return data.size();
} @Override
public Object getItem(int position) { return null;
} @Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHold vh = null;
if (convertView == null) {
convertView = View.inflate(context, R.layout.item_right, null);
vh = new ViewHold();
convertView.setTag(vh);
vh.tv_content = (TextView) convertView
.findViewById(R.id.tv_content);
vh.tv_right = (TextView) convertView.findViewById(R.id.tv_right);
} else {
vh = (ViewHold) convertView.getTag();
}
vh.tv_content.setText(data.get(position).getName());
if (position == 0) {//如果是第一个 需要显示标题
vh.tv_right.setVisibility(View.VISIBLE);
vh.tv_right.setText(data.get(position).getTitle());
} else if (!TextUtils.equals(data.get(position).getTitle(),
data.get(position - 1).getTitle())) {//如果这个标题和上一个不一样 也需要将标题显示出来
vh.tv_right.setVisibility(View.VISIBLE);
vh.tv_right.setText(data.get(position).getTitle());
} else {
vh.tv_right.setVisibility(View.GONE);
}
return convertView;
} public class ViewHold {
TextView tv_content;
TextView tv_right;
} }</span>

四.MainActivity中操作

1.初始化数据

     <span style="font-size:14px;">private void initData() {
lists = new ArrayList<BaseData>();
String title[] = { "蔬菜1", "水果1", "姓氏1", "蔬菜2", "水果2", "姓氏2", "蔬菜3",
"水果3", "姓氏3" };
String name1[] = { "萝卜", "大葱", "茄子", "大蒜", "生姜", "萝卜", "大葱", "茄子",
"大蒜", "生姜", "萝卜", "大葱" };
String name2[] = { "苹果", "梨", "香蕉", "西瓜", "橘子", "大枣", "菠萝", "红提", "葡萄",
"樱桃", "椰子" };
String name3[] = { "郑", "王", "伊", "荆", "汤", "王", "孙", "李", "钱", "赵",
"祁", "韦", "宏" };
for (int i = 0; i < name1.length; i++) {
lists.add(new BaseData(name1[i] + 1, i, title[0]));
}
for (int i = 0; i < name2.length; i++) {
lists.add(new BaseData(name2[i] + 1, i, title[1]));
}
for (int i = 0; i < name3.length; i++) {
lists.add(new BaseData(name3[i] + 1, i, title[2]));
}
for (int i = 0; i < name1.length; i++) {
lists.add(new BaseData(name1[i] + 2, i, title[3]));
}
for (int i = 0; i < name2.length; i++) {
lists.add(new BaseData(name2[i] + 2, i, title[4]));
}
for (int i = 0; i < name3.length; i++) {
lists.add(new BaseData(name3[i] + 2, i, title[5]));
}
for (int i = 0; i < name1.length; i++) {
lists.add(new BaseData(name1[i] + 3, i, title[6]));
}
for (int i = 0; i < name2.length; i++) {
lists.add(new BaseData(name2[i] + 3, i, title[7]));
}
for (int i = 0; i < name3.length; i++) {
lists.add(new BaseData(name3[i] + 3, i, title[8]));
} //假数据创建的方式比较low,大家不喜勿喷 //看下边这个集合,这个集合是右边所有要显示标题的条目的position ArrayList<String> showTitle = new ArrayList<String>();
for (int i = 0; i < lists.size(); i++) {
if (i == 0) {//第一个必须显示
showTitle.add(i + "");
} else if (!TextUtils.equals(lists.get(i).getTitle(),
lists.get(i - 1).getTitle())) {//如果跟上一个条目的type不一样就必须显示
showTitle.add(i + "");
}
}
} //这个集合也就是就是左边和右边类型联系的桥梁</span>

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

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

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

     <span style="font-size:14px;">lv_Right.setOnScrollListener(new OnScrollListener() {  

                 @Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
int currentPosition = showTitle.indexOf(firstVisibleItem + "");//当前选中的一级条目的position //firstVisibleItem是右边Listview当前第一个可见条目的position 根据//showTitle.indexOf(firstVisibleItem + "")可以得到这个数字在showTitle集合中的排序(是第几个),而这个排序刚好就是 //左边Listview当前所选中的条目的position 这样我们就能根据左边的类型判断右边的类型了 // updateLeftListview(firstVisibleItem, currentPosition);//这个方法下面会说 是一个抽出来的方法 左边//Listview的点击事件也会用到 } @Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
} });</span>

4.左边Listview的点击事件

     <span style="font-size:14px;">lv_left.setOnItemClickListener(new OnItemClickListener() {  

                 @Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
int firstVisibleItem = lv_Right.getFirstVisiblePosition();
//右边Listview当前第一个可见条目的position
updateLeftListview(firstVisibleItem, arg2);
lv_Right.setSelection(Integer.parseInt(showTitle.get(arg2)));
//arg2是点击(选择)左边条目的第几个
//根据这个数字我们就能通过Integer.parseInt(showTitle.get(arg2))得到在点击左边后应该跳转到右边第几个条目
// 通过etSelection方法跳转
}
});</span>

5.updateLeftListview方法

 <span style="font-size:14px;">   /**
* 更新左边Listview字体颜色 并且更改主标题的内容
*
* @param firstVisibleItem
* 右边当前第一个可见的条目position
* @param currentPosition
* 左边listview当前被点击或者要显示为红色的条目position
*/
private void updateLeftListview(int firstVisibleItem, int currentPosition) {
if (showTitle.contains(firstVisibleItem + "")) {//右边的Listview滑动到这firstVisibleItem这个条目时
// 而showTitle中包含firstVisibleItem 那么这个时候我们就需要将主标题的内容修改和firstVisibleItem的标题一样
// 并且左边Listview需要更改颜色的条目(点击需要更改或者右边滑动应该改变的textView)的字体颜色改变掉 tv_title.setText(lists.get(firstVisibleItem).getTitle());//将主标题的内容修改和firstVisibleItem的标题一样
TextView lasTextView = (TextView) lv_left
.findViewWithTag(lastPosition);
if (lasTextView != null) {//在右边Listview第一次加载过程中会一直调用监听中的onscroll 这时的textView可能为空
lasTextView.setTextColor(Color.BLACK);//先将上一个textView字体的颜色改成黑色
}
TextView currenTextView = (TextView) lv_left
.findViewWithTag(currentPosition);
if (currenTextView != null) {//再将当前要改变的extView字体的颜色改成红色
currenTextView.setTextColor(Color.RED);
}
lastPosition = currentPosition; }
}</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联动,左边点击切换右边,右边滑动切换左边的更多相关文章

  1. iOS-Andriod百度地图仿百度外卖-饿了么-选择我的地址-POI检索/

    http://zanderzhang.gitcafe.io/2015/09/19/iOS-Andriod百度地图仿百度外卖-饿了么-选择我的地址-POI检索/ 百度外卖选择送货地址: 饿了么选择送货地 ...

  2. listview下拉刷新上拉加载扩展(二)-仿美团外卖

    经过前几篇的listview下拉刷新上拉加载讲解,相信你对其实现机制有了一个深刻的认识了吧,那么这篇文章我们来实现一个高级的listview下拉刷新上拉加载-仿新版美团外卖的袋鼠动画: 项目结构: 是 ...

  3. 仿饿了吗点餐界面两个ListView联动效果

    这篇文章主要介绍了仿饿了点餐界面2个ListView联动效果的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下 如图是效果图: 是仿饿了的点餐界面 1.点击左侧的ListView,通过在在适 ...

  4. 实现外卖选餐时两级 tableView 联动效果

    最近实现了下饿了么中选餐时两级tableView联动效果,先上效果图,大家感受一下: 下面说下具体实现步骤: 首先分解一下,实现这个需求主要是两点,一是点击左边tableView,同时滚动右边tabl ...

  5. listview下拉刷新上拉加载扩展(三)-仿最新版美团外卖

    本篇是基于上篇listview下拉刷新上拉加载扩展(二)-仿美团外卖改造而来,主要调整了headview的布局,并加了两个背景动画,看似高大上,其实很简单: as源码地址:http://downloa ...

  6. iOS漂亮的Toolbar动画、仿美团主页、简易笔记本、流失布局、标签分组等源码

    iOS精选源码 JPLiquidLayout 简单易用的流式布局 labelGroupAndStreamSwift---标签分组,单选,多选 iOS采用UITableView和UIScrollView ...

  7. iOS 类似美团外卖 app 两个 tableView 联动效果实现

    写在前面 首先声明哈,不是广告,我就是用的时候觉得这个功能比较好玩,就想着实现了一下.效果如图: 接下来简单的说一下思路吧~ 大体思路 可能我们看到这种功能的实现的时候,首先想着的是我在这个控制器中左 ...

  8. 美团外卖app可行性分析

    美团外卖app可行性分析 1 引言 1.1编写目的 年轻人追求时尚,快捷,因此外卖行业拥有广阔的消费群体:团购的兴起,也促进了人们的消费欲望,人们继续一个外卖平台,来满足他们的欲望.O2o模式的日渐完 ...

  9. 解析ListView联动的实现--仿饿了么点餐界面

    一.博客的由来 大神王丰蛋哥 之前一篇博客仿饿了点餐界面2个ListView联动(http://www.cnblogs.com/wangfengdange/p/5886064.html) 主要实现了2 ...

随机推荐

  1. HTML5音乐播放器(最新升级改造加强版)

    最近么,单位里面么老不顺心的,公司一直催要程序员要PHP,然后本宅好不容易推荐了一个,我日嘞,最后待遇变成1.3,吾师最后也同意1.3W,然后还说要考虑... 尼玛,4年多5年不到一点的工作经验,前端 ...

  2. ktouch移动端事件库

    最近闲来无事,写了个移动端的事件库,代码贴在下面,大家勿拍. /** @version 1.0.0 @author gangli @deprecated 移动端触摸事件库 */ (function ( ...

  3. seo是什么职业

    SEO(Search Engine Optimization)汉译为搜索引擎优化.seo从业者首要工作就是优化网站,使其符合搜索引擎的基本规律和满足用户的需求,进而获得大量的用户访问.SEO职业属于一 ...

  4. Tomcat6.0 管理器配置

    最近忙着毕业答辩,填写材料,好多事情都给耽搁了!一个月都没有继续翻译tomcat,这回有点时间赶紧补上. 这部分,其实对开发者或者tomcat管理者来说,只要会登录页面管理器或者使用写简单的http就 ...

  5. visual studio2010 “类视图”和“对象浏览器”图标

    “类视图”和“对象浏览器”显示一些图标,这些图标表示代码实体,例如命名空间.类.函数和变量. 下表以图文并茂的形式说明了这些图标. 图标 说明 图标 说明 namespace 方法或函数 类 运算符 ...

  6. JS中的prototype(原文地址:http://www.cnblogs.com/yjf512/archive/2011/06/03/2071914.html)

    JS中的phototype是JS中比较难理解的一个部分 本文基于下面几个知识点: 1 原型法设计模式 在.Net中可以使用clone()来实现原型法 原型法的主要思想是,现在有1个类A,我想要创建一个 ...

  7. expert C Programing notes

    1.寻常算术转换 在运算中 如果其中一个操作数是long double 则另一个转为long double,其次 如果有一个为double 则另一个转为double,再次 float . unsign ...

  8. ProgressDialog使用总结

    以前对ProgressDialog不太熟练,特地看到的这个文章 ProgressDialog的使用  ProgressDialog 继承自AlertDialog,AlertDialog继承自Dialo ...

  9. 架设WEBIM

    使用openfire+jwchat构建. Openfire 采用Java开发,开源的实时协作(RTC)服务器基于XMPP(Jabber)协议.Openfire安装和使用都非常简单,并利用Web进行管理 ...

  10. 从输入 URL 到浏览器接收的过程中发生了什么事情?

    从输入 URL 到浏览器接收的过程中发生了什么事情? What really happens when you navigate to a URL 上面两篇文章都解读的很好,值得阅读. 接下来在总结一 ...