ViewPager在app開發中十分常見。今天以一個例子詳細解讀下ViewPager的基礎知識。
一、什么是ViewPager
可以這樣理解,ViewPager就相當於一個容器,它的里面可以裝view作為頁面,也可以裝Fragment作為頁面。例如常用的微信主界面,就可以用ViewPager做出那樣的效果。下面是一個直觀的效果圖,相信你看了,就會明白什么是ViewPager。
效果說明:在模擬器用的是鼠標,在手機上用的就應該是手指來滑動了,總之就是左右滑動,會出現不同的界面。想想微信主界面是不是左右滑動,就會展現不同的界面呢?道理是一樣的。
我們先將基礎知識給總結一下,然后再來實現這樣子的效果,這樣也好看得懂下面的代碼。
二、關於ViewPager的基礎知識
這些基礎知識並不難。都是很簡單的,總結如下:
在布局中加入ViewPager:
<android.support.v4.view.ViewPager android:id="@+id/view_pager" android:layout_width="wrap_content" android:layout_height="wrap_content" > </android.support.v4.view.ViewPager>
在布局總加入帶標題的ViewPager:
<android.support.v4.view.ViewPager android:id="@+id/view_pager" android:layout_width="wrap_content" android:layout_height="wrap_content" > <android.support.v4.view.PagerTabStrip android:id="@+id/pager_title" android:layout_width="wrap_content" android:layout_height="wrap_content"> </android.support.v4.view.PagerTabStrip> </android.support.v4.view.ViewPager>
ViewPager的監聽器:
即是OnPageChangeListener。實現這個監聽接口,必須重寫三個方法,一般我們比較關注的是onPageSelected方法(當頁卡被選中時會調用)。
ViewPager的適配器也有幾種:
(1)PagerAdapter:數據源是view,即向ViewPager中填充view作為頁卡。
(1)FragmentPagerAdapter:數據源是Fragment,即Fragment作為頁卡。
(3)FragmentStatePagerAdapter:同樣是Fragment作為頁卡。
注意,FragmentPagerAdapter是一次性將所有頁卡都加載完畢,沒有銷毀的。而FragmentStatePagerAdapter並不是一次性將頁卡都加載完畢,而是默認每次加載進三個頁卡,當前頁卡被滑動消失就會被銷毀。這是它們的區別。因此如果頁卡較多,建議采用FragmentStatePagerAdapter適配器。
好了,有了上面的基礎知識,下面就可以看看具體的實現了。畢竟不看代碼,沒法說清楚ViewPager是怎么用的。下面會一步一步實現出本文開頭的效果出來。
三、實際例子
新建項目,然后新建布局layout1.xml。其中的代碼如下:
1 <?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="match_parent" 5 android:orientation="vertical" 6 android:gravity="center" > 7 <TextView 8 android:layout_width="wrap_content" 9 android:layout_height="wrap_content" 10 android:text="我是第一個界面" 11 android:textSize="30sp"/> 12 13 </LinearLayout>
然后這樣的布局再建立三個,分別命名為alyout2.xml,layout3.xml,layout4.xml。每一個布局只是將第10行的文本顯示改了,改為“我是第二個界面”,“我是第三個界面”,“我是第四個界面”。這樣子,要裝進ViewPager里的布局文件我們就寫好了。
然后修改activity_main.xml中的代碼,將ViewPager放進里面。代碼如下:
1 <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 > 6 <android.support.v4.view.ViewPager 7 android:id="@+id/view_pager" 8 android:layout_width="wrap_content" 9 android:layout_height="wrap_content" 10 > 11 12 </android.support.v4.view.ViewPager> 13 14 15 16 </LinearLayout>
接着為ViewPager寫適配器,因為要填充的是view,所以用PagerAdapter作為適配器,新建類ViewAdapter繼承它即可。代碼如下:
1 package com.example.viewpager; 2 3 import java.util.List; 4 5 import android.support.v4.view.PagerAdapter; 6 import android.view.View; 7 import android.view.ViewGroup; 8 /** 9 * ViewPager的適配器 10 * @author fuly1314 11 * 12 */ 13 public class ViewAdapter extends PagerAdapter{ 14 15 private List<View> viewList;//數據源 16 17 public ViewAdapter(List<View> viewList){ 18 19 this.viewList = viewList; 20 } 21 22 //數據源的數目 23 public int getCount() { 24 25 return viewList.size(); 26 } 27 28 29 //view是否由對象產生,官方寫arg0==arg1即可 30 public boolean isViewFromObject(View arg0, Object arg1) { 31 32 return arg0==arg1; 33 34 } 35 36 37 //銷毀一個頁卡(即ViewPager的一個item) 38 public void destroyItem(ViewGroup container, int position, Object object) { 39 40 container.removeView(viewList.get(position)); 41 } 42 43 44 //對應頁卡添加上數據 45 public Object instantiateItem(ViewGroup container, int position) { 46 47 container.addView(viewList.get(position));//千萬別忘記添加到container 48 return viewList.get(position); 49 } 50 51 52 }
從適配器上,可以看出,PagerView是具有銷毀頁卡的屬性的。其實它每次加載3個頁卡,即當前顯示的頁卡以及其前后的頁卡都被加載進來。然后我們再修改MainActivity中的代碼,將這些都組合到一起即可。如下:
1 package com.example.viewpager; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 import android.os.Bundle; 7 import android.support.v4.view.PagerAdapter; 8 import android.support.v4.view.ViewPager; 9 import android.view.LayoutInflater; 10 import android.view.View; 11 import android.app.Activity; 12 13 public class MainActivity extends Activity { 14 15 private ViewPager pager; 16 private List<View> viewList = new ArrayList<View>(); 17 private PagerAdapter viewAdapter; 18 19 20 21 private LayoutInflater inflater; 22 23 24 protected void onCreate(Bundle savedInstanceState) { 25 super.onCreate(savedInstanceState); 26 setContentView(R.layout.activity_main); 27 28 //獲取ViewPager 29 pager = (ViewPager) findViewById(R.id.view_pager); 30 31 inflater = LayoutInflater.from(this); 32 33 //獲取四個view 34 View view1 = inflater.inflate(R.layout.layout1, null); 35 View view2 = inflater.inflate(R.layout.layout2, null); 36 View view3 = inflater.inflate(R.layout.layout3, null); 37 View view4 = inflater.inflate(R.layout.layout4, null); 38 39 //將四個View加入到集合 40 viewList.add(view1); 41 viewList.add(view2); 42 viewList.add(view3); 43 viewList.add(view4); 44 45 //實例化適配器 46 viewAdapter = new ViewAdapter(viewList); 47 48 //設置適配器 49 pager.setAdapter(viewAdapter); 50 } 51 52 53 }
好了,多搞定了,然后我們運行程序,效果如下:
我們左右滑動,就會呈現不同的視圖。但是跟上面的效果好像不太一樣,那是因為我們沒有給它加上標題。下面咱就來給它加上標題。
(1)給ViewPager加標題
怎么加標題,基礎知識里已經講了,那么就先修改activity_main.xml,把標題加上。代碼如下:
1 <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 > 6 <android.support.v4.view.ViewPager 7 android:id="@+id/view_pager" 8 android:layout_width="wrap_content" 9 android:layout_height="wrap_content" 10 > 11 <android.support.v4.view.PagerTabStrip 12 13 android:id="@+id/pager_title" 14 android:layout_width="wrap_content" 15 android:layout_height="wrap_content"> 16 17 </android.support.v4.view.PagerTabStrip> 18 19 </android.support.v4.view.ViewPager> 20 21 22 23 </LinearLayout>
需要說明的是,PagerTabStrip是ViewPager的一個子標簽,一定要加載ViewPager內部。然后再修改適配器,讓標題適配,如下:
1 package com.example.viewpager; 2 3 import java.util.List; 4 5 import android.support.v4.view.PagerAdapter; 6 import android.view.View; 7 import android.view.ViewGroup; 8 /** 9 * ViewPager的適配器 10 * @author fuly1314 11 * 12 */ 13 public class ViewAdapter extends PagerAdapter{ 14 15 private List<View> viewList;//數據源 16 private List<String> titles;//標題 17 18 public ViewAdapter(List<View> viewList,List<String> titles){ 19 20 this.viewList = viewList; 21 this.titles = titles; 22 } 23 24 //數據源的數目 25 public int getCount() { 26 27 return viewList.size(); 28 } 29 30 31 //view是否由對象產生,官方寫arg0==arg1即可 32 public boolean isViewFromObject(View arg0, Object arg1) { 33 34 return arg0==arg1; 35 36 } 37 38 39 //銷毀一個頁卡(即ViewPager的一個item) 40 public void destroyItem(ViewGroup container, int position, Object object) { 41 42 container.removeView(viewList.get(position)); 43 } 44 45 46 //對應頁卡添加上數據 47 public Object instantiateItem(ViewGroup container, int position) { 48 49 container.addView(viewList.get(position));//千萬別忘記添加到container 50 return viewList.get(position); 51 } 52 53 //為對應的頁卡設置標題 54 public CharSequence getPageTitle(int position) { 55 56 return titles.get(position); 57 } 58 59 60 }
注意紅色部分,即第53行到第57行,就是給相應的頁卡適配上相應的標題。最后就是在MainActivity中,將標題數據源建立出來,然后傳入到適配器即可。代碼如下:
1 package com.example.viewpager; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 import android.os.Bundle; 7 import android.support.v4.view.PagerAdapter; 8 import android.support.v4.view.PagerTabStrip; 9 import android.support.v4.view.ViewPager; 10 import android.view.LayoutInflater; 11 import android.view.View; 12 import android.app.Activity; 13 import android.graphics.Color; 14 15 public class MainActivity extends Activity { 16 17 private ViewPager pager; 18 private List<View> viewList = new ArrayList<View>();//數據源 19 private PagerAdapter viewAdapter; 20 21 private List<String> titles = new ArrayList<String>();//標題 22 23 24 25 private LayoutInflater inflater; 26 27 private PagerTabStrip pagerTitle;//ViewPager的標題 28 29 30 protected void onCreate(Bundle savedInstanceState) { 31 super.onCreate(savedInstanceState); 32 setContentView(R.layout.activity_main); 33 34 //獲取ViewPager 35 pager = (ViewPager) findViewById(R.id.view_pager); 36 45 46 //添加標題 47 titles.add("第一頁"); 48 titles.add("第二頁"); 49 titles.add("第三頁"); 50 titles.add("第四頁"); 51 52 53 54 55 inflater = LayoutInflater.from(this); 56 57 //獲取四個view 58 View view1 = inflater.inflate(R.layout.layout1, null); 59 View view2 = inflater.inflate(R.layout.layout2, null); 60 View view3 = inflater.inflate(R.layout.layout3, null); 61 View view4 = inflater.inflate(R.layout.layout4, null); 62 63 //將四個View加入到集合 64 viewList.add(view1); 65 viewList.add(view2); 66 viewList.add(view3); 67 viewList.add(view4); 68 69 //實例化適配器 70 viewAdapter = new ViewAdapter(viewList,titles); 71 72 //設置適配器 73 pager.setAdapter(viewAdapter); 74 } 75 76 77 }
紅色部分就是為添加標題,所增添的代碼。然后我們運行一下程序,再來看看效果:
怎么樣,標題如願已經加上了。如果此時你覺得不是很美觀,那么可以繼續給標題設定一個屬性。比如我們上面的標題的效果,就是這樣子設定的,修改MainActivity中的代碼,如下:
1 package com.example.viewpager; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 import android.os.Bundle; 7 import android.support.v4.view.PagerAdapter; 8 import android.support.v4.view.PagerTabStrip; 9 import android.support.v4.view.ViewPager; 10 import android.view.LayoutInflater; 11 import android.view.View; 12 import android.app.Activity; 13 import android.graphics.Color; 14 15 public class MainActivity extends Activity { 16 17 private ViewPager pager; 18 private List<View> viewList = new ArrayList<View>();//數據源 19 private PagerAdapter viewAdapter; 20 21 private List<String> titles = new ArrayList<String>();//標題 22 23 24 25 private LayoutInflater inflater; 26 27 private PagerTabStrip pagerTitle;//ViewPager的標題 28 29 30 protected void onCreate(Bundle savedInstanceState) { 31 super.onCreate(savedInstanceState); 32 setContentView(R.layout.activity_main); 33 34 //獲取ViewPager 35 pager = (ViewPager) findViewById(R.id.view_pager); 36 37 //獲取pagerTitle 38 pagerTitle = (PagerTabStrip) findViewById(R.id.pager_title); 39 40 //為標題設置屬性,比如背景,顏色線等 41 pagerTitle.setBackgroundColor(Color.RED);//設置背景顏色 42 pagerTitle.setTextColor(Color.YELLOW);//設置標題文字的顏色 43 pagerTitle.setDrawFullUnderline(false);//將標題下的長分割線去掉 44 pagerTitle.setTabIndicatorColor(Color.BLUE);//設置標題下粗一點的短分割線的顏色 45 46 //添加標題 47 titles.add("第一頁"); 48 titles.add("第二頁"); 49 titles.add("第三頁"); 50 titles.add("第四頁"); 51 52 53 54 55 inflater = LayoutInflater.from(this); 56 57 //獲取四個view 58 View view1 = inflater.inflate(R.layout.layout1, null); 59 View view2 = inflater.inflate(R.layout.layout2, null); 60 View view3 = inflater.inflate(R.layout.layout3, null); 61 View view4 = inflater.inflate(R.layout.layout4, null); 62 63 //將四個View加入到集合 64 viewList.add(view1); 65 viewList.add(view2); 66 viewList.add(view3); 67 viewList.add(view4); 68 69 //實例化適配器 70 viewAdapter = new ViewAdapter(viewList,titles); 71 72 //設置適配器 73 pager.setAdapter(viewAdapter); 74 } 75 76 77 }
注意紅色部分的代碼,就是為標題設定的一些屬性。然后再運行程序,效果圖如下:
終於實現了我們一開始展示的效果了。有必要小結一下,為ViewPager的標題設置屬性:
為ViewPager的標題設置屬性:
//獲取pagerTitle pagerTitle = (PagerTabStrip) findViewById(R.id.pager_title); //為標題設置屬性,比如背景,顏色線等 pagerTitle.setBackgroundColor(Color.RED);//設置背景顏色 pagerTitle.setTextColor(Color.YELLOW);//設置標題文字的顏色 pagerTitle.setDrawFullUnderline(false);//將標題下的長分割線去掉 pagerTitle.setTabIndicatorColor(Color.BLUE);//設置標題下粗一點的短分割線的顏色
(2)為ViewPager設置監聽器
為了說明OnPagerChangeListener到底是怎么用的,在此簡單的讓滑動頁卡的時候彈出個提示吧。修改MainActivity中的代碼如下:
1 package com.example.viewpager; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 import android.os.Bundle; 7 import android.support.v4.view.PagerAdapter; 8 import android.support.v4.view.PagerTabStrip; 9 import android.support.v4.view.ViewPager; 10 import android.support.v4.view.ViewPager.OnPageChangeListener; 11 import android.view.LayoutInflater; 12 import android.view.View; 13 import android.widget.Toast; 14 import android.app.Activity; 15 import android.graphics.Color; 16 17 public class MainActivity extends Activity implements OnPageChangeListener{ 18 19 private ViewPager pager; 20 private List<View> viewList = new ArrayList<View>();//數據源 21 private PagerAdapter viewAdapter; 22 23 private List<String> titles = new ArrayList<String>();//標題 24 25 26 27 private LayoutInflater inflater; 28 29 private PagerTabStrip pagerTitle; 30 31 32 protected void onCreate(Bundle savedInstanceState) { 33 super.onCreate(savedInstanceState); 34 setContentView(R.layout.activity_main); 35 36 //獲取ViewPager 37 pager = (ViewPager) findViewById(R.id.view_pager); 38 39 pager.setOnPageChangeListener(this);//設置監聽器 40 41 //獲取pagerTitle 42 pagerTitle = (PagerTabStrip) findViewById(R.id.pager_title); 43 44 //為標題設置屬性,比如背景,顏色線等 45 pagerTitle.setBackgroundColor(Color.RED);//設置背景顏色 46 pagerTitle.setTextColor(Color.YELLOW);//設置標題文字的顏色 47 pagerTitle.setDrawFullUnderline(false);//將標題下的長分割線去掉 48 pagerTitle.setTabIndicatorColor(Color.BLUE);//設置標題下粗一點的短分割線的顏色 49 50 //添加標題 51 titles.add("第一頁"); 52 titles.add("第二頁"); 53 titles.add("第三頁"); 54 titles.add("第四頁"); 55 56 57 58 59 inflater = LayoutInflater.from(this); 60 61 //獲取四個view 62 View view1 = inflater.inflate(R.layout.layout1, null); 63 View view2 = inflater.inflate(R.layout.layout2, null); 64 View view3 = inflater.inflate(R.layout.layout3, null); 65 View view4 = inflater.inflate(R.layout.layout4, null); 66 67 //將四個View加入到集合 68 viewList.add(view1); 69 viewList.add(view2); 70 viewList.add(view3); 71 viewList.add(view4); 72 73 //實例化適配器 74 viewAdapter = new ViewAdapter(viewList,titles); 75 76 //設置適配器 77 pager.setAdapter(viewAdapter); 78 } 79 80 81 82 //當滾動狀態改變時被調用 83 public void onPageScrollStateChanged(int arg0) { 84 85 86 } 87 88 89 //滾動時調用 90 public void onPageScrolled(int arg0, float arg1, int arg2) { 91 92 93 } 94 95 96 //當頁卡被選中時調用 97 public void onPageSelected(int arg0) { 98 99 Toast.makeText(this, "這是第"+(arg0+1)+"個界面", Toast.LENGTH_LONG).show(); 100 101 } 102 103 104 }
紅色部分就是設定監聽器的代碼,當頁卡被調用時,簡單的彈出一個提示框而已。運行效果如下: