前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android中最最常用—Fragment实战篇最详解

Android中最最常用—Fragment实战篇最详解

作者头像
下码看花
发布2019-09-25 15:28:05
5.5K3
发布2019-09-25 15:28:05
举报
文章被收录于专栏:AndroidStudio初识

前言

Hi,各位花粉们,上一节Android中最最常用—Fragment基础篇最详解,我们详细的介绍了 Fragment的基本原理及使用、 Fragment中的常用方法等。在这一节,将结合具体的使用场景,来更加全面的介绍 Fragment的日常使用。

示例一: RadioButton+ Fragment

在之前介绍的你不能错过的RadioButton实践一文中,我们详细介绍了 RadioButton的使用,在示例:实现微信底部Tab效果中,只是实现了底部导航的效果切换,那怎么使导航上面的内容页面随着底部Tab的切换而改变呢?下面就结合 Fragment实现这个效果。

1.修改原 Activity的主布局页面,新增 FrameLayout作为 Fragment的容器。
代码语言:javascript
复制
<?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=".MyFragmentActivity">

    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/radioGroup"
        app:layout_constraintTop_toTopOf="parent" />

    <RadioGroup
        android:id="@+id/radioGroup"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:paddingTop="10dp"
        android:paddingBottom="10dp"
        app:layout_constraintBottom_toBottomOf="parent">

        <RadioButton
            android:id="@+id/rbHome"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:button="@null"
            android:checked="true"
            android:drawableTop="@drawable/tab_home_selector"
            android:gravity="center_horizontal"
            android:text="首页"
            android:textColor="@drawable/tab_text_selector" />

        <RadioButton
            android:id="@+id/rbDiscovery"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@null"
            android:button="@null"
            android:drawableTop="@drawable/tab_discovery_selector"
            android:gravity="center_horizontal"
            android:text="发现"
            android:textColor="@drawable/tab_text_selector" />

        <RadioButton
            android:id="@+id/rbContacts"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@null"
            android:button="@null"
            android:drawableTop="@drawable/tab_contacts_selector"
            android:gravity="center_horizontal"
            android:text="通讯录"
            android:textColor="@drawable/tab_text_selector" />

        <RadioButton
            android:id="@+id/rbMe"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@null"
            android:button="@null"
            android:drawableTop="@drawable/tab_me_selector"
            android:gravity="center_horizontal"
            android:text="我"
            android:textColor="@drawable/tab_text_selector" />
    </RadioGroup>

</androidx.constraintlayout.widget.ConstraintLayout>
2.创建4个 Fragment,然后创建对应的4个布局(根据自己情况而定)。

以下创建了4个示例 Fragment:FragmentHome(首页)、FragmentDiscovery(发现)、FragmentContacts(通讯录)、FragmentMine(我的)。

3.在 Activity中实例化各个 FragmentRadioButtonRadioParent的控件,设置好监听器。
4.关联 RadioButtonFragment,通过 switchFragment()的方法,控制 Fragment的显示和隐藏。
代码语言:javascript
复制
public class MyFragmentActivity extends AppCompatActivity {

    private RadioGroup rg;
    private RadioButton mRbHome;
    private RadioButton mRbDiscovery;
    private RadioButton mRbContacts;
    private RadioButton mRbMe;

    private Fragment mFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my_fragment);

        //初始化View
        initView();

        //初始化Fragment
        initFragment();

        //RadioGroup切换监听
        rg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup radioGroup, int checkedId) {
                switch (checkedId) {
                    case R.id.rbHome:
                        switchFragment(FragmentHome.newInstance("首页Fragment"));
                        break;
                    case R.id.rbDiscovery:
                        switchFragment(FragmentDiscovery.newInstance("发现Fragment"));
                        break;
                    case R.id.rbContacts:
                        switchFragment(FragmentContacts.newInstance("通讯录Fragment"));
                        break;
                    case R.id.rbMe:
                        switchFragment(FragmentMy.newInstance("我的Fragment"));
                        break;
                    default:
                        break;
                }
            }
        });
    }

    /**
     * 加载默认的Fragment
     */
    private void initFragment() {
        mFragment = FragmentHome.newInstance("首页Fragment");
        getSupportFragmentManager().beginTransaction()
                .add(R.id.container, mFragment).commit();
    }

    private void switchFragment(Fragment fragment) {
        //判断当前显示的Fragment是不是切换的Fragment
        if (mFragment != fragment) {
            //判断切换的Fragment是否已经添加过
            if (!fragment.isAdded()) {
                //如果没有,则先把当前的Fragment隐藏,把切换的Fragment添加上
                getSupportFragmentManager().beginTransaction().hide(mFragment)
                        .add(R.id.container, fragment).commit();
            } else {
                //如果已经添加过,则先把当前的Fragment隐藏,把切换的Fragment显示出来
                getSupportFragmentManager().beginTransaction()
                        .hide(mFragment).show(fragment).commit();
            }
            mFragment = fragment;
        }
    }

    /**
     * 动态设置四个tab的样式
     */
    private void initView() {
        rg = findViewById(R.id.radioGroup);
        mRbHome = findViewById(R.id.rbHome);
        mRbContacts = findViewById(R.id.rbContacts);
        mRbDiscovery = findViewById(R.id.rbDiscovery);
        mRbMe = findViewById(R.id.rbMe);

        setStyle(R.drawable.tab_home_selector, mRbHome);
        setStyle(R.drawable.tab_contacts_selector, mRbContacts);
        setStyle(R.drawable.tab_discovery_selector, mRbDiscovery);
        setStyle(R.drawable.tab_me_selector, mRbMe);
    }

    /**
     * 动态设置每个tab的图片宽高以及文字间距
     *
     * @param selector RadioButton的样式选择器
     * @param rb       RadioButton的样式选择器
     */
    private void setStyle(int selector, RadioButton rb) {
        Drawable drawableHome = getResources().getDrawable(selector);
        drawableHome.setBounds(0, 0, 80, 80);
        rb.setCompoundDrawables(null, drawableHome, null, null);
    }
}

switchFragment()的方法中,判断切换的 Fragment是否已经添加过,避免每一次切换 Fragment的时候都调用 add()或者 replace(),而是通过 hide()show(),减少频繁地创建新的实例。

mFragment:用于记录当前加载的 Fragment,用户切换时隐藏。

5.最后效果如下。

示例二: ViewPager+ Fragment

上面初步实现了一个APP的底部导航栏效果,但细心地读者可能会发现,微信的四个主页面是可以左右滑动切换的,而上面的效果只能是点击底部导航Tab进行切换。要实现左右页面滑动切换,就要使用我们接下来需要介绍的控件 ViewPager了。

ViewPagersupport v4库中提供界面滑动的类,继承自 ViewGroupPagerAdapterViewPager的适配器类,为 ViewPager提供界面。但是一般来说,通常都会使用 PagerAdapter的两个子类:FragmentPagerAdapterFragmentStatePagerAdapter作为 ViewPager的适配器,他们的特点是界面是 Fragment

默认, ViewPager会缓存当前页相邻的界面,比如当滑动到第2页时,会初始化第1页和第3页的界面(即 Fragment对象,且生命周期函数运行到 onResume()),可以通过 setOffscreenPageLimit(count)设置离线缓存的界面个数。

FragmentPagerAdapterFragmentStatePagerAdapter需要重写的方法都一样,常见的重写方法如下:

  • publicFragmentPagerAdapter(FragmentManagerfm):构造函数,参数为 FragmentManager。如果是嵌套 Fragment场景,子 PagerAdapter的参数传入 getChildFragmentManager()
  • FragmentgetItem(intposition):返回第position位置的 Fragment必须重写
  • intgetCount():返回 ViewPager的页数,必须重写
  • ObjectinstantiateItem(ViewGroupcontainer,intposition):container是 ViewPager对象,返回第position个位置的 Fragment
  • voiddestroyItem(ViewGroupcontainer,intposition,Objectobject):container是 ViewPager对象,object是 Fragment对象。
  • getItemPosition(Objectobject):object是 Fragment对象,如果返回POSITIONUNCHANGED,则表示当前 Fragment不刷新,如果返回POSITIONNONE,则表示当前Fragment需要调用 destroyItem()instantiateItem()进行销毁和重建。默认情况下返回POSITION_UNCHANGED。

FragmentPagerAdapterFragmentStatePagerAdapter区别

  • FragmentPagerAdapter该类内的每一个生成的 Fragment都将保存在内存之中,因此适用于那些相对静态的页,数量也比较少的那种。
  • FragmentStatePagerAdapter其内部不断重建和销毁,适合处理有很多页,并且数据动态性较大、占用内存较多的情况。

修改原代码,新增 ViewPager关联 RadioButtonFragment,步骤如下:

1.修改 Activity布局文件,替换 FrameLayoutViewPager
代码语言:javascript
复制
<?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=".MyFragmentActivity">

    <!--替换FrameLayout为ViewPager-->
    <androidx.viewpager.widget.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/radioGroup"
        app:layout_constraintTop_toTopOf="parent" />

    <RadioGroup
        android:id="@+id/radioGroup"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:paddingTop="10dp"
        android:paddingBottom="10dp"
        app:layout_constraintBottom_toBottomOf="parent">

        <RadioButton
            android:id="@+id/rbHome"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:button="@null"
            android:checked="true"
            android:drawableTop="@drawable/tab_home_selector"
            android:gravity="center_horizontal"
            android:text="首页"
            android:textColor="@drawable/tab_text_selector" />

        <RadioButton
            android:id="@+id/rbDiscovery"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@null"
            android:button="@null"
            android:drawableTop="@drawable/tab_discovery_selector"
            android:gravity="center_horizontal"
            android:text="发现"
            android:textColor="@drawable/tab_text_selector" />

        <RadioButton
            android:id="@+id/rbContacts"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@null"
            android:button="@null"
            android:drawableTop="@drawable/tab_contacts_selector"
            android:gravity="center_horizontal"
            android:text="通讯录"
            android:textColor="@drawable/tab_text_selector" />

        <RadioButton
            android:id="@+id/rbMe"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@null"
            android:button="@null"
            android:drawableTop="@drawable/tab_me_selector"
            android:gravity="center_horizontal"
            android:text="我"
            android:textColor="@drawable/tab_text_selector" />
    </RadioGroup>
</androidx.constraintlayout.widget.ConstraintLayout>
2.新建 MyViewPagerAdapter,继承自 FragmentPagerAdapter
代码语言:javascript
复制
public class MyViewPagerAdapter extends FragmentPagerAdapter {

    private List<Fragment> mFragments;

    public MyViewPagerAdapter(FragmentManager fm, List<Fragment> mFragments) {
        super(fm);
        this.mFragments = mFragments;
    }

    @Override
    public Fragment getItem(int i) {
        return mFragments.get(i);
    }

    @Override
    public int getCount() {
        return mFragments == null ? 0 : mFragments.size();
    }
}
3.初始化 ViewPagerMyViewPagerAdapter,并进行关联。
代码语言:javascript
复制
//添加Fragment到集合中
List<Fragment> mFragmentList = new ArrayList<>();
mFragmentList.add(FragmentHome.newInstance("首页Fragment"));
mFragmentList.add(FragmentDiscovery.newInstance("发现Fragment"));
mFragmentList.add(FragmentContacts.newInstance("通讯录Fragment"));
mFragmentList.add(FragmentMy.newInstance("我的Fragment"));

//关联ViewPager与Adapter
MyViewPagerAdapter myViewPagerAdapter = new MyViewPagerAdapter(getSupportFragmentManager(), mFragmentList);
mViewPager.setAdapter(myViewPagerAdapter);
4.设置 RadioGroupViewPager和监听,进行 RadioGroupViewPager关联。
代码语言:javascript
复制
//RadioGroup切换监听 关联ViewPager相关页面
mRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
    @Override
    public void onCheckedChanged(RadioGroup radioGroup, int checkedId) {
        switch (checkedId) {
            case R.id.rbHome:
                mViewPager.setCurrentItem(0);
                break;
            case R.id.rbDiscovery:
                mViewPager.setCurrentItem(1);
                break;
            case R.id.rbContacts:
                mViewPager.setCurrentItem(2);
                break;
            case R.id.rbMe:
                mViewPager.setCurrentItem(3);
                break;
            default:
                break;
        }
    }
});

//ViewPager滑动监听 关联相关RadioButton
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
    @Override
    public void onPageSelected(int position) {
        if (position == 0) {
            mRbHome.setChecked(true);
        } else if (position == 1) {
            mRbDiscovery.setChecked(true);
        } else if (position == 2) {
            mRbContacts.setChecked(true);
        } else if (position == 3) {
            mRbMe.setChecked(true);
        }
    }
});
5. Activity 完整代码及效果如下。
代码语言:javascript
复制
public class MyFragmentActivity extends AppCompatActivity {

    private RadioGroup mRadioGroup;
    private RadioButton mRbHome;
    private RadioButton mRbDiscovery;
    private RadioButton mRbContacts;
    private RadioButton mRbMe;
    private ViewPager mViewPager;

    private MyViewPagerAdapter myViewPagerAdapter;
    private List<Fragment> mFragmentList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my_fragment);

        initView();

        //添加Fragment到集合中
        mFragmentList = new ArrayList<>();
        mFragmentList.add(FragmentHome.newInstance("首页Fragment"));
        mFragmentList.add(FragmentDiscovery.newInstance("发现Fragment"));
        mFragmentList.add(FragmentContacts.newInstance("通讯录Fragment"));
        mFragmentList.add(FragmentMy.newInstance("我的Fragment"));

        //关联ViewPager与Adapter
        myViewPagerAdapter = new MyViewPagerAdapter(getSupportFragmentManager(), mFragmentList);
        mViewPager.setAdapter(myViewPagerAdapter);

        //默认选中首页
        mViewPager.setCurrentItem(0);
        mRbHome.setChecked(true);

        //RadioGroup切换监听 关联ViewPager相关页面
        mRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup radioGroup, int checkedId) {
                switch (checkedId) {
                    case R.id.rbHome:
                        mViewPager.setCurrentItem(0);
                        break;
                    case R.id.rbDiscovery:
                        mViewPager.setCurrentItem(1);
                        break;
                    case R.id.rbContacts:
                        mViewPager.setCurrentItem(2);
                        break;
                    case R.id.rbMe:
                        mViewPager.setCurrentItem(3);
                        break;
                    default:
                        break;
                }
            }
        });

        //ViewPager滑动监听 关联相关RadioButton
        mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                if (position == 0) {
                    mRbHome.setChecked(true);
                } else if (position == 1) {
                    mRbDiscovery.setChecked(true);
                } else if (position == 2) {
                    mRbContacts.setChecked(true);
                } else if (position == 3) {
                    mRbMe.setChecked(true);
                }
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
    }

    /**
     * 动态设置四个tab的样式
     */
    private void initView() {
        mRadioGroup = findViewById(R.id.radioGroup);
        mRbHome = findViewById(R.id.rbHome);
        mRbContacts = findViewById(R.id.rbContacts);
        mRbDiscovery = findViewById(R.id.rbDiscovery);
        mRbMe = findViewById(R.id.rbMe);
        mViewPager = findViewById(R.id.viewPager);

        setStyle(R.drawable.tab_home_selector, mRbHome);
        setStyle(R.drawable.tab_contacts_selector, mRbContacts);
        setStyle(R.drawable.tab_discovery_selector, mRbDiscovery);
        setStyle(R.drawable.tab_me_selector, mRbMe);
    }

    /**
     * 动态设置每个tab的图片宽高以及文字间距
     *
     * @param selector RadioButton的样式选择器
     * @param rb       RadioButton的样式选择器
     */
    private void setStyle(int selector, RadioButton rb) {
        //定义底部标签图片大小和位置
        Drawable drawableHome = getResources().getDrawable(selector);
        //当这个图片被绘制时,给他绑定一个矩形 ltrb规定这个矩形
        drawableHome.setBounds(0, 0, 80, 80);
        //设置图片在文字的哪个方向
        rb.setCompoundDrawables(null, drawableHome, null, null);
    }
}

结语

以上就是Fragment的一些常见使用场景,根据示例,可以变换多种使用形式,这就要求我们举一反三,根据具体业务、具体需求灵活运用。赶快在项目中练习使用吧!

如果你觉得本篇对你有所帮助,欢迎转载分享,标志出处即可,谢谢支持。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-09-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 下码看花 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 示例一: RadioButton+ Fragment
    • 1.修改原 Activity的主布局页面,新增 FrameLayout作为 Fragment的容器。
      • 2.创建4个 Fragment,然后创建对应的4个布局(根据自己情况而定)。
        • 3.在 Activity中实例化各个 Fragment和 RadioButton和 RadioParent的控件,设置好监听器。
          • 4.关联 RadioButton和 Fragment,通过 switchFragment()的方法,控制 Fragment的显示和隐藏。
            • 5.最后效果如下。
            • 示例二: ViewPager+ Fragment
              • 1.修改 Activity布局文件,替换 FrameLayout为 ViewPager。
                • 2.新建 MyViewPagerAdapter,继承自 FragmentPagerAdapter。
                  • 3.初始化 ViewPager和 MyViewPagerAdapter,并进行关联。
                    • 4.设置 RadioGroup和 ViewPager和监听,进行 RadioGroup和 ViewPager关联。
                      • 5. Activity 完整代码及效果如下。
                      • 结语
                      相关产品与服务
                      容器服务
                      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档