Tablayout+Viewpager+Fragment組合使用以及懶載入機制

getan525發表於2018-04-20

下面這個介面在日常開發中簡直太常見不過了,viewpager+fragment組合出來的效果!

                              

首先介紹一下使用方法:

xml檔案

[java]  view plain  copy
  1. <android.support.design.widget.TabLayout  
  2.        android:id="@+id/tab_layout"  
  3.        android:layout_width="match_parent"  
  4.        android:layout_height="wrap_content"  
  5.        android:background="#EF8D11"  
  6.        app:tabIndicatorColor="#EF4A11"  
  7.        app:tabMode="scrollable"  
  8.        app:tabSelectedTextColor="#FFFFFF"  
  9.        app:tabTextAppearance="@style/MyTabLayoutTextAppearance"  
  10.        app:tabTextColor="#FFFFFF" />  
  11.    <android.support.v4.view.ViewPager  
  12.        android:id="@+id/view_pager"  
  13.        android:layout_width="match_parent"  
  14.        android:layout_height="match_parent" />  

屬性說明:
android:background="#EF8D11" 背景色
app:tabIndicatorColor="#EF4A11" tab文字下方的那條線的顏色
app:tabMode="scrollable" 如果tab過多超出螢幕寬度可以水平滾動
app:tabSelectedTextColor="#FFFFFF" tab被選中的時候文字的顏色
app:tabTextColor="#FFFFFF" tab未被選中時文字的顏色
app:tabTextAppearance="@style/MyTabLayoutTextAppearance" 自定義字型大小(一般使用預設即可)

1
2
3
<style name="MyTabLayoutTextAppearance" parent="TextAppearance.AppCompat.Widget.ActionBar.Title.Inverse">
    <item name="android:textSize">12sp</item>
</style>

java 程式碼

[java]  view plain  copy
  1. private void initView(View view) {  
  2.   
  3.     mTablayout = (TabLayout) view.findViewById(R.id.tab_layout);  
  4.     //mTablayout.setTabMode(TabLayout.MODE_SCROLLABLE);//擠在一起顯示  
  5.     viewpager = (ViewPager) view.findViewById(R.id.viewpager);  
  6.     setupViewPager(viewpager);  
  7.     mTablayout.addTab(mTablayout.newTab().setText("頭條"));  
  8.     mTablayout.addTab(mTablayout.newTab().setText("NBA"));  
  9.     mTablayout.addTab(mTablayout.newTab().setText("汽車"));  
  10.     mTablayout.addTab(mTablayout.newTab().setText("笑話"));  
  11.   
  12.     mTablayout.setupWithViewPager(viewpager);  
  13.   
  14. }  
  15.   
  16. private void setupViewPager(ViewPager viewpager) {  
  17.     MyPagerAdapter adapter=new MyPagerAdapter(getChildFragmentManager());  
  18.     adapter.addFragment(FirstListFragment.newInstance(ONE),"頭條");  
  19.     adapter.addFragment(FirstListFragment.newInstance(TWO),"NBA");  
  20.     adapter.addFragment(FirstListFragment.newInstance(THREE),"汽車");  
  21.     adapter.addFragment(FirstListFragment.newInstance(FOUR),"笑話");  
  22.     viewpager.setAdapter(adapter);  
  23. }  
MyPagerAdaper

[java]  view plain  copy
  1. public  static class MyPagerAdapter extends FragmentPagerAdapter{  
  2.        private final List<Fragment> mFragment=new ArrayList<Fragment>();  
  3.        private final List<String> mFragmentTitle=new ArrayList<String>();  
  4.   
  5.        public void addFragment(Fragment  fragment,String title){  
  6.            mFragment.add(fragment);  
  7.            mFragmentTitle.add(title);  
  8.        }  
  9.        public MyPagerAdapter(FragmentManager fm) {  
  10.            super(fm);  
  11.        }  
  12.   
  13.        @Override  
  14.        public Fragment getItem(int position) {  
  15.            return mFragment.get(position);  
  16.        }  
  17.   
  18.        @Override  
  19.        public int getCount() {  
  20.            return mFragment.size();  
  21.   
  22.        }  
  23.        @Override  
  24.        public CharSequence getPageTitle(int position) {  
  25.            return mFragmentTitle.get(position);  
  26.        }  
  27.    }  

懶載入定義

Fragment的UI介面對使用者可見的時候才載入資料。

怎麼判斷什麼是否對使用者可見呢?

[java]  view plain  copy
  1. public void setUserVisibleHint(boolean isVisibleToUser) {  
  2.         super.setUserVisibleHint(isVisibleToUser);  
  3.         if (getUserVisibleHint()) {  
  4.             //可見  
  5.         } else {  
  6.             //不可見  
  7.         }  
  8.     }  

注意:fragment的緩載入,優先於oncreate方法執行,且每次切換fragment都會執行此方法!

程式碼

為了方便,封裝一個基類 LazyLoadFragment,提供一個 loadData() 方法供呼叫去載入資料

[java]  view plain  copy
  1. public abstract class LazyLoadFragment extends Fragment {  
  2.   
  3.     /** 
  4.      * 控制元件是否初始化完成 
  5.      */  
  6.     private boolean isViewCreated;  
  7.     /** 
  8.      * 資料是否已載入完畢 
  9.      */  
  10.     private boolean isLoadDataCompleted;  
  11.   
  12.     @Nullable  
  13.     @Override  
  14.     public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {  
  15.         View view = inflater.inflate(getLayout(), container, false);  
  16.         initViews(view);  
  17.         isViewCreated = true;  
  18.         return view;  
  19.     }  
  20.   
  21.     public abstract int getLayout();  
  22.     public abstract void initViews(View view);  
  23.   
  24.     @Override  
  25.     public void setUserVisibleHint(boolean isVisibleToUser) {  
  26.         super.setUserVisibleHint(isVisibleToUser);  
  27.         if (isVisibleToUser && isViewCreated && !isLoadDataCompleted) {  
  28.             isLoadDataCompleted = true;  
  29.             loadData();  
  30.         }  
  31.     }  
  32.   
  33.     @Override  
  34.     public void onActivityCreated(@Nullable Bundle savedInstanceState) {  
  35.         super.onActivityCreated(savedInstanceState);  
  36.   
  37.         if (getUserVisibleHint()) {  
  38.             isLoadDataCompleted = true;  
  39.             loadData();  
  40.         }  
  41.     }  
  42.   
  43.     /** 
  44.      * 子類實現載入資料的方法 
  45.      */  
  46.     public abstract  void loadData();  
注:

      為什麼 loadData() 會在兩個地方執行?在 setUserVisibleHint 方法裡執行我還能理解,為什麼 onActivityCreated 也要執行呢?

        因為,ViewPager 預設顯示第一頁,第一頁肯定要先載入資料,而且 setUserVisibleHint 的執行順序又是在 onCreatView 之前,同時 onCreatView 需要初始化介面和修改 isViewCreated 的值。所以就需要在 onActivityCreated 裡執行一次。

相關文章