React Native - View组件

View组件

View组件React Native最基本的组件。View是一个支持Flexbox布局、样式、一些触摸处理、和一些无障碍功能的容器,并且它可以放到其它的视图里,也可以有任意多个任意类型的子视图。不论在什么平台上,View 都会直接对应一个平台的原生视图,无论它是 UIViewdiv还是 android.view.View

1、View组件的颜色与边框

borderStyle的取值为enum('solid', 'dotted', 'dashed'),用来设置边框的风格,三个值分别对应着实线边框、点状边框和虚线边框,默认值为solid。除了可以设置边框的风格,还可以用定义边框的颜色和边框的圆角。

边框的颜色设置有

borderColor
borderTopColor 
borderRightColor 
borderBottomColor 
borderLeftColor

取值都为string,通常情况下用borderColor

边框的圆角设置有

borderRadius 
borderTopLeftRadius 
borderTopRightRadius 
borderBottomLeftRadius 
borderBottomRightRadius

取值为number

显示圆角

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

export default class ViewComponent extends Component {
    // 设置多个view的显示样式
    render() {
        return (
            // opacity组件透明度,取值0-1,当值为0,表示组件透明,值为1完全不透明
            
                 
                
                
                
                
                
            
        );
    }
}

// 定义显示样式
var styles = StyleSheet.create({
    container: {
        flex: 1, // flex布局
        justifyContent: 'space-around',
        alignItems: "center", // 据中显示
        backgroundColor: 'grey', // 灰色
    },
    welcome: {
        width: 50, // 组件宽
        height: 50, // 组件高
        borderWidth: 1, // 边框
        backgroundColor: 'white', // 指定背景颜色,如果没有指定,默认的背景颜色会浅
        borderRadius: 25, // 边框圆角大小
        borderStyle: "solid", // 边框风格,默认为solid(实线边框),还有dotted(点状边框) 、dashed(虚线边框)
    },
});

上面代码渲染了多个View组件,并设置了圆角和透明度

实现效果

React Native - View组件_第1张图片
4010043-40687add86b39607.png

2、View组件阴影和其他效果

下面是阴影相关的样式键

export interface ShadowStyleIOS {
    shadowColor?: string; // 阴影颜色
    shadowOffset?: { width: number; height: number }; // 阴影位移
    shadowOpacity?: number; //阴影透明度
    shadowRadius?: number; // 阴影圆角
}

设置View组件的阴影属性并没有什么意义,在View组件中定义这些样式是为了让继承它的组件去各自实现这些效果,比如:Text组件需要注意的是只有iOS平台能使用shadow属性

  • elevation (Android)

elevation取值为numberAndroid平台没有shadow来设置阴影,但是,可以用elevation属性来间接的设置阴影`,这样就会在界面上呈现出阴影的效果,此属性仅支持Android 5.0及以上版本。

import React, {Component} from 'react';
import {AppRegistry, StyleSheet, View} from 'react-native';
class ViewApp extends Component {
    render() {
        return (
             
                   
             
        );
    }
}

var styles = StyleSheet.create({
    shadow: {
        height: 120,
        width: 120,
        backgroundColor: 'black',
        elevation: 20,
        shadowOffset: {width: 0, height: 0},
        shadowColor: 'black',
        shadowOpacity: 1,
        shadowRadius: 5
    }
});

AppRegistry.registerComponent('ViewSample', () => ViewApp);

在iOS平台运行如上代码,效果为:

React Native - View组件_第2张图片
屏幕快照 2019-11-25 下午2.53.00.png

在Android平台运行效果则为:

React Native - View组件_第3张图片
屏幕快照 2019-11-25 下午2.53.04.png

很明显,elevation的效果远远不及shadow,这时我们可以采用第三方库react-native-shadow。

  • overflow属性

定义当View组件中的子组件宽高超出View组件宽高时的行为。默认是hidden隐藏,也可以设置visible显示出来

3、View组件的变形

React Native开发中,使用transform样式键设置组件的变形,从而实现文字或图像的变形

translate:移动
scale:缩放
ratate:旋转
skew:倾斜

样式属性如下

export interface TransformsStyle {
    transform?: (
        | PerpectiveTransform // 3D变换
        | RotateTransform
        | RotateXTransform
        | RotateYTransform
        | RotateZTransform
        | ScaleTransform
        | ScaleXTransform
        | ScaleYTransform
        | TranslateXTransform
        | TranslateYTransform
        | SkewXTransform
        | SkewYTransform)[];
    transformMatrix?: Array;
    rotation?: number;
    scaleX?: number;
    scaleY?: number;
    translateX?: number;
    translateY?: number;
}

简单使用View的变形效果

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

export default class ViewTransform extends Component {
    render() {
        return (
            
                
                    Welcome to React native!
                
 
                
                    Welcome to React native!
                
 
                
                    Welcome to React native!
                
 
                
                    Welcome to React native!
                
 
                
                    Welcome to React native!
                
 
                
                    Welcome to React native!
                
 
                
                    Welcome to React native!
                
 
                
                    Welcome to React native!
                
 
                
                    Welcome to React native!
                
 
                
                    Welcome to React native!
                
 
                
                    Welcome to React native!
                
            
      );
    }
 }
 
// 定义变形样式
 var transformStyles = StyleSheet.create({
     container: {
         flex: 1,
         justifyContent: "center", // 主轴排列方向
         alignItems: "center", // 次轴排列方向
         backgroundColor: '#f5fcff',
     },
     welcome0: {
         flex: 1,
         justifyContent: "center",
         alignItems: "center",
         transform: [{rotate: '45deg'}], // 角度用xdeg来表示,这里x的取值为45,可以使用0-360任意角度
     },
     welcome1: {
         flex: 1,
         justifyContent: "center",
         alignItems: "center",
         transform: [{rotateX: '45deg'}],
     },
     welcome2: {
         flex: 1,
         justifyContent: "center",
         alignItems: "center",
         transform: [{rotateY: '45deg'}],
     },
     welcome3: {
         flex: 1,
         justifyContent: "center",
         alignItems: "center",
         transform: [{rotateZ: '45deg'}],
     },
     welcome4: {
         flex: 1,
         justifyContent: "center",
         alignItems: "center",
         transform: [{scale: 2}],
     },
     welcome5: {
         flex: 1,
         justifyContent: "center",
         alignItems: "center",
         transform: [{scaleX: 2}],
     },
     welcome6: {
         flex: 1,
         justifyContent: "center",
         alignItems: "center",
         transform: [{scaleY: 2}],
     },
     welcome7: {
         flex: 1,
         justifyContent: "center",
         alignItems: "center",
         transform: [{translateX: 200}],
     },
     welcome8: {
         flex: 1,
         justifyContent: "center",
         alignItems: "center",
         transform: [{translateY: 150}],
     },
     welcome9: {
         flex: 1,
         justifyContent: "center",
         alignItems: "center",
         transform: [{skewX: '45deg'}],
     },
     welcome10: {
         flex: 1,
         justifyContent: "center",
         alignItems: "center",
         transform: [{skewY: '45deg'}],
     },
 });

实现效果如下

React Native - View组件_第4张图片
4010043-0b0f8e3549515c88.png

4、合成触摸事件

用于 View 响应属性 (例如, onResponderMove), 合成触摸事件采用以下的格式:

nativeEvent

  • changedTouches - 从上一次事件以来的触摸事件数组。
    -identifier - 触摸事件的 ID。
  • locationX - 触摸事件相对元素位置的 X 坐标。
  • locationY - 触摸事件相对元素位置的 Y 坐标。
  • pageX - 触摸事件相对根元素位置的 X 坐标。
  • pageY - 触摸事件相对根元素位置的 Y 坐标。
  • target - 接收触摸事件的元素 ID.
  • timestamp - 触摸事件的时间标记,用来计算速度.
  • touches - 屏幕上所有当前触摸事件的数组.

5、View组件的回调函数

假设A组件有一个属性,名称为onB(表示B事件发生了),它要求开发者提供的onB的值必须是一个函数的引用,当B事件发生时,RN框架通过onB的值来回调这个函数。

  • onMoveShouldSetResponder

这个视图想要“认领”这个touch move事件吗?每当有touch move事件在这个视图中发生,并且这个视图没有被设置为这个touch move的响应时,这个函数就会被调用。

View.props.onMoveShouldSetResponder: (event) => [true | false]

其中event是一个合成触摸事件。

  • onMoveShouldSetResponderCapture

如果父视图想要阻止子视图响应touch move事件时,它就应该设置这个方法并返回true

View.props.onMoveShouldSetResponderCapture: (event) => [true | false]

其中event是一个合成触摸事件。

  • onResponderGrant

这个视图开始响应触摸事件。此时需要高亮告诉用户正在响应。(对于大部分的触摸处理,你只需要用TouchableHighlightTouchableOpacity包装你的组件。)

  • onResponderMove

当用户正在屏幕上移动手指时调用这个函数。

View.props.onResponderMove: (event) => {},

其中event是一个合成触摸事件。

  • onResponderReject

有一个响应器正处于活跃状态,并且不会向另一个要求响应这个事件的视图释放这个事件。

View.props.onResponderReject: (event) => {}

其中 event 是一个合成触摸事件。

  • onResponderRelease

在整个触摸事件结束时调用这个函数。

View.props.onResponderRelease: (event) => {}

其中event是一个合成触摸事件。

  • onResponderTerminate

响应被从这个视图上“劫走”了。可能是在调用了 onResponderTerminationRequest之后,被另一个视图“劫走”了(见 onresponderterminationrequest), 也可能是由于 OS 无条件终止了响应(比如说被 iOS 上的控制中心/消息中心)

View.props.onResponderTerminate: (event) => {}

其中event是一个合成触摸事件

  • onResponderTerminationRequest

其他某个视图想要成为事件的响应者,并要求这个视图放弃对事件的响应时,就会调用这个函数。如果允许释放响应,就返回true。

View.props.onResponderTerminationRequest: (event) => {}

其中event是一个合成触摸事件。

  • onStartShouldSetResponderCapture

如果父视图想要阻止子视图响应touch start 事件,它就应该设置这个方法并返回 true。

View.props.onStartShouldSetResponderCapture: (event) => [true | false]

其中event是一个合成触摸事件。

  • onStartShouldSetResponder

设置这个视图是否要响应touch start事件。

View.props.onStartShouldSetResponder: (event) => [true | false]

其中event是一个合成触摸事件。

6、屏幕设置状态与Layout函数

RN开发中,通过指定根View组件Layout回调函数可以很方便的得到初始设备状态,检测设备放置状态并得到改变后新的屏幕宽度和高度

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

export default class ScreenChanged extends Component {

    render() {
        return (
            
                
                    Welcome to React Native!
                
            
        );
    }

    _onLayout(event) {
        // 解构赋值
        let {x,y,width,height} =  event.nativeEvent.layout;
        // 打印坐标
        console.log('width from View onLayout: ' + width);
        console.log('height from View onLayout' + height);
        console.log('x from View onLayout' + x);
        console.log('y from View onLayout' + y);
    }

    _onLayoutText(event) {
         // 解构赋值
         let {x,y,width,height} =  event.nativeEvent.layout;
         // 打印坐标
         console.log('width from Text onLayout: ' + width);
         console.log('height from Text onLayout' + height);
         console.log('x from Text onLayout' + x);
         console.log('y from Text onLayout' + y);
    }
}

var styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: "center",
        alignItems: "center",
        backgroundColor: "#f5fcff",
    },
    welcome: {
        fontSize: 20,
        textAlign: "center",
        margin: 10,
    },
});

7、pointerEvents属性

在开发中,很多组件被布局到屏幕上,其中有一些组件使用决定定位布局,在代码运行时的某个时刻有可能会遮盖它的位置下方的组件部分或全部。在React Native框架中,触摸事件总是被传送给最上层的组件。对于某些情况,被遮盖的组件需要处理触摸事件,这时就需要使用组件的pointerEvents属性解决

pointerEvents属性是字符串类型,可以取值为none、box-none、box-only、auto。

  • 当取值none时,发生在本组件与子组件上的触摸事件交给本组件的父组件处理
  • 当取值box-none,发生在本组件显示范围内(但非本组件的子组件的显示范围)的触摸事件交由本组件的父组件处理,发生在本组件的子组件显示范围内触摸事件交由子组件处理
  • 当取值box-only,发生在本组件显示范围内的触摸事件交由本组件处理(即使触摸事件发生在子组件显示范围)
  • 当取值auto,视组件的不同而不同

简单使用

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

export default class ScreenChanged extends Component {
     // 构造函数
    constructor(props) {
        super(props);
        this.state = {bigButtonPointerEvents: null};
        this.onBigButtonPressed = this.onBigButtonPressed.bind(this);
        this.onSmallButtonPressed = this.onSmallButtonPressed.bind(this);
    }

    // 按钮点击触发函数
    onBigButtonPressed() {
        console.log('big button pressed');
    }

    onSmallButtonPressed() {
        if (this.state.bigButtonPointerEvents == null){
            console.log('big button will not responde');
            this.setState({bigButtonPointerEvents: 'none'});
            return;
        }
        console.log('big button willresponde');
        this.setState({bigButtonPointerEvents: null}); // 改变状态机变量值
    }

    render() {
        return (
            
                
                    small button
                

                
                    big button
                
            
        );
    }
}

var styles = StyleSheet.create({
    container: {
        flex: 1,
    },
    bigButtonStyle: { // 大按钮显示样式
        fontSize: 20,
        left: 130,
        top: 130,
        width: 150,
        height: 70,
        backgroundColor: 'grey',
    },
    smallButtonStyle: { // 小按钮显示样式
        fontSize: 20,
        left: 130,
        top: 50,
        width: 150,
        height: 35,
        backgroundColor: 'red',
    },
});

效果如下

React Native - View组件_第5张图片
4010043-ba8b00a97215aa2f.png

最开始,屏幕上的big button可以正常工作,点击后打印输出,当点击small button之后big button点击无效,当再次点击small button之后big button点击才有效

9、removeClippedSubviews

removeClippedSubviews的取值为bool。它的一个特殊的与性能优化相关的属性,通常在ListViewScrollView中使用,当组件有很多子组件不在屏幕显示范围时,可以将removeClippedSubviews设置为true,允许释放不在显示范围子组件,从而优化了性能。需要注意的是,要想让此属性生效,要确保overflow属性为默认的hidden

10、动画相关

  • needsOffscreenAlphaCompositing (Android)

needsOffscreenAlphaCompositing的取值为bool,是Android平台独有的属性。它用来决定视图是否要先离屏渲染再进行半透明度处理,来确保颜色和混合效果正确。为了正确的显示透明表现而进行离屏渲染会带来极大的开销,对于非原生开发者来说很难调试,因此,它的默认值为false。

  • renderToHardwareTextureAndroid (Android)

renderToHardwareTextureAndroid的取值为bool,同样是是Android平台独有的属性。它用来决定视图是否要把它本身(以及所有的子视图)渲染到一个GPU上的硬件纹理中。

在Android平台上,这对于只修改透明度、旋转、位移和缩放的动画和交互是很有用的:视图不必每次都重新绘制,显示列表也不需要重新执行,纹理可以被重用于不同的参数。负面作用是这会大量消耗显存,所以当交互/动画结束后应该把此属性设置回false。

  • shouldRasterizeIOS (iOS)

shouldRasterizeIOS的取值为bool,是iOS平台独有的属性。它决定视图是否需要在被混合之前绘制到一个位图上。

这对于动画和交互来说是有很有用的,它不会修改这个组件的尺寸和它的子组件。举例来说,当我们移动一个静态视图的位置的时候,栅格化允许渲染器重用静态视图的缓存位图,并快速合成。

栅格化会导致离屏的绘图传递,位图会消耗内存。所以使用此属性需要进行充分的测试和评估。

还有一些View属性这里没有给出,比如RN为了方便失能人士使用手机而提供的相关属性等等,具体的属性请查看官方文档。

参考

View组件

你可能感兴趣的:(React Native - View组件)