uni-app利用原生子窗体解决悬浮窗口播放问题及踩坑记录

2,001 阅读4分钟

“我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第15篇文章,点击查看活动详情

实现效果如图:参考得到app交互,音频课程返回时,app下方展示悬浮窗口播放,可暂停、播放、关闭,点击可返回至音频文章查看文章。关闭app,再进入有缓存上次音频课程,可点击继续播放。上滑显示悬浮框,下滑隐藏悬浮框。

图片.png

原生子窗体

subNVues 是 vue 页面的原生子窗体。用于解决App中 vue 页面中的层级覆盖和原生界面灵活自定义用的。它不是全屏页面,也不是组件,就是一个原生子窗体。它是一个 nvue 页面,使用 weex 引擎渲染,提供了比 cover-view、plus.nativeObj.view 更强大的原生排版能力,方便自定义原生导航或覆盖原生地图、视频等。

详细配置见这个:原生子窗体

请详读:subNVues 开发指南

如何获取原生子窗体实例及实例方法,见这篇:subNVue原生子窗体

请先熟读:如何配置  —  开发指南  —  实例及方法

解决方案

1、在需要展示的页面增加原生子窗体配置

{
    "path": "pages/course/course",
    "style":{
        "app-plus":{
            "subNVues":[{
                "id": "course-bgAudio",
                "path": "pages/subNVue/bgAudio",
                "style": {
                    "width": "710rpx",
                    "height": "100rpx",
                    "bottom": "30rpx",
                    "margin": "auto",
                    "background": "transparent"
                }
            }]
        }
    }
},

注意:

id 需唯一不能重复;

margin: auto; 代表左右居中。

path 代表子窗体页面路径。我们这个需求都是要一样的窗口展示,所以可以共用一个 nvue 页面。页面路径指南上有说,只要可以正确引入即可。

2、在 pages/subNVue/bgAudio.nvue 页面编写自己的页面样式及代码逻辑即可,这个就不多说了。

3、上滑滚动、下滑隐藏。这里我们接可以写一个 mixin  - submixin.js

export const submixin = {
    data() {
        return {
            curTop: 0
        }
  },
    methods: {
        showSubOrNot(subId) {
            if(!uni.getStorageSync('curArticle')) {
                const _sub = uni.getSubNVueById(subId + '-bgAudio')
                _sub.hide()
            }else{
                const _sub = uni.getSubNVueById(subId + '-bgAudio')
                _sub.show()
            }
        },
        pageScroll(subId, top) {
            if(!uni.getStorageSync('curArticle')) return
            const _sub = uni.getSubNVueById(subId + '-bgAudio')
            top > this.curTop ? _sub.hide() : _sub.show()
            this.curTop = top
        }
    }
}

4、那么如何使用呢?

// 1、引入submixin
import { submixin } from '@/mixins/submixin.js'

// 2、注册mixins
mixins:[submixin],

// 3、onShow的时候控制sub窗口展示与否的逻辑
// 4、onPageScroll的时候控制sub窗口滚动显示的逻辑
onShow() {
    this.showSubOrNot('course')
},
onPageScroll(top) {
    this.pageScroll('course', top.scrollTop)
},

业务逻辑处理,肯定是需要结合 vuex 状态管理了。

踩坑点

1、获取sub窗口实体的方法易踩坑:

我刚开始为了简便不写sub窗口的id,以为可以使用 uni.getCurrentSubNVue() 任意获取当前页面的子窗体实例,但是好像不是这样的,这样用的话,就很容易卡死不动。不知道为啥,后来认真看了官网上对 2 种获取实例的方法描述。uni.getCurrentSubNVue() 说的是在一个subnvue窗体的nvue页面代码中,获取当前 subNVues 原生子窗体的实例。所以猜到可能是这里的问题,然后换成 uni.getSubNVueById(subNVueId) 之后就 ok 了。具体原因不详,只能说是个踩坑点。

2、不知道是否有设置公共的子窗体的配置,查了一下,没找到。

目前我是需要悬浮窗体播放的几个页面,就加了 子窗体 的配置,不需要的不加即可。

不过也确实应该是这样,总不可能所有页面都放子窗体,对用户也不那么友好。看得到也是在个别与音频播放相关和tabbar列表的页面加了悬浮窗体播放,其他位置就没加。

通过这个原生子窗体感觉就可以做很多事情了,比如这篇博客说的这个:视频聊天,可以了解下:uniapp 使用原生子窗体进行视频聊天

PS:其实之前就想做这个东西,之前研究的是通过 Html5+ 的接口:plus.webview.create 去做这个事情,也可以实现置顶悬浮,但是那个悬浮窗口的样式包括业务逻辑就不好控制了,研究了一下也没有很好的解决方案。后来看到这个原生子窗体,感觉挺可以,一试确实可以,感觉还行。