Android开发 - (适配器)Adapter类中FragmentPagerAdapter实现类详细解析

简介

  • 用于 ViewPager,与 Fragment 一起使用,适合少量静态页面

具体作用

  • FragmentPagerAdapter 专用于在 ViewPager 中管理和显示 Fragment它允许你在滑动视图(ViewPager)中实现分页功能每个页面都是一个 FragmentFragmentPagerAdapter 适用于需要管理少量 Fragment 的场景,因为它会将所有的 Fragment 一次性加载到内存中保持它们的生命周期避免频繁地创建和销毁 Fragment。它的主要用途为:

    分页显示

    • FragmentPagerAdapter 允许在 ViewPager 中展示多个 Fragment,并通过左右滑动进行页面切换

    管理 Fragment 生命周期

    • 通过 FragmentPagerAdapter每个 Fragment 只会创建一次保持在内存中,这样可以更有效地管理 Fragment 的生命周期避免频繁的销毁和重建

    适用于少量 Fragment

    • FragmentPagerAdapter 适合于 Fragment 数量较少的情况(通常少于 5 个)因为它会将所有 Fragment 对象保存在内存中

参数、方法解析

  • FragmentPagerAdapter(FragmentManager fm);基本的构造方法适用于早期的 Android 版本FragmentManager 用于在适配器中添加、移除或替换 Fragment抽象类无法直接实例化,需要重写一个子类继承它

    public class MyPagerAdapter extends FragmentPagerAdapter {
    
        private int numOfTabs;	// 自定义参数:Fragment 的总数量
    
        // 自定义构造方法:接受 FragmentManager、自定义参数:Fragment 的总数量
        public MyPagerAdapter(@NonNull FragmentManager fm, int numOfTabs) {
            super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
            this.numOfTabs = numOfTabs;
        }
    
        @NonNull
        @Override
        public Fragment getItem(int position) {
            // 根据 position 返回对应的 Fragment 对象
            return PageFragment.newInstance(position + 1);
        }
    
        //重写方法并导入 Fragment 的总数量
        @Override
        public int getCount() {
            // 返回 Fragment 的总数量
            return numOfTabs;
        }
    }
    // 实例化,并传入 FragmentManager 和 tab 的数量
    MyPagerAdapter adapter = new MyPagerAdapter(getSupportFragmentManager(), 3);
    
    • 参数解析
      • fm:用于与 Fragment 进行交互可以是 FragmentActivity 中的 getSupportFragmentManager();也可以是 Fragment 中的 getChildFragmentManager();
  • FragmentPagerAdapter(FragmentManager fm, int behavior);此构造方法允许你指定适配器的行为模式,从而更好地控制 Fragment 的生命周期管理抽象类无法直接实例化,需要重写一个子类继承它

    public class MyPagerAdapter extends FragmentPagerAdapter {
    
        private int numOfTabs;	// 自定义参数:Fragment 的总数量
    
        // 自定义构造方法:接受 FragmentManager、自定义参数:Fragment 的总数量
        public MyPagerAdapter(@NonNull FragmentManager fm, int numOfTabs) {
            super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); // 直接使用 BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT,在实例化时就不需要重复操作了
            this.numOfTabs = numOfTabs;
        }
    
        @NonNull
        @Override
        public Fragment getItem(int position) {
            // 根据 position 返回对应的 Fragment 对象
            return PageFragment.newInstance(position + 1);
        }
    	
        //重写方法并导入 Fragment 的总数量
        @Override
        public int getCount() {
            // 返回 Fragment 的总数量
            return numOfTabs;
        }
    }
    // 实例化,并传入 FragmentManager 和 tab 的数量
    MyPagerAdapter adapter = new MyPagerAdapter(getSupportFragmentManager(), 3);
    
    • 参数解析
      • fm:用于与 Fragment 进行交互可以是 FragmentActivity 中的 getSupportFragmentManager();也可以是 Fragment 中的 getChildFragmentManager();
      • behavior:表示适配器的行为类型;可以是以下常量之一:
        • FragmentStatePagerAdapter.BEHAVIOR_SET_USER_VISIBLE_HINT:在 API 24 及更低版本中使用,这种行为控制 Fragment 的可见性
        • FragmentStatePagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT推荐使用的行为模式,表示只有当前可见的 Fragment 会被设置为活动状态(Resumed)
  • adapter.instantiateItem(ViewGroup container, int position);根据给定的位置创建 Fragment 对象并将其添加到 container 中

    • 参数解析
      • containerViewGroup,即 ViewPager,用于将新创建的 Fragment 添加到这个容器中
      • position:表示当前页面的位置
  • adapter.destroyItem(ViewGroup container, int position, Object object);:从 container 中移除并销毁指定位置的 Fragment 对象

    • 参数解析
      • containerViewGroup,即 ViewPager,用于从这个容器中移除 Fragment
      • position:表示要销毁的页面的位置
      • object:即 Fragment 对象
  • adapter.getItem(int position);返回指定位置的 Fragment 对象每次需要新的 Fragment 时,ViewPager 会调用这个方法。此方法必须被重写返回对应位置的 Fragment

    @Override
    public Fragment getItem(int position) {
        switch (position) {
            case 0:
                return new Fragment1();
            case 1:
                return new Fragment2();
            case 2:
                return new Fragment3();
            default:
                return null;
        }
    }
    //调用
    Fragment Item = adapter.getItem(0)	//Fragment1 在 ViewPager 中的位置
    
    • 参数解析
      • position返回的 Fragment 在 ViewPager 中的位置
  • adapter.getCount();返回 Fragment 的总数量即 ViewPager 中页面的数量。此方法必须被重写

    @Override
    public int getCount() {
        return 3; // 总共3个页面
    }
    

使用环境与完整代码解析

  • FragmentPagerAdapter 主要用于 ViewPager 中管理和显示 Fragment。以下是一些典型的使用环境和场景

    经典的 Tab 界面

    • 使用了 TabLayoutViewPagerViewPager 允许用户通过左右滑动来切换页面,同时 TabLayout 提供了页签来快速跳转到特定页面。用户可以通过点击不同的 tab 或者左右滑动来切换页面

    • 代码示例MainActivity 中的 ViewPager 以及 MyPagerAdapter 的设置支持左右滑动

      • 创建主布局文件res/layout/activity_main.xml

        <?xml version="1.0" encoding="utf-8"?>
        <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
        
            <com.google.android.material.tabs.TabLayout
                android:id="@+id/tabLayout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentTop="true"/>
        
            <androidx.viewpager.widget.ViewPager
                android:id="@+id/viewPager"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_below="@id/tabLayout"/>
        </RelativeLayout>
        
      • 创建fragment1布局文件res/layout/fragment_first.xml

        <?xml version="1.0" encoding="utf-8"?>
        <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
        
            <TextView
                android:id="@+id/textView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="This is the first tab"
                android:textSize="24sp"
                android:layout_gravity="center"/>
        </FrameLayout>
        
      • 创建fragment2布局文件res/layout/fragment_second.xml

        <?xml version="1.0" encoding="utf-8"?>
        <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
        
            <TextView
                android:id="@+id/textView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="This is the second tab"
                android:textSize="24sp"
                android:layout_gravity="center"/>
        </FrameLayout>
        
      • 创建fragment3布局文件res/layout/fragment_third.xml

        <?xml version="1.0" encoding="utf-8"?>
        <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
        
            <TextView
                android:id="@+id/textView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="This is the third tab"
                android:textSize="24sp"
                android:layout_gravity="center"/>
        </FrameLayout>
        
      • 每个 Fragment 的实现类似,只需修改显示的内容

        • FirstFragment.java

          //定义了具体的视图和行为
          public class FirstFragment extends Fragment {
          
              @Override
              public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
                  return inflater.inflate(R.layout.fragment_first, container, false);
              }
          }
          
        • SecondFragment.java

          //定义了具体的视图和行为
          public class SecondFragment extends Fragment {
          
              @Override
              public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
                  return inflater.inflate(R.layout.fragment_second, container, false);
              }
          }
          
        • ThirdFragment.java

          //定义了具体的视图和行为
          public class ThirdFragment extends Fragment {
          
              @Override
              public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
                  return inflater.inflate(R.layout.fragment_third, container, false);
              }
          }
          
      • 自定义FragmentPagerAdapter类MyPagerAdapter.java

        public class MyPagerAdapter extends FragmentPagerAdapter {
        
            public MyPagerAdapter(FragmentManager fm) {
                super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
            }
        
            @Override
            public Fragment getItem(int position) {
                // 根据位置返回不同的 Fragment
                switch (position) {
                    case 0:
                        return new FirstFragment();
                    case 1:
                        return new SecondFragment();
                    case 2:
                        return new ThirdFragment();
                    default:
                        return new FirstFragment();
                }
            }
        
            @Override
            public int getCount() {
                // 返回页数
                return 3;
            }
        
            @Override
            public CharSequence getPageTitle(int position) {
                // 返回每个 tab 的标题
                switch (position) {
                    case 0:
                        return "Tab 1";
                    case 1:
                        return "Tab 2";
                    case 2:
                        return "Tab 3";
                    default:
                        return null;
                }
            }
        }
        
      • 启动类

        public class MainActivity extends AppCompatActivity {
        
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                //加载主布局文件,该布局文件定义了活动的 UI 结构。这包括 ViewPager、TabLayout(如果使用)、和其他 UI 元素
                setContentView(R.layout.activity_main);
        	
                //获取布局中的 ViewPager 和其他 UI 组件的引用,以便后续的操作和设置
                ViewPager viewPager = findViewById(R.id.viewPager);
                TabLayout tabLayout = findViewById(R.id.tabLayout);
        
                // 创建适配器
                MyPagerAdapter adapter = new MyPagerAdapter(getSupportFragmentManager());
                //通过适配器(FragmentPagerAdapter)与 Fragment 类关联。适配器负责创建和管理 Fragment 实例,并将这些实例添加到 ViewPager 中
                //自定义的 FragmentPagerAdapter 子类中定义了如何创建和管理 Fragment 对象
                viewPager.setAdapter(adapter);
                //将 TabLayout 绑定到 ViewPager 上,以便用户可以通过点击标签页快速切换,同时也可以通过左右滑动切换
                tabLayout.setupWithViewPager(viewPager);
            }
        }
        

    带有动态内容的多页面界面

    • 使用了 ViewPager 来展示多个页面,每个页面展示不同的动态内容。用户可以通过左右滑动来浏览不同的页面

    • 代码示例MainActivity 中的 ViewPager 和 DynamicPagerAdapter 支持左右滑动

      • 创建主布局文件res/layout/activity_main.xml

        <?xml version="1.0" encoding="utf-8"?>
        <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
        
            <com.google.android.material.tabs.TabLayout
                android:id="@+id/tabLayout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentTop="true"/>
        
            <androidx.viewpager.widget.ViewPager
                android:id="@+id/viewPager"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_below="@id/tabLayout"/>
        </RelativeLayout>
        
      • 创建fragment布局文件res/layout/fragment_dynamic.xml

        <?xml version="1.0" encoding="utf-8"?>
        <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
        
            <TextView
                android:id="@+id/textView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="24sp"
                android:layout_gravity="center"/>
        </FrameLayout>
        
      • 自定义FragmentPagerAdapter类DynamicPagerAdapter.java

        public class DynamicPagerAdapter extends FragmentPagerAdapter {
        
            private List<String> dataList;
        
            public DynamicPagerAdapter(FragmentManager fm, List<String> data) {
                super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
                this.dataList = data;
            }
        
            @Override
            public Fragment getItem(int position) {
                // 获取每个 Fragment 的动态数据
                String data = dataList.get(position);
                return DynamicFragment.newInstance(data);
            }
        
            @Override
            public int getCount() {
                // 返回数据项的数量
                return dataList.size();
            }
        }
        
      • 自定义 Fragment 类DynamicFragment.java

        public class DynamicFragment extends Fragment {
        
            private static final String ARG_DATA = "data";
        
            // 创建新实例并传递数据
            public static DynamicFragment newInstance(String data) {
                DynamicFragment fragment = new DynamicFragment();
                Bundle args = new Bundle();
                args.putString(ARG_DATA, data);
                fragment.setArguments(args);
                return fragment;
            }
            
        	//定义了具体的视图和行为
            @Override
            public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
                View view = inflater.inflate(R.layout.fragment_dynamic, container, false);
                // 获取传递的数据并显示
                String data = getArguments().getString(ARG_DATA);
                TextView textView = view.findViewById(R.id.textView);
                textView.setText(data);
                return view;
            }
        }
        
      • 启动类

        public class MainActivity extends AppCompatActivity {
        
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                //加载主布局文件,该布局文件定义了活动的 UI 结构。这包括 ViewPager、TabLayout(如果使用)、和其他 UI 元素
                setContentView(R.layout.activity_main);
        
                //获取布局中的 ViewPager 和其他 UI 组件的引用,以便后续的操作和设置
                ViewPager viewPager = findViewById(R.id.viewPager);
                // 模拟动态数据:提供数据源(例如 List<String> data),并将数据传递给适配器,以便动态生成页面
                List<String> data = Arrays.asList("Page 1", "Page 2", "Page 3");
                // 创建适配器
                DynamicPagerAdapter adapter = new DynamicPagerAdapter(getSupportFragmentManager(), data);
                //通过适配器(FragmentPagerAdapter)与 Fragment 类关联。适配器负责创建和管理 Fragment 实例,并将这些实例添加到 ViewPager 中
                //自定义的 FragmentPagerAdapter 子类中定义了如何创建和管理 Fragment 对象
                viewPager.setAdapter(adapter);
            }
        }
        

    复杂的内容展示

    • 场景中同样使用了 ViewPager每个页面可能包含更复杂的 UI 组件和交互,但 ViewPager 依然支持左右滑动来切换不同的页面

    • 代码示例MainActivity 中的 ViewPager 和 ComplexPagerAdapter 支持左右滑动

      • 创建主布局文件res/layout/activity_main.xml

        <?xml version="1.0" encoding="utf-8"?>
        <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
        
            <com.google.android.material.tabs.TabLayout
                android:id="@+id/tabLayout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentTop="true"/>
        
            <androidx.viewpager.widget.ViewPager
                android:id="@+id/viewPager"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_below="@id/tabLayout"/>
        </RelativeLayout>
        
      • 创建fragment布局文件res/layout/fragment_complex.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"
            android:padding="16dp">
        
            <TextView
                android:id="@+id/positionTextView"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="24sp"/>
        
            <Button
                android:id="@+id/actionButton"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Click Me"
                android:layout_marginTop="16dp"/>
        </LinearLayout>
        
      • 自定义FragmentPagerAdapter类ComplexPagerAdapter.java

        public class ComplexPagerAdapter extends FragmentPagerAdapter {
        
            public ComplexPagerAdapter(FragmentManager fm) {
                super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
            }
        
            @Override
            public Fragment getItem(int position) {
                // 根据位置创建不同的 Fragment
                return ComplexFragment.newInstance(position);
            }
        
            @Override
            public int getCount() {
                // 返回页数
                return 5;
            }
        }
        
      • 自定义 Fragment 类ComplexFragment.java

        public class ComplexFragment extends Fragment {
        
            private static final String ARG_POSITION = "position";
        
            // 创建新实例并传递位置参数
            public static ComplexFragment newInstance(int position) {
                ComplexFragment fragment = new ComplexFragment();
                Bundle args = new Bundle();
                args.putInt(ARG_POSITION, position);
                fragment.setArguments(args);
                return fragment;
            }
        	
            //定义了具体的视图和行为
            @Override
            public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
                View view = inflater.inflate(R.layout.fragment_complex, container, false);
                int position = getArguments().getInt(ARG_POSITION);
        
                // 初始化视图并处理复杂内容
                TextView positionTextView = view.findViewById(R.id.positionTextView);
                positionTextView.setText("Position: " + position);
        
                Button actionButton = view.findViewById(R.id.actionButton);
                actionButton.setOnClickListener(v -> {
                    // 处理按钮点击事件
                    Toast.makeText(getActivity(), "Button in position " + position + " clicked!", Toast.LENGTH_SHORT).show();
                });
        
                return view;
            }
        }
        
      • 启动类

        //
        public class MainActivity extends AppCompatActivity {
        
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                //加载主布局文件,该布局文件定义了活动的 UI 结构。这包括 ViewPager、TabLayout(如果使用)、和其他 UI 元素
                setContentView(R.layout.activity_main);
        		
                //获取布局中的 ViewPager 和其他 UI 组件的引用,以便后续的操作和设置
                ViewPager viewPager = findViewById(R.id.viewPager);
                // 创建适配器
                ComplexPagerAdapter adapter = new ComplexPagerAdapter(getSupportFragmentManager());
                //通过适配器(FragmentPagerAdapter)与 Fragment 类关联。适配器负责创建和管理 Fragment 实例,并将这些实例添加到 ViewPager 中
                //自定义的 FragmentPagerAdapter 子类中定义了如何创建和管理 Fragment 对象
                viewPager.setAdapter(adapter);
            }
        }
        
posted @ 2024-08-01 21:50  阿俊学JAVA  阅读(303)  评论(0编辑  收藏  举报