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

样式

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',
    },
});

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

<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>
        );
    }
};

弹性(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>
        );
    }
};


子组件能够充满父容器剩余空间必须父容器的尺寸不为 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)方向。
比如说我们把上面例程改成这样

<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>

效果图就会有所变化


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'}}>
            <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>
                <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>
                <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>
                <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>
                <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>
        );
    }
};

他们的效果分别如下


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="在此输入文字"
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容