Android 應用開發---ViewPager---5.使用Fragment實現ViewPager滑動
ViewPager 詳解(五)-----使用Fragment實現ViewPager滑動
在第一個頁面加一個Btn 第一頁面向第二頁面滑動
第二頁面向第三個頁面滑動
一、概述
從前面幾篇文章,我們知道,實現ViewPager是要有介面卡的,我們前面用的介面卡是PagerAdapter,而對於fragment,它所使用的介面卡是:FragmentPagerAdapter.先看看官方對於這個類的解釋:(英文下面有中文解釋)
原文:
Class Overview
Implementation of that represents each page as a that is persistently kept in the fragment manager as long as the user can return to the page.
This version of the pager is best for use when there are a handful of typically more static fragments to be paged through, such as a set of tabs. The fragment of each page the user visits will be kept in memory, though its view hierarchy may be destroyed when not visible. This can result in using a significant amount of memory since fragment instances can hold on to an arbitrary amount of state. For larger sets of pages, consider .
When using FragmentPagerAdapter the host ViewPager must have a valid ID set.
Subclasses only need to implement and to have a working adapter.
譯文:(譯的不好,大家可在評論中補充)
FragmentPagerAdapter派生自PagerAdapter,它是用來呈現Fragment頁面的,這些Fragment頁面會一直儲存在fragment manager中,以便使用者可以隨時取用。
這個介面卡最好用於有限個靜態fragment頁面的管理。儘管不可見的檢視有時會被銷燬,但使用者所有訪問過的fragment都會被儲存在記憶體中。因此fragment例項會儲存大量的各種狀態,這就造成了很大的記憶體開銷。所以如果要處理大量的頁面切換,建議使用FragmentStatePagerAdapter.
每一個使用FragmentPagerAdapter的ViewPager都要有一個有效的ID集合,有效ID的集合就是Fragment的集合(感謝夫諸同學的提示)
對於FragmentPagerAdapter的派生類,只需要重寫getItem(int)和getCount()就可以了。
二、具體實現
1、介面卡實現——FragmentPagerAdapter
先看完整程式碼,再細講:
- public class FragAdapter extends FragmentPagerAdapter {
- private List<Fragment> mFragments;
- public FragAdapter(FragmentManager fm,List<Fragment> fragments) {
- super(fm);
- // TODO Auto-generated constructor stub
- mFragments=fragments;
- }
- @Override
- public Fragment getItem(int arg0) {
- // TODO Auto-generated method stub
- return mFragments.get(arg0);
- }
- @Override
- public int getCount() {
- // TODO Auto-generated method stub
- return mFragments.size();
- }
- }
這裡有三個函式,根據第一部分的官方文件,可知,對於FragmentPagerAdapter的派生類,只重寫getItem(int)和getCount()就可以了。
對於建構函式,這裡申請了一個Fragment的List物件,用於儲存用於滑動的Fragment物件,並在創造函式中初始化:
- public FragAdapter(FragmentManager fm,List<Fragment> fragments) {
- super(fm);
- // TODO Auto-generated constructor stub
- mFragments=fragments;
- }
然後在getItem(int arg0)中,根據傳來的引數arg0,來返回當前要顯示的fragment,下面是getItem的官方解釋,難度不大,不再細講。
public abstract Fragment getItem (int position)
Return the Fragment associated with a specified position.
最後,getCount()返回用於滑動的fragment總數; 從建構函式所以看出,我們要構造Fragment的集合才行,所以下面我們就先產生我們所需要的Fragment類;
2、三個Fragment類
第一個Fragment類:
XML:(layout1.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"
- android:background="#ffffff"
- android:orientation="vertical" >
- <Button android:id="@+id/fragment1_btn"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="show toast"
- />
- </LinearLayout>
在其中加入了一個Btn
Java程式碼:
- public class Fragment1 extends Fragment {
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- // TODO Auto-generated method stub
- View view= inflater.inflate(R.layout.layout1, container, false);
- //對View中控制元件的操作方法
- Button btn = (Button)view.findViewById(R.id.fragment1_btn);
- btn.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // TODO Auto-generated method stub
- Toast.makeText(getActivity(), "點選了第一個fragment的BTN", Toast.LENGTH_SHORT).show();
- }
- });
- return view;
- }
- }
在onCreateView()中返回要顯示的View,上面這段程式碼簡單演示瞭如何對視圖裡的控制元件進行操作,難度不大,不再細講,如果對Fragment不太熟悉的同學,先看看這篇文章:《Android Fragment完全解析,關於碎片你所需知道的一切》
第二個Fragment類:
XML程式碼:(layout2.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"
- android:background="#ffff00"
- android:orientation="vertical" >
- </LinearLayout>
java程式碼: [java] view plain copy
- public class Fragment2 extends Fragment {
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- // TODO Auto-generated method stub
- View view=inflater.inflate(R.layout.layout2, container, false);
- return view;
- }
- }
第三個Fragment類:
XML程式碼:(layout3.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"
- android:background="#ff00ff"
- android:orientation="vertical" >
- </LinearLayout>
java程式碼: [java] view plain copy
- public class Fragment3 extends Fragment {
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- // TODO Auto-generated method stub
- View view=inflater.inflate(R.layout.layout3, container, false);
- return view;
- }
- }
3、主activity實現
核心程式碼:
- public class MainActivity extends FragmentActivity {
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- //構造介面卡
- List<Fragment> fragments=new ArrayList<Fragment>();
- fragments.add(new Fragment1());
- fragments.add(new Fragment2());
- fragments.add(new Fragment3());
- FragAdapter adapter = new FragAdapter(getSupportFragmentManager(), fragments);
- //設定介面卡
- ViewPager vp = (ViewPager)findViewById(R.id.viewpager);
- vp.setAdapter(adapter);
- }
- }
首先有一個最值得注意的地方:Activity派生自FragmentActivity,其實這是有關Fragment的基礎知識,只有FragmentActivity才能內嵌fragment頁面,普通Activity是不行的。
這段程式碼主要分為兩步,第一步:構造介面卡;第二步:設定介面卡。
先看構造介面卡的過程:
- //構造介面卡
- List<Fragment> fragments=new ArrayList<Fragment>();
- fragments.add(new Fragment1());
- fragments.add(new Fragment2());
- fragments.add(new Fragment3());
- FragAdapter adapter = new FragAdapter(getSupportFragmentManager(), fragments);
構造一個fragment列表,然後將上面的三個Fragment類對應的例項新增進去,最後生成FragAdapter例項。 至於第二步,設定介面卡,沒什麼好講的。
4、可能出現的問題
問題:在MainActivity中,當寫到這句:fragments.add(new Fragment1()); 向Fragment列表中新增Fragement物件例項時,會提示“無法將Fragment1()轉換為fragment”
解決辦法 :這是因為匯入包不一致,一般的問題在於:在Fragment1中匯入的是android.app.Fragment, 而在這裡匯入類確是:android.support.v4.app.Fragment,包不同當然無法轉換,統一匯入為android.support.v4.app.Fragment之後就正常了.參考文章《android之cannot convert from Fragment1 to Fragment》