NavigatorLayout 导航布局
1. 概述
1.0 开始加入
涂鸦设备控制面板几乎不会是由单个页面组成, 组织和管理多个页面之间的关联, 嵌套关系, 以及页面之间如何过渡的组件,我们通常称之为Navigator.
而NavigatorLayout就是一个支持导航路由的基础布局, 能轻易的处理面板页面间的切换.
默认NavigatorLayout集成了常用的最佳实践,比如FullView, OfflineView和TopBar, 同时保留了扩展性,这些组件均允许用户替换.
FullView封装了设备控制面板页面常用的组件布局,包括工具栏(TopBar), 遮罩层(MaskView), 离线视图(OfflineView)和背景(Background)
FullView默认会铺满父容器(flex: 1), 配合NavigatorLayout 导航布局使用,会铺满从状态栏到底部虚拟按键之间的所有区域, 没有虚拟按键的设备,会铺满状态栏至屏幕底部的区域。
FullView没有直接开放给用户,NavigatorLayout默认集成了FullView, 同时保留了扩展点,允许用户自定义FullView视图传入
OfflineView是涂鸦提供的默认离线视图,如果没有特殊要求,默认的OfflineView已经适用大部分面板场景.
2. 基础使用
使用NavigatorLayout, 需要以下步骤
- 写一个React组件,继承tuya-panel-kit提供的NavigatorLayout
- 重写renderScene方法以渲染用户自己的页面, 需要返回一个合法的React组件
- 由于页面之间跳转,可能会带一些参数,重写hookRoute方法,可以实现更精细的路由控制
3. 代码演示
3.1 在两个页面之间跳转
首先定义好一个路由配置,然后写一个组件继承自NavigatorLayout
import React from 'react'
import { StyleSheet } from 'react-native'
import { NavigatorLayout } from 'tuya-panel-kit'
import Page from './page'
import Home from './home'
const routers = [
{
id: 'page1',
title: 'page1',
Scene: props =>
},
{
id: 'page2',
title: 'page2',
Scene: props =>
}
]
export default class MainLayout extends NavigatorLayout {
// eslint-disable-next-line
hookRoute(route) {
const theRoute = routers.find(r => r.id === route.id)
return {
...route,
topbarStyle: { backgroundColor: '#ff6024' },
showOfflineView: false,
title: route.id === 'main' ? 'Basic Jump Usage' : theRoute.title
}
}
renderScene(route, navigator) {
let Scene =
const router = routers.find(r => r.id === route.id)
if (router && router.Scene) {
const Component = router.Scene
Scene =
}
return Scene
}
}
这里我们定义了 2 个页面的路由表(routers), 分别是page1和page2, 在renderScene方法里我们可以拿到Naviagtor, 以及当前路由对象的情况,然后我们在渲染页面的时候, 根据当前路由的 id 去路由表查找相应的页面,如果没有对应的页面,我们就渲染默认的主页。
下面是page和home的实现
// page.js
import React from 'react'
import { View, Text, StyleSheet } from 'react-native'
import { Button } from 'tuya-panel-kit'
// eslint-disable-next-line
export default ({ num, navigator }) => (
This is Page {num}
)
// home.js
import React from 'react'
import { View, StyleSheet, Text } from 'react-native'
import { Button } from 'tuya-panel-kit'
// eslint-disable-next-line
export default ({ navigator }) => (
Welcome to basic usage of NavigatorLayout
{[1, 2].map(v => (
))}
)
通过Navigator的push方法,我们能跳转到某个页面,通过pop方法,能回退一个页面。
在工程目录下运行yarn start, 并且在 app 输入相应的调试地址,之后我们就可以在 app 上看到效果了。
3.2 自定义过渡动画效果
NavigatorLayout使用了默认的页面过渡动画配置,即
const SceneConfigs = {
...Navigator.SceneConfigs.HorizontalSwipeJump,
gestures: {
pop: {
...Navigator.SceneConfigs.FloatFromRight.gestures.pop
}
}
}
体现出的行为将会是: 平台有关的水平滑动页面跳转, 以及从右到左的页面回退.
使用 3.1 的例子,修改下navigator.push传入的参数,即可自定义过渡动画
import React from 'react'
import { View, StyleSheet, Text } from 'react-native'
import { Button } from 'tuya-panel-kit'
import { Navigator } from 'react-native-deprecated-custom-components'
const sceneConfig = {
...Navigator.SceneConfigs.HorizontalSwipeJump,
gestures: {
pop: {
...Navigator.SceneConfigs.FloatFromRight.gestures.pop
}
}
}
const RouterConfig = [
{
txt: \`VerticalUpSwipeJump to page 1\`,
transition: {
...sceneConfig,
...Navigator.SceneConfigs.VerticalUpSwipeJump
}
},
{
txt: \`SwipeFromLeft to page 2\`,
transition: {
...sceneConfig,
...Navigator.SceneConfigs.SwipeFromLeft
}
}
]
// eslint-disable-next-line
export default ({ navigator }) => (
Screen Transition Example!
{[1, 2].map(v => (
))}
)
这里我们使用了效果VerticalUpSwipeJump和SwipeFromLeft, 以下是效果图
4. 应用
NavigatorLayout是涂鸦面板应用的基石,基本所有面板都用到了它。
5. 函数 API
renderScene(route, navigator) 渲染页面组件
route: 一个普通对象,里面放着用于渲染的参数,这些参数可以被自定义组件获取到用于渲染。一般 route 会至少带以下参数
id: 当前页面的 id
title: 当前页面的在TopBar里显示的标题
topbarStyle: 当前页面的TopBar的样式,是一个 js 对象, 值是React Native的StyleSheet允许的值。
background: 用于渲染页面背景, 可以是一个图片或者渐变
backgroundColor: 背景色,只能是合法的ReactNative颜色值字符串
style: FullView背景样式
hideFullView: true或者false, 表示隐藏 FullView, 一般用于自定义FullView
renderFullView: 一个渲染函数,一般配合hideFullView一起使用, 允许用户自己渲染FullView
hideTopBar: 是否隐藏TopBar
OfflineView: 离线图组件,用于自定义离线图, 需要是一个合法的 React 组件
showOfflineView: 控制是否隐藏离线图, 一般开发调试的时候,会置为false
navigator: 即React Native提供的 Navigator, navigator 的 api 可以在这里看到: Navigator 的函数 - route: 一个普通对象,里面放着用于渲染的参数,这些参数可以被自定义组件获取到用于渲染。一般 route 会至少带以下参数
- id: 当前页面的 id
- title: 当前页面的在TopBar里显示的标题
- topbarStyle: 当前页面的TopBar的样式,是一个 js 对象, 值是React Native的StyleSheet允许的值。
- background: 用于渲染页面背景, 可以是一个图片或者渐变
- backgroundColor: 背景色,只能是合法的ReactNative颜色值字符串
- style: FullView背景样式
- hideFullView: true或者false, 表示隐藏 FullView, 一般用于自定义FullView
- renderFullView: 一个渲染函数,一般配合hideFullView一起使用, 允许用户自己渲染FullView
- hideTopBar: 是否隐藏TopBar
- OfflineView: 离线图组件,用于自定义离线图, 需要是一个合法的 React 组件
- showOfflineView: 控制是否隐藏离线图, 一般开发调试的时候,会置为false
- navigator: 即React Native提供的 Navigator, navigator 的 api 可以在这里看到: Navigator 的函数
hookRoute(route) 修改 route 参数
hookRoute(route) 修改 route 参数
由于 route 对象放着用于渲染的参数,开发者会经常修改,为方便开发, 提供 hookRoute 函数用于修改 route 对象的值, route 对象的属性和 renderScene 里的 route 是一致的,用户可以自行往里面放自定义参数, route 只是一个普通对象.
onBack() 返回回调
返回行为一般是指按下安卓返回键, 或者iOS 从左至右滑动的行为, 通常结果是返回上一页. onBack函数就是用于定制返回行为,如果返回 false, 那么将不会返回上一页, 注意,直接调用navigator的 api 还是可以操作页面切换的。
6. PropTypes 传入属性定义
此处是原始的devInfo定义,如果使用涂鸦提供的模板,其中的devInfo经过了特殊的处理以便开发者使用
devInfo: 一个普通 js 对象,包含大量设备的信息, 至少会提供以下字段:
- name: 设备名称
- productId: 产品 id
- uiId: 当前产品对应的面板 id
- homeId: 设备所属的家庭的id
- bv: 硬件基线版本
- devId: 设备 Id
- gwId: 网关 Id, 如果是单品,devId 一般和 gwId 相等
- ability: 只有蓝牙设备使用, 如果是单点蓝牙设备,值是 5
- attribute: 设备所属的产品的能力标志, 一般表示有没有开通某些服务, 如alexa语音控制
- isOnline: 总判断是否在线
- isLocalOnline: 局域网是否在线
- isShare: 是否共享设备
- isVDevice: 是否是演示设备
- networkType: 设备的在线类型
- capability: 设备的能力类型, 标志设备支持什么能力, 如支持 zigbee, 红外, 蓝牙等
- schema: 设备所属产品的功能点(dp, data point)定义, 功能点解释请看dp 解释