目录

0、准备工作 

(1)结构展示

 (2)底部tab栏准备

1、创建布局  

 2、创建 VPfragment  

   (1) 构造 VPfragment 类

(2)子页面布局 fragment_v_p.xml

3、创建适配器 

4、在 Activity_index 内整合

第一步:先确认变量确认变量

第二步: 获取控件

 第三步:准备fragment页面

第四步:创建适配器,并设置监听 (页面绑定底部按钮)

第五步:设置监听(底部按钮绑定页面)

第六步:在onCreate方法内调用以上方法

5、对“首页”字页面重新设置

第一步:给子 fragment(“首页”)写一个适配器

第二步:构造VPHomeFragment 类


效果展示如下,完整代码在文章末尾 

0、准备工作 

(1)结构展示

首先由一个主页面来展示三个字页面(“首页”,“推荐”,“我的”),这三个子页面由fragment来显示。

 (2)底部tab栏准备

首页底部tab栏用 BottomNavigationView,我们可以创建一个menu文件来给tab栏按钮设置样式

BottomNavigationView 控件引用该menu,来显示底边按钮

 bottom_nav_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/menu_home"
        android:icon="@drawable/index"
        android:title="首页"/>
    <item  android:id="@+id/menu_recommend"
        android:icon="@drawable/recommend"
        android:title="推荐"/>
    <item android:id="@+id/menu_mine"
        android:icon="@drawable/chicken"
        android:title="我的"/>

</menu>

icon:设置图标 

 

1、创建布局  

    主页用 ViewPager + BottomNavigationView 来布局

ViewPager控件作用:作为容器,显示子页面

BottomNavigationView控件作用:制作底部按钮 

activity_index.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical">
    <androidx.viewpager.widget.ViewPager
        android:id="@+id/vp"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>
    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_nav_menu"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:menu="@menu/bottom_nav_menu" />

</LinearLayout>

 2、创建 VPfragment  

   (1) 构造 VPfragment 类

我们可以把每个页面当成一个对象,我们要想创建这个对象就要使用fragment里的一些方法。所以要创建一个类并继续fragment,来构建子页面的布局

因为这里是创建最简单的fragment类,所以我们之间选择编译器为我们提供的创建方法就行 

主要实现三个方法:

  1. newInstance 接收参数,存放在bundle内
  2. onCreate  设置参数,从bundle内取参数
  3. onCreateView 构建页面

 因为我们要在子页面内放一张照片,所以我们要定义一个img参数来接收图片,并在onCreateView方法内进行设置 

    VPFrament

package com.example.tabfragment.fragment;

import android.os.Bundle;

import androidx.fragment.app.Fragment;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

import com.example.tabfragment.R;

public class VPFragment extends Fragment {

    private static final String ARG_PARAM1 = "title";
    private static final String ARG_PARAM2 = "img";

    private String title;
    private int img;
    
    public static VPFragment newInstance(String title, int img) {
        VPFragment fragment = new VPFragment();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, title);
        args.putInt(ARG_PARAM2,img);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            title = getArguments().getString(ARG_PARAM1);
            img = getArguments().getInt(ARG_PARAM2);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_v_p, container, false);
        Bundle argument = getArguments();
        ImageView iv = view.findViewById(R.id.iv);
        iv.setImageResource(argument.getInt(ARG_PARAM2,R.drawable.ji1));
        return view;
    }
}

(2)子页面布局 fragment_v_p.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/iv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"/>

</LinearLayout>

3、创建适配器 

为什么要创建适配器?

      适配器作用是把每个单独的fragment页面放在一起打包,传给ViewPager。只有ViewPager设置了适配器我们才能看见翻页的效果。

所以我们要单独写一个类并继承 FragmentPagerAdapte

Alt + Enter 主要实现 FragmentPagerAdapter 方法和构造方法

  1. MyFragmentStateVPAdapter  构造方法,用来接收参数
  2. getItem 根据position来获取页面
  3. 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<Fragment> myFragmentList;
    public MyFragmentStateVPAdapter(@NonNull FragmentManager fm,List<Fragment> 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<Fragment> 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<Fragment> mFragmentList;
    private List<String> titleList;

    public MyFragmentStVpTitleAdapter(@NonNull FragmentManager fm,
                                      List<Fragment> mFragmentList,
                                      List<String> 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<Fragment> mFragmentList;
    private List<String> 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

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

    <androidx.viewpager.widget.ViewPager
        android:id="@+id/home_vp"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

最后在Activity_index.java 内把 homeFragment类型修改为 VPHomeFragment

VPHomeFragment homeFragment = VPHomeFragment.newInstance("我的",R.drawable.ji1);

gitte获取代码:点击跳转 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐