开头:

在做android开发的时候,我们经常会遇到这样的布局,上面是一个图片轮播图,下面是一些列表的项目。很多新闻app,视频类app都采用这样的布局。起初的时候

由于没有很多参考,我自己想到了一种实现方式,就是用scrollview作为外面最大的布局,然后里面嵌套viewpager和listview,但是我现在非常不推荐这种方式,一方面由于这种方式

需要将listview完全展开,缺少了getview函数中应该有的复用与优化。而且结构嵌套复杂。经过一番查找与学习,学习到两种比较规范或者结构比较清晰的实现方式,那么下面,我来分别介绍

一下这两种方式。

转载请注明出处   http://www.cnblogs.com/gaoteng/p/4162749.html   www.gaotenglife.com

方法一:listview的addheadview方法

首先我们新建一个布局文件,存放listview,如下

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" > <TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="16dp"
android:text="first" />
<ListView
android:id="@+id/list_view_first"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/textView1"
/>
</RelativeLayout>

  布局很简单,里面就主要有一个listview。

然后顶部的轮播图,我们采用viewpager的方式去实现。同样新建一个布局,里面存放viewpager

<?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="100dp"
android:orientation="vertical" > <android.support.v4.view.ViewPager
android:id="@+id/headviewpager"
android:layout_width="match_parent"
android:layout_height="100dp"
/>
</LinearLayout>

 通过上面两步,我们已经建立好了用到的布局文件,很简单。

那么接下来,viewpager需要一个adapter来填充数据,这里我们的数据,就是一些图片,让viewpager去展示。

我们再新建一个自己的viewpageradapter,这个adapger在后面的另一种实现方式中也会用到,所以,单独建立一个文件存放。

下面是代码:

/**
*
* @author xuelang www.gaotenglife.com
*
*/
public class ViewPageAdapter extends PagerAdapter
{ List<ImageView> list = null;//我们用一个list存放所有的imageview
public ViewPageAdapter (List<ImageView> _list)
{
list = _list;
} @Override
public void destroyItem(View container, int position, Object object) {
// TODO Auto-generated method stub
((ViewPager)container).removeView(list.get(position)); } @Override
public Object instantiateItem(View container, int position) {
// TODO Auto-generated method stub
((ViewPager) container).addView(list.get(position));
return list.get(position);
} @Override
public int getCount() {
// TODO Auto-generated method stub
return list.size();//返回数据的个数
} @Override
public boolean isViewFromObject(View arg0, Object arg1) {
// TODO Auto-generated method stub
return (arg0 == arg1);//这句话,比较重要,加上之后才能正确显示
} }

  上面的代码很简单,是一个pageadapter的标准用法。这样我们基本上所有的准备工作已经完成了,最后一步,就是我们把viewpager通过listview的addheadview方式加入到listview的头上。

下面便是acitivity中的主要代码(在文章的结尾,我会附加源代码的下载地址,有需要的可以下载详细看)

private void initHeadView()
{
listview = (ListView)this.findViewById(R.id.list_view_first);
View view = LayoutInflater.from(this).inflate(R.layout.head_viewpager, null);
ViewPager viewpager = (ViewPager)view.findViewById(R.id.headviewpager);
List<ImageView> listtemp = new ArrayList<ImageView>();
for(int i = 0;i<4;i++)
{
ImageView img = new ImageView(this);
img.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,100));
img.setScaleType(ScaleType.FIT_XY);
img.setBackgroundResource(R.drawable.ic_launcher);
listtemp.add(img);
}
ViewPageAdapter viewadapter = new ViewPageAdapter(listtemp);
listview.addHeaderView(view);
listview.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,data));
viewpager.setAdapter(viewadapter);
}

  

简单解释一下上面的内容:

LayoutInflater.from(this).inflate(R.layout.head_viewpager, null);
这句话将我们之前建立好的布局文件载入进来 然后通过for循环初始化imageview的list
for(int i = 0;i<4;i++)
.... 最重要的就是这句话
listview.addHeaderView(view);

将初始化好的view添加到head上面。至此我们的第一种方法,就已经完成,是不是很简单。

方法二:viewpager作为listview的一个item

  这种方式是我受到别的文章的启发,一个listview可以指定它每一个item为不同的布局类型,从而实现listview的多元化,那么我们同样可以利用这个方法。

把listview的第一项初始化为viewpager,这样不也就实现了顶部时viewpager的效果了嘛。说干就干,代码继续码起来。

在这种方式中,最主要的内容部分就在listview的adapter中。所以我也就主要介绍这一个adapter,我相信,看懂了这个adapter,那么其他部分,自然很容易理解了。

在官方api中提供了下面这两个方法,这也是今天实现这个功能主要的两个方法。

getViewTypeCount //用来返回在这个listview中有几种不同的item类型

getItemViewType //用来返回某个具体位置上面的item的类型()

@Override
public int getItemViewType(int position) {
// TODO Auto-generated method stub
return position>0?0:1;
} @Override
public int getViewTypeCount() {
// TODO Auto-generated method stub
return 2;
}

  由于我们只做一个简单演示,所以就分为两种类型,一种是viewpager类型的item,另一种是不同类型的item,所以当position大于0,也就是我们的普通类型,position等于0,就是第一项,也就是viewpager。

接下来便是这个功能最最重要的一个函数getview,因为我们将在这个函数中做所有的显示工作。

我们先把代码附上,然后详细介绍。

	@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View view = null;
if(getItemViewType(position) == 0)//
{
ViewHolder holder = null; if(convertView==null)
{ view = m_inflater.inflate(R.layout.list_item, null);
holder = new ViewHolder();
holder.textView = (TextView)view.findViewById(R.id.list_item);
view.setTag(holder);
}
else
{
view = convertView;
holder = (ViewHolder)view.getTag();
}
holder.textView.setText(position+"");
}
else if(getItemViewType(position) == 1)//如果是顶部viewpager
{
ViewPagerHolder holder = null;
if(convertView==null)
{
view = m_inflater.inflate(R.layout.head_viewpager, null);
holder = new ViewPagerHolder();
holder.viewPager = (ViewPager)view.findViewById(R.id.headviewpager); List<ImageView> listtemp = new ArrayList<ImageView>();
for(int i = 0;i<4;i++)
{
ImageView img = new ImageView(SecondActivity.this);
img.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,100));
img.setScaleType(ScaleType.FIT_XY);
img.setBackgroundResource(R.drawable.ic_launcher);
listtemp.add(img);
} ViewPageAdapter viewadapter = new ViewPageAdapter(listtemp);
holder.viewPager.setAdapter(viewadapter); view.setTag(holder);
}
else
{
view = convertView;
holder = (ViewPagerHolder)view.getTag();
}
} return view;
} }

  

下面我来详细说明一下上面的函数。其实基本的骨架大家应该都能看懂。使用了listview复用的概念。

 if(getItemViewType(position) == 1)

通过这个判断目前需要显示的view是哪种类型。那么这里如果是1,就是我们的viewpager项,

然后再判断convertView是否为空,来决定是否复用。

如果为空,说明在内存中没有保留过,于是通过LayoutInflate创建view,同时我们创建了一个

 holder = new ViewPagerHolder();

缓冲,用来保存之前创建好的布局,以便下次使用。

然后创建好viewpager的数据List<ImageView> data,使用前面的ViewPageAdapter,将数据与viewpager绑定,然后用settag的方式,把holder数据,保存到view里面。

当判断convertview不为空的时候,我们从convertview中取出tag,转换为holder,然后就又得到了viewpager对象了。

这是if(getItemViewType(position) == 1)的情况。

那么if(getItemViewType(position) == 0)的情况就更简单了,基本上和这类似。

也是复用了convertview,然后通过holder的方式,将view对象保存起来,不用下一次通过findviewbyid的方式来查找了,提高了效率。

转载请注明出处   http://www.cnblogs.com/gaoteng/p/4162749.html   www.gaotenglife.com

下面附上源码下载地址

csdn资源

http://download.csdn.net/detail/gaotengguojianhong/8308407

github资源

https://github.com/langxuelang/ListViewDemo

实现顶部轮播,下部listview经典布局的两种方式的更多相关文章

  1. Android ScrollView监听滑动到顶部和底部的两种方式(你可能不知道的细节)

    Android ScrollView监听滑动到顶部和底部,虽然网上很多资料都有说,但是不全,而且有些细节没说清楚 使用场景: 1. 做一些复杂动画的时候,需要动态判断当前的ScrollView是否滚动 ...

  2. 实现CSS等分布局的4种方式

    × 目录 [1]float [2]inline-block [3]table[4]flex 前面的话 等分布局是指子元素平均分配父元素宽度的布局方式,本文将介绍实现等分布局的4种方式 思路一: flo ...

  3. Android一个ListView列表之中插入两种不同的数据

    http://www.cnblogs.com/roucheng/ Android一个ListView列表之中插入两种不同的数据 代码如下: public class ViewHolder{ Butto ...

  4. 实现Comet(服务器推送)的两种方式:长轮询和http流

    Comet 是一种高级的Ajax技术,实现了服务器向页面实时推送数据的技术,应用场景有体育比赛比分和股票报价等. 实现Comet有两种方式:长轮询与http流 长轮询是短轮询的翻版,短轮询的方式是:页 ...

  5. 实现CSS等分布局的5种方式

    前面的话 等分布局是指子元素平均分配父元素宽度的布局方式,本文将介绍实现等分布局的5种方式 float [思路一]float 缺点:结构和样式存在耦合性,IE7-浏览器下对宽度百分比取值存在四舍五入的 ...

  6. web网页 页面布局的几种方式(转)

    web网页 页面布局的几种方式 转载 2017年06月16日 12:19:40 2218 网页基本布局方式: (1)流式布局 Fluid 流布局与固定宽度布局基本不同点 就在于对网站尺寸的侧量单位不同 ...

  7. 淘宝(阿里百川)手机客户端开发日记第二篇 android首页之顶部轮播特效制作 (二)

    1.我们来设计flash_slide.xml 布局,这个xml主要做成模块化,方便其它的activity可以动态去调用. flash_slide.xml内容如下: <?xml version=& ...

  8. Flask实战第49天:cms轮播图管理页面布局

    新建cms_banners.html继承cms_base.html {% extends 'cms/cms_base.html' %} {% block title %} 轮播图管理-CMS管理系统 ...

  9. 一段不错的代码JS的顶部轮播广告

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

随机推荐

  1. BITED数学建模七日谈之六:组队建议和比赛流程建议

    今天进入数学建模经验谈第六天:组队建议和比赛流程建议 数学模型的组队非常重要,三个人的团队一定要有分工明确而且互有合作,三个人都有其各自的特长,这样在某方面的问题的处理上才会保持高效率. 三个人的分工 ...

  2. PHP获取curl的错误

    curl_error($ch) 用 curl_error 来获取 curl 的错误

  3. TortoiseGit's Settings

    将鼠标停放在Settings-TortoiseGit窗体上的editbox,checkbox上,有些会弹出有用的提示信息. 2.35.1. General settings: 设定自己偏好的语言,Gi ...

  4. 使用HttpClient实现文件的上传下载

    1 HTTP HTTP 协议可能是现在 Internet 上使用得最多.最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源. 虽然在 JDK 的 java.net ...

  5. WPF 简介

    简介 一.   WPF产生的背景 因为人们的生活水平不断提前,审美观也随着提升,而软件的应用发展水平目前无法赶上大家的审美观和使用要求:比如:像电影中的软件能够方便的使用,而且有动态的效果同时附加形象 ...

  6. Java实现中文字符串的排序功能

    package test; /** * * @Title 书的信息类 * @author LR * @version 1.0 * @since 2016-04-21 */ public class B ...

  7. Google Test资料

    Google Test资料 玩转Google开源C++单元测试框架Google Test系列(gtest)(总) gtest.h file not found googletest xcode 7.0 ...

  8. SCAU 10690 分面包

    10690 分面包 时间限制:1000MS  内存限制:65535K 题型: 编程题   语言: 无限制 Description 在大一的时候,XCC还在stu union打酱油~~~~和十三还有奶子 ...

  9. windows下python的包管理器pip安装

    pip:  A tool for installing and managing Python packages. 要用到第三方包,python的版本就必须是2.7 https://pypi.pyth ...

  10. html5 base64基础

    base64常见的编码形式,二进制文件.图片.视频等     如何弄出来一个base64?     a). FileReader         readAsDataURL();     b). 工具 ...