没有接口使用,只能找到网上大神的项目,找到接口加入进去使用了。算是第一个rn的练习项目了
图片有点瞎了
一,自己写了标题栏title
我单独写到了一个js文件中的
const {height, width} = Dimensions.get('window');
export default class Header extends Component {
render() {
return (
<View style={styles.view}>
<Text style={styles.textView}>北京</Text>
<TextInput style={styles.textInPut}
// inlineImageLeft='serch'
multiline={true}
placeholder="北京烤鸭"></TextInput>
<Image
source={require('../imag/lingdang_n.png')}
style={{width: 30, height: 30}}
/>
</View>
)
}
}
const styles = StyleSheet.create({
view: {
height: 55,
flexDirection: 'row',
backgroundColor: '#00f9ff',
alignItems: 'center',
justifyContent: 'space-around'
},
textView: {
fontSize: 20,
color: '#FFFFFF',
},
textInPut: {
width: width * 0.6,
height: 40,
borderTopLeftRadius: 20,
borderTopRightRadius: 20,
borderBottomRightRadius: 20,
borderBottomLeftRadius: 20,
backgroundColor: '#FFFFFF'
}
});
使用的时候直接import就好了
二,ScrollView横向分屏的菜单栏
这个就需要设置FlatList的头部布局了,定义了两个数组存放每个tab标签,第一个数组第一屏,第二个数组第二屏。
ListHeaderComponent={FlatListHeader}
const {height, width} = Dimensions.get('window');
const headerItemData = [
{name: '美食', imag: require('../imag/tuangou/meishi.png')},
{name: '电影', imag: require('../imag/tuangou/dianying.png')},
{name: '酒店', imag: require('../imag/tuangou/jiudian.png')},
{name: 'KTV', imag: require('../imag/tuangou/KTV.png')},
{name: '优惠', imag: require('../imag/tuangou/youhui.png')},
{name: '周边游', imag: require('../imag/tuangou/zhoubianyou.png')},
{name: '生活服务', imag: require('../imag/tuangou/shenghuofuwu.png')},
{name: '休闲娱乐', imag: require('../imag/tuangou/yule.png')},
{name: '丽人美发', imag: require('../imag/tuangou/meifa.png')},
{name: '购物', imag: require('../imag/tuangou/gouwu.png')},
{name: '小龙虾', imag: require('../imag/tuangou/xiaolongxia.png')},
{name: '骑车', imag: require('../imag/tuangou/qiche.png')},
{name: '玩', imag: require('../imag/tuangou/kaixin.png')},
{name: '滑雪', imag: require('../imag/tuangou/huaxue.png')},
// {name: '', imag: require('')},
// {name: '', imag: require('')},
// {name: '', imag: require('')},
];
export default class FlatListHeader extends Component {
constructor(props) {
super(props);
this.state = {
isPage: 0,
}
}
render() {
let menuViews1 = []
let menuViews2 = []
for (let i = 0; i < 10; i++) {
menuViews1.push(
<ScrollViewItem name={headerItemData[i].name} img={headerItemData[i].imag} key={i}/>
)
}
for (let i = 10; i < headerItemData.length; i++) {
menuViews2.push(
<ScrollViewItem name={headerItemData[i].name} img={headerItemData[i].imag} key={i}/>
)
}
return (
<View>
<ScrollView
style={styles.header}
horizontal={true} //横向
showsHorizontalScrollIndicator={false} //不显示滚动条
pagingEnabled={true} //固定整屏
onScroll={(e) => this.onScroll(e)}>
<View style={{width: width, flexDirection: 'row', flexWrap: 'wrap'}}>{menuViews1}</View>
<View style={{width: width, flexDirection: 'row'}}>{menuViews2}</View>
</ScrollView>
<PageContro contro={this.state.isPage}/>
<GruidView></GruidView>
</View>
)
}
onScroll(e: any) {
let x = e.nativeEvent.contentOffset.x
let currentPage = Math.round(x / width)
if (this.state.isPage != currentPage) {
this.setState({
isPage: currentPage
})
}
}
}
const styles = StyleSheet.create({
header: {
height: 160,
}
})
ScrollViewItem我自己定义了一个组建,接收两个属性,名字和url。
const {height, width} = Dimensions.get('window');
type Props = {
name: String,
img: String,
}
export default class ScrollViewItem extends Component<Props> {
constructor(props) {
super(props);
}
render() {
let {name, img} = this.props
return (
<View style={styles.itemView}>
<Image style={styles.itemImage}
source={img}
/>
<Text>{name}</Text>
</View>
)
}
}
const styles = StyleSheet.create({
itemView: {
width: width * 0.2,
height: width * 0.2,
backgroundColor: '#FFFFFF',
justifyContent:'center',
alignItems: 'center',
},
itemImage: {
width: 30,
height: 30,
}
})
PageContro 是提示显示哪一屏。接收一个属性切换显示状态,只有两屏,所以就是互斥的。通过onScroll监听滑动改变状态。刷新了界面
type Props = {
contro:String,
}
export default class PageContro extends Component<Props>{
constructor(props){
super(props);
}
render(){
let {contro} =this.props
return(
<View style={styles.view}>
<Image style={styles.img}
source={contro == 0 ? require('../imag/tuangou/dian_s.png') : require('../imag/tuangou/dian_n.png')}/>
<Image style={styles.img}
source={contro == 0 ? require('../imag/tuangou/dian_n.png') : require('../imag/tuangou/dian_s.png')}/>
</View>
)
}
}
const styles = StyleSheet.create({
view:{
height:15,
backgroundColor:'#ffffff',
alignItems: 'center',
flexDirection:'row',
justifyContent: 'center',
},
img:{
width:20,
height: 20,
}
})
三,FlatList列表加随便填了一些数据
列表组件前边说过就不贴了。添加分割线的属性ItemSeparatorComponent,接收一个组件。
ItemSeparatorComponent={ItemDivideComponent}
class ItemDivideComponent extends Component {
render() {
return (
<View style={{height: 1, backgroundColor: '#a5a5a5',marginRight: 10,marginLeft: 10}}/>
);
}
};
FlatList下拉刷新,
添加一个属性:refreshControl
refreshControl={<RefreshControl
refreshing={this.state.refreshing}
onRefresh={this._onRefresh}
/>}
refreshing为true时,显示下拉刷新的进度圆,反之不显示。
onRefresh属性是刷新要做的事,当然是重新请求网络数据。
_onRefresh = () => {
this.setState({refreshing: true});
this.fetchData()
}
fetchData() {
fetch("https://raw.githubusercontent.com/facebook/react-native/0.51-stable/docs/MoviesExample.json")
.then((response) => response.json())
.then((responseData) => {
// 注意,这里使用了this关键字,为了保证this在调用时仍然指向当前组件,我们需要对其进行“绑定”操作
this.setState({
isShowActivityIndicator: false,
food: responseData.movies,
refreshing: false,
});
});
}
还有一块是中间的四个元素,类似于广告位的展示。
也是定义了一个组件用属性接收参数,创造出来4个布局展示。
const {height, width} = Dimensions.get('window');
//轮播图下边的四个框
const hotData = [
{
name: '免费拍',
detailed: '婚照写真',
color:'#FF9800',
imag: 'http://images.meishij.net/p/20170330/dacf1e18c99c4fe2f056f0c8f3aacbce_180x180.jpg'
},
{
name: '大片特惠',
detailed: '速度与激情8',
color:'#F78B9A',
imag: 'http://images.meishij.net/p/20110822/6a89f9eeb6eeec4427e5807b4ed0cb02_180x180.jpg'
},
{
name: '特价日',
detailed: '跟团游清仓',
color:'#7EC50E',
imag: 'http://images.meishij.net/p/20170330/cbe31e4ef6176df562054b6b5297ca50_180x180.jpg'
},
{
name: '今日推荐',
detailed: '品质生活',
color:'#46C9B9',
imag: 'http://images.meishij.net/p/20170330/41f12e50219c6afdc4735e336a99f16f_180x180.jpg'
},
]
export default class GruidView extends Component {
constructor(props) {
super(props);
}
render() {
let list = [];
for (let i = 0; i < 4; i++) {
list.push(
<GruidViewItem name={hotData[i].name} detailed={hotData[i].detailed} imag={hotData[i].imag} color={hotData[i].color} key={i}/>
)
}
return (
<View style={styles.view}>
<View style={{height: 10, backgroundColor: '#EFEFEF'}}/>
<View style={styles.itemView}>
{list}
</View>
<View style={{height: 10, backgroundColor: '#EFEFEF'}}/>
</View>
)
}
}
type Props = {
name: String,
detailed: String,
imag: any,
color:any,
}
class GruidViewItem extends Component<Props> {
constructor(props) {
super(props);
}
render() {
let {name, detailed, imag, color} = this.props
return (
<View style={styles.itemTab}>
<View style={styles.flex}>
<Text style={[styles.text,{color:color}]}>{name}</Text>
<Text style={styles.text}>{detailed}</Text>
</View>
<Image style={styles.imag}
roundAsCircle={true}
source={{uri: imag}}/>
</View>
);
}
}
const styles = StyleSheet.create({
view: {
width: width,
height: 220,
backgroundColor: '#EFEFEF',
// borderBottomColor: '#000000',
// borderBottomWidth: StyleSheet.hairlineWidth,
},
itemView: {
width: width,
height: 200,
flexDirection: 'row',
flexWrap: 'wrap'
},
itemTab: {
width: width * 0.5-2,
height: 99,
flexDirection: 'row',
backgroundColor: '#ffffff',
margin: 1,
alignItems: 'center'
},
flex: {
flex: 1,
justifyContent: 'center',
alignItems:'center',
textAlign: 'center',
},
imag: {
width: width * 0.2-4,
height: width * 0.2-4,
overflow:'hidden',
borderTopLeftRadius:50,
borderTopRightRadius:50,
borderBottomLeftRadius:50,
borderBottomRightRadius:50,
marginRight: 15,
},
text:{
flex:1,
alignItems: 'center',
height:50,
marginTop: 15,
}
})
这样实现了上图界面(辣眼睛),知识点与解决的问题:
1.key 例如for循环里边的组件key={i} 这个key只针对于当前的组件,和其他组件没有关系。
2.属性接收参数,Props记得Component后边加泛型
3.API与其他