首頁功能
前面,我們已經完成了影視信息組件的開發,接下來,我們要用該組件來完成首頁界面功能的開發,如下圖
可以看到,首頁頂部一個標題欄,下面是‘最新’、‘最熱’兩個選項卡。我們要完成的有標題欄、選項卡、以及選項卡切換的內容。
標題欄
這裏的標題欄,我們使用的是ToolbarAndroid,看名稱我們就知道這個是android下特有的組件view,所以就立馬想到,這個組件是ios、android不能通用的。因此,我們定義一個TitleBarComponent,方便以後重複使用和ios適配。這裏,先提一下關於組件適配的一些問題。
組件平臺適配
不同平臺使用不同的組件,React Native 提供了以下四種解決方案
- 最直接的方案就是把組件放置到不同的文件夾下:
/common/components/
/android/components/
/ios/components/
- 根據平臺不同在組件的文件命名上加以區分,如下:
BigButtonIOS.js
BigButtonAndroid.js
- 使用擴展名
BigButton.ios.js
BigButton.android.js
以上三種方案,再引用的時候去掉平臺標識,如下
import BigButton from './components/BigButton';
- Platform.select()
import React, {Component,Platform} from 'react';
var Component = Platform.select({
ios: () => require('ComponentIOS'),
android: () => require('ComponentAndroid'),
});
Platform.OS在iOS上會返回ios,而在Android設備或模擬器上則會返回android。
創建標題欄
根據上面的方案,我們這裏使用的是使用擴展名的方案來適配平臺的。在js/component下創建TitleBarComponent.android.js文件。
標題欄總共有標題、副標題和左邊的返回按鈕icon,返回按鈕只有在子頁面(二級頁面)纔有,因此我們定義如下屬性
//初始化props
static defaultProps = {
title:'',//標題
subtitle:'',//副標題
subScene:true,//是否是子頁面
};
然後,在render返回一個ToolbarAndroid
render() {
return(
<ToolbarAndroid
title={this.props.title}
navIcon={this.props.subScene?require('../../img/ic_actionbar_back.png'):null}
titleColor='white'
subtitle={this.props.subtitle}
subtitleColor='#ebf0f6'
actions={actions}
onActionSelected={this._onActionClick.bind(this)}
onIconClicked={this._onIconClick.bind(this)}
style={styles.toolbar}
/>
);
}
//返回按鈕事件
_onIconClick(){
}
這裏幾個屬性說明下
- title 就是標題
- titleColor 設置標題顏色
- subtitle 就是副標題
- subtitleColor 設置副標題顏色
- actions 瞭解android的都知道Toolbar右邊還可以設置一些動作按鈕(我們這裏沒有就不設置該屬性)
它的格式如下,可以設置多個
const actions = [
{title:'全部',show:'always',icon:require('../../img/icon_all.png'),showWithText:true},
]
- onActionSelected 動作按鈕被觸發時的回調(我們這裏沒有就不設置該屬性)
- onIconClicked 標題欄左邊的圖標被點擊後的回調(我們這裏是返回按鈕,返回圖標可以到github上得到)
- style 設置整個標題欄的樣式,高度、背景等。
TitleBarComponent的完整代碼如下
import React,{Component} from 'react';
import {
ToolbarAndroid,
DeviceEventEmitter,
StyleSheet,
Text,
TouchableOpacity,
}from 'react-native';
export default class TitleBarComponent extends Component {
constructor(props) {
super(props);
}
//初始化props
static defaultProps = {
title:'',//標題
subtitle:'',//副標題
subScene:true,//是否是子頁面
};
render() {
return(
<ToolbarAndroid
title={this.props.title}
navIcon={this.props.subScene?require('../../img/ic_actionbar_back.png'):null}
titleColor='white'
subtitle={this.props.subtitle}
subtitleColor='#ebf0f6'
onIconClicked={this._onIconClick.bind(this)}
style={styles.toolbar}
/>
);
}
//返回按鈕事件
_onIconClick(){
}
}
const styles = StyleSheet.create({
toolbar:{
height:56,
backgroundColor:'#ff5722',
},
});
這樣我們就完成了標題欄的設計。
創建首頁Scene
添加標題
接下來我們需要創建一個首頁Scene,來展示首頁功能。在js文件夾新建HomeScene.js文件,併爲首頁添加一個標題欄。
import React,{Component} from 'react';
import {
View,
Text,
StyleSheet,
TouchableOpacity
} from 'react-native';
import TitleBar from './component/TitleBarComponent'
export default class HomeScene extends Component{
constructor(props){
super(props);
}
render(){
return(
<View style={{flex:1}}>
<TitleBar title="首頁" subtitle="看韓劇,上稀飯" subScene={false}/>
</View>
);
};
}
然後將index.android.js使用HomeScene
import HomeScene from './js/HomeScene';
class XiFan extends Component {
render(){
return(
<HomeScene/>
);
}
}
AppRegistry.registerComponent('XiFan', () => XiFan);
執行代碼,就可以看到如下效果
添加選項卡
這樣首頁的標題有了,我們接下來要添加‘最新’、‘最熱’兩個選項卡
在HomeScene內添加如下代碼
state增加一個tabIndex屬性,標識當前選中的tab項
constructor(props){
super(props);
this.state = {
tabIndex:0,
};
}
接着就是繪製Tab了
//tab切換
_onTabPress(index){
this.setState({
tabIndex:index,
});
}
render(){
return(
<View style={{flex:1}}>
<TitleBar title="首頁" subtitle="看韓劇,上稀飯" subScene={false}/>
<View style={{height:35,flexDirection:'row',justifyContent:'center',alignItems:'center',backgroundColor:'#ff5722'}}>
<View style={{flex:1}}>
<TouchableOpacity style={{flex:1,justifyContent:'center'}} activeOpacity={0.6} onPress={this._onTabPress.bind(this,0)}>
<Text style={this.state.tabIndex===0?styles.TabSelect:styles.TabUnSelect}>最新</Text>
</TouchableOpacity>
<View style={this.state.tabIndex===0?styles.TabUnderlineSelect:styles.TabUnderlineUnSelect}/>
</View>
<View style={{flex:1}}>
<TouchableOpacity style={{flex:1,justifyContent:'center'}} activeOpacity={0.6} onPress={this._onTabPress.bind(this,1)}>
<Text style={this.state.tabIndex===0?styles.TabUnSelect:styles.TabSelect}>最熱</Text>
</TouchableOpacity>
<View style={this.state.tabIndex===0?styles.TabUnderlineUnSelect:styles.TabUnderlineSelect}/>
</View>
</View>
</View>
);
};
該段代碼的核心主要是根據tabIndex是否被選中項,動態修改View的樣式
var styles = StyleSheet.create({
TabSelect:{
flex:1,
textAlign:'center',
color:'white',
},
TabUnderlineSelect:{
backgroundColor:'white',
height:2,
},
TabUnSelect:{
flex:1,
textAlign:'center',
color:'#d5d5d5',
},
TabUnderlineUnSelect:{
height:0,
},
});
現在的效果是這樣的
添加選項卡內容
應用的功能就是像在堆積木一樣,一點一點疊起來。現在給選項卡下方添加對應的內容。選項卡切換時,底下切換到對應的內容,我們這裏使用的是ViewPagerAndroid。
//ViewPager 頁面發生切換時調用,修改tabIndex
_onPageSelected(event){
const position = event.nativeEvent.position;
this.setState({
tabIndex:position,
});
}
_onPageScrollStateChanged(status){
//idle 空閒,意味着當前沒有交互。
//dragging 拖動中,意味着當前頁面正在被拖動。
//settling 處理中,意味着當前頁面發生過交互,且正在結束開頭或收尾的動畫。
}
render(){
return(
<View style={{flex:1}}>
...//省略其它代碼
<ViewPagerAndroid
style={{flex:1}}
initialPage={0}
onPageSelected={this._onPageSelected.bind(this)}
scrollEnabled={true}
pageMargin={0}
onPageScrollStateChanged={this._onPageScrollStateChanged}
keyboardDismissMode='on-drag'
ref={(viewPager)=>{this.viewPager = viewPager}}
>
<View style={{flex:1}}>
<DramaComponent url='/hanju/new/'/>
</View>
<View style={{flex:1}}>
<DramaComponent url='/hanju/renqi/'/>
</View>
</ViewPagerAndroid>
</View>
);
};
主要說幾個屬性
- initialPage 初始顯示哪個頁面
- onPageSelected頁面選中時的回調函數
- onPageScrollStateChanged 滾動狀態發生變化時調用(目前沒用到)
- ref 定義該組件的實例對象,這裏我們將ViewPagerAndroid實例對象聲明爲viewPager,然後我們就可以在這個頁面內使用該對象,比如,前面的_onTabPress方法,在tab切換時需要下面的內容也切換到對應的內容,所以我們對_onTabPress方法添加如下代碼:
//tab切換
_onTabPress(index){
this.viewPager.setPage(index);
this.setState({
tabIndex:index,
});
}
調用了viewPager對象setPage方法,進行頁面切換。
還有另一種定義ref方式,如下:
<ViewPagerAndroid
...//省略其它代碼
ref="viewPage">
...//省略其它代碼
</ViewPagerAndroid>
然後使用對象時
//tab切換
_onTabPress(index){
this.refs.viewPage.setPage(index);
this.setState({
tabIndex:index,
});
}
再看下上面的代碼,我們在ViewPagerAndroid內部塞了兩個View,這兩個View實際上就是要顯示的內容了,它們就是我們之前自定義的DramaComponent,傳入了不同的url,一個是最新的地址,一個是最熱的人氣,這樣解析顯示出來就是對應的數據了。
關於ViewPagerAndroid更多信息,可以查看ViewPagerAndroid
最後上一下本節的完成的成果效果圖:
HomeScene.js的所有代碼
import React,{Component} from 'react';
import {
View,
Text,
StyleSheet,
TouchableOpacity,
ViewPagerAndroid
} from 'react-native';
import TitleBar from './component/TitleBarComponent'
import DramaComponent from './component/DramaComponent';
export default class HomeScene extends Component{
constructor(props){
super(props);
this.state = {
tabIndex:0,
};
}
//tab切換
_onTabPress(index){
this.viewPager.setPage(index);
this.setState({
tabIndex:index,
});
}
//ViewPager 頁面發生切換時調用
_onPageSelected(event){
const position = event.nativeEvent.position;
this.setState({
tabIndex:position,
});
}
_onPageScrollStateChanged(status){
//idle 空閒,意味着當前沒有交互。
//dragging 拖動中,意味着當前頁面正在被拖動。
//settling 處理中,意味着當前頁面發生過交互,且正在結束開頭或收尾的動畫。
}
render(){
return(
<View style={{flex:1}}>
<TitleBar title="首頁" subtitle="看韓劇,上稀飯" subScene={false}/>
<View style={{height:35,flexDirection:'row',justifyContent:'center',alignItems:'center',backgroundColor:'#ff5722'}}>
<View style={{flex:1}}>
<TouchableOpacity style={{flex:1,justifyContent:'center'}} activeOpacity={0.6} onPress={this._onTabPress.bind(this,0)}>
<Text style={this.state.tabIndex===0?styles.TabSelect:styles.TabUnSelect}>最新</Text>
</TouchableOpacity>
<View style={this.state.tabIndex===0?styles.TabUnderlineSelect:styles.TabUnderlineUnSelect}/>
</View>
<View style={{flex:1}}>
<TouchableOpacity style={{flex:1,justifyContent:'center'}} activeOpacity={0.6} onPress={this._onTabPress.bind(this,1)}>
<Text style={this.state.tabIndex===0?styles.TabUnSelect:styles.TabSelect}>最熱</Text>
</TouchableOpacity>
<View style={this.state.tabIndex===0?styles.TabUnderlineUnSelect:styles.TabUnderlineSelect}/>
</View>
</View>
<ViewPagerAndroid
style={{flex:1}}
initialPage={0}
onPageSelected={this._onPageSelected.bind(this)}
scrollEnabled={true}
pageMargin={0}
onPageScrollStateChanged={this._onPageScrollStateChanged}
keyboardDismissMode='on-drag'
ref={(viewPager)=>{this.viewPager = viewPager}}
>
<View style={{flex:1}}>
<DramaComponent url='/hanju/new/'/>
</View>
<View style={{flex:1}}>
<DramaComponent url='/hanju/renqi/'/>
</View>
</ViewPagerAndroid>
</View>
);
};
}
var styles = StyleSheet.create({
TabSelect:{
flex:1,
textAlign:'center',
color:'white',
},
TabUnderlineSelect:{
backgroundColor:'white',
height:2,
},
TabUnSelect:{
flex:1,
textAlign:'center',
color:'#d5d5d5',
},
TabUnderlineUnSelect:{
height:0,
},
});
總結
這節,我們完成了首頁功能的開發,主要涉及到了標題欄、選項卡切換的功能,細節上提到了組件的平臺適配、ViewPager的使用等。下一節,我們將開發主界面的功能,包括底部TabBar的開發以及Navigator實現頁面的跳轉,而頁面的跳轉將是最主要的一個功能,下一節我們再詳細來述說。