首页 > 其他分享 >Android studio开发实战之碎片Fragment

Android studio开发实战之碎片Fragment

时间:2025-01-20 11:57:30浏览次数:3  
标签:Fragment 视图 int studio position Android public 页面

        一、碎片化的概念

        碎片化(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();
    }
}

效果:

标签:Fragment,视图,int,studio,position,Android,public,页面
From: https://blog.csdn.net/weixin_51020083/article/details/145255248

相关文章

  • 运维系列&安卓系列【仅供参考】:fastutil-7.2.0.jar下载依赖包超时问题,Android
    fastutil-7.2.0.jar下载依赖包超时问题,Androidfastutil-7.2.0.jar下载依赖包超时问题,Android摘要正文fastutil-7.2.0.jar下载依赖包超时问题,Android摘要文章介绍了在下载FastUtil-7.2.0.jar时遇到的网络问题,提出解决方案是使用阿里云的国内镜像,并给出了G......
  • 运维系列&安卓系列【仅供参考】:android studio 3.1 升级gradle4.4时所踩到的坑
    androidstudio3.1升级gradle4.4时所踩到的坑androidstudio3.1升级gradle4.4时所踩到的坑androidstudio3.1升级gradle4.4时所踩到的坑公司原项目是使用Androidstudio2.3编译的,最近将Androidstudio升级到3.1后,buildapk时提示:Theprojectisusing......
  • Android JecPack组件之LifeCycles 使用详解
    一、背景LifeCycle是一个可以感知宿主生命周期变化的组件。常见的宿主包括Activity/Fragment、Service和Application。LifeCycle会持有宿主的生命周期状态的信息,当宿主生命周期发生变化时,会通知监听宿主的观察者。LifeCycle的出现主要是为了解决:系统组件的生命周期与......
  • AndroidStudio:GPS定位与网络定位定位服务
    前言:如今主流的定位方式有两种:GPS定位和网络定位。GPS即通过卫星定位,网络定位则需要通过手机附近的基站,WIFI等确定位置信息。二者的优缺点各有不同,Gps较为精准但是耗电量大,网络定位功耗小但是不精确。这篇文章会以LocationManager为例,讲解如何在Androidstudio中使用这两种定位......
  • Android系统开发(十):标准协议和通讯的桥梁:探索蓝牙、NFC、WLAN 的工作原理
    引言:现代社会已经是信息互联的世界,各种设备之间的互联互通已经成为了生活的一部分。而在这个过程中,Android设备与其他硬件之间的通信扮演着至关重要的角色。从蓝牙耳机到WiFi路由器,甚至与电话功能的互动,所有这些连接都依赖于标准Android连接协议的支持。本篇文章将带......
  • Android程序导入unity工程
    用到的软件1.AndroidStudio2.Unity3D1.AndroidStudio生成Arr包1.1Android中所有的Activity都必须继承Activity类,不能继承默AppCompatActivity1.2修改Res文件下的styles修改前修改后1.3将applyplugin:'com.android.application'改成applyplugin:'com.androi......
  • 用Python检查Android字符串文件通配符
    #!/usr/bin/envpython3importosimportsysfromdatetimeimportdatetime,timedeltaimportreimportxml.etree.ElementTreeasETiflen(sys.argv)<3:exit()print(datetime.now(),'start')timestamp=int(datetime.now().timestamp())en_t......
  • 用Shell检查Android字符串文件通配符
    #!/bin/sh#$1=english$2=others$3=outputif[[$3]];thendate+%F""%T"--------------------start---------------------">>$3fitimestamp=`date+%s`en_type=others_type=#获得第1个参数最后3个字符为后缀en_postfix=`echo${1:-3}`others_......
  • SpringBoot基于Android的建筑工地施工项目管理系统的设计与实现
    1.引言在当今的软件开发领域,企业级应用的开发和部署速度直接影响着业务的竞争力。SpringBoot以其轻量级、快速启动和强大的集成能力,成为构建现代企业级应用的首选框架。本文将带您深入了解SpringBoot框架的核心特性,并展示如何利用它构建一个高效、可扩展的系统。2.开发......
  • Android Audio基础(53)——PCM逻辑设备Write数据
    1.前言本文,我们将以回放(Playback,播放音频)为例,讲解PCMData是如何从用户空间到内核空间,最后传递到Codec硬件。在ASoC音频框架简介中,我们给出了回放(Playback)PCM数据流示意图。:对于Linux来说,由于分为userspace和kernelspace,而且两者之间数据不能随便互相访问。因此用......