ViewFlipper一般僅用于圖片的展示,如果要進行布局文件的切換就要用到ViewPager控件,其繼承結(jié)構(gòu)如下:
public class
ViewPager
extends ViewGroup
java.lang.Object
? android.view.View
? android.view.ViewGroup
? android.support.v4.view.ViewPager
繼承自ViewGroup可以看出來是一個容器類,類前包名是android.support.v4,這是一個兼容包,注意在布局文件中引入該控件時,標(biāo)簽要寫全即:< android.support.v4.view.ViewPager >。API文檔中對ViewPager進行了描述,總結(jié)如下:
實現(xiàn)PageAdapter必須實現(xiàn)四個方法,這里進行介紹:
<?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">
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
注意,標(biāo)簽內(nèi)需要填入包.類名,否則會報錯。 子布局文件(view1.xml)
<?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="match_parent">
<TextView
android:layout_width="match_parent"
android:gravity="center"
android:text="頁面1"
android:textSize="30sp"
android:layout_height="match_parent" />
</LinearLayout>
一共有三個子View文件作為演示,每個子View中都包含一個TextView,由于只是text屬性的不同,這里僅貼出view1的代碼。 適配器類(MyViewPagerAdapter.java)
public class MyViewPagerAdapter extends PagerAdapter {
private List<View> datas;
public MyViewPagerAdapter(List<View> datas ){
this.datas=datas;
}
@Override
public int getCount() {//返回頁卡數(shù)量
return datas.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {//判斷View是否來自O(shè)bject
return view==object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {//初始化一個頁卡
container.addView(datas.get(position));
return datas.get(position);
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {//銷毀一個頁卡
container.removeView(datas.get(position));
}
}
自定義適配器類MyViewPagerAdapter繼承自PagerAdapter,編寫了構(gòu)造函數(shù),用于傳入datas數(shù)據(jù)集。此外,覆寫了四個必須要覆寫的方法,這四個方法的含義參照注釋。 (MainActivity.java)
public class MainActivity extends Activity {
private ViewPager viewPager;
private List<View> datas;
private MyViewPagerAdapter myViewPagerAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager=(ViewPager)findViewById(R.id.viewPager);
initDatas();//初始化數(shù)據(jù)集
myViewPagerAdapter=new MyViewPagerAdapter(datas);
viewPager.setAdapter(myViewPagerAdapter);//設(shè)置適配器
}
private void initDatas() {
datas=new ArrayList<>();
View view1= LayoutInflater.from(this).inflate(R.layout.view1,null);
View view2= LayoutInflater.from(this).inflate(R.layout.view2,null);
View view3= LayoutInflater.from(this).inflate(R.layout.view3,null);
datas.add(view1);
datas.add(view2);
datas.add(view3);
}
}
總結(jié)一下,PagerView的實現(xiàn)可以分為三個步驟:
運行實例如下:
http://wiki.jikexueyuan.com/project/twenty-four-Scriptures/images/17-1.png" alt="這里寫圖片描述" />
http://wiki.jikexueyuan.com/project/twenty-four-Scriptures/images/17-2.png" alt="這里寫圖片描述" />
這時,左右滑動屏幕就可以切換不同的View了,下面我們看一下如何添加頂部或底部導(dǎo)航,Android提供了兩種方式供我們選擇,分別是PagerTitleStrip和PagerTabStrip,下面分別研究一下兩者的異同點。
主布局文件(activity_main.xml)
<?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">
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.PagerTitleStrip
android:id="@+id/pagerTitleStrip"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.v4.view.PagerTitleStrip>
</android.support.v4.view.ViewPager>
</RelativeLayout>
PagerTitleStrip標(biāo)簽也要設(shè)置全路徑,并放在ViewPager標(biāo)簽內(nèi),默認沒有添加layout_gravity屬性,標(biāo)簽顯示在頁面頂部,若想設(shè)置在底部,添加這一屬性設(shè)置其值為BOTTOM即可。 適配器類(MyViewPagerAdapter.java)
public class MyViewPagerAdapter extends PagerAdapter {
private List<View> datas;
private List<String> titles;
public MyViewPagerAdapter(List<View> datas,List<String> titles ){
this.datas=datas;
this.titles=titles;
}
@Override
public int getCount() {//返回頁卡數(shù)量
return datas.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {//判斷View是否來自O(shè)bject
return view==object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {//初始化一個頁卡
container.addView(datas.get(position));
return datas.get(position);
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {//銷毀一個頁卡
container.removeView(datas.get(position));
}
@Override
public CharSequence getPageTitle(int position) {
return titles.get(position);
}
}
為了方便觀察,較上一個實例增加或修改的代碼部分進行了加粗,首先是修改了構(gòu)造方法,多傳入了一個標(biāo)題的數(shù)據(jù)集,然后覆寫了一個getPagerTitle的方法,這個方法可以根據(jù)position參數(shù)返回對應(yīng)的title。
MainActivity(MainActivity.java)
public class MainActivity extends Activity {
private ViewPager viewPager;
private PagerTitleStrip pagerTitleStrip;
private List<View> datas;
private List<String> titles;
private MyViewPagerAdapter myViewPagerAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager=(ViewPager)findViewById(R.id.viewPager);
pagerTitleStrip=(PagerTitleStrip)findViewById(R.id.pagerTitleStrip);
initDatas();
myViewPagerAdapter=new MyViewPagerAdapter(datas,titles);
viewPager.setAdapter(myViewPagerAdapter);
}
private void initDatas() {
datas=new ArrayList<>();
titles=new ArrayList<>();
View view1= LayoutInflater.from(this).inflate(R.layout.view1,null);
View view2= LayoutInflater.from(this).inflate(R.layout.view2,null);
View view3= LayoutInflater.from(this).inflate(R.layout.view3,null);
datas.add(view1);
datas.add(view2);
datas.add(view3);
titles.add("第一頁");
titles.add("第二頁");
titles.add("第三頁");
}
}
較上一個實例來講,這里添加了一個標(biāo)題的數(shù)據(jù)集titles,初始化MyViewPagerAdapter的時候傳入了兩個參數(shù),頁面布局數(shù)據(jù)集(datas)和標(biāo)題數(shù)據(jù)集(titles)。 運行實例如下:
http://wiki.jikexueyuan.com/project/twenty-four-Scriptures/images/17-3.png" alt="這里寫圖片描述" />
點擊頂部的標(biāo)題欄,不會進行頁面切換,正如API文檔里描述的那樣-non-interactive indicator,只能作為一個頁面指示器,不具有交互作用,下面我們共同來實踐一下具有交互效果的PagerTabStrip。
PagerTabStrip is an interactive indicator of the current, next, and previous pages of a ViewPager. It is intended to be used as a child view of a ViewPager widget in your XML layout. Add it as a child of a ViewPager in your layout file and set its android:layout_gravity to TOP or BOTTOM to pin it to the top or bottom of the ViewPager. The title from each page is supplied by the method getPageTitle(int) in the adapter supplied to the ViewPager.
For a non-interactive indicator, see PagerTitleStrip. 這里把英文的API文檔貼出來,帶領(lǐng)大家大致翻譯一下:PagerTabStrip是一個關(guān)于當(dāng)前頁、下一頁和上一頁可交互的頁面指示器。作為一個子View布局在ViewPager控件內(nèi)部。同時,也可以通過設(shè)置layout_gravity屬性為TOP或BOTTOM來決定顯示在頁面頂部或底部。每個頁面標(biāo)題是通過適配器類中覆寫getPageTitle方法提供給ViewPager的。最后一句也點明了,若要使用一個非交互指示器,可以參考PagerTitleStrip。
從API文檔上可以看出,兩個方式使用方法一樣,因此,這里只要在布局文件中更換一下標(biāo)簽如下:
<?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">
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.PagerTabStrip
android:id="@+id/pagerTabStrip"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.v4.view.PagerTabStrip>
</android.support.v4.view.ViewPager>
</RelativeLayout>
將標(biāo)簽換成android.support.v4.view.PagerTabStrip。 MainActivity.java中,將PagerTitleStrip換成PagerTabStrip即可,其余代碼不變:
private PagerTabStrip pagerTabStrip= (PagerTabStrip)findViewById(R.id.pagerTabStrip);
運行實例如下:
http://wiki.jikexueyuan.com/project/twenty-four-Scriptures/images/17-4.png" alt="這里寫圖片描述" />
點擊頂部指示頁,可以進行頁面切換,除此之外,較PagerTitleStrip而言,PagerTabStrip當(dāng)前頁的下面還多了一個小橫標(biāo),以上功能基本實現(xiàn)了,下面來研究一下,如何讓外觀變得更漂亮,Android也給我們提供了一些方法用于改變指示欄的樣式。常用方法參考下表:
http://wiki.jikexueyuan.com/project/twenty-four-Scriptures/images/17-5.png" alt="這里寫圖片描述" />
在MainActivity.java的onCreate方法中加入如下代碼:
pagerTabStrip.setDrawFullUnderline(false);//取消標(biāo)題欄子View之間的分割線
pagerTabStrip.setTabIndicatorColor(Color.WHITE);//改變指示器顏色為白色
pagerTabStrip.setTextColor(Color.WHITE);//該變字體顏色為白色
pagerTabStrip.setBackgroundResource(android.R.drawable.alert_dark_frame);//設(shè)置標(biāo)題欄背景圖片
再次運行實例如下:
http://wiki.jikexueyuan.com/project/twenty-four-Scriptures/images/17-6.png" alt="這里寫圖片描述" />
上面講解了加載布局文件的ViewPager,由API文檔可知,ViewPager還可以加載Fragment控件,也有兩個適配器類(FragmentPagerAdapter和FragmentStatePagerAdapter)可以實現(xiàn),下面分別實現(xiàn)并介紹相關(guān)異同點。
public abstract class
FragmentPagerAdapter
extends PagerAdapter
java.lang.Object
? android.support.v4.view.PagerAdapter
? android.support.v4.app.FragmentPagerAdapter
由繼承結(jié)構(gòu)可以看出FragmentPagerAdapter繼承自PagerAdapter,子頁面由Fragment組成,該適配器沒有實現(xiàn)頁面銷毀的方法,所有的頁面都保存在內(nèi)存當(dāng)中,當(dāng)頁面比較大時要考慮使用FragmentStatePagerAdapter適配器類。 實現(xiàn)FragmentPagerAdapter時必須要覆寫的方法是getItem和getCount方法。
下面通過一個實例進行實現(xiàn),分三個步驟實現(xiàn):
public class MyFragment1 extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.view1,null);
}
}
Fragment中只覆寫了onCreateView方法,其他兩個Fragment差別只是載入了不同的view,這里就不再貼出。
適配器類代碼(MyFragmentViewPagerAdapter.java)
public class MyFragmentViewPagerAdapter extends FragmentPagerAdapter{
private List<Fragment> datas;
private List<String> titles;
public MyFragmentViewPagerAdapter(FragmentManager fm, List<Fragment> datas,List<String> titles) {
super(fm);
this.titles=titles;
this.datas=datas;
}
@Override
public Fragment getItem(int position) {
return datas.get(position);
}
@Override
public int getCount() {
return datas.size();
}
@Override
public CharSequence getPageTitle(int position) {
return titles.get(position);
}
}
這里構(gòu)建構(gòu)造方法時傳入了FragmentManager參數(shù),并傳入了Fragment類的數(shù)據(jù)集合String型的標(biāo)題集。必須要覆寫的方法只有g(shù)etI tem(獲取子項)和getCount(獲取子項個數(shù))兩個。為了顯示標(biāo)題欄,這里覆寫了getPageTitle方法。
MainActivity(MainActivity.java)
public class MainActivity extends FragmentActivity {
private ViewPager viewPager;
private PagerTabStrip pagerTabStrip;
private List<Fragment> datas;//數(shù)據(jù)源
private List<String> titles;
private MyFragmentViewPagerAdapter myFragmentViewPagerAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager=(ViewPager)findViewById(R.id.viewPager);
pagerTabStrip=(PagerTabStrip)findViewById(R.id.pagerTabStrip);
pagerTabStrip.setDrawFullUnderline(false);//取消標(biāo)題欄和子View直接的分割線
pagerTabStrip.setTabIndicatorColor(Color.WHITE);
pagerTabStrip.setTextColor(Color.WHITE);
pagerTabStrip.setBackgroundResource(android.R.drawable.alert_dark_frame);
initDatas();
myFragmentViewPagerAdapter=new MyFragmentViewPagerAdapter(getSupportFragmentManager(),datas,titles);
viewPager.setAdapter(myFragmentViewPagerAdapter);
}
private void initDatas() {
datas=new ArrayList<>();
titles=new ArrayList<>();
datas.add(new MyFragment1());
datas.add(new MyFragment2());
datas.add(new MyFragment3());
titles.add("第一頁");
titles.add("第二頁");
titles.add("第三頁");
}
}
初始化數(shù)據(jù)源時,加入的是Fragment對象,初始化適配器類MyFragmentViewPagerAdapter時要傳入FragmentManager對象,這里使用getSupportFragmentManager方法獲取,不過,要注意這時MainActivity要繼承自FragmentActivity,才好調(diào)用這個方法。 運行實例如下:
http://wiki.jikexueyuan.com/project/twenty-four-Scriptures/images/17-7.png" alt="這里寫圖片描述" />
運行效果和PagerAdapter類實現(xiàn)的一樣。
@Override
public Object instantiateItem(ViewGroup container, int position) {
return super.instantiateItem(container, position);
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
}
此方式可以銷毀不可見的頁面(不在標(biāo)題欄中的頁面,標(biāo)題欄中一般存在三個頁面),回收內(nèi)存,在實際開發(fā)中推薦使用。 ViewPager控件提供了頁面切換時的事件監(jiān)聽,下面就在MainActivity中實現(xiàn)一下:
public class MainActivity extends FragmentActivity implements ViewPager.OnPageChangeListener{
private ViewPager viewPager;
private PagerTabStrip pagerTabStrip;
private List<Fragment> datas;
private List<String> titles;
private MyFragmentViewPagerAdapter myFragmentViewPagerAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager=(ViewPager)findViewById(R.id.viewPager);
pagerTabStrip=(PagerTabStrip)findViewById(R.id.pagerTabStrip);
pagerTabStrip.setDrawFullUnderline(false);//取消標(biāo)題欄和子View直接的分割線
pagerTabStrip.setTabIndicatorColor(Color.WHITE);
pagerTabStrip.setTextColor(Color.WHITE);
pagerTabStrip.setBackgroundResource(android.R.drawable.alert_dark_frame);
initDatas();
myFragmentViewPagerAdapter=new MyFragmentViewPagerAdapter(getSupportFragmentManager(),datas,titles);
viewPager.setAdapter(myFragmentViewPagerAdapter);
viewPager.setOnPageChangeListener(this);
}
private void initDatas() {
datas=new ArrayList<>();
titles=new ArrayList<>();
datas.add(new MyFragment1());
datas.add(new MyFragment2());
datas.add(new MyFragment3());
titles.add("第一頁");
titles.add("第二頁");
titles.add("第三頁");
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
Toast.makeText(MainActivity.this,"當(dāng)前是第:"+(position+1)+"頁",Toast.LENGTH_SHORT).show();
}
@Override
public void onPageScrollStateChanged(int state) {
}
}
實現(xiàn)了onPageChangeListener接口,需要覆寫三個方法:
在頁面選擇觸發(fā)的方法里通過position參數(shù)獲得當(dāng)前頁面信息,然后由Toast輸出信息。
運行實例如下:
http://wiki.jikexueyuan.com/project/twenty-four-Scriptures/images/17-8.png" alt="這里寫圖片描述" />
切換頁面后會Toast出當(dāng)前所在頁。