【Android】ViewPager2和TabLayout协同使用,实现多Fragment页面切换类似于QQ音乐,bilibili效果

2024-06-04 9740阅读

一、ViewPager2的基本用法

使用前先添加依赖:

   implementation 'androidx.appcompat:appcompat:1.4.0' // AndroidX AppCompat
    implementation 'com.google.android.material:material:1.4.0' // Material Design Components

1、制作Fragment

首先制作一个Fragment的xml布局页面


    

然后使用Fragment类绑定这个布局

public class HomeFragment extends Fragment {
    FragmentBinding binding;
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        binding = FragmentBinding.inflate(inflater,container,false);
        return binding.getRoot();
    }
    @Override
    public void onDestroyView() {
        super.onDestroyView();
        binding = null;
    }
}

2、制作Adapter

        

自定义自己的Adapter继承FragmentStateAdapter

制作一个fragmentList管理所有的fragment

public class MyPagerAdapter extends FragmentStateAdapter {
    List fragmentList;    //管理所有的fragment
    public MyPagerAdapter(@NonNull FragmentActivity fragmentActivity, List fragmentList) {
        super(fragmentActivity);
        this.fragmentList = fragmentList;
    }
    @NonNull
    @Override
    public Fragment createFragment(int position) {
        return fragmentList.get(position);
    }
    @Override
    public int getItemCount() {
        return fragmentList != null ? fragmentList.size() : 0;
    }
}

createFragment:用于返回指定的frgment界面

getItemCount:用于加载容器大小

除此之外,FragmentStateAdapter有三个构造方法剩下两个分别是:

public FragmentStateAdapter(@NonNull Fragment fragment)
public FragmentStateAdapter(@NonNull FragmentManager fragmentManager,@NonNull Lifecycle lifecycle)

FragmentStateAdapter(Fragment fragment):

这个构造方法通常用于在 Fragment 内部创建 FragmentStateAdapter,并将其附加到该 Fragment 的生命周期。

public class MyFragment extends Fragment {
    private ViewPager2 viewPager;
    private FragmentStateAdapter adapter;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_layout, container, false);
        // 初始化 ViewPager2
        viewPager = rootView.findViewById(R.id.viewPager);
        // 创建适配器并将其附加到当前 Fragment 的生命周期
        adapter = new MyFragmentStateAdapter(this);
        viewPager.setAdapter(adapter);
        return rootView;
    }
}

FragmentStateAdapter(FragmentManager fragmentManager, Lifecycle lifecycle)

这个构造方法通常用于在活动中创建 FragmentStateAdapter,并通过提供 FragmentManager 和 Lifecycle 对象来管理 Fragment 的生命周期。

public class MainActivity extends AppCompatActivity {
    private ViewPager2 viewPager;
    private FragmentStateAdapter adapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 初始化 ViewPager2
        viewPager = findViewById(R.id.viewPager);
        // 创建适配器并将其附加到活动的生命周期
        adapter = new MyFragmentStateAdapter(getSupportFragmentManager(), getLifecycle());
        viewPager.setAdapter(adapter);
    }
}

3、使用Adapter加载fragment页面

        List fragmentList = new ArrayList();
        fragmentList.add(new HomeFragment());
        fragmentList.add(new HomeFragment());
        fragmentList.add(new HomeFragment());
        fragmentList.add(new HomeFragment());
        fragmentList.add(new HomeFragment());
        fragmentList.add(new HomeFragment());
        fragmentList.add(new HomeFragment());
        fragmentList.add(new HomeFragment());
        MyPagerAdapter adapter = new MyPagerAdapter(this,fragmentList);
        //禁用预加载
        binding.viewPager.setOffscreenPageLimit(ViewPager2.OFFSCREEN_PAGE_LIMIT_DEFAULT);
        binding.viewPager.setAdapter(adapter);

预加载是在页面还未滑动时,提前加载页面。一般默认加载1个页面。

FragmentStateAdapter内部封装有 FragmentManager和 FragmentTransaction,用于管理Fragment;

使用FragmentManager可以根据ID或TAG来查找Fragment , 动态添加、删除、替换

让Fragment 成为ViewPager的一页时,FragmentManager会一直保存管理创建好了的Fragment,即使当前不是显示的这一页,Fragment对象也不会被销毁,在后台默默等待重新显示。但如果Fragment不再可见时,它的视图层次会被销毁掉,下次显示时视图会重新创建

二、ViewPager2和TabLayout协同使用

1、制作TabLayout与ViewPager2布局文件

    
        
        
         
        
    
        
    

**tabIndicatorAnimationMode ** :设置加载动画样式,elastic表示粘粘性动画,linear表示线性动画

tabIndicatorColor :指示器颜色

tabIndicatorHeight :指示器高度

tabIndicatorFullWidth :设置为false 则指示器跟文本宽度一致

tabUnboundedRipple :设置为true点击时会有一个水波纹效果

tabGravity :可设置center或fill;center指的是居中显示,fill指的是沾满全屏。

tabMode :可设置fixed和 scrollable;fixed:指的是固定tab;scrollable指的是tab可滑动。

tabTextColor :tab文字颜色

tabSelectedTextColor :选中时的tab颜色

【Android】ViewPager2和TabLayout协同使用,实现多Fragment页面切换类似于QQ音乐,bilibili效果 第1张

关于更多的TabLayou的使用可以参考:Android控件-TabLayout使用介绍

2、绑定TabLayout到ViewPager2

2.1 动态自定义Tab

这里采取了自定义TabView的方式,同样的也可以直接操作tab修改样式。

        new TabLayoutMediator(binding.tabMode, binding.viewPager, new TabLayoutMediator.TabConfigurationStrategy() {
            @Override
            public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
                //自定义TabView
                TextView tabView = new TextView(MainActivity.this);
                tabView.setText("Fragment " + position);
                //将tabbView绑定到tab
                tab.setCustomView(tabView);
            }
        }).attach();

注意一定要使用.attach()进行启动。

2.2 静态自定义Tab——tabTextAppearance

设置文字的大小和样式,在values下新建文件如下:


    
        20sp
        bold
    

在TabLayout中导入文件即可

【Android】ViewPager2和TabLayout协同使用,实现多Fragment页面切换类似于QQ音乐,bilibili效果 第2张

3、Viewpager2的滑动监听事件

ViewPager2.OnPageChangeCallback有三个构造方法:

        binding.viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
            //该方法开始滑动到滑动结束前不断调用
            // 参数一:position表示当前页面的位置(当前页面在翻页适配器中的下标,索引),因为不断调用,position也可能表示目标页面的下标
            // 参数二:positionOffset表示页面偏移的百分比,翻页时不断增大(不断趋近1),最后翻页完成时突变成0
            // 这个参数在左滑时由1趋近0,右滑由0趋近1
            // 参数三:positionOffsetPixel表示页面完成滑动的像素数,变化趋势和positionOffset一样
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                super.onPageScrolled(position, positionOffset, positionOffsetPixels);
            }
            //该方法在页面切换成功后调用(滑动前与滑动后不是同一页面)
            //position表示当前页面在适配器中的下标,索引
            @Override
            public void onPageSelected(int position) {
                super.onPageSelected(position);
            }
            //该方法在页面滑动状态改变时调用
            // ViewPager2.SCROLL_STATE_IDLE表示空闲状态,当前页面处于静止状态,没有要翻页的趋势 == 0
            // ViewPager2.SCROLL_STATE_DRAGGING表示拖动状态,用户正在拖动页面,准备进行翻页滚动 == 1
            // ViewPager2.SCROLL_STATE_SETTLING表示滚动状态,页面正在自动滚动到目标页面 == 2
            @Override
            public void onPageScrollStateChanged(int state) {
                super.onPageScrollStateChanged(state);
            }
        });

3.1 使用动态方法实现字体大小颜色变化

监听ViewPager2的页面滑动实现修改tab

        //viewPager 页面切换监听
        binding.viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
            
            //用于回调ViewPager2的当前页面,当页面发送变化就会调用这个方法onPageSelected
            @Override
            public void onPageSelected(int position) {
                //获取总的TabLayout的个数
                int tabCount = binding.tabMode.getTabCount();
                //遍历选择所有的Tab,如果判断是当前的Tab则进行相关操作,不是则还原操作
                for (int i = 0; i  

3.2 使用静态的方法实现字体大小和颜色变化

首先设置静态的style选项卡,在values下新建一个xml文件


    
        20sp
        #B22222
    
    
        15sp
        #000080
    

然后在TabLayout的布局文件中设置初始状态的tab颜色字体

    
        	//注意在这个地方使用tabTextAppearance设置初始状态tab的文字效果
        
        
    

监听TabLayout实现修改,TabLayout监听事件有三个Override方法,当然这里也可以继续使用ViewPager2页面的监听方法实现。

        binding.tabMode.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            //选中时的变化
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                // 创建新的 TextView 实例,并设置样式和文本
                TextView selectedTextView = new TextView(MainActivity.this);
                selectedTextView.setTextAppearance(R.style.TabLayoutTextSelected);	//在这里动态使用刚刚的style文件
                selectedTextView.setText("Fragment " + tab.getPosition());	//设置文字内容,tab因为是重新加载的textView内容,所以原来的数据被覆盖掉了
                tab.setCustomView(selectedTextView);
            }
            //未选中时的变化
            @Override
            public void onTabUnselected(TabLayout.Tab tab) {
                // 清除未选中标签的自定义视图
                tab.setCustomView(null);
            }
            //重复选中的变化,当用户再次点击已经选中的Tab时,这个方法就会被调用。
            @Override
            public void onTabReselected(TabLayout.Tab tab) {
                // 处理标签重新选择,如果需要
            }
        });

注意点:

1、在onTabSelected中重新设置加载的文本内容,否则原数据会被覆盖,出现这样的情况

【Android】ViewPager2和TabLayout协同使用,实现多Fragment页面切换类似于QQ音乐,bilibili效果 第3张

2、在onTabUnselected中一定要清除覆盖在tab的自定义视图否则视图会不停重复的加在tab上面,出现这样的情况:

【Android】ViewPager2和TabLayout协同使用,实现多Fragment页面切换类似于QQ音乐,bilibili效果 第4张

4、TabLayout的监听事件

        binding.tabMode.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            TextView textView = new TextView(MainActivity.this);
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                //选中时的变化
            }
            public void onTabUnselected(TabLayout.Tab tab) {
                //未选中的变化
            }
            @Override
            public void onTabReselected(TabLayout.Tab tab) {
                //重复选中的变化,当用户再次点击已经选中的Tab时,这个方法就会被调用。
            }
        });

5、禁止Viewpager2左右滑动翻页

        //false表示禁止,true表示允许
        binding.viewPager.setUserInputEnabled(false);

此时就只能通过点击Tab才能加载Fragment.

6、TabLayout+Viewpager2效果展示

【Android】ViewPager2和TabLayout协同使用,实现多Fragment页面切换类似于QQ音乐,bilibili效果 第5张


    免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

    目录[+]