1、概述
從前面幾篇文章,咱們知道,實現ViewPager是要有適配器的,咱們前面用的適配器是PagerAdapter,而對於fragment,它所使用的適配器是:FragmentPagerAdapter.先看看官方對於這個類的解釋:(英文下面有中文解釋)html
原文:java
Class Overview
Implementation of PagerAdapter
that represents each page as a Fragment
that is persistently kept in the fragment manager as long as the user can return to the page.android
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 FragmentStatePagerAdapter
.api
When using FragmentPagerAdapter the host ViewPager must have a valid ID set.app
Subclasses only need to implement getItem(int)
and getCount()
to have a working adapter.ide
譯文:(譯的很差,你們可在評論中補充)函數
FragmentPagerAdapter派生自PagerAdapter,它是用來呈現Fragment頁面的,這些Fragment頁面會一直保存在fragment manager中,以便用戶能夠隨時取用。oop
這個適配器最好用於有限個靜態fragment頁面的管理。儘管不可見的視圖有時會被銷燬,但用戶全部訪問過的fragment都會被保存在內存中。所以fragment實例會保存大量的各類狀態,這就形成了很大的內存開銷。因此若是要處理大量的頁面切換,建議使用FragmentStatePagerAdapter.spa
每個使用FragmentPagerAdapter的ViewPager都要有一個有效的ID集。(沒理解什麼意思).net
對於FragmentPagerAdapter的派生類,只須要重寫getItem(int)和getCount()就能夠了。
2、具體實現
一、適配器實現——FragmentPagerAdapter
先看完整代碼,再細講:
- public class FragAdapter extends FragmentPagerAdapter {
-
- private List<Fragment> mFragments;
-
- public FragAdapter(FragmentManager fm,List<Fragment> fragments) {
- super(fm);
-
- mFragments=fragments;
- }
-
- @Override
- public Fragment getItem(int arg0) {
-
- return mFragments.get(arg0);
- }
-
- @Override
- public int getCount() {
-
- return mFragments.size();
- }
-
- }
這裏有三個函數,根據第一部分的官方文檔,可知,對於FragmentPagerAdapter的派生類,只重寫getItem(int)和getCount()就能夠了。
對於構造函數,這裏申請了一個Fragment的List對象,用於保存用於滑動的Fragment對象,並在創造函數中初始化:
- public FragAdapter(FragmentManager fm,List<Fragment> fragments) {
- super(fm);
-
- 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類;
二、三個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) {
-
- View view= inflater.inflate(R.layout.layout1, container, false);
-
-
- Button btn = (Button)view.findViewById(R.id.fragment1_btn);
- btn.setOnClickListener(new View.OnClickListener() {
-
- @Override
- public void onClick(View v) {
-
- 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代碼:
- public class Fragment2 extends Fragment {
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
-
- 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代碼:
- public class Fragment3 extends Fragment {
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
-
- View view=inflater.inflate(R.layout.layout3, container, false);
- return view;
- }
-
- }
三、主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實例。
至於第二步,設定適配器,沒什麼好講的。
四、可能出現的問題
問題:在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》
轉載出處: ViewPager 詳解(五)-----使用Fragment實現ViewPager滑動