React Native 样式及其布局

news2025/1/9 4:17:38

React Native 样式及其布局

参考 https://reactnative.cn/docs/flexbox

一、样式

在 React Native 中,你并不需要学习什么特殊的语法来定义样式。我们仍然是使用 JavaScript 来写样式。所有的核心组件都接受名为style的属性。这些样式名基本上是遵循了 web 上的 CSS 的命名,只是按照 JS 的语法要求使用了驼峰命名法,例如将background-color改为backgroundColor

style属性可以是一个普通的 JavaScript 对象。这是最简单的用法,因而在示例代码中很常见。你还可以传入一个数组——在数组中位置居后的样式对象比居前的优先级更高,这样你可以间接实现样式的继承。

实际开发中组件的样式会越来越复杂,我们建议使用StyleSheet.create来集中定义组件的样式。比如像下面这样:

import React from 'react';
import {StyleSheet, View, Text} from 'react-native';

const App = () => {
  return (
    <View style={styles.container}>
      <Text style={styles.red}> 红色的文字 </Text>
      <Text style={styles.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({
  container: {
    marginTop: 50,
  },
  bigBlue: {
    color: 'blue',
    fontWeight: 'bold',
    fontSize: 30,
  },
  red: {
    color: 'red',
  },
});

export default App;

一行一行来解释:

  • 第1行是需要导入React 包,是因为 react 在编译 jsx 后的需要使用 React.createElement

  • 第2行是需要导入StyleSheet、View、Text三个库

  • 第4~13行是App组件里的样式

  • 第15~27行是声明styles属性,方便App组件里使用这个属性里的子属性

  • 第29行就是导出App组件,方便index.js里渲染这个组件

    image-20231102160648668

最后效果如下图所示:

rn样式

二、高度与宽度

2.1 固定宽高

组件的高度和宽度决定了其在屏幕上显示的尺寸。

最简单的给组件设定尺寸的方式就是在样式中指定固定的widthheight。React Native 中的尺寸都是无单位的,表示的是与设备像素密度无关的逻辑像素点。

一种是这样写

import React from 'react';
import {View} from 'react-native';

const FixedDimensionsBasics = () => {
  return (
    <View>
      <View style={{width: 50, height: 50, backgroundColor: 'blue'}} />
      <View style={{width: 100, height: 100, backgroundColor: 'red'}} />
      <View style={{width: 200, height: 200, backgroundColor: 'yellow'}} />
    </View>
  );
};

export default FixedDimensionsBasics;

一种是这样写

import React from 'react';
import {StyleSheet, View} from 'react-native';

const FixedDimensionsBasics = () => {
  return (
    <>
      <View style={styles.smallStyle} />
      <View style={styles.midStyle} />
      <View style={styles.bigStyle} />
    </>
  );
};

const styles = StyleSheet.create({
  smallStyle: {
    width: 50,
    height: 50,
    backgroundColor: 'blue',
  },
  midStyle: {
    width: 100,
    height: 100,
    backgroundColor: 'red',
  },
  bigStyle: {
    width: 200,
    height: 200,
    backgroundColor: 'yellow',
  },
});

export default FixedDimensionsBasics;

上面代码运行如下:

RN高度和宽度

个人更加推荐使用第二种写法,便于统一编写样式和查看样式。因为通常而言一个文件里会有很多种样式,如果都写在view组件的括号里,视觉效果看起来会很不友好,而且去排查样式问题的时候也不利于去排查到底是哪块的问题。

2.2 弹性(Flex)宽高

在组件样式中使用flex可以使其在可利用的空间中动态地扩张或收缩。一般而言我们会使用flex:1来指定某个组件扩张以撑满所有剩余的空间。如果有多个并列的子组件使用了flex:1,则这些子组件会平分父容器中剩余的空间。如果这些并列的子组件的flex值不一样,则谁的值更大,谁占据剩余空间的比例就更大(即占据剩余空间的比等于并列组件间flex值的比)。

组件能够撑满剩余空间的前提是其父容器的尺寸不为零。如果父容器既没有固定的widthheight,也没有设定flex,则父容器的尺寸为零。其子组件如果使用了flex,也是无法显示的。

import React from 'react';
import {StyleSheet, View} from 'react-native';

const FlexDimensionsBasics = () => {
  return (
    // 试试去掉父View中的`flex: 1`。
    // 则父View不再具有尺寸,因此子组件也无法再撑开。
    // 然后再用`height: 300`来代替父View的`flex: 1`试试看? => 结果是三个view平分父view的300高度的
    <View style={styles.container}>
      <View style={styles.powderblueStyle} />
      <View style={styles.skyblueStyle} />
      <View style={styles.steelblueStyle} />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  powderblueStyle: {
    flex: 1,
    backgroundColor: 'powderblue',
  },
  skyblueStyle: {
    flex: 2,
    backgroundColor: 'skyblue',
  },
  steelblueStyle: {
    flex: 3,
    backgroundColor: 'steelblue',
  },
});

export default FlexDimensionsBasics;

上述代码效果图如下:

flex弹性宽高

如果上述代码的container下的样式flex不为1,设置的是height: 300的话,则效果如下所示:

剩余铺满

三、使用Flexbox布局

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

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

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

3.1 Flex

flex 属性决定元素在主轴上如何填满可用区域。整个区域会根据每个元素设置的 flex 属性值被分割成多个部分。

在下面的例子中,在设置了flex: 1的容器 view 中,有红色,黄色和绿色三个子 view。红色 view 设置了flex: 1,黄色 view 设置了flex: 2,绿色 view 设置了flex: 31+2+3 = 6,这意味着红色 view 占据整个区域的1/6,黄色 view 占据整个区域的2/6,绿色 view 占据整个区域的3/6

import React from "react";
import { StyleSheet, Text, View } from "react-native";

const Flex = () => {
  return (
    <View style={[styles.container, {
      // Try setting `flexDirection` to `"row"`.
      flexDirection: "column"
    }]}>
      <View style={{ flex: 1, backgroundColor: "red" }} />
      <View style={{ flex: 2, backgroundColor: "darkorange" }} />
      <View style={{ flex: 3, backgroundColor: "green" }} />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
  },
});

export default Flex;

image-20231102165815456

如果将上述 flexDirection: “column” 改为 flexDirection: "row"的话,效果图如下:

横向布局

3.2 Flex Direction

在组件的style中指定flexDirection可以决定布局的主轴。子元素是应该沿着**水平轴(row)方向排列,还是沿着竖直轴(column)方向排列呢?默认值是竖直轴(column)**方向。

  • column默认值):将子元素从上到下对齐。如果启用换行,则下一行将从容器顶部的第一个项目右侧开始。
  • row:将子元素从左到右对齐。如果启用换行,则下一行将在容器左侧的第一个项目下方开始。
  • column-reverse:将子元素从底部向上对齐。如果启用换行,则下一行将从容器底部的第一个项目右侧开始。
  • row-reverse:将子元素从右到左对齐。如果启用换行,则下一行将在容器右侧的第一个项目下方开始。
import React, {useState} from 'react';
import {StyleSheet, Text, TouchableOpacity, View} from 'react-native';

const FlexDirectionBasics = () => {
  const [flexDirection, setFlexDirection] = useState('column');

  return (
    <PreviewLayout
      label="flexDirection"
      values={['column', 'row', 'row-reverse', 'column-reverse']}
      selectedValue={flexDirection}
      setSelectedValue={setFlexDirection}>
      <View style={[styles.box, {backgroundColor: 'powderblue'}]} />
      <View style={[styles.box, {backgroundColor: 'skyblue'}]} />
      <View style={[styles.box, {backgroundColor: 'steelblue'}]} />
    </PreviewLayout>
  );
};

const PreviewLayout = ({
  label,
  children,
  values,
  selectedValue,
  setSelectedValue,
}) => (
  <View style={{padding: 10, flex: 1}}>
    <Text style={styles.label}>{label}</Text>
    <View style={styles.row}>
      {values.map(value => (
        <TouchableOpacity
          key={value}
          onPress={() => setSelectedValue(value)}
          style={[styles.button, selectedValue === value && styles.selected]}>
          <Text
            style={[
              styles.buttonLabel,
              selectedValue === value && styles.selectedLabel,
            ]}>
            {value}
          </Text>
        </TouchableOpacity>
      ))}
    </View>
    <View style={[styles.container, {[label]: selectedValue}]}>{children}</View>
  </View>
);

const styles = StyleSheet.create({
  container: {
    flex: 1,
    marginTop: 8,
    backgroundColor: 'aliceblue',
  },
  box: {
    width: 50,
    height: 50,
  },
  row: {
    flexDirection: 'row',
    flexWrap: 'wrap',
  },
  button: {
    paddingHorizontal: 8,
    paddingVertical: 6,
    borderRadius: 4,
    backgroundColor: 'oldlace',
    alignSelf: 'flex-start',
    marginHorizontal: '1%',
    marginBottom: 6,
    minWidth: '48%',
    textAlign: 'center',
  },
  selected: {
    backgroundColor: 'coral',
    borderWidth: 0,
  },
  buttonLabel: {
    fontSize: 12,
    fontWeight: '500',
    color: 'coral',
  },
  selectedLabel: {
    color: 'white',
  },
  label: {
    textAlign: 'center',
    marginBottom: 10,
    fontSize: 24,
  },
});

export default FlexDirectionBasics;

解析一下:

第5行:设置flexDirection这个属性默认值为column

第8行和第16行:调用PreviewLayout这个组件

第9~12行:分别给PreviewLayout传参

  • label=“flexDirection” 一个字符串
  • values={[‘column’, ‘row’, ‘row-reverse’, ‘column-reverse’]} 一个字符串数组
  • selectedValue={flexDirection} selectedValue属性值就是flexDirection变量的值
  • setSelectedValue={setflexDirection} setSelectedValue属性值调用setflexDirection方法,相当于会改变flexDirection的值

第13~15行:声明三个正方形的view,宽和高分别为50

第20~26行:声明PreviewLayout组件

第27和46行:声明整个父容器,距离边距是10,flex为1代表占据整个边距是10的容器

第28行:声明一个Text的组件,样式是styles.label,居中显示距离下面组件的间距是10,字体大小是24。文字内容是21行传参过来的label,也就是第九行的"flexDirection"

label: {
  textAlign: 'center',
  marginBottom: 10,
  fontSize: 24,
}

第29行和44行:声明要展示的第二部分view

第30行:对传下来的values数组,遍历里面的每个元素

第31行和第42行:声明一个TouchableOpacity系统组件

第32行:声明TouchableOpacity组件的key为values数组里每个元素的值

第33行:声明TouchableOpacity组件的按压下去触发的动作会调用setSelectedValue(value)方法,而setSelectedValue(value)实际上就是改变flexDirection这个变量的值

第34行:声明TouchableOpacity组件的style属性为styles.button的属性,以及如果selectedValue的值等于遍历当前values数组的值,那么就会再拼接上styles.selected属性的值,也就是下面两个css的值。(遍历到的那个组件的元素css样式是下面两个css样式组合起来的,否则就只是button一个css样式的)

button: {
  paddingHorizontal: 8,
  paddingVertical: 6,
  borderRadius: 4,
  backgroundColor: 'oldlace',
  alignSelf: 'flex-start',
  marginHorizontal: '1%',
  marginBottom: 6,
  minWidth: '48%',
  textAlign: 'center',
},
selected: {
  backgroundColor: 'coral',
  borderWidth: 0,
},

第35行和第41行:在TouchableOpacity组件里声明一个Text组件

第36~39行:如果被选中,声明Text的样式为下面两个css的样式;否则声明的Text样式为buttonLabel的css样式

buttonLabel: {
  fontSize: 12,
  fontWeight: '500',
  color: 'coral',
},
selectedLabel: {
  color: 'white',
}

第45行:声明在PreviewLayout组件里的子组件,也就是13到15行里的组件,对应的样式是container,其中每个组件里的flexDirection属性就是当前selectedValue的属性值

<View style={[styles.box, {backgroundColor: 'powderblue'}]} />
<View style={[styles.box, {backgroundColor: 'skyblue'}]} />
<View style={[styles.box, {backgroundColor: 'steelblue'}]} />

上述代码运行如下:

测试FlexDirection

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1163057.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

液滴微流控,助力国人单细胞

单细胞RNA测序&#xff08;scRNA-seq&#xff09;技术已经成为揭示单个细胞内RNA转录本的异质性和复杂性&#xff0c;以及揭示组织/器官/生物体内不同细胞类型的组成和功能的最先进的方法。迄今为止&#xff0c;单细胞RNA测序技术已经在动植物等真核细胞中取得了许多重要的发现…

【Python基础】IF、Else判断以及Whlie、for循环介绍符实例

运算符 1. if 语句体验2.逻辑运算3. if 语句进阶4.While循环4.1基本语法 5.break 和 continue6. for循环 1. if 语句体验 if 判断语句基本语法 在 Python 中&#xff0c;if 语句 就是用来进行判断的&#xff0c;格式如下&#xff1a; if 要判断的条件: 条件成立时&#xff0c;…

EasyCVR智能边缘网关用户信息泄漏漏洞

EasyCVR智能边缘网关用户信息泄漏漏洞 免责声明漏洞描述漏洞影响漏洞危害网络测绘Fofa: title"EasyCVR" 漏洞复现1. 构造poc2. 获取管理员账户密码3. 登录后台 免责声明 仅用于技术交流,目的是向相关安全人员展示漏洞利用方式,以便更好地提高网络安全意识和技术水平…

车载终端构筑智慧工厂:无人配送车的高效物流体系

​随着科技的不断进步和应用&#xff0c;智能化已经成为许多领域的关键词。在物流行业中&#xff0c;随着无人配送车的兴起和智慧工厂的崛起&#xff0c;车载终端正引领着无人配送车的科技变革之路。 文章同款&#xff1a;https://www.key-iot.com/iotlist/sv900.html 车载终端…

springboot+vue基于hive旅游数据的分析与应用【内含源码+文档+部署教程】

博主介绍&#xff1a;✌全网粉丝10W,前互联网大厂软件研发、集结硕博英豪成立工作室。专注于计算机相关专业毕业设计项目实战6年之久&#xff0c;选择我们就是选择放心、选择安心毕业✌ &#x1f345;由于篇幅限制&#xff0c;想要获取完整文章或者源码&#xff0c;或者代做&am…

成本中心修改后推送其他SAP系统更新成本中心(ALE)

成本中心修改后推送给其他系统 KSH2成本中心组新增成本中心&#xff08;服务器A 400client&#xff09; KAVB 输入成本中心组、控制范围、目标系统 Y 查看&#xff08;服务器B 430client&#xff09;

ubuntu 开机进入 advanced 选项 可选择内核 kernel

Ubuntu版本为22.04 1 .首先再命令窗口&#xff0c;输入 sudo gedit /etc/default/grub 命令打开grub配置文件 2.1 具体操作&#xff1a; 将 GRUB_TIMEOUT_STYLEhidden 注释掉 将 GRUB_TIMEOUT的值改为20&#xff08;界面引导显示时间&#xff09; 将GRUB_CMDLINE_LINUX_DEFA…

S32K312 DTCM在代码中使用示例

TCM是一种被直接集成在CPU芯片中的高速缓存&#xff0c;TCM又分为ITCM&#xff08;Instruction TCM&#xff09;和DTCM&#xff08;Data TCM&#xff09;。ITCM是用来存储代码段的&#xff0c;DTCM是用来存储数据的。 为什么要使用DTCM来存储数据&#xff1f;1&#xff09;频繁…

APP攻防--签名组件权限

前言 上文说到了反编译的方式&#xff0c;这期就深入到APP内部&#xff0c;即客户端安全。 安装包签名 在Android操作系统中&#xff0c;每个应用程序&#xff08;APP&#xff09;安装包&#xff08;APK&#xff09;都必须经过数字签名&#xff0c;以确保应用的完整性和来源…

【从删库到跑路】详解MySQL数据库的视图以及相关操作

&#x1f38a;专栏【MySQL】 &#x1f354;喜欢的诗句&#xff1a;更喜岷山千里雪 三军过后尽开颜。 &#x1f386;音乐分享【如愿】 &#x1f970;欢迎并且感谢大家指出小吉的问题 文章目录 &#x1f384;视图介绍&#x1f384;视图特点&#x1f33a;基本操作⭐创建视图⭐查询…

java--对象在计算机中的执行原理

1.多个对象在计算机中的执行原理 解析&#xff1a;首先是先回扫描(scan)class文件&#xff0c;加载进入方法区&#xff0c;然后在扫描文件内部的main方法&#xff0c;扫描后会在栈内存中创造一个main空间&#xff0c;然后继续扫描第一节创造对象的话&#xff0c;然后就会在方法…

金融帝国实验室(Capitalism Lab)即将隆重推出『出口公司』功能

『金融帝国实验室』&#xff08;Capitalism Lab&#xff09;即将迎来v10.0.00重大版本更新&#xff01; 并将为〔实验性DLC〕引入全新【出口公司】功能。 ————————————— 【出口公司】允许您&#xff1a; >通过出口客户搜索查找全球买家&#xff1b; >建立…

企业如何防止文件泄密

企业如何防止文件泄密 安企神数据防泄密系统下载使用 在互联网飞速发展的时代&#xff0c;数据成为大多数公司的重要组成部分&#xff0c;数据安全则是企业的安身立命之本&#xff0c;管理者应当重视保密措施。企业应当采取一系列措施来防止文件泄密&#xff0c;以确保敏感信…

消息中间件——RabbitMQ(二)各大主流消息中间件综合对比介绍!

前言 消息队列已经逐渐成为企业IT系统内部通信的核心手段。它具有低耦合、可靠投递、广播、流量控制、最终一致性等一系列功能&#xff0c;成为异步RPC的主要手段之一。当今市面上有很多主流的消息中间件&#xff0c;如老牌的ActiveMQ、RabbitMQ&#xff0c;炙手可热的Kafka&a…

Ambari-2.7.4和HDP-3.1.4安装

提示&#xff1a;Ambari-2.7.4和HDP-3.1.4安装 Hadoop集群安装目录 一、所需机器二、系统环境配置2.1准备2.2配置5台主机的SSH免密登录&#xff08;所有机器 &#xff09;2.3同步时钟&#xff0c;开启NTP服务&#xff08;所有机器&#xff09;2.4每台节点里配置FQDN&#xff0c…

10个技巧,确保项目团队按时完成任务

作为项目经理&#xff0c;你的绩效取决于有效的截止日期管理&#xff0c;以便按时交付项目。 然而&#xff0c;我们都知道&#xff0c;项目很少会按计划进行&#xff0c;因此&#xff0c;在时间和截止日期方面&#xff0c;能够驾驭项目中出现的众多不确定因素非常重要。本文将…

指针运算笔试题解析(1)

指针运算笔试题解析 题目一解析 题目二解析 题目三解析 题目四解析 题目五解析 题目一 #include<stdio.h> int main() {int a[5]{1,2,3,4,5};int *p(int*)(&a1);printf("%d %d",*(a1),*(p-1));return 0; } 答案&#xff1a;2 5 解析 int a[5]{1,2,3,4,5…

vscode1.83远程连接失败

&#xff08;报错信息忘记截图了 总之卡在vscode-server.tar.gz的下载那里&#xff0c;一直404&#xff0c;删了C:\Users\Administrator\.ssh\known_hosts也不管用 看了一下vscode1.83的commitID为a6606b6ca720bca780c2d3c9d4cc3966ff2eca12&#xff0c;网友说可以通过以下网…

XUnit单元测试(实用项目)——看完不会用你打我

一、简介 xUnit.net 是针对 .NET 的免费、开源单元测试框架&#xff0c;可并行测试、数据驱动测试。测试项目需要同时引用 xUnit和被测试项目&#xff0c;从而对其进行测试。测试编写完成后&#xff0c;用 Test Runner 来测试项目&#xff0c;Test Runner 可以读取测试代码&am…

最新版付费进群源码带自动定位和分销以及分站功能完整版无加密

简介 看到别人发那些不是挂羊头卖狗肉&#xff0c;要么就是发的缺少文件引流的。非常滴恶心 这源码是我付费花钱买的免费分享给大家&#xff0c;功能完整。而且无加密 功能&#xff1a;新建分销会员&#xff0c;设置账号密码&#xff0c;收款方式等 说明&#xff1a; 分站…