React Native 开发豆瓣评分(七)首页组件开发

Stella981
• 阅读 675

首页内容拆分

看效果图,首页由热门影院、豆瓣热门、热门影视等列表组成,每个列表又由头加横向滑动的 电影海报列表构成。

所以可以先把页面的电影海报、评分、列表头做成组件,然后在使用 ScrollView 将内容包裹即可构成首页。

React Native 开发豆瓣评分(七)首页组件开发

开发头部组件

头部组件结构简单,唯一需要注意的就是点击查看更多的时候需要跳转页面,所有需要一个自定义事件,供页面使用。

在 src 目录创建 itemsHeader.js,内容如下:

import { Text, View, StyleSheet, TouchableWithoutFeedback } from 'react-native';
import PropTypes from 'prop-types';
import { px } from '../utils/device';
import Icon from 'react-native-vector-icons/AntDesign';

export default class ItemsHeader extends Component {
    constructor(props) {
        super(props);
    }
    static propTypes = {
        title: PropTypes.string,
        onPress: PropTypes.func
    }
    static defaultProps = {}
    render() {
        const { title, onPress } = this.props;
        return (
            <View style={styles.header}>
                <Text style={styles.title}>{title}</Text>
                <TouchableWithoutFeedback onPress={() => onPress && onPress()}>
                    <View style={styles.getMore}>
                        <Text style={styles.moreText}>查看更多</Text>
                        <Icon name='right' size={px(30)} color='#00b600'></Icon>
                    </View>
                </TouchableWithoutFeedback>
            </View>
        )
    }
}

const styles = StyleSheet.create({
    header: {
        height: px(90),
        width: px(750),
        paddingLeft: px(30),
        paddingRight: px(30),
        backgroundColor: '#ffffff',
        flexDirection: 'row',
        alignItems: 'center',
        justifyContent: 'space-between'
    },
    title: {
        fontSize: px(32),
        color: '#333',
        fontWeight: '600'
    },
    getMore: {
        flexDirection: 'row',
        alignItems: 'center',
    },
    moreText: {
        fontSize: px(28),
        marginLeft: px(30),
        color: '#00b600',
        marginRight: px(6)
    }
});

开发评分组件

评分组件需要考虑到星星大小、间距、颜色、数量,点击星星时改变星星的选中状态,并返回自定义事件 onPress 供调用者使用。

如果使用组件时调用了onPress,那么组件的值为可以改变,如果没有,那么组件应该为只读状态。

import React, { Component } from 'react';
import { Text, View, StyleSheet } from 'react-native';
import PropTypes from 'prop-types';
import { px } from '../utils/device';
import Icon from 'react-native-vector-icons/AntDesign';

export default class Rate extends Component {
    constructor(props) {
        super(props);
        this.state = {
            value: this.props.value
        }
    }
    componentWillReceiveProps(newProps) {
        const { value } = newProps;
        if (value !== this.state.value) {
            this.setState({
                value
            });
        }
    }
    static propTypes = {//如果使用组件时调用了onPress,那么组件默认为可以改变,如果没有,那么组件应该为只读
        value: PropTypes.number,
        size: PropTypes.number,
        margin: PropTypes.number,
        max: PropTypes.number,
        color: PropTypes.string,
        onPress: PropTypes.func
    }
    static defaultProps = {
        value: 0,
        size: 20,
        margin: 5,
        max: 5,
        color: '#00b600'
    }
    bindClick = (index) => {
        const { onPress } = this.props;
        if (!onPress) {
            return;
        }
        onPress(index + 1);
        this.setState({
            value: index + 1
        })
    }
    render() {
        const { size, margin, max, color, onPress } = this.props;
        const { value } = this.state;
        const defaultStars = [], activeStars = [];
        for (let i = 0; i < max; i++) {
            defaultStars.push(<Icon name='star' key={i} size={size} color='#ececec' onPress={() => this.bindClick(i)} style={{ marginRight: margin }}></Icon>)
        }
        for (let i = 0; i < value; i++) {
            activeStars.push(<Icon name='star' key={i} size={size} color={color} onPress={() => this.bindClick(i)} style={{ marginRight: margin }}></Icon>)
        }
        // 选中状态的星星的宽度
        const activeStarsWidth = (size + margin) * Math.floor(value) + size * (value - Math.floor(value));
        return (
            <View style={styles.rate}>
                <View style={[styles.stars, styles.active, { width: activeStarsWidth }]}>
                    {activeStars.map(item => item)}
                </View>
                <View style={styles.stars}>
                    {defaultStars.map(item => item)}
                </View>
            </View>
        )
    }
}


const styles = StyleSheet.create({
    rates: {
        flexDirection: 'row',
        position: 'relative'
    },
    stars: {
        flexDirection: 'row',
        alignItems: 'center',
        overflow: 'hidden',
        flexGrow: 0
    },
    active: {
        position: 'absolute',
        zIndex: 200,
        left: 0,
        top: 0
    }
});

开发电影海报组件

海报组件开发需要注意的是:

  1. 点击电影海报,跳转详情页面,跳转逻辑都是一样的,所以可以不用自定义事件的方式跳转,直接在组件里面调用 this.props.navigation.push 进行跳转。页面在 router 里注册后可以直接使用 _this.props.navigation.push_,但是组件不行。在组件中,想要使用 navigation 进行跳转,要么是使用自定义属性,将 navigation 传入组件,要么使用 react-navigation 提供的 withNavigation翻翻,withNavigation(component) 返回一个 render 函数,默认将 navigation 作出自定义属性传入组件。

  2. 有些海报图片背景纯白,和页面背景融合了,看不到边界,所以需要给他设置 border,由于 Image 组件不能设置 border,所以这里需要使用 ImageBackground 组件。

  3. title 只能为一行,产出部分省略,需要加一个 numberOfLines={1} 的属性。

    import React, { Component } from 'react'; import { Text, View, StyleSheet, ImageBackground, TouchableWithoutFeedback } from 'react-native'; import PropTypes from 'prop-types'; import { withNavigation } from 'react-navigation'; import { px } from '../utils/device'; import Rate from './rate';

    class MoviesItem extends Component { constructor(props) { super(props); } static propTypes = { data: PropTypes.object } render() { const { data, navigation } = this.props; const { id, title, cover, rating, null_rating_reason } = data; return ( <TouchableWithoutFeedback onPress={() => navigation.push('Detail', { id })}> <ImageBackground source={{ uri: cover.url }} style={styles.img}> {title} {rating ? ( <Rate value={rating.value / 2} size={px(20)} margin={px(4)} /> {rating.value.toFixed(1)} ) : ( {null_rating_reason} )} ) } }

    export default withNavigation(MoviesItem);

    const styles = StyleSheet.create({ page: { width: px(160) }, img: { width: px(160), height: px(224), overflow: 'hidden', borderRadius: px(8), borderWidth: 1, borderStyle: 'solid', borderColor: '#f8f8f8' }, title: { fontSize: px(28), fontWeight: '600', color: '#333', marginTop: px(12), lineHeight: px(40) }, rate: { flexDirection: 'row', alignItems: 'center' }, rateText: { fontSize: px(24), color: '#999', marginLeft: px(6) } });

使用

React Native 开发豆瓣评分(七)首页组件开发 React Native 开发豆瓣评分(七)首页组件开发
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
java将前端的json数组字符串转换为列表
记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
4cast
4castpackageloadcsv.KumarAwanish发布:2020122117:43:04.501348作者:KumarAwanish作者邮箱:awanish00@gmail.com首页:
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Stella981 Stella981
3年前
React Native 开发豆瓣评分(八)首页开发
首页完成效果展示:<divstyle"textalign:center;"<imgsrc"https://img2018.cnblogs.com/blog/1312841/201907/1312841201907181353098021875493361.gif"/</div一、开发占位图组件在没有数
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这