# react-native组件
# Image
以常见的基础组件Image为例,在创建一个图片时,可以传入一个名为 source 的 prop 来指定要显示的图片的地址,以及使用名为style的 prop 来控制其尺寸。
import React, { Component } from 'react';
import { Image } from 'react-native';
export default class Bananas extends Component {
render() {
let pic = {
uri: 'https://upload.wikimedia.org/wikipedia/commons/d/de/Bananavarieties.jpg'
};
return (
<Image source={pic} style={{width: 193, height: 110}} />
);
}
}
//要往 App 中添加一个静态图片,只需把图片文件放在代码文件夹中某处,然后像下面这样去引用它:
<Image source={require('./my-icon.png')} />
注意:为了使新的图片资源机制正常工作,require 中的图片名字必须是一个静态字符串(不能使用变量!因为 require 是在编译时期执行,而非运行时期执行!)。
// 正确
<Image source={require('./my-icon.png')} />;
// 错误
var icon = this.props.active ? 'my-icon-active' : 'my-icon-inactive';
<Image source={require('./' + icon + '.png')} />;
// 正确
var icon = this.props.active
? require('./my-icon-active.png')
: require('./my-icon-inactive.png');
<Image source={icon} />;
TIP
请注意:通过这种方式引用的图片资源包含图片的尺寸(宽度,高度)信息,如果你需要动态缩放图片(例如,通过 flex),你可能必须手动在 style 属性设置{ width: null, height: null }。
# 使用混合 App 的图片资源
如果你在编写一个混合 App(一部分 UI 使用 React Native,而另一部分使用平台原生代码),也可以使用已经打包到 App 中的图片资源(以拖拽的方式放置在 Xcode 的 asset 类目中,或是放置在 Android 的 drawable 目录里)。注意此时只使用文件名,不带路径也不带后缀:
<Image source={{uri: 'app_icon'}} style={{width: 40, height: 40}} />
对于放置在 Android 的 assets 目录中的图片,还可以使用asset:/ 前缀来引用:
<Image source={{uri: 'asset:/app_icon.png'}} style={{width: 40, height: 40}} />
注意:这些做法并没有任何安全检查。你需要自己确保图片在应用中确实存在,而且还需要指定尺寸。
# 网络图片
很多要在 App 中显示的图片并不能在编译的时候获得,又或者有时候需要动态载入来减少打包后的二进制文件的大小。这些时候,与静态资源不同的是,你需要手动指定图片的尺寸。同时我们强烈建议你使用 https 以满足 iOS App Transport Security 的要求。
// 正确
<Image source={{uri: 'https://facebook.github.io/react/logo-og.png'}}
style={{width: 400, height: 400}} />
// 错误
<Image source={{uri: 'https://facebook.github.io/react/logo-og.png'}} />
# 网络图片的请求参数
你可以在 Image 组件的 source 属性中指定一些请求参数,如下面的示例:
<Image
source={{
uri: 'https://facebook.github.io/react/logo-og.png',
method: 'POST',
headers: {
Pragma: 'no-cache',
},
body: 'Your Body goes here',
}}
style={{width: 400, height: 400}}
/>
# View Text
import React, { Component } from 'react';
import { Text, View } from 'react-native';
class Greeting extends Component {
render() {
return (
<View style={{alignItems: 'center', marginTop: 50}}>
<Text>Hello {this.props.name}!</Text>
</View>
);
}
}
export default class LotsOfGreetings extends Component {
render() {
return (
<View style={{alignItems: 'center'}}>
<Greeting name='Rexxar' />
<Greeting name='Jaina' />
<Greeting name='Valeera' />
</View>
);
}
}
# TextInput
TextInput是一个允许用户输入文本的基础组件。它有一个名为 onChangeText 的属性,此属性接受一个函数,而此函数会在文本变化时被调用。另外还有一个名为 onSubmitEditing 的属性,会在文本被提交后(用户按下软键盘上的提交键)调用。
import React, { Component } from 'react';
import { AppRegistry, Text, TextInput, View } from 'react-native';
export default class PizzaTranslator extends Component {
constructor(props) {
super(props);
this.state = {text: ''};
}
render() {
return (
<View style={{padding: 10}}>
<TextInput
style={{height: 40}}
placeholder="Type here to translate!"
onChangeText={(text) => this.setState({text})}
onSubmitEditing={()=>{
alert(1)
}}
/>
<Text style={{padding: 10, fontSize: 42}}>
{this.state.text.split(' ').map((word) => word && '🍕').join(' ')}
</Text>
</View>
);
}
}
# StyleSheet
# Touchable
这个组件的样式是固定的。所以如果它的外观并不怎么搭配你的设计,那就需要使用TouchableOpacity或是TouchableNativeFeedback组件来定制自己所需要的按钮。
具体使用哪种组件,取决于你希望给用户什么样的视觉反馈:
一般来说,你可以使用TouchableHighlight来制作按钮或者链接。注意此组件的背景会在用户手指按下时变暗。
在 Android 上还可以使用TouchableNativeFeedback,它会在用户手指按下时形成类似墨水涟漪的视觉效果。
TouchableOpacity会在用户手指按下时降低按钮的透明度,而不会改变背景的颜色。
如果你想在处理点击事件的同时不显示任何视觉反馈,则需要使用TouchableWithoutFeedback。
某些场景中你可能需要检测用户是否进行了长按操作。可以在上面列出的任意组件中使用onLongPress属性来实现。
import React, { Component } from 'react';
import { Alert, AppRegistry, Platform, StyleSheet, Text, TouchableHighlight, TouchableOpacity, TouchableNativeFeedback, TouchableWithoutFeedback, View } from 'react-native';
export default class Touchables extends Component {
_onPressButton() {
Alert.alert('You tapped the button!')
}
_onLongPressButton() {
Alert.alert('You long-pressed the button!')
}
render() {
return (
<View style={styles.container}>
<TouchableHighlight onPress={this._onPressButton} underlayColor="white">
<View style={styles.button}>
<Text style={styles.buttonText}>TouchableHighlight</Text>
</View>
</TouchableHighlight>
<TouchableOpacity onPress={this._onPressButton}>
<View style={styles.button}>
<Text style={styles.buttonText}>TouchableOpacity</Text>
</View>
</TouchableOpacity>
<TouchableNativeFeedback
onPress={this._onPressButton}
background={Platform.OS === 'android' ? TouchableNativeFeedback.SelectableBackground() : ''}>
<View style={styles.button}>
<Text style={styles.buttonText}>TouchableNativeFeedback</Text>
</View>
</TouchableNativeFeedback>
<TouchableWithoutFeedback
onPress={this._onPressButton}
>
<View style={styles.button}>
<Text style={styles.buttonText}>TouchableWithoutFeedback</Text>
</View>
</TouchableWithoutFeedback>
<TouchableHighlight onPress={this._onPressButton} onLongPress={this._onLongPressButton} underlayColor="white">
<View style={styles.button}>
<Text style={styles.buttonText}>Touchable with Long Press</Text>
</View>
</TouchableHighlight>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
paddingTop: 60,
alignItems: 'center'
},
button: {
marginBottom: 30,
width: 260,
alignItems: 'center',
backgroundColor: 'green',
borderRadius:40,
},
buttonText: {
padding: 20,
color: 'white'
}
})
# ScrollView
ScrollView 是一个通用的可滚动的容器,你可以在其中放入多个组件和视图,而且这些组件并不需要是同类型的。ScrollView 不仅可以垂直滚动,还能水平滚动(通过horizontal属性来设置)。
import React, { Component } from 'react';
import { AppRegistry, ScrollView, Image, Text ,View} from 'react-native';
export default class IScrolledDownAndWhatHappenedNextShockedMe extends Component {
render() {
return (
<ScrollView>
<Text style={{fontSize:100}}>2121</Text>
<Text style={{fontSize:100}}>2121</Text>
<Text style={{fontSize:100}}>2121</Text>
<Text style={{fontSize:100}}>2121</Text>
<Text style={{fontSize:100}}>2121</Text>
<Text style={{fontSize:100}}>2121</Text>
<Text style={{fontSize:100}}>2121</Text>
<Text style={{fontSize:100}}>2121</Text>
<Text style={{fontSize:100}}>2121</Text>
<Text style={{fontSize:100}}>2121</Text>
<Text style={{fontSize:100}}>2121</Text>
<Text style={{fontSize:100}}>2121</Text>
</ScrollView>
);
}
}
# FlatList
FlatList组件用于显示一个垂直的滚动列表,其中的元素之间结构近似而仅数据不同。
FlatList更适于长列表数据,且元素个数可以增删。和ScrollView不同的是,FlatList并不立即渲染所有元素,而是优先渲染屏幕上可见的元素。
FlatList组件必须的两个属性是data和renderItem。data是列表的数据源,而renderItem则从数据源中逐个解析数据,然后返回一个设定好格式的组件来渲染。
import React, { Component } from 'react';
import { FlatList, StyleSheet, Text, View } from 'react-native';
export default class FlatListBasics extends Component {
render() {
return (
<View style={styles.container}>
<FlatList
data={[
{key: 'Devin'},
{key: 'Jackson'},
{key: 'James'},
{key: 'Joel'},
{key: 'John'},
{key: 'Jillian'},
{key: 'Jimmy'},
{key: 'Julie'},
]}
renderItem={({item}) => <Text style={styles.item}>{item.key}</Text>}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 22
},
item: {
padding: 10,
fontSize: 18,
height: 44,
},
})
# SectionList
如果要渲染的是一组需要分组的数据,也许还带有分组标签的,那么SectionList将是个不错的选择
import React, { Component } from 'react';
import { SectionList, StyleSheet, Text, View } from 'react-native';
export default class SectionListBasics extends Component {
render() {
return (
<View style={styles.container}>
<SectionList
sections={[
{title: 'D', data: ['Devin']},
{title: 'J', data: ['Jackson', 'James', 'Jillian', 'Jimmy', 'Joel', 'John', 'Julie']},
]}
renderItem={({item}) => <Text style={styles.item}>{item}</Text>}
renderSectionHeader={({section}) => <Text style={styles.sectionHeader}>{section.title}</Text>}
keyExtractor={(item, index) => index}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 22
},
sectionHeader: {
paddingTop: 2,
paddingLeft: 10,
paddingRight: 10,
paddingBottom: 2,
fontSize: 14,
fontWeight: 'bold',
backgroundColor: 'rgba(247,247,247,1.0)',
},
item: {
padding: 10,
fontSize: 18,
height: 44,
},
})
# Platform 模块
React Native 提供了一个检测当前运行平台的模块。如果组件只有一小部分代码需要依据平台定制,那么这个模块就可以派上用场。
import { Platform, StyleSheet } from "react-native";
......
<View style={{flex: 1, paddingTop:20},styles.a} >
<FlatList
data={this.state.dataSource}
renderItem={({item}) => <Text>{item.title}, {item.releaseYear}</Text>}
keyExtractor={(item, index) => item.id}
/>
</View>
......
const styles = StyleSheet.create({
a:{backgroundColor: Platform.OS === "ios" ? 'orange' : 'green'}
});
Platform.OS在 iOS 上会返回ios,而在 Android 设备或模拟器上则会返回android。
还有个实用的方法是 Platform.select(),它可以以 Platform.OS 为 key,从传入的对象中返回对应平台的值,见下面的示例:
import React from 'react';
import { FlatList, ActivityIndicator, Text, View ,Platform, StyleSheet } from 'react-native';
export default class FetchExample extends React.Component {
constructor(props){
super(props);
this.state ={ isLoading: true}
}
componentDidMount(){
return fetch('https://facebook.github.io/react-native/movies.json')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson.movies,
}, function(){
});
})
.catch((error) =>{
console.error(error);
});
}
render(){
if(this.state.isLoading){
return(
<View style={{flex: 1, padding: 20}}>
<ActivityIndicator/>
</View>
)
}
return(
<View style={{flex: 1, paddingTop:20},styles.container} >
<FlatList
data={this.state.dataSource}
renderItem={({item}) => <Text>{item.title}, {item.releaseYear}</Text>}
keyExtractor={(item, index) => item.id}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
...Platform.select({
ios: {
backgroundColor: "red"
},
android: {
backgroundColor: "blue"
}
})
}
});
# 导航器
管理多个页面的呈现、跳转的组件就是我们通常所说的导航器(navigator)。
React Navigation 提供了简单易用的跨平台导航方案。
如果你想同时在iOS和Android上达到看起来像原生,或者你想把RN整合到一个已经有原生导航管理的APP里, 下面这个库提供了在两个平台都适用的原生导航: react-native-navigation.
import {createStackNavigator, createAppContainer} from 'react-navigation';
const MainNavigator = createStackNavigator({
Home: {screen: HomeScreen},
Profile: {screen: ProfileScreen},
});
const App = createAppContainer(MainNavigator);
export default App;
class HomeScreen extends React.Component {
static navigationOptions = {
title: 'Welcome',
};
render() {
const {navigate} = this.props.navigation;
return (
<Button
title="Go to Jane's profile"
onPress={() => navigate('Profile', {name: 'Jane'})}
/>
);
}
}