6.Android高级控件ViewPager和Fragment

ViewPager的使用

ViewPager简介

  1. 它是Android 3.0后引入的一个UI控件(视图滑动切换工具)
  2. 通过手势滑动可以完成View的切换,一般是用来做APP的引导页或者实现图片轮播。

ViewPager的使用要点

  • ViewPager是v4包中的一个类,继承自ViewGroup,是一个容器,可以在其中添加其他的view类。
  • ViewPager布局管理器允许翻转带数据的页面,可以通过实现PagerAdapter来显示视图。
  • ViewPager类需要一个PagerAdapter适配器类给它提供数据。

PagerAdapter的介绍

  • 适配器就像显示器,是把复杂的数据按人们易于接受的方式来展示。

  • PagerAdapter也是android.support.v4包中的类。

  • PagerAdapter主要是对ViewPager进行数据适配,以实现ViewPager控件的滑动效果。

PagerAdapter的使用(继承PagerAdapter类)

  • getCount()// 显示多少个页面
  • isViewFromObject(View, Object)//判断返回的view是否是来自Object
  • instantiateItem(ViewGroup, int)// 初始化指定位置的页面
  • destroyItem(ViewGroup, int, Object) // 销毁指定位置的页面

案例1:APP启动页的开发

  1. 在主布局文件中添加ViewPager控件
  2. 隐藏工程导航栏
  3. 新建三个布局页面,用来作为启动页面。
  4. 编写Adapter类,为ViewPager控件创建一个适配器。
  5. 编程实现启动页面的滑动功能

Fragment的使用

Fragment简介

  • Android在3.0版本引入了 Fragment(碎片) 功能,它非常类似于Activity,可以像Activity一样包含布局。

  • 它出现的初衷是为了适应大屏幕的平板电脑,使用Fragment我们可以把屏幕划分成几块,合理利用屏幕空间。

  • Fragment 通常是嵌套在 Activity 中使用。

  • 现在想象这种场景:有两个Fragment,Fragment 1包含了一个ListView,每行显示一本新闻的标题。Fragment 2包含了TextView和自定义View,来显示新闻的标题和详细内容。

  • 程序运行竖屏模式的平板或手机上,Fragment 1可能嵌入在一个Activity中,而Fragment 2可能嵌入在另一个Activity中,如下图:

    image-20210128141113712
  • 程序运行在横屏模式的平板上,两个 Fragment 就可以嵌入在同一个 Activity 中,如下图:

image-20210128141139950

Fragment使用要点

  • Fragment并不能单独使用,他需要嵌套在Activity 中使用,作为Activity界面的一部分组成出现。
  • 可以在一个Activity中同时出现多个Fragment,并且一个Fragment也可在多个Activity中使用;
  • 在Activity运行过程中,可以通过transaction的add()、remove()、replace()方法来添加、移除或者替换Fragment;
  • Fragment可以响应自己的输入事件,并且有自己的生命周期,但它的生命周期受其宿主Activity的生命周期影响。比如Activity 被destory销毁了,它也会跟着被销毁。
  • 3.0之前的系统,需要先导入android-support-v4的jar包

Fragment 的生命周期

image-20210128141531802

案例2:APP底部导航功能开发

  1. 在主布局文件中加入Fragment替换区,底部导航区,分割线等。

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".FragmentActivity">
    
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
            <LinearLayout
                android:id="@+id/content_layout"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_above="@id/view_line_1"
                android:orientation="vertical">
    
            </LinearLayout>
    
            <View
                android:id="@+id/view_line_1"
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:layout_above="@id/Bottom_tap"
                android:layout_alignParentBottom="false"
                android:background="#4A1A1A" />
    
            <LinearLayout
                android:id="@+id/Bottom_tap"
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:layout_alignParentBottom="true"
                android:orientation="horizontal">
    
                <ImageView
                    android:id="@+id/iv_home"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:src="@mipmap/home" />
    
                <View
                    android:id="@+id/view_line_2"
                    android:layout_width="1dp"
                    android:layout_height="match_parent"
                    android:background="#231313" />
    
                <ImageView
                    android:id="@+id/iv_letter"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:src="@mipmap/letter" />
    
                <View
                    android:id="@+id/view_line_3"
                    android:layout_width="1dp"
                    android:layout_height="match_parent"
                    android:background="#231313" />
    
                <ImageView
                    android:id="@+id/iv_my"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:src="@mipmap/my" />
            </LinearLayout>
        </RelativeLayout>
    </androidx.constraintlayout.widget.ConstraintLayout>
    
  2. 新建三个简单的布局文件,作为Fragment的View对象,并分别进行标识。

    每个文件代码格式如下:

    package com.example.timeemail.Fragments;
    
    import android.os.Bundle;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    
    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    import androidx.fragment.app.Fragment;
    
    import com.example.timeemail.R;
    
    public class Fragment_home extends Fragment {
        @Nullable
        @Override
        public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            //创建Fragment布局
            View view = inflater.inflate(R.layout.layout_home, container, false);
    
            return view;
        }
    }
    
    
  3. 在MainActivity.java里编写逻辑代码,实现UI及底部标签切换。

  4. 开启事务transaction,以实现底部导航功能。

    package com.example.timeemail;
    
    import androidx.appcompat.app.AppCompatActivity;
    import androidx.fragment.app.Fragment;
    import androidx.fragment.app.FragmentTransaction;
    
    import android.graphics.Color;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.ImageView;
    
    import com.example.timeemail.Fragments.Fragment_home;
    import com.example.timeemail.Fragments.Fragment_letter;
    import com.example.timeemail.Fragments.Fragment_my;
    
    public class FragmentActivity extends AppCompatActivity implements View.OnClickListener {
    
        private Fragment fragment_home, fragment_letter, fragment_my, nowFragment;
        private ImageView iv_home, iv_letter, iv_my;
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_fragment);
            initUI();
        }
    
        /**
         * 初始化ui界面
         *
         * @param
         */
        private void initUI() {
            iv_my = (ImageView) findViewById(R.id.iv_my);
            iv_home = (ImageView) findViewById(R.id.iv_home);
            iv_letter = (ImageView) findViewById(R.id.iv_letter);
    
    //        //设置底部tab变化,默认第一个被选中
    //        iv_home.setBackgroundColor(Color.DKGRAY);
    //        iv_letter.setBackgroundColor(Color.WHITE);
    //        iv_my.setBackgroundColor(Color.WHITE);
            show_Fragment_home();
    
            //为底部标签添加点击事件
            iv_my.setOnClickListener(this);
            iv_home.setOnClickListener(this);
            iv_letter.setOnClickListener(this);
        }
    
        //第一个标签被点击
        private void show_Fragment_home() {
            //开启事务,Fragment的切换是由事务控制的
            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
            //判断Fragment是否为空
            if (fragment_home == null) {
                fragment_home = new Fragment_home();
                //添加Fragment到事务中
                transaction.add(R.id.content_layout, fragment_home);
            }
    
            //隐藏所有的Fragment
            hideAllFragment(transaction);
            //显示Fragment
            transaction.show(fragment_home);
            //记录当前显示的Fragmnet
            nowFragment = fragment_home;
            //提交事务
            transaction.commit();
            //设置底部标签的变化
            iv_home.setBackgroundColor(Color.DKGRAY);
            iv_letter.setBackgroundColor(Color.WHITE);
            iv_my.setBackgroundColor(Color.WHITE);
        }
    
        //第二个标签被点击
        private void show_Fragment_letter() {
            //开启事务,Fragment的切换是由事务控制的
            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
            //判断Fragment是否为空
            if (fragment_letter == null) {
                fragment_letter = new Fragment_letter();
                //添加Fragment到事务中
                transaction.add(R.id.content_layout, fragment_letter);
            }
    
            //隐藏所有的Fragment
            hideAllFragment(transaction);
            //显示Fragment
            transaction.show(fragment_letter);
            //记录当前显示的Fragmnet
            nowFragment = fragment_letter;
            //提交事务
            transaction.commit();
            //设置底部标签的变化
            iv_home.setBackgroundColor(Color.WHITE);
            iv_letter.setBackgroundColor(Color.DKGRAY);
            iv_my.setBackgroundColor(Color.WHITE);
    
        }
    
        //第三个标签被点击
        private void show_Fragment_my() {
            //开启事务,Fragment的切换是由事务控制的
            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
            //判断Fragment是否为空
            if (fragment_my == null) {
                fragment_my = new Fragment_my();
                //添加Fragment到事务中
                transaction.add(R.id.content_layout, fragment_my);
            }
    
            //隐藏所有的Fragment
            hideAllFragment(transaction);
            //显示Fragment
            transaction.show(fragment_my);
            //记录当前显示的Fragmnet
            nowFragment = fragment_my;
            //提交事务
            transaction.commit();
            //设置底部标签的变化
            iv_home.setBackgroundColor(Color.WHITE);
            iv_letter.setBackgroundColor(Color.WHITE);
            iv_my.setBackgroundColor(Color.DKGRAY);
        }
    
        //隐藏所有的Fragment
        private void hideAllFragment(FragmentTransaction transaction){
            if (fragment_home!=null){
                transaction.hide(fragment_home);
            }
            if (fragment_letter!=null){
                transaction.hide(fragment_letter);
            }
            if (fragment_my!=null){
                transaction.hide(fragment_my);
            }
        }
    
        @Override
        public void onClick(View view) {
            if (view.getId() == R.id.iv_home) {
                //第一个标签被点击
                show_Fragment_home();
            } else if (view.getId() == R.id.iv_letter) {
                //第二个标签被点击
                show_Fragment_letter();
            } else if (view.getId() == R.id.iv_my) {
                //第三个标签被点击
                show_Fragment_my();
            }
        }
    }
    

ViewPager与Fragment的综合应用

  • Google 官方也建议我们使用Fragment来填充ViewPager,这样可以更加方便的生成每个Page以及管理每个Page的生命周期。

  • Google给我们提供了两个不同的Adapter,他们分别是:FragmentPageAdapter和FragmentStatePagerAdapter,它们是专程用来呈现Fragment页面的,这些 Fragment页面会一直保存在Fragment Manager中,以便用户可以随时取用。

  • 如果要使用FragmentPagerAdapter类,需要重写getItem()和getCount()两个方法。

  • ViewPager还有一个比较重要的函数是:

    • viewPager.setOffscreenPageLimit(int limit); 默认:1(limit的值代表着还要缓存当前Fragment左右各limit个Fragment,一共会创建2*limit+1个Fragment。)

image-20210128195223394

Fragment适配器介绍

FragmentPageAdapter
  1. 用于实现Fragment的滑动效果
  2. 使用Fragment来填充ViewPager
  3. 适用于页面比较少的情况
  4. FragmentPagerAdapter消耗更多的内存
FragmentStatePagerAdapter
  1. 用于实现Fragment的滑动效果
  2. 使用Fragment来填充ViewPager
  3. 适用于页面比较多的情况
  4. FragmentStatePagerAdapter省内存

FragmentPagerAdapter适用于Fragment比较少的情况,它会把每一个Fragment保存在内存中,不用每次切换的时候,去保存现场,切换回来在重新创建,所以用户体验比较好。而对于Fragment比较多的情况,需要切换的时候销毁以前的Fragment以释放内存,就可以使用FragmentStatePagerAdapter

案例3:商城导航APP

  1. 在主布局文件中加入ViewPager切换区,底部导航区,分割线。(复用)
  2. 新建三个简单的布局文件,作为Fragment的View对象,并分别进行标识。(复用)
  3. 创建FragmentPagerAdapter适配器,提供ViewPager数据源。
  4. 在MainActivity.java里编写逻辑代码,实现UI及底部标签切换。
  5. 编写代码,以实现对底部导航功能。
    dapter适用于Fragment比较少的情况,它会把每一个Fragment保存在内存中,不用每次切换的时候,去保存现场,切换回来在重新创建,所以用户体验比较好。而对于Fragment比较多的情况,需要切换的时候销毁以前的Fragment以释放内存,就可以使用FragmentStatePagerAdapter

案例3:商城导航APP

  1. 在主布局文件中加入ViewPager切换区,底部导航区,分割线。(复用)
  2. 新建三个简单的布局文件,作为Fragment的View对象,并分别进行标识。(复用)
  3. 创建FragmentPagerAdapter适配器,提供ViewPager数据源。
  4. 在MainActivity.java里编写逻辑代码,实现UI及底部标签切换。
  5. 编写代码,以实现对底部导航功能。
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值