通过自定义FragmentController的FragmentHostCallback实现浮窗界面的管理

效果

在这里插入图片描述

FragmentController介绍

FragmentController用于控制fragment,它把activity的许多事件分发给fragment处理。更准确的说法是分配给fragment manager,然后由fragment manager分发给fragment。FragmentController通常都是在activity中创建的,并且activity作为FragmentController的host存在。

FragmentHostCallback介绍

在创建FragmentController的时候,我们需要指定一个FragmentHostCallback实例用于指定FragmentController的宿主。FragmentHostCallback定义了许多宿主依赖行为:

  1. 宿主实例回调onGetHost(),返回宿主实例。
  2. 查找容器的回调onFindViewById(id: Int),返回fragment添加容器。
  3. 生成LayoutInflater的回调onGetLayoutInflater(),返回用于实例化fragment布局的LayoutInflater
private val mFragments =
        FragmentController.createController(object : FragmentHostCallback<Service>(
            this,
            Handler(Looper.getMainLooper()),
            0
        ) {
            override fun onGetHost(): Service? {
                return this@FloatWindowService
            }

            override fun onFindViewById(id: Int): View? {
                return rootContainer.findViewById(id)//rootContainer已经被添加到WindowManager管理
            }

            override fun onGetLayoutInflater(): LayoutInflater {
                return super.onGetLayoutInflater().cloneInContext(this@FloatWindowService)
            }
        })

通过service管理浮窗

app显示浮窗的功能通常要求应用退出的时候也能正常显示,所以我们需要启动service来管理浮窗。service没有画面描绘的权利,我们需要结合window manager来添加浮窗界面显示。关于window manager添加View的权限申请问题,有大量的文章都有介绍。这里他不是讨论的重点。如果浮窗的业务逻辑不是很复杂,并且没有过多的ui状态转换,那么我们可以简单地在service中控制浮窗ui的切换。如果浮窗的逻辑复杂,ui状态转换频繁且有许多ui状态需要维护。这种情况下,service管理ui状态就力不从心。所以本篇文章想利用fragment来管理ui状态。

如何将FragmentController与service绑定并管理浮窗状态

根据前面的介绍,我们已经掌握了创建FragmentController的方法。接下来我们把service的状态分发给FragmentController。当service被创建的时候,我们把FragmentController的状态切换到resume状态。当service被销毁的时候,我们把FragmentController的状态切换到destroy状态。


    override fun onCreate() {
        super.onCreate()
        windowManager.addView(rootContainer, layoutParameter)
        mFragments.attachHost(null)//没有parent fragment,所以是null参数。
        mFragments.dispatchResume()
    }


    override fun onDestroy() {
        super.onDestroy()
        mFragments.dispatchDestroy()
        windowManager.removeView(rootContainer)
    }

fragment使用时需要注意的问题

  1. 由于FragmentController是从Service中创建的,所以Fragment中获取不到activity实例。
  2. 由于获取不到activity实例,所以启动activity时使用的Context都是Service类型的或是Application类型的。我们都知道Service 或Application类型的Context启动activity的时候都需要添加Intent.FLAG_ACTIVITY_NEW_TASK flag。

Git

https://github.com/mjlong123123/TestFloaWindow.git

我的公众号已经开通,公众号会同步发布。
欢迎关注我的公众号

在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mjlong123123

你的鼓励时我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值