3、创建适配器
为什么要创建适配器?
适配器作用是把每个单独的fragment页面放在一起打包,传给ViewPager。只有ViewPager设置了适配器我们才能看见翻页的效果。
所以我们要单独写一个类并继承 FragmentPagerAdapte
Alt + Enter 主要实现 FragmentPagerAdapter 方法和构造方法
MyFragmentStateVPAdapter 构造方法,用来接收参数
getItem 根据position来获取页面
getCount 获取页面的个数
基本方法都实现完后,我们要定义一个变量来存储我们每个fragment子页面
private List<Fragment> myFragmentList;
定义变量 myFragmentList 后,我们需要在构造方法内赋值,并在getItem 和getCount 方法进行操作,具体看下面代码
MyFragmentStateVPAdapter
package com.example.tabfragment.adapter; import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentPagerAdapter; import java.util.List; public class MyFragmentStateVPAdapter extends FragmentPagerAdapter { private List myFragmentList; public MyFragmentStateVPAdapter(@NonNull FragmentManager fm,List myFragmentList) { super(fm); this.myFragmentList = myFragmentList; } /** * 获取页面 * @param position 页面的位置 * @return 返回具体页面 */ @NonNull @Override public Fragment getItem(int position) { return myFragmentList == null ? null:myFragmentList.get(position); } /** * 获取adapter内存储的页面个数 * @return */ @Override public int getCount() { return myFragmentList == null ? 0 : myFragmentList.size(); } }
4、在 Activity_index 内整合
第一步:先确认变量确认变量
private ViewPager mViewPager; // 主页面来展示子页面 Viewpager private BottomNavigationView mBottomNavigationView; //主页面底部tab按钮 private List mFragmentList; //存储fragment页面,用来作为构造adapter的参数 private MyFragmentStateVPAdapter mStateVPAdapter;
第二步: 获取控件
private void initeView() { mViewPager = findViewById(R.id.vp); mBottomNavigationView = findViewById(R.id.bottom_nav_menu); }
第三步:准备fragment页面
因为我们要在ViewPage内滑动显示多个页面,所以我们要先把这几个页面创建好,存储到 mFragmentList,为下一步显示页面做准备
private void initData() { mFragmentList = new ArrayList<>(); VPFragment homeFragment = VPFragment.newInstance("首页", R.drawable.ji1); VPFragment recommendFragment = new VPFragment().newInstance("推荐",R.drawable.ji5); VPFragment mineFragment = new VPFragment().newInstance("我的",R.drawable.ji6); //添加页面 mFragmentList.add(homeFragment); mFragmentList.add(recommendFragment); mFragmentList.add(mineFragment); }
第四步:创建适配器,并设置监听 (页面绑定底部按钮)
我们把上一步创建好的fragment页面,作为参数来构造适配器
new MyFragmentStateVPAdapter(getSupportFragmentManager(), mFragmentList )
第一个参数:getSupportFragmentManager() 这个大家记着就可以了,固定用法
第二个参数: mFragmentList
然后让mViewPager 设置该适配器,调用setAdapter() 方法
接下来,让给mViewPager设置监听,调用addOnPageChangeListener(),目的是让mViewPager内的子页面与底部menu按钮相关联。
private void setFListener() { mStateVPAdapter = new MyFragmentStateVPAdapter(getSupportFragmentManager(),mFragmentList); mViewPager.setAdapter(mStateVPAdapter); mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {} @Override public void onPageSelected(int position) {onPagerSelected(position);} @Override public void onPageScrollStateChanged(int state) {} }); }
这里我把页面绑定底部按钮的代码提取出来了,方便大家查看。
这里我们设置监听会返回翻页面的位置,然后在该页面下绑定对于的按钮mBottomNavigationView调用 setSelectedItemId方法,传入的参数是menu内每个item的id值
//给每个页面设置按钮,页面关联按钮,页面动,按钮动 private void onPagerSelected(int position) { switch(position){ case 0: mBottomNavigationView.setSelectedItemId(R.id.menu_home); break; case 1: mBottomNavigationView.setSelectedItemId(R.id.menu_recommend); break; case 2: mBottomNavigationView.setSelectedItemId(R.id.menu_mine); break; } }
第五步:设置监听(底部按钮绑定页面)
我们还要给底部按钮设置监听(按哪个按钮,跳到对于的页面)
//反向处理,按钮设置点击事件,按钮关联页面 private void setBListener() { mBottomNavigationView.setOnItemSelectedListener(new NavigationBarView.OnItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { switch(item.getItemId()){ case R.id.menu_home: mViewPager.setCurrentItem(0); break; case R.id.menu_recommend: mViewPager.setCurrentItem(1); break; case R.id.menu_mine: mViewPager.setCurrentItem(2); break; } return true; } }); }
第六步:在onCreate方法内调用以上方法
调用以上方法并允许,结果如下
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_index); initeView(); initData(); setFListener(); setBListener(); }
5、对“首页”字页面重新设置
在开头我们会发现,“首页”对应的子页面并不只是显示一个图片,而是tab栏+四个fragment,所以我们要重新准备一个fragment类和一个新的适配器。
第一步:给子 fragment(“首页”)写一个适配器
因为新的页面顶部到导航栏有标题,所以我们要重新再写一个适配器,实现getPageTitle()方法。
getPageTitle方法用来返回每个页面的标题
package com.example.tabfragment.adapter; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentStatePagerAdapter; import java.util.List; public class MyFragmentStVpTitleAdapter extends FragmentStatePagerAdapter { private List mFragmentList; private List titleList; public MyFragmentStVpTitleAdapter(@NonNull FragmentManager fm, List mFragmentList, List titleList) { super(fm); this.mFragmentList = mFragmentList; this.titleList = titleList; } @NonNull @Override public Fragment getItem(int position) { return mFragmentList == null ? null:mFragmentList.get(position); } @Override public int getCount() { return mFragmentList==null? 0:mFragmentList.size(); } @Nullable @Override public CharSequence getPageTitle(int position) { return titleList.get(position); } }
第二步:构造VPHomeFragment 类
构造VPHomeFragment 类 跟 构造 VPfragment 的步骤是一样的,唯一不同就VPHomeFragment 类中多了一个 onCreateView 方法。
首先,VPHomeFragment 类要添加几个变量
private ViewPager mViewPager; private TabLayout mTabLayout; private List mFragmentList; private List titleList; private MyFragmentStVpTitleAdapter mStVPTitleAdapter; onCreateView 方法 @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); mViewPager = view.findViewById(R.id.home_vp); mTabLayout = view.findViewById(R.id.tab_layout); initData(); //注意此处,getChild 嵌套 mStVPTitleAdapter = new MyFragmentStVpTitleAdapter(getChildFragmentManager(),mFragmentList,titleList); mViewPager.setAdapter(mStVPTitleAdapter); mTabLayout.setupWithViewPager(mViewPager);//tab 适配页面 } private void initData() { mFragmentList = new ArrayList<>(); VPFragment vPfragment1 = VPFragment.newInstance("鸡",R.drawable.ji1); VPFragment vPfragment2 = VPFragment.newInstance("你",R.drawable.ji2); VPFragment vPfragment3 = VPFragment.newInstance("太",R.drawable.ji3); VPFragment vPfragment4 = VPFragment.newInstance("美",R.drawable.j4); mFragmentList.add(vPfragment1); mFragmentList.add(vPfragment2); mFragmentList.add(vPfragment3); mFragmentList.add(vPfragment4); titleList = new ArrayList<>(); titleList.add("鸡"); titleList.add("你"); titleList.add("太"); titleList.add("美"); }
布局
为了让首页实现下面效果,我们要对VPHomeFragment 类调用的xm文件重新布局
fragment_v_p_home.xml
android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> android:id="@+id/tab_layout" android:layout_width="match_parent" android:layout_height="wrap_content"/> android:id="@+id/home_vp" android:layout_width="match_parent" android:layout_height="match_parent"/>
最后在Activity_index.java 内把 homeFragment类型修改为 VPHomeFragment
VPHomeFragment homeFragment = VPHomeFragment.newInstance("我的",R.drawable.ji1);
gitte获取代码:点击跳转