在开发中经常用到TabLayout+ViewPager+Fragment的组合。如下图所示:
首先介绍一下使用方法:
xml文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <android.support.design.widget.TabLayout android:id="@+id/tab_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#EF8D11" app:tabIndicatorColor="#EF4A11" app:tabMode="scrollable" app:tabSelectedTextColor="#FFFFFF" app:tabTextAppearance="@style/MyTabLayoutTextAppearance" app:tabTextColor="#FFFFFF" /> <android.support.v4.view.ViewPager android:id="@+id/view_pager" android:layout_width="match_parent" 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 代码
1 2 3 4 5 6 7 8 9 | private void setTabs() { HomePagerAdapter homePagerAdapter = new HomePagerAdapter(getSupportFragmentManager()); homePagerAdapter.addTab(new FragmentOne(), "tab1"); homePagerAdapter.addTab(new FragmentTwo(), "tab2"); homePagerAdapter.addTab(new FragmentThree(), "tab3"); viewPager.setAdapter(homePagerAdapter); //把tabLayout和Viewpager关联起来 tabLayout.setupWithViewPager(viewPager); } |
HomePagerAdapter.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | package com.jetsun.demo; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentStatePagerAdapter; import java.util.ArrayList; import java.util.List; /** * Overview: */ public class HomePagerAdapter extends FragmentStatePagerAdapter { private List<Fragment> fragments = new ArrayList<>(); private List<String> titles = new ArrayList<>(); public HomePagerAdapter(FragmentManager fm) { super(fm); } public void addTab(Fragment fragment, String title) { fragments.add(fragment); titles.add(title); } @Override public CharSequence getPageTitle(int position) { return titles.get(position); } @Override public Fragment getItem(int position) { return fragments.get(position); } @Override public int getCount() { return fragments.size(); } } |
懒加载机制
默认情况下,当显示tab1时,tab2已经加载了(已经调用了生命周期的oncreate,oncreateview,onactivitycreate,onresume方法),也就是默认加载当前fragment两边的一个fragment。加载的个数可以通过viewpager.setoffscreenpagelimit方法控制,模式是viewpager.setoffscreenpagelimit(1).最少也就是1,即使设置成0也默认预加载一个。假如现在的需求是要在fragment显示出来的时候才加载数据,那么通过viewpager.setoffscreenpagelimit方法是无法做到控制的。
下面就介绍另外一种方法来实现这种需求:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | package com.jetsun.demo; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import butterknife.Bind; import butterknife.ButterKnife; /** * Overview: */ public class FragmentDemo extends Fragment { @Bind(R.id.recycler_view) RecyclerView recyclerView; @Bind(R.id.swipe_refresh_layout) SwipeRefreshLayout swipeRefreshLayout; //控件是否已经初始化 private boolean isCreateView = false; @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment, null, false); ButterKnife.bind(this, view); initViews(); isCreateView = true; return view; } private void initViews() { //初始化控件 } //此方法在控件初始化前调用,所以不能在此方法中直接操作控件会出现空指针 @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (isVisibleToUser && isCreateView) { lazyLoad(); } } private void lazyLoad() { //加载数据操作 } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); //第一个fragment会调用 if (getUserVisibleHint()) lazyLoad(); } @Override public void onDestroyView() { super.onDestroyView(); ButterKnife.unbind(this); } } |
在实际开发中,可以把上面的代码抽取到BaseFragment中使用。上面这个方法实现了每次fragment显示出来的时候加载数据,但是这样切换回来的时候还会重复加载,我们只需加载一次就好了。所以改进一下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | package com.jetsun.demo; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import butterknife.Bind; import butterknife.ButterKnife; /** * Overview: */ public class FragmentDemo extends Fragment { @Bind(R.id.recycler_view) RecyclerView recyclerView; @Bind(R.id.swipe_refresh_layout) SwipeRefreshLayout swipeRefreshLayout; //控件是否已经初始化 private boolean isCreateView = false; //是否已经加载过数据 private boolean isLoadData = false; @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment, null, false); ButterKnife.bind(this, view); initViews(); isCreateView = true; return view; } private void initViews() { //初始化控件 } //此方法在控件初始化前调用,所以不能在此方法中直接操作控件会出现空指针 @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); if (isVisibleToUser && isCreateView) { lazyLoad(); } } private void lazyLoad() { //如果没有加载过就加载,否则就不再加载了 if(!isLoadData){ //加载数据操作 isLoadData=true; } } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); //第一个fragment会调用 if (getUserVisibleHint()) lazyLoad(); } @Override public void onDestroyView() { super.onDestroyView(); ButterKnife.unbind(this); } } |