Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【提案】一种新的窗口控制标准 #120

Open
Gaubee opened this issue Feb 11, 2024 · 0 comments
Open

【提案】一种新的窗口控制标准 #120

Gaubee opened this issue Feb 11, 2024 · 0 comments

Comments

@Gaubee
Copy link
Contributor

Gaubee commented Feb 11, 2024

我们基于 Manifest/display 提供对应的方案

窗口浮动模式

  1. 全局的顶部控制栏,类似 macos 的顶部工具栏,这里暂时命名为 “应用控制栏(app-controller-bar)”
    • 控制栏的左上角是 “应用图标” “应用名称”
      • 点击左上角可以展开“应用菜单>应用详情页”
        • 这里可以看到应用的 manifest 信息
        • 这里可以看到权限信息,用户可以在这里看到应用正在使用的权限,进一步可以看到这权限的调用历史,还能对权限进行简单的控制
        • 这里可以跳转到应用安装界面,对应用进行升级
        • 这里可以对应用进行卸载
        • 这里可以对应用的数据进行管理
    • 控制栏的右上角是 “应用菜单” “窗口切换” “窗口关闭”
      • 点击“应用菜单”可以展开“应用菜单>应用控制页”,控制页包含大量功能性按钮,基本都可以进行专业操作
        • 应用控制器包含“旋转方向”、“亮暗主题”、“置顶”、“允许后台”等等
        • 如果有多个一级窗口,那么这些控制器在专业操作面板下,会在二级菜单中提供选择指定窗口的的选项
        • 如果有多个一级窗口,底部会有一个“高级设置”,里头会列出所有一级窗口以及它们的控制器
      • 点击“窗口切换”,会切换到该应用的下一个窗口
        • 在“窗口切换”的专业操作面板中:会将窗口的预览图列表展示,点击预览图,可以激活对应窗口
    1. 点击“窗口关闭”,会关闭当前窗口
        • 在“窗口关闭”的专业操作面板中:会提供“强制推出”的功能按钮,会给出解释告诉用户用户会被完全关闭。
        • 开发者可以通过接口来配置“原因/动作/动作状态”,这是一个 steps 组件,从而用户可以在这个流程中被开发者引导做安全的工作,或者也可以直接点击流程中的最后一步:“强制退出”、或者用户也可以随时中断流程
    • 窗口的顶部仍然存在,名为 “窗口标题栏(app-title-bar)”
      • 如果是 minimal-ui 模式,那么窗口顶栏左上角是“返回按钮”
      • 窗口顶栏的右上角是默认为空,开发者可以通过 menu-api 来进行提供一些功能性按钮
      1. menu-api 是可以被多方进行扩展的,比方说如果是 webview 进行渲染,那么它可以注入“翻译”、“前进(默认支持,但应用可以通过接口来禁用前进)、“字体大小”、“页面查照”、“刷新”、“复制链接”等功能
      • 窗口顶栏的中间是 “窗口页标题”
        • 拖拽模式可以对整个窗口进行移动
        • 单击会进入“应用菜单>应用控制页>高级设置>窗口控制页”,如果只有一个窗口,那么则是路由到“应用菜单>应用控制页”
    • 窗口底部是 left-resize-button、 appid+version、right-resize-button
在窗口模式下,一些扩展交互
    • 触摸标题栏时,会立刻进入移动模式

      参考 Android-Youtube 应用中,播放列表的拖动排序的反馈

      • 如果移动量少于 5pt,且少于专业模式的触发时间阈值,那么属于 tap/click 操作
    • 在移动模式下,控制栏会显示的一些图标槽,推动到槽内,会触发震动,松手会触发相应功能
      • 图标槽包括“建议布局”、“最大化”、“置顶”、“画中画”、“跨设备流转”,这些功能其实在“应用菜单>应用控制页”都能找到,只不过这里额外提供

        目前只需要提供“最大化”
        跨设备流转首先需要应用声明支持。比方说 Web 应用本质就是提供一个 http-url 和 http-headers,然后在另外一个设备进行打开这个网页。未来 plaoc 也许会使用 yjs 提供默认支持。
        否则跨设备流转就要使用截屏推流的功能?这点我不建议,我个人建议使用 Web 的能力来做这个事情,尽可能放大 Web-API 所能带来的体验,并且在另外一个设备上使用它自己的 webview 进行渲染,体验绝大多数情况下是更好的。不然像现在 Android 做的跨设备流转,本质是一种推流的模式,这就导致它天生是不能多设备同时协作的,而 OpenHarmony 会更类似 web,它会将代码与数据分发到另外的设备上,然后独立运行。而 Web 天生支持动态渲染,因此能在同时在多个设备上,用各自设备的最佳屏幕尺寸进行独立渲染,我觉得这是更加先进的。
        并且 Web 这种协作,我们可以提供一些社区组件来减轻开发者的负担,比方说提供 sync-zone 组件:即便页面都是独立渲染,但是这个组件可以让用户在<sync-zone></sync-zone>发生的事情实时同步到其它设备上。

    • [ ]移动模式下,第二个手指参与进来,会进入窗口缩放模式,可以形成捏合和放大的手势

      这个功能可以用在特定模式下,窗口大小进入过大的状态,此时可以用这个功能将窗口缩小到可控制的范围内。
      窗口有最小高度,持续继续缩小,高度不会变,但是宽度会继续缩小。同理于最小宽度。

    • 移动模式和缩放模式模式下,界面默认会暂停实时渲染,进行截取操作后只显示原生的图片
      • 开发者改变这种默认的优化成“实时模式”,主动声明应用支持实时布局,那么不会使用“截图模式”
      • 在“截图模式”下,图片以拉伸的方式进行渲染
      • 在“截图模式”下,如果用户操作的运动量减少到一定程度了,那么会以 2fps 的频率更新截图
      • 如果当前窗口层未支持截图,或者截图被禁止,那么就显示成:应用图标居中有阴影,截图高斯模糊(如果没有截图那么就主题色;如果没有主题色,那么就亮色、暗色)

        通常来说是支持截图的,但是在“防截图”的模式下,只能使用这种备用方案

    • 拉动右下角的图标进入缩放模式,右下角会出现一个“建议布局”图标槽,将窗口缩放拖入,会显示开发者提供的最佳视窗大小的建议。

      同理拉动左下角的图标进入缩放模式,图标槽会出现在左下角


窗口最大化模式

    • fullscreen 模式

      该模式一般用于游戏类、视频类、沉浸类应用,在该模式下,状态栏与导航栏都会被隐藏

      • 这种模式将进入真正意义上的全屏,但不是独立的 Activity,而是类似多桌面模式,这个应用会被独立渲染在一个单独的桌面空间(workspace)中
      • 我们将提供一个“浮动按钮”,按钮中显示着应用图标,点击它会展开成“全屏控制栏”(展开缩小的动画时间大概时 300ms,需要比较快的动画,同时不也要有一定的视觉暂留时间来告知用户)
        • “浮动按钮”可以被拖拽改变位置
        • 每次在 workspace 被激活的时候,“浮动按钮”都会展开成一个 toast,告诉用户:“滑动顶部或者底部边缘,可以展开控制栏”,如果用户没有操作,2s 后,它会缩小成“浮动按钮”
        • 单击“浮动按钮”也可以展开控制栏
        • “浮动按钮”总是贴边渲染,会贴在屏幕方向的两侧,并且会与顶部与底部保持安全触摸的距离,确保不感染系统手势
      • 控制栏中会提供“退出全屏”的功能
      • 控制栏会显示应用基本信息:logo+appid+version
      • 控制栏显示时,其区域以外的手势操作仍然会触发到应用里头,不会被 mask 消费掉,从而防止游戏模式下的操作丢失的行为
      • 控制栏显示时,再执行返回手势,那么会直接触发“退出全屏”
      • 控制栏可以被接口控制进行打开

        未来如果 dweb-ui 开发完善,那么控制栏可以被二次开发,用户可以提供一些自定义的功能或者组件,从而满足比如视频控制、视频进度等需求

      • 如果用户在唤出全屏控制栏后却没有对控制栏进行操作,而是在其它地方进行操作,那么在展开动画完成后、并等待 200ms 后,全屏控制栏会自动缩小回去。
    • standalone 模式的最大化

      该模式用于应用类,在该模式下,状态栏导航栏都存在,同时应用顶部和底部还有存在一些基本的应用信息

      • 应用顶部会居中显示“应用名称”的信息,显示的大小参考 IOS 应用中,左上角“返回来源应用”的文字大小

        可以从 Apple Store 打开某一个应用就能看到这行左上角的小字

      • 应用底部会显示 appid+version 的信息
      • 我们将提供一个“浮动按钮”,按钮中显示着“应用图标”,以及“显示桌面”的图标
        • 点击“应用图标”,会展开菜单面板
        • 点击“显示桌面”,应用将会最小化
    • minimal-ui 模式的最大化

      该模式是最适合开发传统原生应用的模式,它在 standalon 的基础上,提供了系统级的应用顶栏
      “应用顶栏(app-top-bar)”是控制栏与标题栏会合并渲染而成的
      在 IOS 中,我们可以使用原生的 UINavigationBar 来进行实现,效果是最好的
      在 Android 中,我们使用 Jetpack Compose 提供的 Top app bars 来进行实现

      • 应用顶栏的左上角是返回按钮,符合传统返回按钮在顶部的习惯
      • 应用顶栏的中间是 “窗口页标题”,默认会使用 “应用名称”。
        • 如果使用 webview 渲染,它会自动使用 document.title 作为 “窗口页标题”。
        • 点击应用顶栏,可以展开菜单面板
        • 向下拖拽应用顶栏,可以解除最大化模式,进入浮动窗口的模式
      • 应用顶栏的右上角默认是“胶囊”,其中胶囊左边是“应用图标”,右边是“显示桌面”
        • 点击“应用图标”,会显示“应用控制栏”与“菜单面板”
        • 点击“显示桌面”,应用将会最小化
      • 应用可以配置应用顶栏的样式和风格,参考 ionic 的 ion-header 组件
        • 应用可以配置 overlay 模式,那么会使用 env(safe-area) 来提供给页面

          目前 safe-area 是通过一些私有手段达成的,可能不长远,所以建议还是用 var(safe-area) 来解决。

      • 应用的底部是 app-bottom-bar,一般来说它只显示 appid 和 version。

        未来随着 dweb-ui 的完善,app-bottom-bar 可以被二次开发注入一些组件,从而保证了其灵活性与性能

辅助参考资料
  1. compose nested-scrolling-interop
  2. Nested Scrolling with Android Webviews

应用在启动阶段,不会显示窗口,而只会显示控制栏

  1. 如果没有窗口,左上角会显示“退出”按钮,右上角会显示“打开”按钮
    1. 右上角默认不显示“打开”按钮,每次展示控制栏,它应该立刻被执行:应该立刻向应用发送相对应的渲染指令。
    2. 但如果应用启用了“后台模式”,那么该按钮应该显示
  2. “应用控制栏” 替代了原本启动应用时总是会显示一个空白窗口的问题,我们不再需要显示奇怪的窗口了,这也应用可就能自由显示 app-bottom-sheet 或者 app-window
  3. 未来还能实现 app-bottom-sheet 拉到顶部与 “应用控制栏” 进行融合的原生交互

    参考 Android/Google-map 与 Android/didi 拉动 bottom-sheet 到顶部后在顶部创建搜索栏的交互特性


终述


总的来说,我们消除了原本在底部的控制栏带来的问题,并且进一步优化了控制栏与标题栏与应用顶栏三者的关系

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant