美文网首页
react-native 的样式、布局和文本输入

react-native 的样式、布局和文本输入

作者: 咸鱼Jay | 来源:发表于2018-11-16 14:40 被阅读16次

    样式

    React Native中,仍然是使用JavaScript来写样式。所有的核心组件都接受名为style的属性。这些样式名基本上是遵循了web上的CSS的命名,只是按照JS的语法要求使用了驼峰命名法,例如将background-color改为backgroundColorstyle属性可以是一个普通的JavaScript对象。实际开发中组件的样式会越来越复杂,建议使用StyleSheet.create来集中定义组件的样式。比如像下面这样:

    import React, { Component } from 'react';
    import { AppRegistry, StyleSheet, Text, View } from 'react-native';
    
    export default class LotsOfStyles extends Component {
        render() {
            return (
                <View>
                    <Text style={styles.red}>just red</Text>
                    <Text style={styles.bigblue}>just bigblue</Text>
                    <Text style={[styles.bigblue, styles.red]}>bigblue, then red</Text>
                    <Text style={[styles.red, styles.bigblue]}>red, then bigblue</Text>
                </View>
            );
        }
    }
    
    const styles = StyleSheet.create({
        bigblue: {
            color: 'blue',
            fontWeight: 'bold',
            fontSize: 30,
        },
        red: {
            color: 'red',
        },
    });
    
    image

    看一下效果图,值得注意的是这个地方

    <Text style={[styles.bigblue, styles.red]}>bigblue, then red</Text>
    <Text style={[styles.red, styles.bigblue]}>red, then bigblue</Text>
    

    明显可以看出在数组中位置居后的样式对象比居前的优先级更高,即后声明的属性会覆盖先声明的同名属性

    高度和宽度

    指定宽高

    最简单的给组件设定尺寸的方式就是在样式中指定固定的widthheightReact Native中的尺寸都是无单位的,这样给组件设置尺寸的好处是可以在不同尺寸的屏幕上都显示成一样的大小。

    import React, { Component } from 'react';
    import { AppRegistry, View } from 'react-native';
    
    export default class FixedDimensionsBasics extends Component {
        render() {
            return (
                <View>
                    <View style={{width: 50, height: 50, backgroundColor: 'powderblue'}} />
                    <View style={{width: 100, height: 100, backgroundColor: 'skyblue'}} />
                    <View style={{width: 320, height: 150, backgroundColor: 'steelblue'}} />
                </View>
            );
        }
    };
    
    image

    弹性(Flex)宽高

    上面那种方法,设置了具体的宽、高,那么在任何设备上都是同样的尺寸,不存在适配这么一说。考虑到不同机型的适配问题,使用比例布局的方法则不用担心尺寸的误差。

    一般而言我们会使用flex:1来指定某个组件扩张以撑满所有剩余的空间。如果有多个并列的子组件使用了flex:1,则这些子组件会平分父容器中剩余的空间。如果这些并列的子组件的flex值不一样,则按比例平分整个屏幕。默认是纵向平分,当然也可以设置成横向平分,在下面的使用Flexbox布局中会有介绍。

    比如说我举个官方栗子

    import React, { Component } from 'react';
    import { AppRegistry, View } from 'react-native';
    
    export default class FlexDimensionsBasics extends Component {
        render() {
            return (
                // 试试去掉父View中的`flex: 1`。
                // 则父View不再具有尺寸,因此子组件也无法再撑开。
                // 然后再用`height: 300`来代替父View的`flex: 1`试试看?
                <View style={{flex: 1}}>
                    <View style={{flex: 1, backgroundColor: 'powderblue'}} />
                    <View style={{flex: 2, backgroundColor: 'skyblue'}} />
                    <View style={{flex: 3, backgroundColor: 'steelblue'}} />
                </View>
            );
        }
    };
    
    image

    子组件能够充满父容器剩余空间必须父容器的尺寸不为 0 ,如果父容器既没有指定widthheight,同时也没有设定flex:1,那么子组件将不会显示(即使子组件设置了flex)。父组件默认设置flex:1(默认充满整个剩余空间)

    使用Flexbox布局

    我们在React Native中使用flexbox规则来指定某个组件的子元素的布局。Flexbox可以在不同屏幕尺寸上提供一致的布局结构。

    一般来说,使用flexDirectionalignItemsjustifyContent三个样式属性就已经能满足大多数布局需求。

    React Native中的Flexbox的工作原理和web上的CSS基本一致,当然也存在少许差异。首先是默认值不同:flexDirection的默认值是column而不是row,而flex也只能指定一个数字值。

    Flex Direction

    在组件的style中指定flexDirection可以决定布局的主轴。默认值是竖直轴(column)方向。

    比如说我们把上面例程改成这样(列)row

    <View style={{flex: 1,flexDirection: 'row'}}>
        <View style={{width: 50,backgroundColor: 'powderblue'}} />
        <View style={{flex: 2, backgroundColor: 'skyblue'}} />
        <View style={{flex: 3, backgroundColor: 'steelblue'}} />
    </View>
    

    效果图就会有所变化

    image

    Justify Content

    在组件的style中指定justifyContent可以决定其子元素沿着主轴的排列方式。对应的这些可选项有:flex-startcenterflex-endspace-around以及space-between。为了便于理解这些排列方式的效果,我们可以全列出来先看一下,代码还可以再简化,暂时不管了

    import React, { Component } from 'react';
    import { AppRegistry, View } from 'react-native';
    
    export default class FlexDimensionsBasics extends Component {
        render() {
            return (
                <View style={{flex:1, flexDirection:'row'}}>
                    {/*1*/}
                    <View style={{
                        flex: 1,
                        flexDirection: 'column',
                        justifyContent: 'space-between',
                    }}>
                        <View style={{height: 50, backgroundColor: 'powderblue'}} />
                        <View style={{height: 50, backgroundColor: 'skyblue'}} />
                        <View style={{height: 50, backgroundColor: 'steelblue'}} />
                    </View>
                    {/*2*/}
                    <View style={{
                        flex: 1,
                        flexDirection: 'column',
                        justifyContent: 'flex-start',
                    }}>
                        <View style={{height: 50, backgroundColor: 'powderblue'}} />
                        <View style={{height: 50, backgroundColor: 'skyblue'}} />
                        <View style={{height: 50, backgroundColor: 'steelblue'}} />
                    </View>
                    {/*3*/}
                    <View style={{
                        flex: 1,
                        flexDirection: 'column',
                        justifyContent: 'center',
                    }}>
                        <View style={{height: 50, backgroundColor: 'powderblue'}} />
                        <View style={{height: 50, backgroundColor: 'skyblue'}} />
                        <View style={{height: 50, backgroundColor: 'steelblue'}} />
                    </View>
                    {/*4*/}
                    <View style={{
                        flex: 1,
                        flexDirection: 'column',
                        justifyContent: 'flex-end',
                    }}>
                        <View style={{height: 50, backgroundColor: 'powderblue'}} />
                        <View style={{height: 50, backgroundColor: 'skyblue'}} />
                        <View style={{height: 50, backgroundColor: 'steelblue'}} />
                    </View>
                    {/*5*/}
                    <View style={{
                        flex: 1,
                        flexDirection: 'column',
                        justifyContent: 'space-around',
                    }}>
                        <View style={{height: 50, backgroundColor: 'powderblue'}} />
                        <View style={{height: 50, backgroundColor: 'skyblue'}} />
                        <View style={{height: 50, backgroundColor: 'steelblue'}} />
                    </View>
    
                </View>
            );
        }
    };
    

    他们的效果分别如下

    image

    Align Items

    在组件的style中指定alignItems可以决定其子元素沿着次轴(与主轴垂直的轴,比如若主轴方向为row,则次轴方向为column)的排列方式。对应的这些可选项有:flex-startcenterflex-end以及stretch

    注意:要使stretch选项生效的话,子元素在次轴方向上不能有固定的尺寸。以下面的代码为例:只有将子元素样式中的width: 50去掉之后,alignItems: 'stretch'才能生效。因为stretch是平铺。此样式和CSS中的align-items表现一致,默认值为 stretch

    处理文本输入

    TextInput是一个允许用户输入文本的基础组件。它有一个名为onChangeText的属性,此属性接受一个函数,而此函数会在文本变化时被调用。另外还有一个名为onSubmitEditing的属性,会在文本被提交后(用户按下软键盘上的提交键)调用。TextInput是一个允许用户在应用中通过键盘输入文本的基本组件。
    目前从TextInput里取值唯一的做法:在onChangeText中用setState把用户的输入写入到state中,然后在需要取值的地方从this.state中取出值。
    假如我们要实现当用户输入时,实时将其以单词为单位翻译为另一种文字。我们假设这另一种文字来自某个吃货星球,只有一个单词:🍕。所以"Hello there Bob"将会被翻译为"🍕🍕🍕"。

    import React, { Component } from 'react';
    import { AppRegistry, Text, TextInput, View } from 'react-native';
    
    export default class PizzaTranslator extends Component {
        constructor(props) {
            super(props);
            //设置当前状态是text  初始值为空
            this.state = {text: ''};
        }
    
        render() {
            return (
                <View style={{padding: 10}}>
                    <TextInput
                        style={{height: 40}}
    //如果没有任何文字输入,会显示此字符串。
                        placeholder="在此输入文字"
                        onChangeText={(text) => this.setState({text})}
                    />
                    <Text style={{padding: 10, fontSize: 42}}>
                        {this.state.text.split(' ').map((word) => word && '🍕').join(' ')}
                    </Text>
                </View>
            );
        }
    }
    
    onChangeText={(text) => this.setState({text})}
    

    当文本框内容变化时调用此回调函数。改变后的文字内容会作为参数传递。使用onChangeText属性,这个属性的值是一个函数,setState()方法会通知界面重新渲染,即只要有setState就会走render, 里面的参数代表的是构造函数中的state----text

    {this.state.text.split(' ').map((word) => word && '🍕').join(' ')}
    

    JavaScript中字符串的split()方法返回的是一个数组,并且这个数组的长度不会为零(即便这个字符串的长度为零),数组的map()方法相当于Java中的for循环foreach,参数是一个函数,返回值类型还是一个数组。
    =>符号,代表一个函数,左边括号中代表的是函数的参数,右边代表的是这个函数的函数体返回的东西,join()方法是数组的转字符串的一个方法,比如[1,2,3].join('0')的结果就是字符串102030
    上面出现了&&符号,在这里并不是起到逻辑表达式的作用

    a&&b 当a为真时 返回b
    &&使用:
    1:当做逻辑表达式
    2:用于判空 然后得到后者
    

    当下面两条语句同时存在时,如果text值为空,则会显示提示文字,否则显示text文字。

    value = {this.state.text}
    placeholder="在此输入文字"
    

    此文章引用自邪人君子的react-native 入门之 样式、布局和文本输入

    相关文章

      网友评论

          本文标题:react-native 的样式、布局和文本输入

          本文链接:https://www.haomeiwen.com/subject/modmfqtx.html