TabLayout+Viewpager加载动态多个fragment_viewpage 动态调整fragment-程序员宅基地

技术标签: Android源码  

  • 废话不多说,直接上图
代码展示
  1. 布局

    <?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">
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:paddingStart="16dp"
            android:paddingEnd="16dp">
    
            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:text="点击添加"
                android:onClick="addPage"/>
    
            <Space
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"/>
            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:text="点击删除"
                android:onClick="removePage"/>
    
        </LinearLayout>
    
    
        <android.support.design.widget.TabLayout
            android:id="@+id/tab_titles"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            app:tabSelectedTextColor="#FFF"
            app:tabTextColor="#3f9"
            android:background="@color/design_default_color_primary"
            app:tabIndicatorHeight="10dp"
            app:tabTextAppearance="@style/TabTextAppearance"/>
    
    
        <android.support.v4.view.ViewPager
            android:id="@+id/viewpagers_mypager"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </LinearLayout>
    

    Tab的字体大小和样式需要使用属性app:tabTextAppearance设置
    fragment的布局就不贴出来了

  2. Activity

    	public class ActivityViewPagers extends FragmentActivity {
          
    
        private TabLayout mTab;
        private ViewPager mViewPager;
        private ViewPagerFragAdapter mPagerAdapter;
        String[] array = {
          "Damian", "Madison", "Henry", "Jamey", "Farrell", "Pandora"};
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
          
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_viewpagers);
    
            mTab = findViewById(R.id.tab_titles);
            mViewPager = findViewById(R.id.viewpagers_mypager);
            /**关键方法,使Tab与ViewPager绑定,tab个数同步*/
            mTab.setupWithViewPager(mViewPager);
    
            mPagerAdapter = new ViewPagerFragAdapter(getSupportFragmentManager());
            mViewPager.setAdapter(mPagerAdapter);
        }
    
        public void addPage(View view) {
          
            mPagerAdapter.addTitle(array[(int) (Math.random()*array.length)]);
            int count = mPagerAdapter.getCount();
            if (count > 3){
          
                mTab.setTabMode(TabLayout.MODE_SCROLLABLE);
            }
        }
    
        public void removePage(View view) {
          
            mPagerAdapter.removeTitle();
            int count = mPagerAdapter.getCount();
            if (count <= 3){
          
                mTab.setTabMode(TabLayout.MODE_FIXED);
            }
        }
    }
    

    Activity必须是FragmentActivity才能调用getSupportFragmentManager()

  3. Adapter

    public class ViewPagerFragAdapter extends FragmentPagerAdapter {
          
    
        private ArrayList<String> mData = new ArrayList<>();
    
        public ViewPagerFragAdapter(FragmentManager fm) {
          
            super(fm);
        }
    
        @Override
        public Fragment getItem(int position) {
          
            String title = mData.get(position);
            FragmentCommon fragment = FragmentCommon.newInstance(title);
            return fragment;
        }
    
        @Override
        public int getCount() {
          
            return mData.size();
        }
    
        @Nullable
        @Override
        public CharSequence getPageTitle(int position) {
          
        	//使用首字母作为title
            return String.valueOf(mData.get(position).charAt(0));
        }
    
        public void setTitleList(ArrayList<String> strings) {
          
            this.mData.clear();
            this.mData.addAll(strings);
            notifyDataSetChanged();
        }
    
        public void addTitle(String str){
          
            this.mData.add(str);
            notifyDataSetChanged();
        }
    
        public void removeTitle() {
          
            if (mData.size() <= 0){
          
                return;
            }
            this.mData.remove(mData.size() -1);
            notifyDataSetChanged();
        }
    }
    

    跟BaseAdapter的思路一样,先数据处理,然后notifyDataSetChanged()通知适配器更新
    关键方法getPageTitle(int position), 与Tab有关,tab从这里获取标题的内容,不重写就是空标题了;

说明:
  • TabLayout需要的gradle依赖: implementation 'com.android.support:design:28.0.0'
源码分析

TabLayout 的 setupWithViewPager方法内部实现:

private void setupWithViewPager(@Nullable ViewPager viewPager, boolean autoRefresh, boolean implicitSetup) {
    
        //去除老的监听器
        if (this.viewPager != null) {
    
            if (this.pageChangeListener != null) {
    
                this.viewPager.removeOnPageChangeListener(this.pageChangeListener);
            }

            if (this.adapterChangeListener != null) {
    
                this.viewPager.removeOnAdapterChangeListener(this.adapterChangeListener);
            }
        }

        if (this.currentVpSelectedListener != null) {
    
            this.removeOnTabSelectedListener(this.currentVpSelectedListener);
            this.currentVpSelectedListener = null;
        }

		//更换新的监听器
        if (viewPager != null) {
    
            this.viewPager = viewPager;
            if (this.pageChangeListener == null) {
    
                this.pageChangeListener = new TabLayout.TabLayoutOnPageChangeListener(this);
            }

            this.pageChangeListener.reset();
            //设置PageChangeListener,监听页面滑动、选中状态,来同步滑动Tab标题
            viewPager.addOnPageChangeListener(this.pageChangeListener);
            this.currentVpSelectedListener = new TabLayout.ViewPagerOnTabSelectedListener(viewPager);
            this.addOnTabSelectedListener(this.currentVpSelectedListener);
            PagerAdapter adapter = viewPager.getAdapter();
            if (adapter != null) {
    
                this.setPagerAdapter(adapter, autoRefresh);
            }

            if (this.adapterChangeListener == null) {
    
                this.adapterChangeListener = new TabLayout.AdapterChangeListener();
            }

            this.adapterChangeListener.setAutoRefresh(autoRefresh);
            //监听ViewPager的适配器变化
            viewPager.addOnAdapterChangeListener(this.adapterChangeListener);
            this.setScrollPosition(viewPager.getCurrentItem(), 0.0F, true);
        } else {
    
            this.viewPager = null;
            this.setPagerAdapter((PagerAdapter)null, false);
        }

        this.setupViewPagerImplicitly = implicitSetup;
    }

这里对Viewpager的多个参数做监听,这样的话ViewPager就实实在在的与Tab绑定而同步刷新和选中、滑动

TabLayout内部定义了多种监听器:监听Adapter变化、Pager状态、Tab状态等
在这里插入图片描述

总结:
  1. 关键方法:mTab.setupWithViewPager(mViewPager);这句代码让Tab与Viewpager绑定。如果Viewpager页数变化,相应的tab的个数和标题也会变化。TabLayout在addTab时就会调用getPageTitle(int position)获取标题内容;
  2. viewpager数据变化 —> viewpager adapter 更新 —>Tab更新
  3. 如果remove当前页面,有可能导致后续的页面内容错乱;可能是ViewPager缓存导致的。可能需要换用适配器FragmentStatePagerAdapter
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_40087231/article/details/93379544

智能推荐

MySQL服务启动时显示本地计算机上的MySQL服务启动后停止;mysql服务无法启动_本地计算机上的mysql服务启动后停止 某些-程序员宅基地

文章浏览阅读6.5k次,点赞12次,收藏11次。两个问题:(1) 关闭mysql服务后后再次启动,显示:MySQL服务启动时显示本地计算机上的MySQL服务启动后停止。某些服务在未由其它服务…;(2)cmd窗口输入 net start mysql后显示:mysql服务正在启动 ;mysql服务无法启动解决方案:多半是因为你修改了my.ini文件但是没修改完善,比如修改数据库存储路径到D盘,要注意以下两点:1.将修改后的文件保存为以ANSI方式编码:2.注意有两个地方都要改:上面是修改存储路径的,然后再修改下面这条(没改这条是很多网络教程_本地计算机上的mysql服务启动后停止 某些

k8s拾遗 - NodePort Range 设置-程序员宅基地

文章浏览阅读1.7k次。默认情况下k8s对外暴露端口范围只能是30000-32767,这个范围其实是可以通过设置改变的。编辑配置文件sudo vim /etc/kubernetes/manifests/kube-apiserver.yaml在spec.containers.command 中添加如下配置,要注意格式- --service-node-port-range=1-65535复制代码apiserver会..._nodeport range

matlab2010b显示激活界面_matlab 2012b启动不了,总是弹出激活页面-程序员宅基地

文章浏览阅读484次。%%%%%%%%%%%%%%%%%%%%%%%%%%%%INCREMENT Aerospace_Blockset MLM 99 permanent uncounted\A05070F00D1EB1F92326VENDOR_STRING=QQ=47399897 HOSTID=ANY \ck=216SN=888888 TS_OKINCREMENT Aerospace_Toolbox MLM 99 pe..._matlab2010激活后还要激活

华硕主板破linux密码破解,华硕P8B75-M-LE老主板加持NVMe SSD bios(刷新软件和bios)...-程序员宅基地

文章浏览阅读958次。【实例简介】华硕P8B75-M-LE老主板加持NVMe SSD bios,内包括官方过度低级固件及已修改最新固件。请使用AISuite_II_XPVistaWin7-8-8-1_P9X79-LE_VER20401先刷新过度固件降级。然后再用替换法刷新最新修改固件。【实例截图】【核心代码】856657fb-e3ed-4249-9da0-3beba20c2b70├── AISuite_II_XPVis..._华硕p8b75-mle更新nvme

《Python学习手册》学习笔记——第5章_pytho学习手册第五版目录-程序员宅基地

文章浏览阅读448次。本章习题import math 后调用 math.sqrt(N)求根,math.pow(N)求平方int(N), math.trunc(N) #省略小数部分 round(N, digit) #四舍五入 另:答案中显示,使用math.floor(N) 来计算floor,并且使用字符串格式化操作来舍入以便于显示。 存疑:floor操作只有已经是忽略小数的值,为何还需要使用字符串格式化。bin_pytho学习手册第五版目录

VS2022为项目配置OpenCv4.5.3_vs2022配置opencv4.5.3环境-程序员宅基地

文章浏览阅读1.3k次。1 安装opencv4.5.32 配置opencv环境变量%opencv%\build\x64\vc15\bin注:vc14对应vs2015,若使用可加%opencv%\buildmingw\install\x64\mingw\bin然后重启电脑_vs2022配置opencv4.5.3环境

随便推点

python 中如何根据步长取相应下标的数据_python 字符串取值 步长-程序员宅基地

文章浏览阅读874次。python中根据步长取相应下标的数据_python 字符串取值 步长

刘铁猛-深入浅出WPF-系列资源汇总_刘铁猛博客-程序员宅基地

文章浏览阅读1.6w次,点赞10次,收藏36次。首先奉上原作者刘铁猛博客地址:http://www.cnblogs.com/prism/作者讲的很不错,没有之一,另外作者出了一本书,希望大家支持。送上全套高清晰视频教程(我注册了3个51cto的帐号收集全的):高清视频、源代码、电子书、MVVM视频所用源代码下载地址:https://download.csdn.net/download/waleswood/11049657源..._刘铁猛博客

log4j屏蔽掉某个包下的log日志打印_log4j 过滤包-程序员宅基地

文章浏览阅读1.7w次。在log4j的配置文件下配置## Disable other loglog4j.logger.com.summaryday.framework.db=OFFlog4j定义了8个级别的log(除去OFF和ALL,可以说分为6个级别),优先级从高到低依次为:OFF、FATAL、ERROR、WARN、INFO、DEBUG、TRACE、 ALL。ALL 最低等级的,用于打开所有日志记录。TRA..._log4j 过滤包

使用ExtJS做一个用户的增删改查-程序员宅基地

文章浏览阅读136次。extjs版本为4.2,用户数据放在静态list中存储    User.java 1 package com.ext.demo.dao; 2 3 public class User { 4 private int id; 5 private String name; 6 private String loginName; 7..._使用extjs4.2增删改查

word设置页码(不同分节符的页码设置)(全网最超级详细)_word 分节符 设置页码共多少页-程序员宅基地

文章浏览阅读2k次,点赞2次,收藏2次。注意【节与节之间】都有一个默认页码连续的设置,就是【链接到上一节】是默认开启的,需要鼠标点击下,就可以取消该功能。如下这里有4页,我们目标是分成2节内容,并且每节设置不一样的页码。备注:【链接到上一节】又分为页眉链接到上一节、和页码链接到上一节。在设置下页码的起始数字。_word 分节符 设置页码共多少页

LDAP服务器搭建教程-程序员宅基地

文章浏览阅读395次。您可以使用ldapmodify和ldapdelete命令来修改和删除LDAP服务器中的条目。在本教程中,我们将详细介绍如何在Linux系统上搭建LDAP服务器。[No]: 选择 “No”。Organization name: 输入您的组织名称,例如 Example Organization。[No]: 选择 “No”。在安装过程中,您将被要求设置管理员密码。[No]: 选择 “No”。您将被要求输入管理员密码。导入成功后,LDAP服务器将包含该条目。完成配置后,LDAP服务器将根据您提供的信息进行设置。_ldap服务器搭建

推荐文章

热门文章

相关标签