当前位置: 首页 > article >正文

Android studio开发实战之碎片Fragment

        一、碎片化的概念

        碎片化(Fragment)是 Android 应用开发中的一个重要概念,它的设计初衷是增强界面模块化,便于开发者灵活构建和管理复杂的界面。

  • 什么是模块化?
    • 将应用界面拆分成多个可复用的小模块(Fragment),每个模块可以独立定义自己的布局、逻辑和交互。
  • 为什么需要模块化?
    • 当界面变得复杂时,将整个界面写在一个 Activity 中会导致代码混乱、维护困难。
    • 使用 Fragment,可以将界面逻辑独立开来,方便开发、调试和测试。

举例:在一个购物应用中:

  • 商品列表是一个 Fragment。
  • 商品详情是另一个 Fragment。
  • 购物车页面又是一个 Fragment。

这样,每个模块的开发和调试是独立的,避免了代码耦合。

Fragment 同样可以解决 手机屏幕和平板屏幕差异。Fragment 作为一个独立的 UI 模块,可以被多个 Activity 复用。

  • 在小屏设备上(如手机):
    • 每个 Fragment 通常占据一个 Activity,全屏显示,用户需要通过页面跳转查看不同内容。
  • 在大屏设备上(如平板):
    • 可以在同一个 Activity 中显示多个 Fragment,比如左侧是导航列表,右侧是详情界面。
  • 不同 Activity 都可以加载这个 Fragment,而不需要重复写界面和逻辑代码。

 二、碎片的静态注册

        每个Activity有自己的xml布局文件,作为Activity的一个模块,fragment也需要写自己的xml布局文件。

例如书中案例:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:background="#bbffbb">

    <TextView
        android:id="@+id/tv_adv"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:gravity="center"
        android:text="广告图片"
        android:textColor="#000000"
        android:textSize="17sp" />

    <ImageView
        android:id="@+id/iv_adv"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="4"
        android:src="@drawable/adv"
        android:scaleType="fitCenter" />

</LinearLayout>

一个简单的线性布局,水平方向上有两个组件,按照1:4的比例水平分布,效果如下:

        上面已经说了,这里再强调一遍“将应用界面拆分成多个可复用的小模块(Fragment),每个模块可以独立定义自己的布局、逻辑和交互。

        因此上面的xml布局文件不必直接用于Activity,而是拥有自己的逻辑和交互代码。

例如:

public class StaticFragment extends Fragment implements View.OnClickListener {
    private static final String TAG = "StaticFragment";
    protected View mView; // 声明一个视图对象
    protected Context mContext; // 声明一个上下文对象

    // 创建碎片视图
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        mContext = getActivity(); // 获取活动页面的上下文
        // 根据布局文件fragment_static.xml生成视图对象
        mView = inflater.inflate(R.layout.fragment_static, container, false);
        TextView tv_adv = mView.findViewById(R.id.tv_adv);
        ImageView iv_adv = mView.findViewById(R.id.iv_adv);
        tv_adv.setOnClickListener(this); // 设置点击监听器
        iv_adv.setOnClickListener(this); // 设置点击监听器
        Log.d(TAG, "onCreateView");
        return mView; // 返回该碎片的视图对象
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.tv_adv) {
            Toast.makeText(mContext, "您点击了广告文本", Toast.LENGTH_LONG).show();
        } else if (v.getId() == R.id.iv_adv) {
            Toast.makeText(mContext, "您点击了广告图片", Toast.LENGTH_LONG).show();
        }
    }
  • FragmentStaticFragment 是一个 Fragment 类,用来定义用户界面的一部分,可以被嵌入到 Activity 中。
  • implements View.OnClickListener:实现了 View.OnClickListener 接口,用于处理视图的点击事件。

碎片视图代码详细分析:

  1. mContext = getActivity();

    • getActivity() 获取当前 Fragment 所附加的 Activity,即 Fragment 的宿主。
    • 这里将 Activity 的上下文赋值给 mContext,方便后续在 Fragment 中使用。
    • 为什么这么写?Fragment 不能直接访问全局上下文(如 this),而是依附于宿主 Activity。因此需要通过 getActivity() 获取。
    • 用途:上下文在后续创建视图、设置监听器、弹出 Toast 等操作中使用。
  2. inflater.inflate(R.layout.fragment_static, container, false)

    • inflater 是布局填充器,用于将 XML 布局文件(fragment_static.xml)转换为对应的视图对象。LayoutInflater 是 Android 用来解析 XML 布局文件并将其转化为实际的 View 对象的工具。
    • container 是宿主 Activity 中用于容纳当前 Fragment 的容器。传入这个参数可以让视图正确地嵌入父容器中。
    • false 表示是否立即将解析后的视图添加到父容器中。通常传 false,因为实际添加操作由系统完成。
  3. 视图查找与点击监听

    • mView.findViewById(...):从加载的视图中查找指定 ID 的控件。
    • setOnClickListener(this):将 StaticFragment 本身作为点击事件的监听器。

        在 Fragment 中必须通过 视图对象 调用 findViewById,而不能像 Activity 那样直接调用,这是由 Fragment 的设计原理和生命周期决定的。

Activity 的 findViewById
在 Activity 中,findViewById 是直接调用的,因为 Activity 会直接加载布局文件并管理所有控件。

setContentView(R.layout.activity_main);
Button button = findViewById(R.id.button);
  • setContentView 将布局文件加载到 Activity 的根视图中。
  • findViewById 会在整个视图树(View hierarchy)中查找指定的控件。

 

Fragment 的 findViewById
Fragment 的视图是通过 onCreateView 动态生成的,并不直接属于 Activity 的视图树。
因此:

  • 只能通过 Fragment 的根视图(mView)调用 findViewById,在其对应的视图范围内查找控件。
mView = inflater.inflate(R.layout.fragment_static, container, false);
TextView textView = mView.findViewById(R.id.text_view);
  • Fragment 的视图是在 onCreateView 中动态加载的,而 Activity 的视图是随着 setContentView 初始化的。
  • 原因: 在 Fragment 中,控件只存在于 onCreateView 加载的布局中,只有通过 mView(Fragment 的根视图)才能访问这些控件。如果尝试直接调用 findViewById会导致空指针异常,因为 Fragment 的控件并没有加入到 Activity 的视图树中,Activity 无法找到这些控件。

 

好,现在碎片准备完毕,逻辑是点击碎片部分,会在活动页面上显示文本。下面要在活动页面上引用上面定义的碎片代码:步骤是先引用碎片控件,再在活动页面引入布局文件。

活动界面的xml布局文件如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <!-- 把碎片当作一个控件使用,其中android:name指明了碎片来源 -->
    <fragment
        android:id="@+id/fragment_static"
        android:name="com.example.testapplication.fragment.StaticFragment"
        android:layout_width="match_parent"
        android:layout_height="60dp" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="这里是每个页面的具体内容"
        android:textColor="#000000"
        android:textSize="17sp" />
</LinearLayout>

<fragment> 元素:

  • 是一个特殊的 XML 标签,用于在布局文件中静态嵌入 Fragment。
  • 系统会根据 android:name 指定的 Fragment 类,将其加载到 <fragment> 标签的位置,并显示其视图。
  • android:name 指定需要加载的 Fragment 的类的完整路径(包名+类名)。

活动页面的代码如下:

public class FragmentStaticActivity extends AppCompatActivity {
    private static final String TAG = "FragmentStaticActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fragment_static);
        Log.d(TAG, "onCreate");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy");
    }

运行测试结果正常,那么碎片和活动页面的生命周期是怎样的呢?

单独看碎片的生命周期:

  • onAttach()
    • Fragment 被添加到 Activity 上时调用。可以获取 Activity 的引用。
  • onCreate()
    • Fragment 被创建时调用,适合初始化非视图相关的资源或逻辑。
  • onCreateView()
    • 为 Fragment 创建视图时调用。必须返回根视图对象。
  • onActivityCreated()
    • 宿主 Activity 的 onCreate() 方法完成后调用。
  • onStart()
    • Fragment 对用户可见时调用。
  • onResume()
    • Fragment 与用户交互时调用。
  • onPause()
    • Fragment 进入后台时调用,适合保存非持久数据。
  • onStop()
    • Fragment 不再对用户可见时调用。
  • onDestroyView()
    • Fragment 的视图被销毁时调用。
  • onDestroy()
    • Fragment 自身被销毁时调用。
  • onDetach()
    • Fragment 从 Activity 中移除时调用。

 碎片和活动页面的调用顺序如下,碎片的创建被优先调用,然后才是活动页面的视图创建。

三、碎片的动态注册 

        静态注册是通过在 XML 布局文件中直接声明 Fragment 来实现的。系统在加载布局时会自动实例化并显示 Fragment。

静态注册的特点
  • 简单易用:在 XML 中直接定义 Fragment,系统会自动实例化它,减少了手动代码的书写。
  • 生命周期由系统管理:Fragment 的生命周期由系统自动管理,依赖于宿主 Activity 的生命周期。
  • 无法动态替换:一旦静态注册的 Fragment 加载进来,它的存在就固定了,无法像动态注册那样在运行时进行替换或移除。

        动态注册是通过代码中手动创建并管理 Fragment 的实例,以及使用 FragmentTransaction 来进行 Fragment 的添加、替换、移除等操作。        

动态注册的特点
  • 更高的灵活性:可以在运行时动态决定哪些 Fragment 需要显示或隐藏,支持 Fragment 的动态添加、替换、移除等操作。
  • 控制生命周期:通过 FragmentTransaction 手动控制 Fragment 的生命周期,例如添加、移除或替换 Fragment 时,可以通过事务来管理这些操作。
  • 适应性强:适合那些需要动态变化、经常切换内容的页面。例如,Tab 页的切换、登录/注册界面的切换等。

动态注册最常用与翻页类视图并用,因此先回顾翻页类视图是怎样的:

3.1翻页类视图案例

        1创建布局文件:

<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="5dp">

    <!-- 注意翻页视图ViewPager的节点名称要填全路径 -->
    <androidx.viewpager.widget.ViewPager
        android:id="@+id/vp_content"
        android:layout_width="match_parent"
        android:layout_height="370dp" />
</LinearLayout>

   ViewPager 是 Android 中用于实现 翻页效果(即滑动切换不同页面)的专用组件。 

   ViewPager 被用来显示多个页面,可以是图片、文本或其他视图。关于 ViewPager 的使用,有几个要点需要注意 :

   ViewPager 必须通过适配器来管理它的页面内容。在你的布局文件中,ViewPager 并没有定义任何内容,它只是一个容器。你需要为它指定一个 PagerAdapter,通常是 FragmentPagerAdapterPagerAdapter 的子类。

   ViewPager 提供了页面滑动的效果,用户可以左右滑动页面。如果你希望定制滑动效果(例如,设置切换动画、切换速度等),你可以通过修改 ViewPager 的配置或使用 PageTransformer 来实现。

        例如,使用 PageTransformer 实现视差效果:

viewPager.setPageTransformer(true, new ViewPager.PageTransformer() {
    @Override
    public void transformPage(@NonNull View page, float position) {
        page.setRotationY(position * -30);  // 例如:左右翻转效果
    }
});

 

        2创建手机商品实体类:

public class GoodsInfo {
    public long rowid; // 行号
    public int xuhao; // 序号
    public String name; // 名称
    public String desc; // 描述
    public float price; // 价格
    public String pic_path; // 大图的保存路径
    public int pic; // 大图的资源编号

    public GoodsInfo() {
        rowid = 0L;
        xuhao = 0;
        name = "";
        desc = "";
        price = 0;
        pic_path = "";
        pic = 0;
    }

    // 声明一个手机商品的名称数组
    private static String[] mNameArray = {
            "iPhone11", "Mate30", "小米10", "OPPO Reno3", "vivo X30", "荣耀30S"
    };
    // 声明一个手机商品的描述数组
    private static String[] mDescArray = {
            "Apple iPhone11 256GB 绿色 4G全网通手机",
            "华为 HUAWEI Mate30 8GB+256GB 丹霞橙 5G全网通 全面屏手机",
            "小米 MI10 8GB+128GB 钛银黑 5G手机 游戏拍照手机",
            "OPPO Reno3 8GB+128GB 蓝色星夜 双模5G 拍照游戏智能手机",
            "vivo X30 8GB+128GB 绯云 5G全网通 美颜拍照手机",
            "荣耀30S 8GB+128GB 蝶羽红 5G芯片 自拍全面屏手机"
    };
    // 声明一个手机商品的价格数组
    private static float[] mPriceArray = {6299, 4999, 3999, 2999, 2998, 2399};
    // 声明一个手机商品的大图数组
    private static int[] mPicArray = {
            R.drawable.iphone, R.drawable.huawei, R.drawable.xiaomi,
            R.drawable.oppo, R.drawable.vivo, R.drawable.rongyao
    };

    // 获取默认的手机信息列表
    public static List<GoodsInfo> getDefaultList() {
        List<GoodsInfo> goodsList = new ArrayList<GoodsInfo>();
        for (int i = 0; i < mNameArray.length; i++) {
            GoodsInfo info = new GoodsInfo();
            info.name = mNameArray[i];
            info.desc = mDescArray[i];
            info.price = mPriceArray[i];
            info.pic = mPicArray[i];
            goodsList.add(info);
        }
        return goodsList;
    }

}

        在 Android 开发中,适配器(Adapter) 是一个用于连接数据源和视图组件的桥梁。它的主要作用是将数据映射到界面元素上,从而使数据能够在界面中展示。

        适配器的作用:数据与视图的桥梁——适配器从数据源中获取数据,然后将这些数据绑定到视图组件上。

        翻页类视图有自己的适配器,通过构造方法传入商品列表,再用instantiateItem实例化视图对象,并添加到容器。

        3翻页类适配器代码如下:

public class ImagePagerAdapater extends PagerAdapter {
    // 声明一个图像视图列表
    private List<ImageView> mViewList = new ArrayList<ImageView>();
    // 声明一个商品信息列表
    private List<GoodsInfo> mGoodsList = new ArrayList<GoodsInfo>();

    // 图像翻页适配器的构造方法,传入上下文与商品信息列表
    public ImagePagerAdapater(Context context, List<GoodsInfo> goodsList) {
        mGoodsList = goodsList;
        // 给每个商品分配一个专用的图像视图
        for (int i = 0; i < mGoodsList.size(); i++) {
            ImageView view = new ImageView(context); // 创建一个图像视图对象
            view.setLayoutParams(new LayoutParams(
                    LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
            view.setImageResource(mGoodsList.get(i).pic);
            mViewList.add(view); // 把该商品的图像视图添加到图像视图列表
        }
    }

    // 获取页面项的个数
    public int getCount() {
        return mViewList.size();
    }

    // 判断当前视图是否来自指定对象
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }

    // 从容器中销毁指定位置的页面
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView(mViewList.get(position));
    }

    // 实例化指定位置的页面,并将其添加到容器中
    public Object instantiateItem(ViewGroup container, int position) {
        container.addView(mViewList.get(position));
        return mViewList.get(position);
    }

    // 获得指定页面的标题文本
    public CharSequence getPageTitle(int position) {
        return mGoodsList.get(position).name;
    }

}

        这段代码是一个自定义的 PagerAdapter,用于在 Android 中实现 ViewPager 的图像滑动展示。PagerAdapter 是一种适配器,用来管理 ViewPager 中的页面数据。具体来说,这段代码将商品信息(GoodsInfo)和对应的商品图片(ImageView)绑定在一起,能够在 ViewPager 中进行滑动展示。

        ImagePagerAdapater 继承了 PagerAdapter,是一个自定义适配器,用于管理 ViewPager 中的页面。

  • mViewList:用于存储 ImageView 对象的列表,每个 ImageView 对应一个商品的图片。
  • mGoodsList:用于存储商品信息的列表,每个商品包含商品名称和商品图片等信息。
  • 构造方法接收一个 Context 和一个 List<GoodsInfo> 类型的商品列表。
  • 通过商品列表中的信息,为每个商品创建一个 ImageView。每个商品对应一张图片,图片来源于 GoodsInfo 对象的 pic 属性。
  • 设置每个 ImageView 的布局参数为 MATCH_PARENTWRAP_CONTENT,使得图片能够填充整个屏幕宽度并自适应高度。
  • 将每个创建的 ImageView 添加到 mViewList 列表中,供 ViewPager 显示。
  • 构造方法接收一个 Context 和一个 List<GoodsInfo> 类型的商品列表。
  • 通过商品列表中的信息,为每个商品创建一个 ImageView。每个商品对应一张图片,图片来源于 GoodsInfo 对象的 pic 属性。
  • 设置每个 ImageView 的布局参数为 MATCH_PARENTWRAP_CONTENT,使得图片能够填充整个屏幕宽度并自适应高度。
  • 将每个创建的 ImageView 添加到 mViewList 列表中,供 ViewPager 显示。
public int getCount() {
    return mViewList.size();
}

返回适配器中总共的页面数量,也就是 mViewList 列表中 ImageView 的数量,即商品的数量。

public boolean isViewFromObject(View view, Object object) {
    return view == object;
}
  • 该方法用于判断一个视图是否与一个对象关联。view 是当前显示的视图,objectinstantiateItem() 方法返回的对象。
  • 这里判断 view 是否等于 object,即判断当前页面的视图是否是该适配器实例化的视图。
public void destroyItem(ViewGroup container, int position, Object object) {
    container.removeView(mViewList.get(position));
}
  • 该方法用于销毁 ViewPager 中某个位置的页面视图。当用户滑动到下一个页面时,当前页面的视图会被销毁以节省内存。
  • 通过 container.removeView()ViewGroup 中移除视图。
public Object instantiateItem(ViewGroup container, int position) {
    container.addView(mViewList.get(position));
    return mViewList.get(position);
}
  • 该方法用于实例化并返回 ViewPager 中某个位置的页面视图。通过 container.addView()mViewList 中对应位置的 ImageView 添加到 ViewPager 容器中。
  • instantiateItem() 方法的返回值会作为 destroyItem() 中的 object 参数来使用。
public CharSequence getPageTitle(int position) {
    return mGoodsList.get(position).name;
}
  • 该方法用于返回每一页的标题。这里的标题来自商品信息列表 mGoodsList 中每个商品的 name 属性。

        4、活动代码

public class ViewPagerActivity extends AppCompatActivity implements OnPageChangeListener {
    private List<GoodsInfo> mGoodsList; // 手机商品列表

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view_pager);
        mGoodsList = GoodsInfo.getDefaultList();
        // 构建一个商品图片的翻页适配器
        ImagePagerAdapater adapter = new ImagePagerAdapater(this, mGoodsList);
        // 从布局视图中获取名叫vp_content的翻页视图
        ViewPager vp_content = findViewById(R.id.vp_content);
        vp_content.setAdapter(adapter); // 设置翻页视图的适配器
        vp_content.setCurrentItem(0); // 设置翻页视图显示第一页
        vp_content.addOnPageChangeListener(this); // 给翻页视图添加页面变更监听器
//        // 给翻页视图添加简化版的页面变更监听器
//        vp_content.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
//            @Override
//            public void onPageSelected(int position) {
//                Toast.makeText(ViewPagerActivity.this, "您翻到的手机品牌是:"
//                        + mGoodsList.get(position).name, Toast.LENGTH_SHORT).show();
//            }
//        });
    }

    // 翻页状态改变时触发。state取值说明为:0表示静止,1表示正在滑动,2表示滑动完毕
    // 在翻页过程中,状态值变化依次为:正在滑动→滑动完毕→静止
    public void onPageScrollStateChanged(int state) {}

    // 在翻页过程中触发。该方法的三个参数取值说明为 :第一个参数表示当前页面的序号
    // 第二个参数表示页面偏移的百分比,取值为0到1;第三个参数表示页面的偏移距离
    public void onPageScrolled(int position, float ratio, int offset) {}

    // 在翻页结束后触发。position表示当前滑到了哪一个页面
    public void onPageSelected(int position) {
        Toast.makeText(this, "您翻到的手机品牌是:" + mGoodsList.get(position).name, Toast.LENGTH_SHORT).show();
    }
}

效果,通过左右滑动,可以显示不同的手机图片:

3.2 碎片动态注册代码

1、布局文件

<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="5dp">

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

        <androidx.viewpager.widget.PagerTabStrip
            android:id="@+id/pts_tab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </androidx.viewpager.widget.ViewPager>
</LinearLayout>

        这段代码定义了一个简单的 Android 布局,包含一个 ViewPager 组件和其内嵌的 PagerTabStrip,用于实现页面翻页功能,同时为翻页视图添加顶部的标签条(Tab Strip)来标识当前页面。

androidx.viewpager.widget.ViewPager:这是一个翻页视图容器,用于实现页面的滑动切换。上面已经讲过。

androidx.viewpager.widget.PagerTabStripPagerTabStripViewPager 的一个子组件,用于在顶部显示页面标题,并标识当前页面。PagerTabStrip 会自动显示与当前页面对应的标题信息。它需要配合 PagerAdapter 来提供标题。

2、碎片适配器

public class MobilePagerAdapter extends FragmentPagerAdapter {
    private List<GoodsInfo> mGoodsList = new ArrayList<GoodsInfo>(); // 声明一个商品列表

    // 碎片页适配器的构造方法,传入碎片管理器与商品信息列表
    public MobilePagerAdapter(FragmentManager fm, List<GoodsInfo> goodsList) {
        super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
        mGoodsList = goodsList;
    }

    // 获取碎片Fragment的个数
    public int getCount() {
        return mGoodsList.size();
    }

    // 获取指定位置的碎片Fragment
    public Fragment getItem(int position) {
        return DynamicFragment.newInstance(position,
                mGoodsList.get(position).pic, mGoodsList.get(position).desc);
    }

    // 获得指定碎片页的标题文本
    public CharSequence getPageTitle(int position) {
        return mGoodsList.get(position).name;
    }
}

MobilePagerAdapter 通过提供 Fragment 的内容和标题,将商品信息(GoodsInfo)展示为滑动页面,用户可以通过滑动切换不同商品的详情页。

public MobilePagerAdapter(FragmentManager fm, List<GoodsInfo> goodsList) {
    super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
    mGoodsList = goodsList;
}
  • 参数解析
    • FragmentManager fm:由外部传入的碎片管理器,用于管理 Fragment 的添加、移除和切换。
    • List<GoodsInfo> goodsList:商品信息列表,由外部传入适配器,用于为每个页面提供商品数据。
  • super 调用
    • BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT:表示只保留当前显示的 Fragment 的视图状态,节省内存和性能。
  • 功能:构造方法将商品信息列表传递给适配器。
public int getCount() {
    return mGoodsList.size();
}
  • 功能:返回商品信息列表的长度,即页面的总数。
  • 适配器作用ViewPager 会调用此方法,确定总共需要显示多少个页面。
public Fragment getItem(int position) {
    return DynamicFragment.newInstance(position,
            mGoodsList.get(position).pic, mGoodsList.get(position).desc);
}
  • 参数解析
    • position:页面索引,表示当前请求的页面在列表中的位置。
  • 功能
    • 创建并返回一个新的 DynamicFragment 实例。
    • DynamicFragment.newInstance 是一个静态方法,用于创建包含特定数据的 Fragment
    • 通过 position 获取对应商品的图片(pic)和描述(desc),并将其传递给 DynamicFragment
  • 适配器作用ViewPager 会调用此方法,为每个页面提供实际的 Fragment 内容。
public CharSequence getPageTitle(int position) {
    return mGoodsList.get(position).name;
}
  • 参数解析
    • position:页面索引。
  • 功能
    • 获取当前页面对应商品的名称(name)作为标题。
    • 返回的标题会显示在配套的标签组件(如 PagerTabStrip)中。

 

运行时的具体流程

  1. 初始化适配器

    • 外部通过 new MobilePagerAdapter(fm, goodsList) 初始化适配器,将商品列表传入。
  2. 绑定到 ViewPager

    • ViewPager 设置此适配器后,会调用适配器的 getCount 方法,确定总页面数。
  3. 加载页面内容

    • 当某个页面需要显示时,ViewPager 会调用 getItem 方法,从适配器获取对应的 Fragment
    • DynamicFragment.newInstance 会根据商品的图片和描述生成一个对应的页面。
  4. 显示标题

    • 如果布局中有标签组件(如 PagerTabStrip),会调用 getPageTitle 方法获取标题,显示为对应页面的标签。

3、碎片代码

public class DynamicFragment extends Fragment {
    private static final String TAG = "DynamicFragment";
    protected View mView; // 声明一个视图对象
    protected Context mContext; // 声明一个上下文对象
    private int mPosition; // 位置序号
    private int mImageId; // 图片的资源编号
    private String mDesc; // 商品的文字描述

    // 获取该碎片的一个实例
    public static DynamicFragment newInstance(int position, int image_id, String desc) {
        DynamicFragment fragment = new DynamicFragment(); // 创建该碎片的一个实例
        Bundle bundle = new Bundle(); // 创建一个新包裹
        bundle.putInt("position", position); // 往包裹存入位置序号
        bundle.putInt("image_id", image_id); // 往包裹存入图片的资源编号
        bundle.putString("desc", desc); // 往包裹存入商品的文字描述
        fragment.setArguments(bundle); // 把包裹塞给碎片
        return fragment; // 返回碎片实例
    }

    // 创建碎片视图
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        mContext = getActivity(); // 获取活动页面的上下文
        if (getArguments() != null) { // 如果碎片携带有包裹,就打开包裹获取参数信息
            mPosition = getArguments().getInt("position", 0); // 从包裹取出位置序号
            mImageId = getArguments().getInt("image_id", 0); // 从包裹取出图片的资源编号
            mDesc = getArguments().getString("desc"); // 从包裹取出商品的文字描述
        }
        // 根据布局文件fragment_dynamic.xml生成视图对象
        mView = inflater.inflate(R.layout.fragment_dynamic, container, false);
        ImageView iv_pic = mView.findViewById(R.id.iv_pic);
        TextView tv_desc = mView.findViewById(R.id.tv_desc);
        iv_pic.setImageResource(mImageId);
        tv_desc.setText(mDesc);
        Log.d(TAG, "onCreateView position=" + mPosition);
        return mView; // 返回该碎片的视图对象
    }

    @Override
    public void onAttach(Activity activity) { // 把碎片贴到页面上
        super.onAttach(activity);
        Log.d(TAG, "onAttach position=" + mPosition);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) { // 页面创建
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate position=" + mPosition);
    }

    @Override
    public void onDestroy() { // 页面销毁
        super.onDestroy();
        Log.d(TAG, "onDestroy position=" + mPosition);
    }

    @Override
    public void onDestroyView() { // 销毁碎片视图
        super.onDestroyView();
        Log.d(TAG, "onDestroyView position=" + mPosition);
    }

    @Override
    public void onDetach() { // 把碎片从页面撕下来
        super.onDetach();
        Log.d(TAG, "onDetach position=" + mPosition);
    }

    @Override
    public void onPause() { // 页面暂停
        super.onPause();
        Log.d(TAG, "onPause position=" + mPosition);
    }

    @Override
    public void onResume() { // 页面恢复
        super.onResume();
        Log.d(TAG, "onResume position=" + mPosition);
    }

    @Override
    public void onStart() { // 页面启动
        super.onStart();
        Log.d(TAG, "onStart position=" + mPosition);
    }

    @Override
    public void onStop() { // 页面停止
        super.onStop();
        Log.d(TAG, "onStop position=" + mPosition);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) { //在活动页面创建之后
        super.onActivityCreated(savedInstanceState);
        Log.d(TAG, "onActivityCreated position=" + mPosition);
    }

}

4、活动页面

public class ViewPagerActivity extends AppCompatActivity implements OnPageChangeListener {
    private List<GoodsInfo> mGoodsList; // 手机商品列表

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view_pager);
        mGoodsList = GoodsInfo.getDefaultList();
        // 构建一个商品图片的翻页适配器
        ImagePagerAdapater adapter = new ImagePagerAdapater(this, mGoodsList);
        // 从布局视图中获取名叫vp_content的翻页视图
        ViewPager vp_content = findViewById(R.id.vp_content);
        vp_content.setAdapter(adapter); // 设置翻页视图的适配器
        vp_content.setCurrentItem(0); // 设置翻页视图显示第一页
        vp_content.addOnPageChangeListener(this); // 给翻页视图添加页面变更监听器
//        // 给翻页视图添加简化版的页面变更监听器
//        vp_content.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
//            @Override
//            public void onPageSelected(int position) {
//                Toast.makeText(ViewPagerActivity.this, "您翻到的手机品牌是:"
//                        + mGoodsList.get(position).name, Toast.LENGTH_SHORT).show();
//            }
//        });
    }

    // 翻页状态改变时触发。state取值说明为:0表示静止,1表示正在滑动,2表示滑动完毕
    // 在翻页过程中,状态值变化依次为:正在滑动→滑动完毕→静止
    public void onPageScrollStateChanged(int state) {}

    // 在翻页过程中触发。该方法的三个参数取值说明为 :第一个参数表示当前页面的序号
    // 第二个参数表示页面偏移的百分比,取值为0到1;第三个参数表示页面的偏移距离
    public void onPageScrolled(int position, float ratio, int offset) {}

    // 在翻页结束后触发。position表示当前滑到了哪一个页面
    public void onPageSelected(int position) {
        Toast.makeText(this, "您翻到的手机品牌是:" + mGoodsList.get(position).name, Toast.LENGTH_SHORT).show();
    }
}

效果:


http://www.kler.cn/a/512263.html

相关文章:

  • pytest+playwright落地实战大纲
  • 2024人工智能AI+制造业应用落地研究报告汇总PDF洞察(附原数据表)
  • springboot项目属性配置方式
  • CamemBERT:一款出色的法语语言模型
  • openharmony应用开发快速入门
  • Go 切片:用法和本质
  • 免费为企业IT规划WSUS:Windows Server 更新服务 (WSUS) 之快速入门教程(一)
  • 如何在C#中处理控件无法执行Invoke或BeginInvoke的情况
  • 多级缓存 JVM进程缓存
  • 【useCallback Hook】在多次渲染中缓存组件中的函数,避免重复创建函数
  • iOS中的设计模式(三)- 工厂方法
  • 分布式系统架构7:本地缓存
  • CSS 实体
  • 第11章:Python TDD实现货币类加法运算初步
  • 深入HDFS——HA和QJM
  • 4.1 AI 大模型应用最佳实践:如何提升 GPT 模型使用效率与质量
  • MySQL多表查询练习
  • 数据库性能优化(sql优化)_SQL执行计划01_yxy
  • 【数据结构篇】顺序表 超详细
  • 从一到无穷大 #42:ClickHouse - 极致工程优化的Lightning Fast Analytics
  • vue3+vite+ts+router4+Pinia+Axios+sass 从0到1搭建
  • Sam Altman亲自确认:o3-mini即将上线!GPT和o系列模型合并!
  • Halcon 3D基础知识及常用函数
  • 基于本地消息表实现分布式事务
  • JAVAweb学习日记(五) SpringBootWeb
  • Vue+Element-ui 中 使用el-table 设置表格单元格 (el -table-column) 保留空格和换行