2015年8月19日 星期三

ViewPager

簡介:

透過滑動螢幕,達到切換不同頁面的效果。只要實作 PagerAdapter,就能顯示各個頁面要顯示的內容,每一頁是由一個 Fragment來呈現。
實作 PagerAdapter方面,通常會實作繼承自 PagerAdapter的 FragmentPagerAdapter和 FragmentStatePagerAdapter。Pager的頁面少使用 FragmentPagerAdapter,反之,則使用FragmentStatePagerAdapter。

Code snippet:

@Override
public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // add view pager
        mSectionsPagerAdapter = new SectionsPagerAdapter(getFragmentManager());
        // Set up the ViewPager with the sections adapter.
        mViewPager = (ViewPager) v.findViewById(R.id.pager);
        mViewPager.setAdapter(mSectionsPagerAdapter);
        .........
}

public class SectionsPagerAdapter extends FragmentPagerAdapter{
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}

@Override
public Fragment getItem(int position) {
Fragment fragment = null;
switch (position){
case 0:
fragment = FirstFragment.newInstance();
break;
case 1:
fragment = SecondFragment.newInstance();
break;
case 2:
fragment = ThirdFragment.newInstance();
break;
default:
break;
}
return fragment;
}

@Override
public int getCount() {
return NUMBERS_OF_PAGER;
}

@Override
public CharSequence getPageTitle(int position) {
Locale l = Locale.getDefault();
Resources res = getActivity().getResources();
switch (position) {
case 0:
return res.getText(R.string.tab_title_showcase).toString().toUpperCase(l);
case 1:
return res.getText(R.string.tab_title_favorite).toString().toUpperCase(l);
case 2:
return res.getText(R.string.tab_title_recent).toString().toUpperCase(l);
                                ...................
default:
break;
}
return null;
}
}

Critical issue:

https://code.google.com/p/android/issues/detail?id=55068
ViewPager doesn't refresh child fragments when back navigation via backstack

當 FragmentA實作一個 ViewPager,在設定 PagerAdapter的建構子時,要使用 getChildFragmentManager() 取代 getFragmentManager()
官方文件說明如下:

public final FragmentManager getChildFragmentManager ()

Added in API level 17
Return a private FragmentManager for placing and managing Fragments inside of this Fragment.
若使用 getFragmentManager(),當 FragmentA透過 FragmentTransaction跳到 FragmentB,再按 Back鍵回到 Fragment時,ViewPager裡的 Fragment會發生顯示異常
(若要按 Back鍵讓 FragmentB能回到 FragmentA,FragmentTransaction要執行下面程式localFragmentTransaction.addToBackStack(null))
若是由 ViewPager裡的 Fragment利用 FragmentTransaction跳到 FragmentB,要透過 getActivity()取得的 Activity object,來執行 replace(),否則會因為找不到 FragmentA、B容器的 container的resource id而發生 IllegalArgumentException

08-17 16:22:02.328: D/AndroidRuntime(1605): Shutting down VM
08-17 16:22:02.329: E/AndroidRuntime(1605): FATAL EXCEPTION: main
08-17 16:22:02.329: E/AndroidRuntime(1605): Process: org.cyanogenmod.theme.chooser, PID: 1605
08-17 16:22:02.329: E/AndroidRuntime(1605): java.lang.IllegalArgumentException: No view found for id 0x7f0d0003 (org.cyanogenmod.theme.chooser:id/content) for fragment ChooserDetailFragment{25b7e683 #2 id=0x7f0d0003 class org.cyanogenmod.theme.chooser.ChooserDetailFragment}

沒有留言: