實現頂部輪播,下部listview經典布局的兩種方式


開頭:

在做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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM