HeaderView
HeaderView 是 CRN 框架提供的一个通用导航栏组件,代码简洁(只有区区129行),但是功能十分强大(通过上面的视频演示可以看出来)。
HeaderView 的强大之处主要体现在下面几方面:
- 每个页面相互独立,互相不会影响
- HeaderView 的 View 控制权交给了使用方
- 提供了不同粒度的局部渲染接口,可以根据需求自行选择使用
- 可以局部动态刷新
- 提供了携程蓝色样式的标准默认导航栏,如果无特殊需求直接使用默认样式方便快捷
注:HeaderView 是一个类,本文中有时提到的 HeaderView 实际上是泛指 HeaderView 类的实例,读者需要注意一下。
HeaderView 集成
HeaderView 对每个页面是独立的,所以需要每个页面单独集成,一般而言 HeaderView 应该放在 ViewPort 内。但是也有特殊情况,比如页面头部需要跟随页面滚动时需要把 HeaderView 放在对应的 ScrollView 内。(实际上,HeaderView 是个 View,所以你可以把它放在任何你想放的地方,而且不会有副作用。)
示例代码:
<
ViewPort
>
<
View style={styles.container}
>
<
HeaderView
ref = 'headerView'
page = {this}
title = {'默认标题'}
rightViewWidth = {44}
renderRightView = {()=
>
{
return (
<
View style = {{flexDirection:'row', height: 44}}
>
<
NavigationBarButton type = {'icon_share'} onPress = {() =
>
{Page.goHome();}}/
>
<
/View
>
);
}}
/
>
<
/ViewPort
>
HeaderView 的控制权
一般通过设置ref
在当前页面取得 HeaderView 的控制权,取得控制权后可以随时刷新 HeaderView,比如页面时数据回来后刷新标题或显示分享按钮等。或者页面滚动时让 HeaderView 做一些动画等。
HeaderView 的属性
title
标题。
titleColor
标题字体颜色。默认白色('white'/'#ffffff'/'rgb(255, 255, 255)')。
titleFontSize
标题字体大小。默认17。
subtitle
副标题。
subtitleColor
副标题字体颜色。默认白色('white'/'#ffffff'/'rgb(255, 255, 255)')。
subtitleFontSize
副标题字体大小。默认15.
backgroundColor
导航栏背景色。默认为携程蓝色('rgb(9, 159, 222)')。
renderHeaderView {Function}
导航栏自定义渲染方法,传入此属性时 HeaderView 不会调用默认渲染方法,整个导航栏将由此方法渲染。
此属性的使用场景是在需要高度定制化导航栏时,比如同一个页面导航栏需要在完全不同样式的导航栏之间切换时可以考虑使用这个属性。
renderContentView {Function}
contentView 自定义渲染方法。
contentView 对 android 来说与 HeaderView 整体 View 区域无差别;对 iOS 来说是除掉状态栏的剩余区域。
一般情况下也不需要此属性,除非导航栏高度定制,比如整个导航栏就放了一个搜索框。
renderLeftView {Function}
左侧 View 自定义渲染方法,如果左侧是标准的携程返回箭头时不需要设置此属性,HeaderView 默认会提供标准返回按钮并绑定返回事件(this.pop())。
建议使用 CRN 框架提供的 NavigationBarButton 来渲染左侧按钮。
leftViewWidth
左侧 view 宽度,只有在设置了renderLeftView
属性时才需要设置此属性,此属性默认值为44。
renderCenterView {Function}
中间区域自定义渲染方法,当中间区域需要自定义时设置此属性,比如中间需要放一个按钮响应点击事件。
HeaderView 默认的渲染方法会渲染一个标题和副标题(如果有设置的话),标题和副标题对应 title 和 subtitle属性。
renderRightView
右侧 View 自定义渲染方法,HeaderView 默认没有右侧 View。
rightViewWidth
左侧 view 宽度,只有在设置了renderRightView
属性时才需要设置此属性,此属性默认值为0。
page
当前页面实例,需要传入,默认导航栏绑定一些默认事件时需要用到,比如默认左侧返回按钮会绑定page.pop()
方法。
其他未提到的
View
标准属性也都支持。注意:上面的所有属性都是可选的,如果全都不设置也没问题,会渲染出一个只带左侧返回按钮的携程标准蓝色导航栏。
HeaderView 局部动态更新
上面的属性都是 HeaderView 初始化时设置的,提供一些设置初始化样式的能力。HeaderView 还有一个很重要的特星星就是局部动态刷新,这个特性由下面一组实例方法提供。
HeaderView 的实例方法
setBackgroundColor(color)
设置导航栏背景色setTitle(title)
设置标题setTitle(title)
设置题文字颜色setSubtitle(subtitle)
设置副标题。setSubtitleColor(color)
设置副标题文字颜色setRenderLeftView(renderLeftView, leftViewWidth = 44)
设置左侧 View 渲染方法setRenderCenterView(renderCenterView)
设置中间 View 渲染方法setRenderRightView(renderRightView, rightViewWidth)
设置右侧 View 渲染方法
导航栏默认按钮
CRN 提供了大量通用按钮,这些按钮是独立于HeaderView
之外的,既可以在HeaderView
中使用,也可以在其他地方使用。
具体请参考文档:NavigationBarButton
为什么有些方法没有提供?
通过上面的说明,可以知道,HeaderView 的自定义渲染能力其实是通过props
和实例方法共同提供的。
但是聪明的读者可能发现了:有些props
并未提供对应的动态刷新方法,比如titleFontSize
,subtitleFontSize
等。
未提供这些方法主要是从业务方面考量,比如未提供titleFontSize
和subtitleFontSize
的刷新方法主要是从业务角度考虑:同一个页面导航栏的标题字体大小一般都是固定的。
HeaderView 无法满足需求时怎么办?
两条路:
- 给 CRN 框架组提需求。(如果是合理性的通用需求,否则参考第二条解决方案)
- 自己写一个 HeaderView。
示例代码
下面是包括了比较全面的关于HeaderView
使用的示例代码:
'use strict';
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
Image,
TextInput,
Dimensions,
} from 'react-native';
import {
Page,
Button,
NavigationBarButton,
ViewPort,
URL,
SpriteImage,
HeaderView
} from '@ctrip/crn';
export default class Page1 extends Page {
render() {
return (
<
ViewPort
>
<
View style={styles.container}
>
<
HeaderView
ref = 'headerView'
page = {this}
title = {'默认标题'}
rightViewWidth = {44}
renderRightView = {()=
>
{
return (
<
View style = {{flexDirection:'row', height: 44}}
>
<
NavigationBarButton type = {'icon_share'} onPress = {() =
>
{Page.goHome();}}/
>
<
/View
>
);
}}
/
>
<
View style = {{flex:1, flexDirection:'row', flexWrap:'wrap'}}
>
<
Button
onPress = {() =
>
{
this.refs.headerView.setTitle('随时随地设置页面标题,标题栏最多支持两行,超出会显示。。。非常方便');
}}
style={{backgroundColor:'rgb(9, 159, 222)', marginTop:10, marginHorizontal:10, height:30, justifyContent:'center', paddingHorizontal:10}}
>
设置字数很多的标题
<
/Button
>
<
Button
onPress = {() =
>
{
this.refs.headerView.setSubtitle('随时随地设置页面标题');
}}
style={{backgroundColor:'rgb(222,100,22)', marginTop:10, height:30, justifyContent:'center', paddingHorizontal:10}}
>
设置副标题
<
/Button
>
<
Button
onPress = {() =
>
{
this.refs.headerView.setRenderRightView(() =
>
{return null;});
}}
style={{backgroundColor:'rgb(222,100,22)', marginTop:10, height:30, justifyContent:'center', paddingHorizontal:10, marginHorizontal:10}}
>
删除右侧按钮
<
/Button
>
<
Button
onPress = {() =
>
{
this.refs.headerView.setRenderRightView(() =
>
{return
<
NavigationBarButton type = {'icon_phone'} onPress = {() =
>
{Page.goHome();}}/
>
;});
}}
style={{backgroundColor:'rgb(222,100,22)', marginTop:10, height:30, justifyContent:'center', paddingHorizontal:10, marginHorizontal:10}}
>
设置右侧按钮1
<
/Button
>
<
Button
onPress = {() =
>
{
this.refs.headerView.setRenderRightView(() =
>
{
return
<
View style = {{flexDirection:'row', height: 44}}
>
<
NavigationBarButton type = {'icon_home_text'} onPress = {() =
>
{Page.goHome();}}/
>
<
NavigationBarButton type = {'icon_more_text'} onPress = {() =
>
{Page.goHome();}}/
>
<
/View
>
;
}, 88);
}}
style={{backgroundColor:'rgb(9, 159, 222)', marginTop:10, height:30, justifyContent:'center', paddingHorizontal:10, marginHorizontal:10}}
>
设置右侧按钮2
<
/Button
>
<
Button
onPress = {() =
>
{
this.refs.headerView.setRenderLeftView(() =
>
{return
<
NavigationBarButton onPress = {() =
>
{this.pop();}}
>
取消
<
/NavigationBarButton
>
;});
}}
style={{backgroundColor:'rgb(9, 159, 222)', marginTop:10, height:30, justifyContent:'center', paddingHorizontal:10, marginHorizontal:10}}
>
设置左侧按钮
<
/Button
>
<
Button
onPress = {() =
>
{
this.refs.headerView.setRenderRightView(() =
>
{return
<
NavigationBarButton onPress = {() =
>
{Page.goHome();}}
>
我的收藏
<
/NavigationBarButton
>
;}, 88);
}}
style={{backgroundColor:'rgb(222,100,22)', marginTop:10, height:30, justifyContent:'center', paddingHorizontal:10, marginHorizontal:10}}
>
设置自定义宽度的右侧按钮
<
/Button
>
<
Button
onPress = {() =
>
{
this.refs.headerView.setTitleColor('blue');
}}
style={{backgroundColor:'rgb(9, 159, 222)', marginTop:10, height:30, justifyContent:'center', paddingHorizontal:10, marginHorizontal:10}}
>
设置标题颜色
<
/Button
>
<
Button
onPress = {() =
>
{
this.refs.headerView.setSubtitleColor('red');
}}
style={{backgroundColor:'rgb(9, 159, 222)', marginTop:10, height:30, justifyContent:'center', paddingHorizontal:10, marginHorizontal:10}}
>
设置副标题颜色
<
/Button
>
<
Button
onPress = {() =
>
{
this.refs.headerView.setBackgroundColor('rgb(222,100,22)');
}}
style={{backgroundColor:'rgb(222,100,22)', marginTop:10, height:30, justifyContent:'center', paddingHorizontal:10, marginHorizontal:10}}
>
设置导航栏背景色
<
/Button
>
<
/View
>
<
/View
>
<
/ViewPort
>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'flex-start',
alignItems: 'center',
backgroundColor: '#F5FCFF',
}
});