React Native教程第二部分: 计算器的布局和样式

泡在网上的日子 / 文 发表于2016-11-14 10:46 第次阅读 React Native,计算器

第一部分: Hello, React | 第二部分: 设计Calculator | 第三部分: 开发Calculator

本教程的完整代码在GitHub

介绍

第一部分我们完成了“Hello, React!” app的配置,在第二部分,我们接着上文开始计算器的布局和样式设定。

计算器的布局

我们首先完成计算器的布局。计算器主要有两部分:

  1. 显示用户输入和计算结果的部分。

  2. 用户输入数字和运算符号的部分。

让我们打开ReactCalculator.js文件,使用flexbox创建两个节点。把 text label从render函数中移除,并用下面的内容替换它:

render() {
    return (
        <View style={{flex: 1}}>
            <View style={{flex: 2, backgroundColor: '#193441'}}></View>
            <View style={{flex: 8, backgroundColor: '#3E606F'}}></View>
        </View>
    )
}

我们所做的就是创建一个包含了这两个节点的View容器,通过样式flex: 1让它的宽度和高度占满可用的空间。每个控件只能有一个根view,因此这个容器是必要的。

在容器里面,我们创建了两个样式分别为flex: 2和flex: 8的view,让它们分别占据根容器的20%和80%。为了能更好区分这两个控件,我们为每个view设置了一个不同的背景颜色。

同样你需要从react-native导入View类,把它添加到现有的import中,如下:

...
import {
    View,
    Text,
    AppRegistry
} from 'react-native';

现在运行app,效果应该是这样的:

react-native-tutorial-3.png

好了现在我们开始把它弄的更像一个计算器的样子。不过在这之前我们需要清理一下这些样式。内联的样式可以让你快速的看到效果,但是一旦失控就会越来越乱。幸运的是我们没有被限制只能这样使用内联样式,而是可以创建一个样式文件,然后被引用进来。这种方式还可以使我们在几个控件之间共享一个样式,接下来就会在我们的按钮上使用。

在src/目录创建一个 Style.js的源文件,导入StyleSheet 类:

import { StyleSheet } from 'react-native';
var Style = StyleSheet.create({
    rootContainer: {
        flex: 1
    },
    displayContainer: {
        flex: 2,
        backgroundColor: '#193441'
    },
    inputContainer: {
        flex: 8,
        backgroundColor: '#3E606F'
    }
});
export default Style;

你会注意到最下面我们导出(export)了Style,这是为了让其它文件可以通过 import Style.js来使用它,马上我们就会这样做。

回到ReactCalculator.js ,更新render函数让它引用定义在 Style.js中的样式:

import Style from './Style';
...
<View style={Style.rootContainer}>
    <View style={Style.displayContainer}></View>
    <View style={Style.inputContainer}></View>
</View>

添加输入按钮

好了现在我们的布局结构设置完毕,样式也是外联的了,那么可以开始添加按钮了。我们先在 src/ 目录创建一个InputButton类,用于显示计算器中的一个按钮:

// InputButton.js
import React, { Component } from 'react';
import {
    View,
    Text
} from 'react-native';
import Style from './Style';
export default class InputButton extends Component {
    
    render() {
        return (
            <View style={Style.inputButton}>
                <Text style={Style.inputButtonText}>{this.props.value}</Text>
            </View>
        )
    }
    
}

这里要注意两点:

  1. We export the class directly using export default on the class definition.我们在类的定义中使用export default来导出类

  2. Text view使用this.props.value。Props本质上是可以传递给子控件的静态数据,后面我们将用到。

让我们在Style.js中为InputButton添加一些样式:

// Style.js
var Style = StyleSheet.create({
    ...
    
    inputButton: {
        flex: 1,
        alignItems: 'center',
        justifyContent: 'center',
        borderWidth: 0.5,
        borderColor: '#91AA9D'
    },
    inputButtonText: {
        fontSize: 22,
        fontWeight: 'bold',
        color: 'white'
    }
});

把可重用的按钮定义好了之后,就可以回到ReactCalculator添加我们的按钮了。

我们不一个一个的定义按钮,而是用更程序化的方式。

我们定义一个二维数组来代表计算器的每一行。然后创建一个动态生成按钮的函数并在render中调用。这个新的函数,_renderInputButtons,将遍历inputButtons数组的每行以及每行中的数字(或者符号),创建一个InputButton并把它添加到inputRow中。

代码如下:

// ReactCalculator.js
...
import InputButton from './InputButton';
// Define the input buttons that will be displayed in the calculator.
const inputButtons = [
    [1, 2, 3, '/'],
    [4, 5, 6, '*'],
    [7, 8, 9, '-'],
    [0, '.', '=', '+']
];
class ReactCalculator extends Component {
    render() {
        return (
            <View style={Style.rootContainer}>
                <View style={Style.displayContainer}></View>
                <View style={Style.inputContainer}>
                    {this._renderInputButtons()}
                </View>
            </View>
        )
    }
    /**
     * For each row in `inputButtons`, create a row View and add create an InputButton for each input in the row.
     */
    _renderInputButtons() {
        let views = [];
        for (var r = 0; r < inputButtons.length; r ++) {
            let row = inputButtons[r];
            let inputRow = [];
            for (var i = 0; i < row.length; i ++) {
                let input = row[i];
                inputRow.push(
                    <InputButton value={input} key={r + "-" + i} />
                );
            }
            views.push(<View style={Style.inputRow} key={"row-" + r}>{inputRow}</View>)
        }
        return views;
    }
}

注:在创建一个控件数组的时候_renderInputButtons中控件上的key是必要的,而且数组上的每个控件key必须唯一。

以上演示了如何动态的创建View,以及如何在render函数中调用它们。这使得我们可以创建非常复杂的界面。

如果细看代码你会发现我们需要在Style.js中定义一个inputRow的样式:

// Style.js
...
    inputRow: {
        flex: 1,
        flexDirection: 'row'
    }
...

好了,运行代码,现在计算器的界面如下:

react-native-tutorial-4.png

总结

目前我们已经完成了计算器的布局和样式,但是还需要开发实际的计算功能。在本教程的第三部分,我们将继续添加触摸事件处理,为UI更新实现State,并根据用户输入执行数学计算。

第三部分点击这里

收藏 赞 (3) 踩 (0)
上一篇:你讨厌写selector背景了吗?手摸手教你封装个控件!
前段时间项目里要写好几个按下去状态变化的button, 于是在drawable文件夹里写了一堆文件, 想想好烦啊, 也是浪费时间,搞了一堆文件,还要起名,真心烦! 一气之下, 一劳永逸, 写一个控件,各种属性代码xml配置或者代码设置。因此也就有了StateButton。
下一篇:Android 蓝牙相关的广播
Android 蓝牙相关的广播 监听蓝牙相关的广播并获得相关的信息,蓝牙相关的广播主要集中在 BluetoothAdapter 和 BluetoothDevice 类中, 可以通过在 AndroidManifest.xml 中注册静态广播,也可以通过在代码中注册动态广播,两种形式的广播都可以监听到 需要相