在很多app应用型APP中,个人中心往往会单独出一个模块,而对于刚入门React Native的朋友来说,怎么去实现一些静态的页面,并且怎么着手实现,怎么分层,怎么去实现这个架构,我想是很基础的(ps,本人新书,《React Native实战经典》定义国庆前后出版,欢迎大家捧场)。 首先,看一下实现的效果:
项目讲解
首先,这是一个纯静态的页面,包括顶部的个人介绍页面,已经下面的一个扩展页面。而下面扩展页面风格基本差不多,我们可以对其做一个简单的封装(MineItemCell.js),为了项目代码维护的方便,我们还可以将这些样式统一一下(text.js)。 text.js文字样式
代码语言:javascript复制/**
* https://github.com/facebook/react-native
* @flow
*/
import React from 'react';
import ReactNative, { StyleSheet, Dimensions, Text ,ReactElement} from 'react-native';
export function HeadingBig({style, ...props}: Object): ReactElement {
return <Text style={[styles.h0, style]} {...props} />
}
export function Heading1({style, ...props}: Object): ReactElement {
return <Text style={[styles.h1, style]} {...props} />
}
export function Heading2({style, ...props}: Object): ReactElement {
return <Text style={[styles.h2, style]} {...props} />
}
export function Paragraph({style, ...props}: Object): ReactElement {
return <Text style={[styles.p, style]} {...props} />
}
export function Tip({style, ...props}: Object): ReactElement {
return <Text style={[styles.tip, style]} {...props} />
}
const styles = StyleSheet.create({
h0: {
fontSize: 40,
color: '#06C1AE',
},
h1: {
fontSize: 15,
fontWeight: 'bold',
color: '#222222',
},
h2: {
fontSize: 14,
color: '#222222',
},
p: {
fontSize: 13,
color: '#777777',
},
tip: {
fontSize: 13,
color: '#999999'
}
});
MineItemCell.js
代码语言:javascript复制/**
* Copyright (c) 2017-present, Liu Jinyong
* All rights reserved.
*
* https://github.com/huanxsd/MeiTuan
* @flow
*/
import React, { Component } from 'react';
import { View, Text, StyleSheet, Image, TouchableOpacity } from 'react-native';
import { Heading2, Paragraph } from './widght/Text'
import Separator from './widght/Separator'
var Dimensions = require('Dimensions');
var ScreenWidth = Dimensions.get('window').width;
class MineItemCell extends Component {
render() {
let icon = null;
if (this.props.image) {
icon = <Image style={styles.icon} source={this.props.image} />
}
return (
<View style={styles.container}>
<TouchableOpacity>
<View style={[styles.content, this.props.style]}>
{icon}
<Heading2>{this.props.title}</Heading2>
<View style={{ flex: 1, backgroundColor: 'blue' }} />
<Paragraph style={{ color: '#999999' }}>{this.props.subtitle}</Paragraph>
<Image style={styles.arrow} source={require('./image/icon_arrow.png')} />
</View>
<Separator />
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: 'white',
},
content: {
height: 44,
flexDirection: 'row',
alignItems: 'center',
paddingLeft: 15,
paddingRight: 10,
},
icon: {
width: 25,
height: 25,
marginRight: 10,
},
subtitleContainer: {
flexDirection: 'row',
justifyContent: 'flex-end',
alignItems: 'center',
},
arrow: {
width: 14,
height: 14,
marginLeft: 5,
}
});
export default MineItemCell;
然后到界面的绘制了,首先绘制顶部个人资料部分:
代码语言:javascript复制renderHeader() {
return (
<View style={styles.header}>
<View style={styles.topContainer}>
<TouchableOpacity>
<Image style={[styles.icon, {marginRight: 15}]}
source={require('./image/icon_navigationItem_message_white.png')}/>
</TouchableOpacity>
<TouchableOpacity>
<Image style={[styles.icon, {marginRight: 10}]}
source={require('./image/icon_navigationItem_set_white.png')}/>
</TouchableOpacity>
</View>
<View style={styles.userContainer}>
<Image style={styles.avatar} source={require('./image/avatar.png')}/>
<View>
<View style={{flexDirection: 'row'}}>
<Heading1 style={{color: 'white'}}>code_xzh</Heading1>
<Image style={{marginLeft: 4}}
source={require('./image/beauty_technician.png')}/>
</View>
<Paragraph style={{color: 'white', marginTop: 4}}>个人信息 ></Paragraph>
</View>
</View>
</View>
)
}
接着,我们在绘制下面的部分,由于下面部分我们队每个子视图做了封装,所以,我们可以这么做:通过getDataList()获取所有的值,进而绘制。 renderCells代码:
代码语言:javascript复制renderCells() {
let cells = []
let dataList = this.getDataList()
for (let i = 0; i < dataList.length; i ) {
let sublist = dataList[i]
for (let j = 0; j < sublist.length; j ) {
let data = sublist[j]
let cell = <MineItemCell image={data.image} title={data.title} subtitle={data.subtitle}
key={data.title}/>
cells.push(cell)
}
cells.push(<SpacingView key={i}/>)
}
return (
<View style={{flex: 1}}>
{cells}
</View>
)
}
getDataList()代码:
代码语言:javascript复制getDataList() {
return (
[
[
{title: '我的钱包', subtitle: '办信用卡', image: require('./image/icon_mine_wallet.png')},
{title: '余额', subtitle: '¥95872385', image: require('./image/icon_mine_balance.png')},
{title: '抵用券', subtitle: '63', image: require('./image/icon_mine_voucher.png')},
{title: '会员卡', subtitle: '2', image: require('./image/icon_mine_membercard.png')}
],
[
{title: '好友去哪', image: require('./image/icon_mine_friends.png')},
{title: '我的评价', image: require('./image/icon_mine_comment.png')},
{title: '我的收藏', image: require('./image/icon_mine_collection.png')},
{title: '会员中心', subtitle: 'v15', image: require('./image/icon_mine_mineorder.png')},
{title: '积分商城', subtitle: '好礼已上线', image: require('./image/icon_mine_member.png')}
],
[
{title: '客服中心', image: require('./image/icon_mine_service.png')},
{title: '关于美团', subtitle: '我要合作', image: require('./image/icon_mine_about.png')}
]
]
)
}
页面完整代码:
代码语言:javascript复制/**
* Sample React Native App
* https://github.com/facebook/react-native
* @flow ScrollView组件
*/
import React, {Component} from 'react';
import {
AppRegistry,
StyleSheet,
RefreshControl,
Image,
ScrollView,
TouchableOpacity,
View
} from 'react-native';
import { Heading1, Heading2, Paragraph } from './widght/Text'
import MineItemCell from './MineItemCell';
import SpacingView from './widght/SpacingView'
var Dimensions = require('Dimensions');
var screenWidth = Dimensions.get('window').width;
var screenHeight = Dimensions.get('window').height;
class MineScene extends Component {
state: {
isRefreshing: boolean
}
constructor(props: Object) {
super(props)
this.state = {
isRefreshing: false
}
}
onHeaderRefresh() {
this.setState({isRefreshing: true})
setTimeout(() => {
this.setState({isRefreshing: false})
}, 2000);
}
renderCells() {
let cells = []
let dataList = this.getDataList()
for (let i = 0; i < dataList.length; i ) {
let sublist = dataList[i]
for (let j = 0; j < sublist.length; j ) {
let data = sublist[j]
let cell = <MineItemCell image={data.image} title={data.title} subtitle={data.subtitle}
key={data.title}/>
cells.push(cell)
}
cells.push(<SpacingView key={i}/>)
}
return (
<View style={{flex: 1}}>
{cells}
</View>
)
}
renderHeader() {
return (
<View style={styles.header}>
<View style={styles.topContainer}>
<TouchableOpacity>
<Image style={[styles.icon, {marginRight: 15}]}
source={require('./image/icon_navigationItem_message_white.png')}/>
</TouchableOpacity>
<TouchableOpacity>
<Image style={[styles.icon, {marginRight: 10}]}
source={require('./image/icon_navigationItem_set_white.png')}/>
</TouchableOpacity>
</View>
<View style={styles.userContainer}>
<Image style={styles.avatar} source={require('./image/avatar.png')}/>
<View>
<View style={{flexDirection: 'row'}}>
<Heading1 style={{color: 'white'}}>code_xzh</Heading1>
<Image style={{marginLeft: 4}}
source={require('./image/beauty_technician.png')}/>
</View>
<Paragraph style={{color: 'white', marginTop: 4}}>个人信息 ></Paragraph>
</View>
</View>
</View>
)
}
getDataList() {
return (
[
[
{title: '我的钱包', subtitle: '办信用卡', image: require('./image/icon_mine_wallet.png')},
{title: '余额', subtitle: '¥95872385', image: require('./image/icon_mine_balance.png')},
{title: '抵用券', subtitle: '63', image: require('./image/icon_mine_voucher.png')},
{title: '会员卡', subtitle: '2', image: require('./image/icon_mine_membercard.png')}
],
[
{title: '好友去哪', image: require('./image/icon_mine_friends.png')},
{title: '我的评价', image: require('./image/icon_mine_comment.png')},
{title: '我的收藏', image: require('./image/icon_mine_collection.png')},
{title: '会员中心', subtitle: 'v15', image: require('./image/icon_mine_mineorder.png')},
{title: '积分商城', subtitle: '好礼已上线', image: require('./image/icon_mine_member.png')}
],
[
{title: '客服中心', image: require('./image/icon_mine_service.png')},
{title: '关于美团', subtitle: '我要合作', image: require('./image/icon_mine_about.png')}
]
]
)
}
render() {
return (
<View style={styles.container}>
<View style={{
position: 'absolute',
width: screenWidth,
height: screenHeight / 2,
backgroundColor: '#06C1AE'
}}/>
<ScrollView
refreshControl={
<RefreshControl
refreshing={this.state.isRefreshing}
onRefresh={() => this.onHeaderRefresh()}
tintColor='gray'
/>
}>
{this.renderHeader()}
<SpacingView />
{this.renderCells()}
</ScrollView>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f3f3f3',
},
header: {
backgroundColor: '#06C1AE',
paddingBottom: 20
},
topContainer: {
flexDirection: 'row',
justifyContent: 'flex-end',
alignItems: 'center',
marginTop: 7,
},
icon: {
width: 27,
height: 27,
},
userContainer: {
flexDirection: 'row',
alignItems: 'center',
margin: 10,
},
avatar: {
width: 50,
height: 50,
marginRight: 10,
borderRadius: 25,
borderWidth: 2,
borderColor: '#51D3C6'
}
});
export default MineScene;
美团项目源码地址:react native美团项目源码