最近想起ViwPager+Fragment一起使用的问题,于是就搞了Demo,随便使用了下TabLayout+ViewPager感觉效果还不错.在这里记录一下便于自己日后使用,也可以和大家分享下.
一,首先TabLayout+ViewPager的搭配使用
①因TabLayout是Design包的首先需要第一步导入Design包,AS直接中央仓库下载或者在dependencies中配置也可以
compile 'com.android.support:design:25.1.0'
②ViewPager+TabLayout的XML布局文件,很简单就二个控件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!--tabIndicatorColor:设置选中下划线颜色;tabTextColor:默认字体颜色
tabSelectedTextColor: 选中字体颜色
-->
<android.support.design.widget.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="40dp"
app:tabIndicatorColor="#E81010"
app:tabSelectedTextColor="@color/colorPrimary"
app:tabTextColor="#A2C437" />
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
③它们一起使用代码,一些重要的都已经备注就不多废话啦
public class MainActivity extends AppCompatActivity {
private TabLayout mTabLayout;
private ViewPager mViewPager;
private List<String> tabTitle=new ArrayList<>();
private List<Fragment> fragmentList=new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
setTabLaout();
initData();
}
private void initView() {
mTabLayout = (TabLayout) findViewById(R.id.tabLayout);
mViewPager = (ViewPager) findViewById(R.id.viewPager);
}
private void initData() {
fragmentList.add(new FirstFragment());
fragmentList.add(new SecondFragment());
fragmentList.add(new ThirdFragment());
fragmentList.add(new FourthFragment());
fragmentList.add(new FivethFragment());
fragmentList.add(new SixthFragment());
mTabLayout.setTabMode(TabLayout.MODE_FIXED);//MODE_FIXED:根据屏幕填充;MODE_SCROLLABLE :超出屏幕左右滑动
mViewPager.setAdapter(new TabFragmentAdapter(getSupportFragmentManager(),fragmentList,tabTitle));
mTabLayout.setupWithViewPager(mViewPager);//设置TabLayout和ViewPager一起使用
mViewPager.setOffscreenPageLimit(2);
}
private void setTabLaout() {
tabTitle.add("第一个");
tabTitle.add("第二个");
tabTitle.add("第三个");
tabTitle.add("第四个");
tabTitle.add("第五个");
tabTitle.add("第六个");
mTabLayout.addTab(mTabLayout.newTab().setText(tabTitle.get(0)));
mTabLayout.addTab(mTabLayout.newTab().setText(tabTitle.get(1)));
mTabLayout.addTab(mTabLayout.newTab().setText(tabTitle.get(2)));
mTabLayout.addTab(mTabLayout.newTab().setText(tabTitle.get(3)));
mTabLayout.addTab(mTabLayout.newTab().setText(tabTitle.get(4)));
mTabLayout.addTab(mTabLayout.newTab().setText(tabTitle.get(5)));
}
}
ViewPager的FragmentPagerAdapter
public class TabFragmentAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList;
private final List<String> mTabTitle;
public TabFragmentAdapter(FragmentManager fm, List<Fragment> fragmentList, List<String> tabTitle) {
super(fm);
this.mFragmentList=fragmentList;
this.mTabTitle=tabTitle;
}
@Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
@Override
public int getCount() {
return mFragmentList.size();
}
@Override
public CharSequence getPageTitle(int position) {
return mTabTitle.get(position % mTabTitle.size());
}
}
二,主角出来啦,解决ViewPager的预加载问题和Fragment的销毁问题
ViewPager的预加载问题是指:应用在打开一个Fragment的时候它会多加载左右各一个Fragment的数据,造成的影响是当用户不需要查看其它Fragment的时候造成数据浪费问题.为了避免这种情况发生我们通常在应用中会做出处理.:
①建立一个BaseFragment类继承Fragment
public abstract class BaseFragment extends Fragment {
abstract View initView();
protected boolean isVisible;
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {//用户可见时调用数据
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser){
isVisible=true;
onVisible();
}else {
isVisible=false;
onInVisible();
}
}
protected void onVisible() { //可见时加载数据
Loading();
}
protected abstract void Loading();
protected void onInVisible() { //不可见时不加载数据
}
}
②其他Fragment继承BaseFragment,并重新Loading()方法(因都是相同操作就直接下一个Fragment啦)
public class FirstFragment extends BaseFragment {
private boolean isPrepared;//初始化是否完成
private boolean isHasLoadedOnce; //是否已经有过一次加载数据
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
isPrepared=true;
TextView textView = new TextView(getContext());
textView.setGravity(Gravity.CENTER);
textView.setTextSize(30);
textView.setTextColor(Color.BLUE);
textView.setText("我是第一个Fragment");
return textView;
}
@Override
View initView() {
//返回Viw
return null;
}
@Override
protected void Loading() {
if (!isVisible||!isPrepared||isHasLoadedOnce){
return;
}else {
new AsyncTask<Void, Void, Boolean>() {
@Override
protected void onPreExecute() { //网络数据加载前
super.onPreExecute();
}
@Override
protected Boolean doInBackground(Void... params) { //网络数据加载中,此方法是在后台运行
return null;
}
@Override
protected void onPostExecute(Boolean sucess) {//网络数据加载后
super.onPostExecute(sucess);
if (sucess){
isHasLoadedOnce=true;
}
}
};
}
}
}
2,防止Fragment销毁的方法.(方法针对fragment中数据量不是很大,对内存消耗不是很在意)
①ViewPager重写setOffscreenPageLimit()方法,其值默认为1。若是设置成2,可见Fragment左右各二个对用户体验较好;
mViewPager.setOffscreenPageLimit(2);
②重写ViewPager的适配器FragmentPagerAdapter,注释其返回值 //super.destroyItem(container, position, object);
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
//super.destroyItem(container, position, object); 避免多出销毁Fragment
}
3,避免FragmentMent多次创建
BaseFragment基类中重写onCReatView()方法定义初始化抽象方法view,这样子类继承BaseFragment的时候就只创建一次,避免多个子类都创建
protected View mView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mView =initView();
return mView;
}
abstract View initView();
三,在使用tabLayout适配平板出现title字体不居中的问题解决方法
在布局文件中添加:
app:tabMaxWidth="0dp"
app:tabGravity="fill"
app:tabMode="fixed"