react-nativa仿照美团。第一页团购的一级界面

没有接口使用,只能找到网上大神的项目,找到接口加入进去使用了。算是第一个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与其他

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值