先说ViewPage+Fragment嵌套ViewPage+Fragment滑动时内部嵌套卡顿和白屏的问题:具体导致原因没有深入去追究,只记录两种实现方案:
- **第一种就是将内部的Fragment替换掉,写一个抽象的Base类,Base类中的布局就一个容器,见代码:
Base类
public abstract class BasePage {
public Activity mActivity;
public View mRootView;//布局对象
public TextView tvTitle;//标题对象
public FrameLayout flContent;//内容
public BasePage(Activity mActivity) {
this.mActivity = mActivity;
init();
initData();
}
private void init() {
mRootView = View.inflate(mActivity, R.layout.base_pager, null);
flContent = (FrameLayout) mRootView.findViewById(R.id.fl_content);
flContent.addView(initView());
}
/**
* 初始化布局
*/
public abstract View initView();
/**
* 初始化数据
*/
public abstract void initData();
}
让子类实现该抽象类,并将布局返回即可,见代码:
public class ExtendsMyFragment extends BasePage {
private MyViewPage viewPager;
private TabLayout tabLayout;
private List<BasePage> list;
private BasePage fragment1, fragment2, fragment3, fragment4;
private FragmentManager manager;
private List<String> titles;
public ExtendsMyFragment(Activity activity) {
super(activity);
}
private void addFragment() {
list = new ArrayList<>();
fragment1 = new MytoFragment(mActivity);
fragment2 = new MytoFragment(mActivity);
fragment3 = new MytoFragment(mActivity);
fragment4 = new MytoFragment(mActivity);
list.add(fragment1);
list.add(fragment2);
list.add(fragment3);
list.add(fragment4);
}
@Override
public View initView() {
View view = LayoutInflater.from(mActivity).inflate(R.layout.extends_fragemnt, null, false);
viewPager = (MyViewPage) view.findViewById(R.id.viewpage);
tabLayout = (TabLayout) view.findViewById(R.id.tablayout);
return view;
}
@Override
public void initData() {
addFragment();
titles = new ArrayList<>();
titles.add("菜单1");
titles.add("菜单2");
titles.add("菜单3");
titles.add("菜单4");
viewPager.setAdapter(new MyAdapter());
tabLayout.setupWithViewPager(viewPager);
}
//注意,此时已经不是Fragment,所以不用继承FragmentPagerAdapter而是继承PagerAdapter
class MyAdapter extends PagerAdapter {
@Override
public int getCount() {
return list.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
BasePage pager = list.get(position);
container.addView(pager.mRootView);
// pager.initData();//初始化数据。。。。不要放在此处初始化数据,否则会预加载下一个页面
return pager.mRootView;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
@Override
public CharSequence getPageTitle(int position) {
return titles.get(position);
}
}
}
然后MainActivity中的代码和ExtendsMyFragment 中的代码基本一样就不贴了,只是这样虽然实现了嵌套滑动,但总体步骤还是略显繁琐,效果图如下:
下面介绍第二种实现方式废话不多说,直接上代码:
public class MainActivity extends AppCompatActivity {
private ViewPager viewPager;
private TabLayout tabLayout;
private List<Fragment> list;
private MyFragment2 fragment2, fragment3, fragment4;
private ExtendsMyFragment2 extendsMyFragment;
private String[] titles = {"页面1", "页面2", "页面3", "页面4"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_first);
addFragment();
viewPager = (ViewPager) findViewById(R.id.viewpage);
tabLayout = (TabLayout) findViewById(R.id.tablayout);
//注意下面这行代码
viewPager.setAdapter(new MyAdapter(getSupportFragmentManager()));
tabLayout.setupWithViewPager(viewPager);
}
private void addFragment() {
list = new ArrayList<>();
extendsMyFragment = new ExtendsMyFragment2();
fragment2 = new MyFragment2();
fragment3 = new MyFragment2();
fragment4 = new MyFragment2();
//下面Bundle相关的都是用来跟fragment传递参数的
Bundle bundle1 = new Bundle();
Bundle bundle2 = new Bundle();
Bundle bundle3 = new Bundle();
Bundle bundle4 = new Bundle();
bundle1.putString("name", "extendsMyFragment");
bundle2.putString("name", "fragment2");
bundle3.putString("name", "fragment3");
bundle4.putString("name", "fragment4");
extendsMyFragment.setArguments(bundle1);
fragment2.setArguments(bundle2);
fragment3.setArguments(bundle3);
fragment4.setArguments(bundle4);
list.add(extendsMyFragment);
list.add(fragment2);
list.add(fragment3);
list.add(fragment4);
}
class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
return list.get(position);
}
@Override
public int getCount() {
return list.size();
}
//重写这个方法,将设置每个Tab的标题
@Override
public CharSequence getPageTitle(int position) {
return titles[position];
}
}
}
Fragment中的代码:ExtendsMyFragment2 和MyFragment2 相比就多了一个嵌套的代码其他都一样,所以直接看ExtendsMyFragment2 中的代码。
public class ExtendsMyFragment2 extends Fragment {
private ViewPager viewPager;
private TabLayout tabLayout;
private List<Fragment> list;
private MyFragment2 fragment1, fragment2, fragment3, fragment4;
private List<String> titles;
private void addFragment() {
list = new ArrayList<>();
fragment1 = new MyFragment2();
fragment2 = new MyFragment2();
fragment3 = new MyFragment2();
fragment4 = new MyFragment2();
Bundle bundle1 = new Bundle();
Bundle bundle2 = new Bundle();
Bundle bundle3 = new Bundle();
Bundle bundle4 = new Bundle();
bundle1.putString("name", "fragment1");
bundle1.putString("tag", "fragment1");
bundle2.putString("name", "fragment2");
bundle2.putString("tag", "fragment2");
bundle3.putString("name", "fragment3");
bundle3.putString("tag", "fragment3");
bundle4.putString("name", "fragment4");
bundle4.putString("tag", "fragment4");
fragment1.setArguments(bundle1);
fragment2.setArguments(bundle2);
fragment3.setArguments(bundle3);
fragment4.setArguments(bundle4);
list.add(fragment1);
list.add(fragment2);
list.add(fragment3);
list.add(fragment4);
titles = new ArrayList<>();
titles.add("菜单1");
titles.add("菜单2");
titles.add("菜单3");
titles.add("菜单4");
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addFragment();
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.extends_fragemnt, container, false);
viewPager = (ViewPager) view.findViewById(R.id.viewpage);
tabLayout = (TabLayout) view.findViewById(R.id.tablayout);
//注意这里。如果这里不用getChildFragmentManager会卡顿白屏
viewPager.setAdapter(new MyAdapter(getChildFragmentManager()));
tabLayout.setupWithViewPager(viewPager);
return view;
}
class MyAdapter extends FragmentPagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
return list.get(position);
}
@Override
public int getCount() {
return list.size();
}
//重写这个方法,将设置每个Tab的标题
@Override
public CharSequence getPageTitle(int position) {
return titles.get(position);
}
}
}
就改这一句就可以了。想看源码的可以参照这位大神的博客,我的第二个方案也是仿照他的例子。黑暗中的一盏明灯的博客
下面介绍一下ViewPage+Fragment的懒加载
大家应该都知道ViewPage会默认缓存当前页及相邻的一个页面来提高流畅度,这样就会加大流量的消耗。如果想实现懒加载也有2种方式。第一种通过ViewPage来实现,让他不缓存相邻的页面;第二种通过Fragment来实现。
**下面主要说第二种:**
即重写Fragment的setUserVisibleHint方法,将网络请求的方法放入该方法中即可,是不是特别简单。参考链接是[傲寒遥的博客](http://www.jianshu.com/p/038229effa43)