ReactNative 活动指示器在动画属性启动 false 时不显示

ReactNative ActivityIndicator not showing when animating property initiate false

本文关键字:false 显示 启动 属性 活动 指示器 动画 ReactNative      更新时间:2023-09-26

我正在玩 react native,但行为很奇怪。

当我尝试显示适用于 Android 的 ActitvityIndicator,将其动画属性设置为 showProgress true 时,如果该变量以 false 启动,则无法正常工作。

在下面的示例中,如果活动指示器动画属性以 true 开头,则按钮会使活动指示器隐藏或正确显示。

import React, { Component } from 'react';
import {
  Text,
  View,
  StyleSheet,
  TextInput,
  TouchableHighlight,
  ActivityIndicator
} from 'react-native';
export class Login extends Component {
    constructor(props) {
        super(props);
        this.state = {
            showProgress: true
        };
    }
    render() {
        return (
            <View>
                <TouchableHighlight onPress={this.progressOff.bind(this)}>
                    <Text>progressOff</Text>
                </TouchableHighlight>
                <TouchableHighlight onPress={this.progressOn.bind(this)}>
                    <Text>progressOn</Text>
                </TouchableHighlight>
                <ActivityIndicator animating={this.state.showProgress} size="large"/>
            </View>
        );
    }
    progressOff() {
        this.setState({showProgress: false}); 
    }
    progressOn() {
        this.setState({showProgress: true});
    }
}

但是,如果我使用以下代码,动画属性以 false 开头,则使活动指示器显示的按钮不起作用:

import React, { Component } from 'react';
import {
  Text,
  View,
  StyleSheet,
  TextInput,
  TouchableHighlight,
  ActivityIndicator
} from 'react-native';
export class Login extends Component {
    constructor(props) {
        super(props);
        this.state = {
            showProgress: false
        };
    }
    render() {
        return (
            <View>
                <TouchableHighlight onPress={this.progressOff.bind(this)}>
                    <Text>progressOff</Text>
                </TouchableHighlight>
                <TouchableHighlight onPress={this.progressOn.bind(this)}>
                    <Text>progressOn</Text>
                </TouchableHighlight>
                <ActivityIndicator animating={this.state.showProgress} size="large"/>
            </View>
        );
    }
    progressOff() {
        this.setState({showProgress: false}); 
    }
    progressOn() {
        this.setState({showProgress: true});
    }
}

我在这里错过了什么?

这似乎是 React Native 中的一个错误。初始状态为showProgress: false的代码适用于 iOS,但不适用于 Android。

如果您想跟踪进度,我已经在 github 上打开了一个问题:https://github.com/facebook/react-native/issues/9023

选项 1

我使用的一种解决方法是使用 showProgress 变量来呈现具有 ActivityIndicator 的完全不同的视图:

render() {
    if (this.state.showProgress) {
        return this.renderLoadingView();
    } else {
        return this.renderMainView();
    }
}

选项 2

您还可以根据状态设置ActivityIndicator的不透明度:

render() {
    return (
        <View>
            <TouchableHighlight onPress={this.progressOff.bind(this)}>
                <Text>progressOff</Text>
            </TouchableHighlight>
            <TouchableHighlight onPress={this.progressOn.bind(this)}>
                <Text>progressOn</Text>
            </TouchableHighlight>
            <ActivityIndicator style={{opacity: this.state.showProgress ? 1.0 : 0.0}} animating={true} size="large"/>
        </View>
    );
}

但是,使用此方法时,微调器动画并不总是从同一位置开始。

这是组件活动指示器的 React-Native 的一个错误。我不确定fb已经解决了它,但你可以试试这个

 constructor(props) {
        super(props);
        this.state = {
            opacity: 0
        };
    }
要显示它,请使用this.setState({opacity:

1}(,并在调用的函数中再次隐藏this.setState({opacity:0}(

并在您使用活动指示器的渲染中

 <ActivityIndicator
    animating={true}
    color="#ffffff"
    style={{height: 80, marginTop: 10, opacity: this.state.opacity }}
    size="large"/>

如果你的项目中你可以使用第三方组件,我建议使用反应原生加载微调器覆盖

轻松解决了我们的问题,因为该组件使用类似的方式显示或隐藏具有属性 visible 的活动。

我发现无需太多代码即可有效解决此问题的另一种方法是:

{ this.state.showProgress &&
  <ActivityIndicator animating={true} size="large"/>
}

我尝试了一种不同的方法,我认为这是一种解决问题的更"反应方式"。因此,opacity解决方案的问题在于,如果您只是将其设置为 0,它仍然是一个动画,因此它不是应用性能中考虑的最佳解决方案。

创建了一个单独的组件,我称之为<Loading/>,这是代码:

import { ActivityIndicator } from "react-native"
import React from "react"
import PropTypes from "prop-types"
const Loading = (props) =>
    props.animating
        ? <ActivityIndicator style={props.style} 
               importantForAccessibility='auto' size={props.size} 
                     color={props.size} /> : null
Loading.propTypes = {
    animating: PropTypes.bool.isRequired,
    style: PropTypes.oneOfType([PropTypes.style, PropTypes.object]),
}
export default Loading

用法:

<Loading animating={true} importantForAccessibility='auto' size="large" color="#A02BFF" style={styles.loading} />

这样,它将避免在不需要时创建动画,您将创建单独的组件,将来可以通过将其替换为原始的活动指示器本机组件来解决活动指示器问题时轻松删除该组件。

我遇到的唯一问题是,由于屏幕上的背景,它在Android中是不可见的。我只将颜色道具更改为我知道应该在背景中脱颖而出的内容来修复:

<ActivityIndicator color={theme.secondary.color} />

我得到这个问题都是一个错误。 我没有把ActivityIndeicator放在视图的中心。 所以它位于视图的顶部,该视图被一个 natigation bar 覆盖。 下面的代码是正确的。 希望这可以帮助您。

<View style={{alignItems: 'center', justifyContent: 'center', flex: 1, backgroundColor: 'white'}}>
  <ActivityIndicator
    animating={true}
    style={
      {
        alignItems: 'center',
        justifyContent: 'center',
        opacity: this.state.loading ? 1 : 0
      }}
    size="large"
  />
</View>

快速修复 使用条件渲染。保持动画:{true},只有可见和不可见视图。

收款处:

https://kylewbanks.com/blog/how-to-conditionally-render-a-component-in-react-native

就我而言,对于 react 本机版本 0.59.10 ,Android 和 iOS 的大小属性类型不同,因此我必须进行如下平台检查,它起作用了。

<ActivityIndicator 
                size={Platform.OS === "ios" ? 0 : "large"} //This platform check worked.
                color={props.color} 
                animating={props.animating}
                style={props.style}
                />
animating

falsetrue的转换在Android上太慢了。但是您可以使用 key 道具强制重新渲染:

<ActivityIndicator
  key={`${props.animating}`}
  animating={props.animating}
/>

props.animatingfalse更改为true时,它们的键也会发生变化。这会强制重新渲染,这意味着使用 animating = true 渲染新组件,这将立即启动微调器。

如果你在Android上测试它,原因之一可能是颜色属性。

请务必为活动指示器指定颜色。例如:

<ActivityIndicator size="large" color="#0000ff" />

这个解决方案非常适合我在安卓中。

希望这对您有所帮助。

import {ActivityIndicator} from 'react-native';
const [opacity, setOpacity] = useState(0)
const onLoadStart = () => {
   setOpacity(1);
};
const onLoad = () => {
   setOpacity(0);
};
const onBuffer = ({isBuffering}) => {
   setOpacity(isBuffering ? 1 : 0);
};
return(
<View>
  <Video
    video={{uri: props.videoSource}}
    autoplay={false}
    customStyles={{
      seekBarProgress: {
        backgroundColor: theme.color.primary,
      },
      seekBarKnob: {
        backgroundColor: theme.color.primary,
      },
    }}
    ref={ref => (player = ref)}
    onBuffer={onBuffer}
    onLoadStart={onLoadStart}
    onLoad={onLoad}
  />
  <ActivityIndicator
    animating
    size="large"
    color={color.primarylight}
    style={{
      opacity: opacity,
      position: 'absolute',
      top: 70,
      left: 70,
      right: 70,
      // height: 50,
    }}
  />
</View>

(