話說IONIC2
和
Angular2
的組合仍然是當前火紅的HyBrid
APP,
但開發行動裝置的語言工具又多了一款React
Native 可直接呼叫原生的API,而且語法近似乎HTML5
和
CSS3,所以讓我嘗鮮看看,找到一款完美的跨平台語法是每個人的夢想。
一、建立react native 的專案
一、建立react native 的專案
react-native init AwesomeProject
cd AwesomeProject react-native run-android |
二、TabNavigator
範例:
適用於IOS和Android
的Navigator
Tab (下方的工具列表上,可切換的頁籤),因為是第三方元件提供的,所以要先安裝
npm
install react-native-tab-navigator --save
|
範例:
index.android.js 建立有兩個頁籤的TAB,分別是頁面Featured
和 Search
首先開始使用react
要先import
基本元件:
import
React, { Component,PropTypes } from 'react';
import
{
AppRegistry,
//用來預設畫面
StyleSheet,
//如同css一樣定義文字大小、排版
Text,
//顯示文字
View
//每個畫面==>screen
}
from 'react-native';
import
TabNavigator from 'react-native-tab-navigator';
//引用外部的元件,所以要import
|
TabNavigator
的第三方元件可以自訂新增tab
頁籤,每頁籤可引用自訂react
component 控件,例如以下引用兩個【Featured】和【Search】在不同component控件
import
React, { Component,PropTypes } from 'react';
import
{
AppRegistry,
StyleSheet,
Text,
View
}
from 'react-native';
import
TabNavigator from 'react-native-tab-navigator';
var
Featured = require('./Featured');
var
ListViewBasics = require('./ListViewDemo');
class
AwesomeProject
extends
Component {
constructor(props)
{
super(props);
this.state
= {
selectedTab:
'Featured'
//預設為Featured
};
}
render()
{
return
(
<TabNavigator>
<TabNavigator.Item
selected={this.state.selectedTab
=== 'Featured'}
title="Featured"
onPress={() => this.setState({
selectedTab: 'Featured'
})}>
<Featured
/>//零組件
</TabNavigator.Item>
<TabNavigator.Item
selected={this.state.selectedTab
=== 'ListViewBasics'}
title="ListViewBasics"
onPress={() => this.setState({
selectedTab: 'ListViewBasics'
})}>
<ListViewBasics /> //零組件
</TabNavigator.Item>
</TabNavigator>
);
}
}
AppRegistry.registerComponent('AwesomeProject',
() => AwesomeProject); //用來當作預設頁的元件
|
設定
StyleSheet
const
styles = StyleSheet.create({
container:
{
flex:
1, //用來在各種不同螢幕大小,元件layout與邊框距離
justifyContent:
'center',
//置中處理
alignItems:
'center',
backgroundColor:
'#F5FCFF',
},
welcome:
{
fontSize:
20,
textAlign:
'center',
margin:
10,
},
instructions:
{
textAlign:
'center',
color:
'#333333',
marginBottom:
5,
},
}); |
三、Navigator
(頁面的轉換路徑)
Navigator
元件允許頁面轉向到另一個新的頁面,接續上面的案例中,Featured是獨立的控件,要能導覽至下一頁MyScene,按下back就回上一頁,所以要先import
Navigator元件和MyScene
控件,才能將畫面導覽至MyScene。
Featured.js
'use
strict';
import
React, { Component } from 'react';
import
{
StyleSheet,
Text,
View,
Navigator
}
from 'react-native';
import
MyScene from './MyScene';
//元件,要自已實作
var
styles = StyleSheet.create({
description:
{
fontSize:
20,
backgroundColor:
'white'
},
container:
{
flex:
1,
justifyContent:
'center',
alignItems:
'center'
}
});
class
Feature extends
Component {
render()
{
return
(
<Navigator
initialRoute={{title:"my
Initial Scene",
index:0}} //傳給下一頁的參數值(Title,index)
renderScene={(route,navigator)=>{
return
<MyScene title={route.title}
onForward={()=>{
const
nextIndex=route.index+1;
navigator.push({
title:"Scene_"+nextIndex,
index:nextIndex,
});
}}
onBack={()
=> {
if
(route.index > 0) {
navigator.pop();
}
}}
/>
}}
/>
);
}
}
module.exports
= Feature; |
名稱
MyScene的自訂屬性
onForward
和
onBack,傳入函式用來控制導覽下一頁
navigator.push
的動作和上一頁
navigator.pop()的動作。
MyScene.js
import
React, { Component,PropTypes } from 'react';
import
{ View, Text, Navigator,StyleSheet,TouchableHighlight } from
'react-native';
var
styles = StyleSheet.create({
toolbar:{
backgroundColor:'#81c04d',
paddingTop:30,
paddingBottom:10,
flexDirection:'row'
//用來控制以列(由左->右)的排列
},
toolbarButton:{
width:
50,
color:'#fff',
textAlign:'center'
},
toolbarTitle:{
color:'#fff',
textAlign:'center',
fontWeight:'bold',
flex:1
}
});
class
MyScene extends
Component {
static
PropTypes={
title:
PropTypes.string.isRequired,
onForward:PropTypes.func.isRequired,
onBack:PropTypes.func.isRequired
}
render()
{
return
(
<View
style={styles.toolbar}>
<TouchableHighlight
onPress={this.props.onBack}>
<Text
style={styles.toolbarButton}>back</Text>
</TouchableHighlight>
<Text
style={styles.toolbarTitle}> {this.props.title}</Text>
<TouchableHighlight
onPress={this.props.onForward}>
<Text
style={styles.toolbarButton}>next</Text>
</TouchableHighlight>
</View>
)
}
}
module.exports=MyScene; |
<TouchableHighlight>
控制允許點選按鈕範圍,所以如上所示
back 和
next是按鈕,各分別按下後呼叫不同的事件產生,
{this.props.onBack}、{this.props.OnFoward}
調用MyScene傳入參數的OnFoward
和
OnBack
的方法。
import
React, { Component } from 'react';
import
{ AppRegistry, ListView,ScrollView,Image,TouchableOpacity,Text,
View, StyleSheet } from 'react-native';
//自訂圖片的檔案路徑
var
THUMB_URLS = [
require('./imgs/like.png'),
require('./imgs/dislike.png'),
require('./imgs/call.png'),
require('./imgs/fist.png'),
require('./imgs/bandaged.png'),
require('./imgs/flowers.png'),
require('./imgs/heart.png'),
require('./imgs/liking.png'),
require('./imgs/party.png'),
require('./imgs/poke.png'),
require('./imgs/superlike.png'),
require('./imgs/victory.png'),
];
class
ListViewDemo extends
Component {
constructor(props)
{
super(props);
const
ds = new
ListView.DataSource({
rowHasChanged:
(r1, r2) => r1 !== r2,
sectionHeaderHasChanged:
(s1, s2) => s1 !== s2
});
this.state
= {
dataSource:
ds.cloneWithRowsAndSections(this.getRows()),
//取得getRows()繫結資料
};
}
getRows(){
let
dataObj = {}
let
section = '测試1'
dataObj[section]
= []
for
(let
i=0;i<10;i++){
let
data = {
name:'第'+i+'行',
num:i
}
dataObj[section][i]
= data
}
section
= '测試2'
dataObj[section]
= []
for
(let
i=0;i<10;i++){
let
data = {
name:'第'+i+'行',
num:i
}
dataObj[section][i]
= data
}
return
dataObj
}
//rowData傳入的資料列(每筆資料物件,分組ID,
資列列索引,
是否選中的狀態),
renderRow(rowData,sectionID,rowID,highlightRow){
var
imgSource = THUMB_URLS[rowID];
return
(
<View
style={styles.rowItem}>
<View
style={styles.rowItemLeft}>
<Image
style={styles.thumb} source={imgSource} resizeMode={"cover"}
/>
</View>
<View
style={styles.rowItemRight}>
<Text
style={styles.rowItemText}>数據:{rowData.num}</Text>
</View>
</View>
)
}
onEndReached(e){
//當資料列執行最後一列的時候,執行此區塊
}
renderSectionHeader(sectionData,
sectionID){
//用來顯示資料列的分組的標題(一維陣列的值)
return(
<View
style={styles.rowTite}>
<Text>{sectionID}</Text>
</View>
)
}
onChangeVisibleRows(visibleRows,
changedRows){
//當資料列有變化時,呼叫此區塊
}
render()
{
return
(
<ListView
style={styles.body}
onEndReached
= {this.onEndReached}
onEndReachedThreshold
= {20}
renderSectionHeader
= {this.renderSectionHeader}
onChangeVisibleRows
= {this.onChangeVisibleRows}
dataSource={this.state.dataSource}
renderRow={this.renderRow}
/>
);
}
}
var
styles = StyleSheet.create({
body:{
flex:1,
},
rowItem:{
flex:1,
height:50,
flexDirection:'row',
justifyContent:'center',
alignItems:'center',
borderBottomWidth:1,
borderBottomColor:'#ddd',
},
rowTite:{
height:30,
alignItems:'center',
justifyContent:'center',
backgroundColor:'#ccc',
},
rowItemLeft:{
flex:1,
borderRightColor:'#ccc',
},
rowItemRight:{
flex:3,
},
rowItemText:{
textAlign:'center'
},
thumb:
{
width:
30,
height:30
},
});
module.exports
= ListViewDemo; |
RenderRow(rowData,sectionID,rowID,highlightRow)
rowData
: 每筆資料列視為物件,可以呼叫出每個物件的屬性
ex:
rowData.name
sectionID
: 分組的ID
rowID
: 顯示資料列的索引值,從0開始
highlightRow
: 是否該資料列被選中
reactNative 的相關指令:
執行Android 的compile : react-native run-android
建議安裝Android 的模擬器,因為作者無法實機連線到react native ,搞了很久…
後來只好將 apk 安裝在實機上面測試 … 搜尋 \專案路徑 \android\app\build\outputs\apk\ app-debug.apk 透過網路 或USB直接安裝在手機上
最後文件中找到這樣一篇文章
A common issue is that the packager is not started automatically when you run
react-native run-android
. You can start it manually using react-native start
.下指令 : react-native start (開始預設PORT 8081)
然後啟動APP就成功囉~謝謝各位
三、參考文獻
- https://medium.com/differential/react-native-basics-how-to-use-the-listview-component-a0ec44cf1fe8#.trzo0fhjo
- http://www.reactnative.com/uiexplorer/
- http://www.lcode.org/%E3%80%90react-native%E5%BC%80%E5%8F%91%E3%80%91react-native%E6%8E%A7%E4%BB%B6%E4%B9%8Blistview%E7%BB%84%E4%BB%B6%E8%AE%B2%E8%A7%A3%E4%BB%A5%E5%8F%8A%E8%AF%A6%E7%BB%86%E5%AE%9E%E4%BE%8B19/
沒有留言:
張貼留言