react-native - 导航器和工具栏Android
react-native - Navigator and toolbarAndroid
有什么方法可以设置仅一个 toolbarAndroid 与导航器一起在应用程序的每个屏幕上使用。
我在index.android.js中设置了一个导航器:
import React, { Component } from 'react';
import {
AppRegistry,
Navigator,
} from 'react-native';
import ContactList from './src/containers/ContactList.js';
class MyIndex extends Component {
render() {
return (
<Navigator
initialRoute={{ name: 'index', component: ContactList }}
renderScene={(route, navigator) => {
if (route.component) {
return React.createElement(route.component, { navigator, ...route.props });
}
return undefined;
}}
/>
);
}
}
AppRegistry.registerComponent('reactest', () => MyIndex);
第一屏显示联系人列表:
import React, { Component, PropTypes } from 'react';
import {
Text,
View,
TouchableOpacity,
TouchableHighlight,
ListView,
Image,
ActivityIndicator,
ToolbarAndroid,
} from 'react-native';
import styles from '../../styles';
import ContactDetails from './ContactDetails';
import logo from '../images/ic_launcher.png';
const url = 'http://api.randomuser.me/?results=15&seed=azer';
export default class ContactList extends Component {
static propTypes = {
navigator: PropTypes.object.isRequired,
}
constructor(props) {
super(props);
const datasource = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
this.state = {
animating: false,
animatingSize: 0,
jsonData: datasource.cloneWithRows([]),
ds: datasource,
appTitle: 'Test',
appLogo: logo,
};
}
_handlePress() {
this.setState({
animating: true,
animatingSize: 80,
});
return fetch(url)
// convert to json
.then((response) => response.json())
// do some string manipulation on json
.then(({ results }) => {
const newResults = results.map((user) => {
const newUser = {
...user,
name: {
title: `${user.name.title.charAt(0).toUpperCase()}${user.name.title.slice(1)}`,
first: `${user.name.first.charAt(0).toUpperCase()}${user.name.first.slice(1)}`,
last: `${user.name.last.charAt(0).toUpperCase()}${user.name.last.slice(1)}`,
},
};
return newUser;
});
return newResults;
})
// set state
.then((results) => {
this.setState({
appSubTitle: 'Contacts list',
animating: false,
animatingSize: 0,
jsonData: this.state.ds.cloneWithRows(results),
});
});
}
renderRow(rowData: string) {
return (
<TouchableHighlight
onPress={() => {
this.props.navigator.push({
first: rowData.name.first,
component: ContactDetails,
props: {
title: rowData.name.title,
first: rowData.name.first,
last: rowData.name.last,
picture: rowData.picture.large,
thumbnail: rowData.picture.thumbnail,
},
});
}}
>
<View style={styles.listview_row}>
<Image
source={{ uri: rowData.picture.thumbnail }}
style={{ height: 48, width: 48 }}
/>
<Text>
{rowData.name.title} {rowData.name.first} {rowData.name.last}
</Text>
</View>
</TouchableHighlight>
);
}
render() {
const view = (
<View style={styles.container}>
<ToolbarAndroid
logo={this.state.appLogo}
title={this.state.appTitle}
subtitle={this.state.appSubTitle}
style={[{ backgroundColor: '#e9eaed', height: 56 }]}
/>
<ActivityIndicator
animating={this.state.animating}
style={[styles.centering, { height: this.state.animatingSize }]}
/>
<TouchableOpacity
onPress={() => this._handlePress()}
style={styles.button}
size="large"
>
<Text>Fetch results?</Text>
</TouchableOpacity>
<ListView
enableEmptySections
dataSource={this.state.jsonData}
renderRow={(rowData) => this.renderRow(rowData)}
onPress={() => this._handleRowClick()}
/>
</View>
);
return view;
}
}
第二个显示联系方式:
import React, {
Component,
PropTypes,
} from 'react';
import {
Text,
View,
Image,
ToolbarAndroid,
} from 'react-native';
import styles from '../../styles';
export default class ContactDetails extends Component {
constructor(props) {
super(props);
this.state = {
animating: false,
animatingSize: 0,
appTitle: 'Test',
appLogo: { uri: this.props.thumbnail, height: 56 },
appSubTitle: `Contact Details - ${this.props.first} ${this.props.last}`,
};
}
render() {
return (
<View style={styles.container}>
<ToolbarAndroid
logo={this.state.appLogo}
title={this.state.appTitle}
subtitle={this.state.appSubTitle}
style={[{ backgroundColor: '#e9eaed', height: 56 }]}
/>
<Image
source={{ uri: this.props.picture }}
style={{ height: 128, width: 128 }}
/>
<Text>{this.props.title} {this.props.first} {this.props.last}</Text>
</View>
);
}
}
ContactDetails.propTypes = {
title: PropTypes.string.isRequired,
first: PropTypes.string.isRequired,
last: PropTypes.string.isRequired,
picture: PropTypes.string.isRequired,
thumbnail: PropTypes.string.isRequired,
};
我在第一个屏幕上设置了一个 toolbarAndroid,在第二个屏幕上设置了另一个,它运行良好,但我感觉最好只定义一个 toolbarAndroid 并调用 setState 更新它。
有可能吗,如果有怎么办?
用你的 ToolbarAndroid
包裹你的 Navigator
class。这样,在 Navigator
上呈现的所有内容都将被 Toolbar
包裹。实际上,这些场景之间的所有共同点都应该放在一个组件上,将其余部分包裹起来。
class MyIndex extends Component {
render() {
return (
<ToolbarAndroid>
<Navigator
initialRoute={{ name: 'index', component: ContactList }}
renderScene={(route, navigator) => {
if (route.component) {
return React.createElement(route.component, { navigator, ...route.props });
}
return undefined;
}}
/>
</ToolbarAndroid>
);
}
}
我设法通过将 toolbarAndroid 和导航器包装在一个视图中来做到这一点:
class MyIndex extends Component {
constructor(props) {
super(props);
this.state = {
appTitle: 'Test',
appLogo: logo,
};
}
render() {
return (
<View
style={styles.container}
>
<ToolbarAndroid
logo={this.state.appLogo}
title={this.state.appTitle}
subtitle={this.state.appSubTitle}
style={[{ backgroundColor: '#e9eaed', height: 56 }]}
/>
<Navigator
initialRoute={{ name: 'index', component: ContactList }}
renderScene={(route, navigator) => {
if (route.component) {
return React.createElement(route.component, { navigator, ...route.props });
}
return undefined;
}}
/>
</View>
);
}
}
有什么方法可以设置仅一个 toolbarAndroid 与导航器一起在应用程序的每个屏幕上使用。
我在index.android.js中设置了一个导航器:
import React, { Component } from 'react';
import {
AppRegistry,
Navigator,
} from 'react-native';
import ContactList from './src/containers/ContactList.js';
class MyIndex extends Component {
render() {
return (
<Navigator
initialRoute={{ name: 'index', component: ContactList }}
renderScene={(route, navigator) => {
if (route.component) {
return React.createElement(route.component, { navigator, ...route.props });
}
return undefined;
}}
/>
);
}
}
AppRegistry.registerComponent('reactest', () => MyIndex);
第一屏显示联系人列表:
import React, { Component, PropTypes } from 'react';
import {
Text,
View,
TouchableOpacity,
TouchableHighlight,
ListView,
Image,
ActivityIndicator,
ToolbarAndroid,
} from 'react-native';
import styles from '../../styles';
import ContactDetails from './ContactDetails';
import logo from '../images/ic_launcher.png';
const url = 'http://api.randomuser.me/?results=15&seed=azer';
export default class ContactList extends Component {
static propTypes = {
navigator: PropTypes.object.isRequired,
}
constructor(props) {
super(props);
const datasource = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
this.state = {
animating: false,
animatingSize: 0,
jsonData: datasource.cloneWithRows([]),
ds: datasource,
appTitle: 'Test',
appLogo: logo,
};
}
_handlePress() {
this.setState({
animating: true,
animatingSize: 80,
});
return fetch(url)
// convert to json
.then((response) => response.json())
// do some string manipulation on json
.then(({ results }) => {
const newResults = results.map((user) => {
const newUser = {
...user,
name: {
title: `${user.name.title.charAt(0).toUpperCase()}${user.name.title.slice(1)}`,
first: `${user.name.first.charAt(0).toUpperCase()}${user.name.first.slice(1)}`,
last: `${user.name.last.charAt(0).toUpperCase()}${user.name.last.slice(1)}`,
},
};
return newUser;
});
return newResults;
})
// set state
.then((results) => {
this.setState({
appSubTitle: 'Contacts list',
animating: false,
animatingSize: 0,
jsonData: this.state.ds.cloneWithRows(results),
});
});
}
renderRow(rowData: string) {
return (
<TouchableHighlight
onPress={() => {
this.props.navigator.push({
first: rowData.name.first,
component: ContactDetails,
props: {
title: rowData.name.title,
first: rowData.name.first,
last: rowData.name.last,
picture: rowData.picture.large,
thumbnail: rowData.picture.thumbnail,
},
});
}}
>
<View style={styles.listview_row}>
<Image
source={{ uri: rowData.picture.thumbnail }}
style={{ height: 48, width: 48 }}
/>
<Text>
{rowData.name.title} {rowData.name.first} {rowData.name.last}
</Text>
</View>
</TouchableHighlight>
);
}
render() {
const view = (
<View style={styles.container}>
<ToolbarAndroid
logo={this.state.appLogo}
title={this.state.appTitle}
subtitle={this.state.appSubTitle}
style={[{ backgroundColor: '#e9eaed', height: 56 }]}
/>
<ActivityIndicator
animating={this.state.animating}
style={[styles.centering, { height: this.state.animatingSize }]}
/>
<TouchableOpacity
onPress={() => this._handlePress()}
style={styles.button}
size="large"
>
<Text>Fetch results?</Text>
</TouchableOpacity>
<ListView
enableEmptySections
dataSource={this.state.jsonData}
renderRow={(rowData) => this.renderRow(rowData)}
onPress={() => this._handleRowClick()}
/>
</View>
);
return view;
}
}
第二个显示联系方式:
import React, {
Component,
PropTypes,
} from 'react';
import {
Text,
View,
Image,
ToolbarAndroid,
} from 'react-native';
import styles from '../../styles';
export default class ContactDetails extends Component {
constructor(props) {
super(props);
this.state = {
animating: false,
animatingSize: 0,
appTitle: 'Test',
appLogo: { uri: this.props.thumbnail, height: 56 },
appSubTitle: `Contact Details - ${this.props.first} ${this.props.last}`,
};
}
render() {
return (
<View style={styles.container}>
<ToolbarAndroid
logo={this.state.appLogo}
title={this.state.appTitle}
subtitle={this.state.appSubTitle}
style={[{ backgroundColor: '#e9eaed', height: 56 }]}
/>
<Image
source={{ uri: this.props.picture }}
style={{ height: 128, width: 128 }}
/>
<Text>{this.props.title} {this.props.first} {this.props.last}</Text>
</View>
);
}
}
ContactDetails.propTypes = {
title: PropTypes.string.isRequired,
first: PropTypes.string.isRequired,
last: PropTypes.string.isRequired,
picture: PropTypes.string.isRequired,
thumbnail: PropTypes.string.isRequired,
};
我在第一个屏幕上设置了一个 toolbarAndroid,在第二个屏幕上设置了另一个,它运行良好,但我感觉最好只定义一个 toolbarAndroid 并调用 setState 更新它。
有可能吗,如果有怎么办?
用你的 ToolbarAndroid
包裹你的 Navigator
class。这样,在 Navigator
上呈现的所有内容都将被 Toolbar
包裹。实际上,这些场景之间的所有共同点都应该放在一个组件上,将其余部分包裹起来。
class MyIndex extends Component {
render() {
return (
<ToolbarAndroid>
<Navigator
initialRoute={{ name: 'index', component: ContactList }}
renderScene={(route, navigator) => {
if (route.component) {
return React.createElement(route.component, { navigator, ...route.props });
}
return undefined;
}}
/>
</ToolbarAndroid>
);
}
}
我设法通过将 toolbarAndroid 和导航器包装在一个视图中来做到这一点:
class MyIndex extends Component {
constructor(props) {
super(props);
this.state = {
appTitle: 'Test',
appLogo: logo,
};
}
render() {
return (
<View
style={styles.container}
>
<ToolbarAndroid
logo={this.state.appLogo}
title={this.state.appTitle}
subtitle={this.state.appSubTitle}
style={[{ backgroundColor: '#e9eaed', height: 56 }]}
/>
<Navigator
initialRoute={{ name: 'index', component: ContactList }}
renderScene={(route, navigator) => {
if (route.component) {
return React.createElement(route.component, { navigator, ...route.props });
}
return undefined;
}}
/>
</View>
);
}
}