前言
之前寫了一個簡單的ViewPager範本。簡單ViewPager頁面 banner自動擴充實現
http://nikeru8.blogspot.tw/2017/11/androidviewpager-viewpager-banner.html
這篇偏向Banner
現在寫的FragmentPagerAdapter偏向頁面的使用方式
如下圖
重點程式碼
step one — FragmentPagerAdapter建構先來看Adapter的部分 FragmentPagerAdapter
需要有幾個方法要複寫
//必要建構子 public adapter(FragmentManager fm) { super(fm); } //你想要顯示的Fragment @Override public Fragment getItem(int position) { return null; } //要顯示的筆數 @Override public int getCount() { return 0; }
step two – Fragment
再來就是Fragment的部分
在開始前,先來看一下Fragment的生命週期
在這邊我們可以複寫onCreate、onCreateView
並創建newInstance
newInstance可以自動創建
public static FragmentSingle newInstance() { //這邊設計呼叫Fragment的方式,Bundle內可以從activity > adapter 帶參數過來 Bundle args = new Bundle(); FragmentSingle fragment = new FragmentSingle(); fragment.setArguments(args); return fragment; }newInstance使用Bundle接參數帶入fragment。
在onCreate的地方真正的把參數帶到fragment內
//繼承fragment後,直接打newInstance會自動生成此方法,裡面都幫你建置好Bundle類了 public static CreateFragment newInstance(int showType, String content) { //Bundle接收傳過來的參數 Bundle args = new Bundle(); args.putInt("showType", showType); args.putString("content", content); CreateFragment fragment = new CreateFragment(); fragment.setArguments(args); return fragment; } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); //帶入參數 showType = getArguments().getInt("showType"); content = getArguments().getString("content"); }
接下來還要複寫兩種方法
onCreateView 和 onViewCreated
onCreateView:用來創建Layout xml的,你想創建什麼型態的xml也可以設定在這裡,有在上方圖片的生命週期內
onViewCreated:用來取得參數,理所當然的這個方法就會在onCreateView之後,使用getView()這個方法取得xml內的id
這邊舉個onViewCreated的使用
@Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); TextView message = getView().findViewById(R.id.item_one); message.setText(content); }
大致上這樣。
這邊說明一下比較妥當的使用時機。
我是希望程式碼已不攏長,可讀性為主,所以可以的話,讓頁面長的雷同的地方再使用會比較好。
舉個例子:
像是這個App這頁面,有著高相似性的頁面,使用這方法就會是上上之選。
STEP THREE –
Fragment寫好後可以把它塞入Adapter內了
public class CustomFragmentAdapter extends FragmentPagerAdapter { String mTitleOne, mTitleTwo; public CustomFragmentAdapter(FragmentManager fm) { super(fm); } public void setDataOne(String messgae) { //這邊你可以在activity內獲取資料,再利用getItem傳入CreateFragment mTitleOne = messgae; notifyDataSetChanged(); } public void setDataTwo(String message) { //這邊你可以在activity內獲取資料,再利用getItem傳入CreateFragment mTitleTwo = message; notifyDataSetChanged(); } @Override public Fragment getItem(int position) { //創作每一個Fragment內的內容 if (position == 0) {//第一頁 return new CreateFragment().newInstance(position, mTitleOne); } else {//第二頁 return new CreateFragment().newInstance(position, mTitleTwo); } } @Override public int getCount() { //你得Fragment頁面數 return 2; } }
說明我寫在方法的上方。
此時你會看到我多寫了兩個方法setDataOne和setDataTwo
如果你兩個頁面的內容相差很多,要帶入不同的參數進去,可以使用這個方法和Activity要資料,在getItem內new不同的Fragment把資料帶進去。
當然你也可以直接寫在Adapter建構子內直接取值,但如果之後需要刷新fragment內的資料就要重新new一個Adapter,不是很聰明的作法。
完整程式碼
今日會動到的地方簡單一個ViewPager
activity_main.xml |
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.hello.kaiser.fragment.MainActivity"> <android.support.v4.view.ViewPager android:id="@+id/view_pager" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/darker_gray" /> </RelativeLayout>
create_fragment_one.xml |
你
<?xml version="1.0" encoding="utf-8"?> <LinearLayout android:background="@color/colorPrimary" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/item_one" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="one" android:textSize="40sp" /> </LinearLayout>
create_fragment_two.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="@color/colorAccent" android:orientation="vertical"> <TextView android:id="@+id/item_two" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="two" android:textSize="40sp" /> </LinearLayout>
畫面畫好了 來看程式碼吧
CustomFragmentAdapter.java
public class CustomFragmentAdapter extends FragmentPagerAdapter { String mTitleOne, mTitleTwo; public CustomFragmentAdapter(FragmentManager fm) { super(fm); } public void setDataOne(String messgae) { //這邊你可以在activity內獲取資料,再利用getItem傳入CreateFragment mTitleOne = messgae; notifyDataSetChanged(); } public void setDataTwo(String message) { //這邊你可以在activity內獲取資料,再利用getItem傳入CreateFragment mTitleTwo = message; notifyDataSetChanged(); } @Override public Fragment getItem(int position) { //創作每一個Fragment內的內容 if (position == 0) {//第一頁 return new CreateFragment().newInstance(position, mTitleOne); } else {//第二頁 return new CreateFragment().newInstance(position, mTitleTwo); } } @Override public int getCount() { //你得Fragment頁面數 return 2; } }
CreateFragment.java
public class CreateFragment extends Fragment { private int showType; private String content; private Context context; //繼承fragment後,直接打newInstance會自動生成此方法,裡面都幫你建置好Bundle類了 public static CreateFragment newInstance(int showType, String content) { //Bundle接收傳過來的參數 Bundle args = new Bundle(); args.putInt("showType", showType); args.putString("content", content); CreateFragment fragment = new CreateFragment(); fragment.setArguments(args); return fragment; } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); //帶入參數 showType = getArguments().getInt("showType"); content = getArguments().getString("content"); } @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { Log.d("checkpoint", "onCreateView onCreateView"); if ("0".equals(String.valueOf(showType))) {//第一頁 return LayoutInflater.from(context).inflate(R.layout.create_fragment_one, null); } else if ("1".equals(String.valueOf(showType))) {//第二頁 return LayoutInflater.from(context).inflate(R.layout.create_fragment_two, null); } else { return null; } } @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { Log.d("checkpoint", "checkonViewCreatedpoint onViewCreated"); super.onViewCreated(view, savedInstanceState); if (showType == 0) {//第一頁 TextView message = getView().findViewById(R.id.item_one); message.setText(content); } else if (showType == 1) {//第二頁 TextView message = getView().findViewById(R.id.item_two); message.setText(content); } } @Override public void onAttach(Context context) { super.onAttach(context); this.context = context; } }
MainActivity.java
public class MainActivity extends AppCompatActivity { private ViewPager mViewPager; private CustomFragmentAdapter mAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initSet(); } private void initView() { mViewPager = (ViewPager) findViewById(R.id.view_pager); } private void initSet() { mAdapter = new CustomFragmentAdapter(getSupportFragmentManager()); mViewPager.setAdapter(mAdapter); mAdapter.setDataOne("你好第一頁"); mAdapter.setDataTwo("歡迎光靈第二頁 hello "); } }
DEMO
https://github.com/nikeru8/FragmentPagerAdapterDemo/tree/master
歡迎交流喔!
Fragment全集
Fragment的使用(一) ─ 在activity內放置Fragment
Fragment的使用(二) ─ 在activity內切換Fragment
Fragment 返回上一頁 - OnBackPressed
Fragment點擊穿透
FragmentPagerAdapter
沒有留言:
張貼留言