React Native UI界面还原,组件布局与动画效果
写React Native UI和写 Android XML layout 布局 ,个人感觉是大同小异
在《ReactJS到React-Native,架构原理概述》里面提过
web 环境中,React 框架,JSX 源码通过 React 框架最终渲染到了浏览器的真实 DOM 中
在 React Native 框架中,JSX 源码通过 React Native 框架编译后,通过对应平台的 Bridge 实现了与原生框架的通信。如果我们在程序中调用了 React Native 提供的 API,那么 React Native 框架就通过 Bridge 调用原生框架中的方法。 因为 React Native 的底层为 React 框架,所以如果是 UI 层的变更,那么就映射为虚拟 DOM 后进行 diff 算法,diff 算法计算出变动后的 JSON 映射文件,最终由 Native 层将此 JSON 文件映射渲染到原生 App 的页面元素上,最终实现了在项目中只需要控制 state 以及 props 的变更来引起 iOS 与 Android 平台的 UI 变更。 编写的 React Native代码最终会打包生成一个 main.bundle.js 文件供 App 加载,此文件可以在 App 设备本地,也可以存放于服务器上供 App 下载更新
Yoga
Yoga C语言写的一个 CSS3/Flexbox 的跨平台 实现的Flexbox布局引擎, 意在打造一个跨iOS、Android、Windows平台在内的布局引擎,兼容Flexbox布局方式,让界面布局更加简单。
Yoga 通过实现许多设计师熟悉的 API 并在不同平台上向开发人员开放。
利用YOGA我们可以:
只写一次布局,就可以得到在不同端上的布局展示。
动态更改view的布局
目前已经被用于在React Native 和 Weex 等开源项目中
但是Yoga只实现了W3C标准的一个子集,所以样式方面,也只有随着Yoga了
其根由还是 yoga FlexBox布局引擎,https://yogalayout.com/
UI组件
| React Native | Android View | iOS View | Web Analog | Description |
|---|---|---|---|---|
<View> |
<ViewGroup> |
<UIView> |
A non-scrollling
|
A container that supports layout with flexbox, style, some touch handling, and accessibility controls |
<Text> |
<TextView> |
<UITextView> |
<p> |
Displays, styles, and nests strings of text and even handles touch events |
<Image> |
<ImageView> |
<UIImageView> |
<img> |
Displays different types of images |
<ScrollView> |
<ScrollView> |
<UIScrollView> |
<div> |
A generic scrolling container that can contain multiple components and views |
<TextInput> |
<EditText> |
<UITextField> |
<input type="text"> |
Allows the user to enter text |
核心组件和API:https://www.reactnative.cn/docs/components-and-apis

UI样式
为了给React-Native组件加上样式,你需要在JavaScript中添加样式表。
<View style={styles.container}>
<Text style={styles.intro}>Hello world!</Text>
</View>
Flexbox构建响应式App的最佳选择——CSS中的表现不太一致,React-Native并不是为web元素而生,不能像web 应用在html里面使用CSS
这里还是体现了Weex优势
React 和宿主平台之间的桥接包含了一个缩减版CSS 子集的实现。这个CSS 子集主要通过flexbox 进行布局,做到了尽量简单化,而不是去实现所有的CSS 规则。
React Native 也坚持使用内联样式,通过JavaScript 对象进行样式组织。React 团队先前也提倡在Web 环境的React 中使用内联样式。
相对于样式表来说,使用样式对象可能需要一些思维上的调整,从而改变你编写样式的方法。然而,在React Native 中,这是一个实用的转变。
当样式复杂时,建议使用StyleSheet.create来集中定义组件的样式。
const styles = StyleSheet.create({
blueText: {
color: 'blue',
fontSize: 30,
}
});
StyleSheet.create可以弥补编写复杂样式时,不能使用css的不便。
宽高单位与布局调整
RN中宽高可以直接通过style指定,与web不同的是,RN中尺寸是无单位的,表示与设备像素无关的逻辑像素点。
在组件样式中使用flex可以使其在可利用的空间中动态地扩张或收缩。flex布局,跟Android LinearLayout layout_weight——值越大,组件获取剩余空间的比例越多,类似。不同的是,LinearLayout可以设置android:weightSum属性,其子元素可以设置android:layout_weight属性,用于等分的效果。与android类似,flex的优先级是高于width的。
推荐阅读《Android XML与HTML5 排布布局分析与对比—style的异同》
动画
React Native 提供了两个互补的动画系统:用于创建精细的交互控制的动画Animated和用于全局的布局动画LayoutAnimation
Animated
Animated旨在以声明的形式来定义动画的输入与输出,在其中建立一个可配置的变化函数,然后使用start/stop方法来控制动画按顺序执行。 Animated仅封装了 6 个可以动画化的组件:View、Text、Image、ScrollView、FlatList和SectionList,不过你也可以使用Animated.createAnimatedComponent()来封装你自己的组件。
import React, { useRef, useEffect } from 'react';
import { Animated, Text, View } from 'react-native';
//在FadeInView的构造函数里,创建了一个名为fadeAnim的Animated.Value,并放在state中
const FadeInView = (props) => {
const fadeAnim = useRef(new Animated.Value(0)).current // 透明度初始值设为0
React.useEffect(() => {
Animated.timing( // 随时间变化而执行动画
fadeAnim, // 动画中的变量值
{
toValue: 1, // 透明度最终变为1,即完全不透明
duration: 10000, // 让动画持续一段时间
}
).start(); // 开始执行动画
}, [fadeAnim])
return (
<Animated.View // 使用专门的可动画化的View组件
style={{
...props.style,
opacity: fadeAnim, // 将透明度绑定到动画变量值
}}
>
{props.children}
</Animated.View>
);
}
// 然后你就可以在组件中像使用`View`那样去使用`FadeInView`了
export default () => {
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<FadeInView style={{width: 250, height: 50, backgroundColor: 'powderblue'}}>
<Text style={{fontSize: 28, textAlign: 'center', margin: 10}}>Fading in</Text>
</FadeInView>
</View>
)
}
这一过程经过特别优化,执行效率会远高于反复调用setState和多次重渲染。
因为这一过程是纯声明式的,因此还有进一步优化的空间,比如我们可以把这些声明的配置序列化后发送到一个高优先级的线程上运行。
配置动画
动画拥有非常灵活的配置项。自定义的或预定义的 easing 函数、延迟、持续时间、衰减系数、弹性常数等都可以在对应类型的动画中进行配置。
Animated.timing(this.state.xPosition, {
toValue: 100,
easing: Easing.back(),
duration: 2000}).start();
https://www.reactnative.cn/docs/animated#配置动画
组合动画
多个动画可以通过parallel(同时执行)、sequence(顺序执行)、stagger和delay来组合使用。它们中的每一个都接受一个要执行的动画数组,并且自动在适当的时候调用start/stop。
Animated.sequence([
// decay, then spring to start and twirl
Animated.decay(position, {
// coast to a stop
velocity: { x: gestureState.vx, y: gestureState.vy }, // velocity from gesture release
deceleration: 0.997
}),
Animated.parallel([
// after decay, in parallel:
Animated.spring(position, {
toValue: { x: 0, y: 0 } // return to start
}),
Animated.timing(twirl, {
// and twirl
toValue: 360
})
])]).start(); // start the sequence group
默认情况下,如果任何一个动画被停止或中断了,组内所有其它的动画也会被停止。Parallel 有一个stopTogether属性,如果设置为false,可以禁用自动停止。
在Animated文档的组合动画一节中列出了所有的组合方法。
合成动画值
const a = new Animated.Value(1);
const b = Animated.divide(1, a); Animated.spring(a, {
toValue: 2
}).start();
可以使用加减乘除以及取余等运算来把两个动画值合成为一个新的动画值。
插值
每个动画属性都可以设置值变化区间
style={{
opacity: this.state.fadeAnim, // Binds directly
transform: [{
translateY: this.state.fadeAnim.interpolate({
inputRange: [-300, -100, 0, 100, 101],
outputRange: [150, 0] // 0 : 150, 0.5 : 75, 1 : 0
}),
}],
}}
interpolate()还支持定义多个区间段落,常用来定义静止区间等。举个例子,要让输入在接近-300 时取相反值,然后在输入接近-100 时到达 0,然后在输入接近 0 时又回到 1,接着一直到输入到 100 的过程中逐步回到 0,最后形成一个始终为 0 的静止区间,对于任何大于 100 的输入都返回 0。
跟踪动态值
动画中所设的值还可以通过跟踪别的值得到。你只要把 toValue 设置成另一个动态值而不是一个普通数字就行了。
Animated.spring(follower, { toValue: leader }).start();Animated.timing(opacity, {
toValue: pan.x.interpolate({
inputRange: [0, 300],
outputRange: [1, 0]
})}).start();
比如在上面的代码片段中,leader和follower可以同时为valueXY类型,这样 x 和 y 的值都会被跟踪。
启用原生动画驱动
通过启用原生驱动,我们在启动动画前就把其所有配置信息都发送到原生端,利用原生代码在 UI 线程执行动画,而不用每一帧都在两端间来回沟通。如此一来,动画一开始就完全脱离了 JS 线程,因此此时即便 JS 线程被卡住,也不会影响到动画了。
Animated.timing(this.state.animatedValue, {
toValue: 1,
duration: 500,
useNativeDriver: true // <-- 加上这一行
}).start();
动画值在不同的驱动方式之间是不能兼容的。因此如果你在某个动画中启用了原生驱动,那么所有和此动画依赖相同动画值的其他动画也必须启用原生驱动。
原生驱动还可以在Animated.event中使用。
<Animated.ScrollView // <-- 使用可动画化的ScrollView组件
scrollEventThrottle={1} // <-- 设为1以确保滚动事件的触发频率足够密集
onScroll={Animated.event(
[
{
nativeEvent: {
contentOffset: { y: this.state.animatedValue }
}
}
],
{ useNativeDriver: true } // <-- 加上这一行
)}>
{content}
</Animated.ScrollView>
其他这里省略了
LayoutAnimation API
LayoutAnimation允许你在全局范围内创建和更新动画,这些动画会在下一次渲染或布局周期运行。它常用来更新 flexbox 布局,因为它可以无需测量或者计算特定属性就能直接产生动画。尤其是当布局变化可能影响到父节点(譬如“查看更多”展开动画既增加父节点的尺寸又会将位于本行之下的所有行向下推动)时,如果不使用LayoutAnimation,可能就需要显式声明组件的坐标,才能使得所有受影响的组件能够同步运行动画。
注意尽管LayoutAnimation非常强大且有用,但它对动画本身的控制没有Animated或者其它动画库那样方便,所以如果你使用LayoutAnimation无法实现一个效果,那可能还是要考虑其他的方案。
另外,如果要在Android上使用 LayoutAnimation,那么目前还需要在UIManager中启用::
// 在执行任何动画代码之前,比如在入口文件App.js中执行
UIManager.setLayoutAnimationEnabledExperimental &&
UIManager.setLayoutAnimationEnabledExperimental(true);
在需要的地方
import React from 'react';
import {
NativeModules,
LayoutAnimation,
Text,
TouchableOpacity,
StyleSheet,
View,
} from 'react-native'; const { UIManager } = NativeModules; UIManager.setLayoutAnimationEnabledExperimental &&
UIManager.setLayoutAnimationEnabledExperimental(true); export default class App extends React.Component {
state = {
w: 100,
h: 100,
}; _onPress = () => {
// Animate the update
LayoutAnimation.spring();
this.setState({w: this.state.w + 15, h: this.state.h + 15})
} render() {
return (
<View style={styles.container}>
<View style={[styles.box, {width: this.state.w, height: this.state.h}]} />
<TouchableOpacity onPress={this._onPress}>
<View style={styles.button}>
<Text style={styles.buttonText}>Press me!</Text>
</View>
</TouchableOpacity>
</View>
);
}
} const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
box: {
width: 200,
height: 200,
backgroundColor: 'red',
},
button: {
backgroundColor: 'black',
paddingHorizontal: 20,
paddingVertical: 15,
marginTop: 15,
},
buttonText: {
color: '#fff',
fontWeight: 'bold',
},
});
https://github.com/facebook/react-native/blob/master/Libraries/LayoutAnimation/LayoutAnimation.js
转载本站文章《React Native UI界面还原,组件布局与动画效果》,
请注明出处:https://www.zhoulujun.cn/html/webfront/AppDev/ReactNative/8482.html
React Native UI界面还原,组件布局与动画效果的更多相关文章
- React Native填坑之旅--布局篇
代码在这里: https://github.com/future-challenger/petshop/tree/master/client/petshop/src/controller 回头看看RN ...
- React Native 学习(三)之 FlexBox 布局
React Native 学习(三)之 FlexBox 布局
- [RN] React Native 使用 FlatList 实现九宫格布局 GridList
React Native 使用 FlatList 实现九宫格布局 先看图片演示实例: 本文以图片列表为例,实现九宫格布局! 主要有两种方法: 1)方法一: 利用FlatList的 numColumns ...
- React Native 项目常用第三方组件汇总
React Native 项目常用第三方组件汇总 https://www.jianshu.com/p/d9cd9a868764?utm_campaign=maleskine&utm_conte ...
- React Native 学习笔记--进阶(二)--动画
React Native 进阶(二)–动画 动画 流畅.有意义的动画对于移动应用用户体验来说是非常必要的.我们可以联合使用两个互补的系统:用于全局的布局动画LayoutAnimation,和用于创建更 ...
- React Native入门教程 3 -- Flex布局
上一篇文章中介绍了基本组件的使用 React Native入门教程(笔记) 2 – 基本组件使用及样式 本节内容将继续沿用facebook官方例子介绍如何使用Flexbox布局把界面设计的多样化. 转 ...
- React Native 开发之 (05) flexbox布局
一 flexbox布局 1 flex布局 flexbox是ReactNative 应用开发中必不可少的内容,也是最常用的内容. 传统的页面布局是基于盒子模型,依赖定位属性,流动属性和显示属性来解决. ...
- React Native(一) FlexBox布局
欢迎转载,转载请标明出处: http://blog.csdn.net/johnny901114/article/details/53241550 本文出自:[余志强的博客] 在React Native ...
- React Native知识5-Touchable类组件
React Native 没有像web那样可以给元素绑定click事件,前面我们已经知道Text组件有onPress事件,为了给其他组件 也绑定点击事件,React Native提供了3个组件来做这件 ...
- React Native超棒的LayoutAnimation(布局动画)
该文翻译自:https://medium.com/@Jpoliachik/react-native-s-layoutanimation-is-awesome-4a4d317afd3e#.6 ...
随机推荐
- Java线程安全详解
并发与多线程 blog:https://devonmusa.github.io 1 常见概念 1.1 操作系统线程运行状态 NEW RUNNABLE RUNNING BLOCKED 1.2 Java虚 ...
- C# WebBrowser document.execCommand()解析
// // Summary: // 对文档执行指定的命令. // // Parameters: ...
- Linux运维技能图谱
前言 该技能图谱依个人经验绘制,不适用于所有运维岗位.对于刚入行的从业者,也不需要按照图谱全学一遍,应该根据岗位工作内容来学习.有些技术我也不会,但作为一个选项我也写进去了,比如容器运行时有Docke ...
- c#享元模式详解
基本介绍: 享元模式的定义:运用共享技术有效地支持大量细粒度的对象重复使用.适用于大量小粒度的对象造成的运行效率和内存使用效率低下的情况. "享元"顾名思义,"享 ...
- 在vue中如何使用echart
1.在前面基础上搭建好vue环境,初始化webpack后,在终端使用npm i echarts -s 下载echart 2.下载完成后全局使用echart 在main.js文件中导入 import e ...
- 将强化学习引入NLP:原理、技术和代码实现
本文深入探讨了强化学习在自然语言处理(NLP)中的应用,涵盖了强化学习的基础概念.与NLP的结合方式.技术细节以及实际的应用案例.通过详细的解释和Python.PyTorch的实现代码,读者将了解如何 ...
- 神经网络入门篇之深层神经网络:详解前向传播和反向传播(Forward and backward propagation)
深层神经网络(Deep L-layer neural network) 复习下前面的内容: 1.逻辑回归,结构如下图左边.一个隐藏层的神经网络,结构下图右边: 注意,神经网络的层数是这么定义的:从左到 ...
- going 小闫 | 学习就像典韦哥:彻底疯狂
看了相关的Hadoop的视频,介绍部分. 刷单词 看了coco电影
- HarmonyOS第一课_构建更加丰富的页面
管理组件状态 概述 组件内的状态管理:@State 从父组件单向同步状态:@Prop 与父组件双向同步状态:@Link 跨组件层级双向同步状态:@Provide 和@Consume 概述 在应用中,界 ...
- Head First Java学习:第九章-构造器和垃圾收集器
对象的前世今生 对象如何创建.存在何处以及如何让保存和抛弃更有效率. 会述及堆.栈.范围.构造器.超级构造器.空引用等. 1.内存的两个区域:堆和栈 堆(heap):对象的生存空间,又称为可垃圾回收的 ...