React Native入门详解--基础组件的使用

1,790 阅读10分钟

本文中你可以学到

  • RN开发-常规组件的使用
  • RN开发-如何使用样式
  • RN开发-如何使用布局(定位、flex布局)
  • RN开发-如何使用动画以及动画的一些示例 该教程默认你具备一定的ReactJS开发经验。

RN常用组件

1、View组件和组件的样式

View是RN中最基础的组件,类似于html中的div标签,他可以作为组件的容器。

组件样式

  • 大部分组件的样式通过组件的style属性来控制,style的值可以为数组也可以为对象
  • 样式属性key要遵循小驼峰命名法
  • style的值为对象时,对象的key为样式属性value则为样式的值;当style的值为数组时,数组的元素必须为对象,并且当数组中多个对象具有相同的样式属性时,后面对象的样式属性会覆盖前面对象的。
     import { View } from 'react-native'
    {/*style值为对象    生成一个宽为200dp,高为100dp背景色为粉色的View组件*/}
     <View style={{height:100,width:200,backgroundColor:"pink"}}><View>  
     
    {/*style值为数组    生成一个宽为200dp,高为200dp背景色为红色的View组件*/}
     <View style={[
         {height:100,width:200,backgroundColor:"pink"},
         {height:200,backgroundColor:"red"}
     ]}><View>
    
  • 某些具有多种特性 复杂样式的值必须为数组,如transform
    <View style={{
        height:100,
        width:200,
        backgroundColor:"pink",
        transform:[{translateX:100}]
    }}><View>  
    

内联式样式

如上,直接在style中书写样式对象就是内联式写法,这种适合样式少,样式简单的组件使用

样式对象式样式

  • 有些组件样式比较复杂如果写在jsx结构上,会让组件结构复杂增加阅读成本
  • 某些样式是可以被其他组件复用不需要多次数书写。为了解决这些问题我们可以用样式对象式样式
{/*导入创建样式对象的 StyleSheet*/}
import { View,StyleSheet, } from 'react-native'
<View style={styles.container}>
    <View style={styles.content}</View>
<View>
{/*创建样式对象*/}
const styles = StyleSheet.create({
    container:{
        width:100,
        height:200
    },
    content:{
        width:50,
        height:50
    }
})

组件布局

RN有三种布局方式:常规的布局、Flex布局、定位布局

Flex布局

常规属性:
flex:同css的flex属性用法类似
flexDirection:RN没有display:flex用法,flexDirection就是将当前盒子设为伸缩盒子,并设置主轴方向

  • 值:row | column | row-reverse | column-reverse justifyContent:同css的flex属性用法类似
    alignItems:同css的flex属性用法类似 flexWrap:同css的flex属性用法类似
    alignSelfflex-start | flex-end | center

定位布局

position:同css的position属性,但是没有fixed值

2、Text组件

在RN的很多组件内没法直接显示文字内容,我们需要使用Text组件来显示文字

组件常规属性

numberOfLines:文本行数限制,超出的内容以省略号形式显示
ellipsizeMode:设置文本缩略格式,配合numberOfLines使用

  • 值:tail:在末尾...省略(默认值)| clip:在末尾切割,直接切割字符无省略符 | head:在前面...省略 | middle:在中间...省略 onPress:点击事件

组件样式属性

color:字体颜色
fontSize:字体大小
fontFamily:字体
fontStyle:字体样式(normal:正常italic:斜体)
fontWeight:设置字体粗体(normal:正常bold:粗体100,200,300, 400, 500, 600, 700, 800, 900)
lineHeight:行高
textAlign:对齐方式(auto:自动对齐left:左对齐right:右对齐 center:居中对齐 justify:仅ios支持 两端对齐) textDecorationLine:文字下划线和删除线样式(none:无线underline:下划线line-through:删除线 underline line-through:下划线和删除线)

3、Image组件

组件属性

source:图片的资源,使用本地图片时需要先将图片导入当前组件中然后绑定到source上;使用网络图片时,source需要绑定一个具有uri字段的对象 这个uri就是图片URL

组件样式属性

resizeMode:图片显示模式

  • contain:保持宽高缩放图片,使图片的长边能完全显示出来
  • cover:保持宽高缩放图片,使图片的短边能完全显示出来,裁剪长边
  • stretch:图片将完全显示出来并拉伸变形铺满整个屏幕
  • repeat:图片将重复并铺满屏幕(只支持ios)
  • center:图片不拉伸不缩放且居中
import { Image } from 'react-native'
{/* 本地图片 */}
const img1 = require("../asstes/img1.png")  
<Image source={img1} />  
<Image source={require("../asstes/img.png")} />  
{/* 网络图片 */}
<Image source={{uri:"http:ww......."}} />

4、TouchAbleopacity组件

某些组件没有点击相关的事件,我们可以将其嵌套TouchAbleopacity组件中使用点击等相关能力

组件常规属性

activeOpacity:设置组件在进行触摸的时候,显示的不透明度(取值在0~1之间)
onPress:触摸事件触发时执行的回调
onPressIn:手指按下时触发的回调 onPressOut:手指松开时触发的回调

function Home() {
    const hPress = () => {console.log("touch事件被触发了")}
    return <TouchableOpacity activeOpacity={1} onPress={hPress}>
        <View style={{width:100,height:200}}></View>  
    </TouchableOpacity>
}

5、ScrollView组件

如果你的页面需要滚动(不管是水平还是竖直方向),你都可以使用这个组件.
ScrollView组件滚动有两个前提:

  • 它自身有一个固定的高度或宽度
  • 它的内容高度或宽度 超过他自身的高度或宽度

组件常规属性

horizontal:控制滚动的方向(true:水平滚动,false:竖向滚动,默认是false)
onScroll:滚动事件触发时的回调
keyboardDismissMode:当拖拽滚动视图时,是否要隐藏软键盘

  • none:(默认值),拖拽时不隐藏软键盘
  • on-drag:当拖拽开始的时候隐藏软键盘
  • interactive:(仅ios),软键盘伴随拖拽操作同步地消失,上滑动会恢复键盘
    keyboardShouldPersistTaps:点击ScrollView是否收起软键盘,TextInput无法自动失去焦点/需点击多次才切换到其他组件原因就是没有TextInput放入ScrollView中。

组件方法

scrollTo(x,y,naimate):让ScrollView滚动到指定位置的方法,参数1:X轴坐标,参数2:Y轴坐标 参数3:滚动是否启用平滑动画
scrollTo({x: 0, y: 0, animated: true})
注意:指定滚动持续时间的示例(仅限 Android):
scrollTo({x: 0, y: 0, duration: 500})

实例

import React, { useEffect, useRef } from 'react'
import { View, Text, StyleSheet, ScrollView } from 'react-native'
// 引入适配工具
import pxTodp from '../../utils/adaptive';
export default function Home(props) {
 const myScrollViewNode = useRef()
 useEffect(() => {
   // 页面初始,让ScrollView滚动到 X:200 Y:0 的位置
   myScrollViewNode.current.scrollTo({ x: 200, y: 0, animated: true })
 }, [])
 const dataList = [{ text: "box1" }, { text: "box2" }, { text: "box3" }, { text: "box4" }, { text: "box5" }, { text: "box6" }, { text: "box7" },]
 const hScroll = (e) => {
  // 获取组件位置和尺寸
   console.log("获取组件位置和尺寸", e.nativeEvent);
 }
 return (
   <View>
     <ScrollView horizontal={true} onScroll={hScroll} ref={myScrollViewNode}>
       { dataList.map(e => {
           return <View key={e.text} style={{ backgroundColor: 'pink', width: pxTodp(200), height: pxTodp(200), flexDirection: "row", justifyContent: "center", alignItems: "center" }}>
             <Text style={{ height: pxTodp(100), width: pxTodp(100), textAlign: "center", lineHeight: pxTodp(100), backgroundColor: "powderblue" }}>{e.text}</Text>
           </View>
         })}
     </ScrollView>
   </View>
 )
}

微信截图_20210330101717.png

6、TextInput组件

组件常规属性

placeholder:输入框的占位符
placeholderTextColor:占位字符串显示的文字颜色 autoFocus:是否在componentDidMount后会获得焦点,默认false multiline:文本框中可以输入多行文字。默认值为 false。 value:输入框的显示内容
onChangeText:输入框内容被改变时触发的回调

组件样式属性

paddingVertical:去除内边距,在安卓中,你可能会出现TextInput占位符显示不全的问题,可以通过 paddingVertical:0 解决这个问题

数据双向绑定示例

import React, { useState } from 'react'
import { View, Text, TextInput } from 'react-native'
// 引入适配工具
import pxTodp from '../../utils/adaptive';
export default function Home(props) {
  const [state, setState] = useState({ value: "11" })
  const hChangeText = (e) => {
    // 获取输入框最新数据 并更新state.value
    setState(oldState => ({ ...oldState, value: e }))
  }
  return (
    <View style={{ height: pxTodp(400), marginTop: pxTodp(100), backgroundColor: "pink" }} >
      <Text>TextInput组件:</Text>
      {/* 将state.value绑定到 TextInput组件上 */}
      <TextInput onChangeText={hChangeText} value={state.value} placeholder="这是占位符" style={{ backgroundColor: "powderblue" }}></TextInput>
    </View >
  )
}

7、StatusBar组件

它是控制应用状态栏的组件,他可以在任何视图加载,当有多个状态栏组件时,后加载的会覆盖前面的这点 在使用导航器的时候需要注意。

组件常规属性

animated:状态栏的某些属性变化时,是否以动画形式呈现默认为false,目前支持的属性:backgroundColor, barStyle 和 hidden。
translucent:状态栏背景是否透明,默认false(仅安卓)
backgroundColor:状态栏背景色(仅安卓)
barStyle:状态栏文本颜色:default | light-content | dark-content
hidden:是否显示状态栏,默认false

8、Animated组件

Animated组件对安卓和ios动画的封装,通过统一的接口为RN提供了的动画的功能

值类型

  • Animated.Value() 用于单个值
  • Animated.ValueXY() 用于矢量值
    AnimatedValue.setValue(newValue):在不触发动画的情况下修改动画的值

配置动画

RN提供了三种类型动画,并对其进行配置

  • Animated.decay(value, config):以指定的初始速度开始变化,然后变化速度越来越慢直至停下
  • Animated.spring(value,config):提供了一个基础的弹簧物理模型
  • Animated.timing(value,config):使用easing 函数让数值随时间动起来。它默认使用对称的easeInOut 曲线,将对象逐渐加速到全速,然后通过逐渐减速停止结束。
    • value:需要被更改的动画值
    • config:动画配置对象
      • duration:动画的持续时间(毫秒)。默认值为 500
      • easing:缓动函数。 默认为Easing.inOut(Easing.ease)。
      • delay: 开始动画前的延迟时间(毫秒)。默认为 0.
      • isInteraction:指定本动画是否在InteractionManager的队列中注册以影响其任务调度。默 认值为 true。
      • useNativeDriver: 启用原生动画驱动。默认不启用(false)。 大部分业务场景用 Animated.timing() 就足够了,这里重点介绍一下它。

执行动画

Animated.timing().start()
配置动画完成后,调用start方法就会执行这个动画,start可以传入一个回调函数,当动画结束后会执行这个回调,同时向这个回调传入动画执行的状态{finished:false | true}

Animated.timing({}).start(({ finished }) => {
  /* 动画完成的回调函数 */
});

动画组件

在RN中,组件必须通过特殊处理才能使用动画。Animated提供了几个可以直接使用的组件:Animated.ImageAnimated.ScrollViewAnimated.TextAnimated.View
如果内置的动画组件无法满足你,你可用通过 createAnimatedComponent() 自己封装动画组件

示例1

这个一个简单的动画示例,会将组件通过scale属性实现组件从小到大的动画。点击红色按钮开始执行动画,点击绿色按钮将组件恢复到动画之前的状态。

500x698_1617092231341.gif

import React, { useEffect, useRef } from 'react'
import { View, Text, Animated } from 'react-native'
// 引入适配工具
import pxTodp from '../../utils/adaptive';
let scaleAnimate = new Animated.Value(0)
const handleAnimate = () => {
  // 点击粉色按钮配置动画,并执行它
  Animated.timing(scaleAnimate, { duration: 1000, toValue: 1, useNativeDriver: false }).start()
}
const resetAnimate = () => {
  // 将动画值设置为0
  scaleAnimate.setValue(0)
}
export default function Home(props) {
  return (
    <View style={{ backgroundColor: "gray", flex: 1 }}>
      <View style={{ width: pxTodp(540), height: pxTodp(540), backgroundColor: "white", flexDirection: "row", justifyContent: "center", alignItems: "center" }}>
        <Animated.View style={{ width: pxTodp(200), height: pxTodp(200), backgroundColor: "pink", transform: [{ scale: scaleAnimate }] }}></Animated.View>
      </View>
      <View style={{ marginTop: pxTodp(50), flexDirection: "row", justifyContent: "space-between", paddingLeft: pxTodp(60), paddingRight: pxTodp(60) }}>
        <Text onPress={handleAnimate} style={{ backgroundColor: "pink", color: "white", borderRadius: pxTodp(10), width: pxTodp(120), height: pxTodp(50), lineHeight: pxTodp(50), textAlign: "center" }}>执行动画</Text>
        <Text onPress={resetAnimate} style={{ backgroundColor: "green", color: "white", borderRadius: pxTodp(10), width: pxTodp(120), height: pxTodp(50), lineHeight: pxTodp(50), textAlign: "center" }}>重置动画</Text>
      </View>
    </View>
  )
}

差值

有些动画效果无法通过纯数字来实现,例如颜色的渐变,0deg-180deg角度的变化,你可以通过差值来实现。 它是指将一定范围的输入值映射到另一组不同的输出值,一般我们使用线性的映射,但是也可以使用 easing 函数
AnimateValue.interpolate({ inputRange: [0,1], outputRange: [0,300]})

  • inputRange:输入值的区间
  • inputRange:输出值的区间 AnimateValue.interpolate({ inputRange: [0,1], outputRange: ["rgba(0,0,0,.1)","rgba(255,255,255,1)"]})
    AnimateValue.interpolate({ inputRange: [0,1], outputRange: ["0deg","300deg"]})
    interpolate()还支持定义多个区间段落,常用来定义静止区间
    AnimateValue.interpolate({ inputRange: [-300, -100, 0, 100, 101], outputRange: [300, 0, 1, 0, 0] });
    这样当AnimateValue=-400时输出值为450;当AnimateValue=-300时输出值为300;当AnimateValue=0时输出值为1;当AnimateValue=100时输出值为0;当AnimateValue大于100时输出值为0;

示例

基于缩放的动画值,创建颜色渐变和旋转角度的差值
530x675_1617095036210.gif

import React, { useEffect, useRef } from 'react'
import { View, Text, StyleSheet, ScrollView, Animated } from 'react-native'
// 引入适配工具
import pxTodp from '../../utils/adaptive';
let scaleAnimate = new Animated.Value(0)
// 颜色渐变差值映射动画
let colorAnimate = scaleAnimate.interpolate({
  inputRange: [0, 1.5],
  outputRange: ["green", "red"]
})
// 旋转角度差值映射动画
let rotateAnimate = scaleAnimate.interpolate({
  inputRange: [0, 1.5],
  outputRange: ["0deg", "360deg"]
})
const handleAnimate = () => {
  // 点击粉色按钮配置动画,并执行它
  Animated.timing(scaleAnimate, { duration: 3000, toValue: 1.5, useNativeDriver: false }).start()
}
const resetAnimate = () => {
  // 将动画值设置为0
  scaleAnimate.setValue(0)
}
export default function Home(props) {
  return (
    <View style={{ backgroundColor: "gray", flex: 1 }}>
      <View style={{ width: pxTodp(540), height: pxTodp(540), backgroundColor: "white", flexDirection: "row", justifyContent: "center", alignItems: "center" }}>
        <Animated.View style={{ width: pxTodp(200), height: pxTodp(200), backgroundColor: colorAnimate, transform: [{ scale: scaleAnimate, }, { rotate: rotateAnimate }] }}></Animated.View>
      </View>
      <View style={{ marginTop: pxTodp(50), flexDirection: "row", justifyContent: "space-between", paddingLeft: pxTodp(60), paddingRight: pxTodp(60) }}>
        <Text onPress={handleAnimate} style={{ backgroundColor: "pink", color: "white", borderRadius: pxTodp(10), width: pxTodp(120), height: pxTodp(50), lineHeight: pxTodp(50), textAlign: "center" }}>执行动画</Text>
        <Text onPress={resetAnimate} style={{ backgroundColor: "green", color: "white", borderRadius: pxTodp(10), width: pxTodp(120), height: pxTodp(50), lineHeight: pxTodp(50), textAlign: "center" }}>重置动画</Text>
      </View>
    </View>
  )
}

最后

相信大家的RN搭建过程可能会不太顺利,如果有需要帮助或者技术上交流的同猿欢迎加 V: gg_0632