实现顶部轮播,下部listview经典布局的两种方式

开头:

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

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

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

一下这两种方式。

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

方法一:listview的addheadview方法

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

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?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

1
2
3
4
5
6
7
8
9
10
11
12
<?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在后面的另一种实现方式中也会用到,所以,单独建立一个文件存放。

 

下面是代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/**
  *
  * @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中的主要代码(在文章的结尾,我会附加源代码的下载地址,有需要的可以下载详细看)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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);
     }

  

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

1
LayoutInflater.from( this ).inflate(R.layout.head_viewpager,  null );<br>这句话将我们之前建立好的布局文件载入进来<br><br>然后通过 for 循环初始化imageview的list
1
for ( int  i =  0 ;i< 4 ;i++)<br>....<br><br> 最重要的就是这句话
1
listview.addHeaderView(view);<br><br>将初始化好的view添加到head上面。至此我们的第一种方法,就已经完成,是不是很简单。<br><br><br>

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

 

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

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

 

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

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

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

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

 

1
2
3
4
5
6
7
8
9
10
11
@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,因为我们将在这个函数中做所有的显示工作。

 

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
@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复用的概念。

1
if (getItemViewType(position) ==  1 )

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

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

 

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

1
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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值