【问题标题】:Image flickers on first load in ReactNative在 React Native 中首次加载时图像闪烁
【发布时间】:2018-11-03 10:32:34
【问题描述】:

我正在尝试使用动画按钮构建 ReactNative 应用程序。问题是这个动画在App启动后第一次不能正常工作。有一些白色的闪烁。但是在动画第一次运行出错后,一切都按预期工作:

我已经尝试过几种方式来预加载图片,但都没有成功。

这是我的最小工作示例,请注意,如果有多个不同的图像,则在加载新图像时会发生闪烁(例如,我有两个蓝色按钮,在我点击第一个按钮后,第二个按钮可以正常工作,但是如果我然后点击一个橙色按钮,它第一次再次闪烁,至少如果我在应用程序启动后没有点击另一个橙色按钮。):

import React, { Component } from 'react';
import {StyleSheet, Text, TouchableWithoutFeedback, View, Image, ScrollView, 
Button, BackHandler} from 'react-native';

export default class Touchables extends Component {
  constructor(props) {
    super(props);
    this.state = {alarm1: (<Image source={require("./assets/alarmoff.png")} 
  style={styles.imageButton}/>),

    }
  }

  componentWillMount(){
  //trying to preload all Images, but it does not help.
    (<Image source={require("./assets/alarmon.png")} style= 
      {styles.imageButton}/>)
  }

  render() {
    return (
      <ScrollView style={styles.contentContainer}>

     <View style={{flex: 3, flexDirection: 'row'}}>
        <View style={styles.container}>
          <TouchableWithoutFeedback onPressIn={() => this.setState({alarm1: 
             <Image source={require("./assets/alarmon.png")} style={styles.imageButton}/>})} onPressOut={() => this.setState({alarm1:  <Image source={require("./assets/alarmoff.png")} style={styles.imageButton}/>})}>
            <View style={styles.button}>
              {this.state.alarm1}
            </View>
          </TouchableWithoutFeedback>
          <Text style={styles.text}>This button flickers on first click. Restart App completly to see the issue. Reloading is not enough.</Text>
        </View>
       </View>
       <View>
        <Button
         onPress={() => BackHandler.exitApp()}
         title="Exit App"
         color="#841584"
         accessibilityLabel="Android only I guess."
        />
       </View>

     </ScrollView>
   );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 2,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
    marginBottom: 30
 },
 button: {
    backgroundColor: '#fff',
    borderRadius: 20,
    padding: 10,
    marginBottom: 20,
    shadowColor: '#303838',
    shadowOffset: { width: 0, height: 5 },
    shadowRadius: 10,
    shadowOpacity: 0
  },
  contentContainer: {
    paddingVertical: 20,
    flex: 1,
    backgroundColor: '#fff',
  },
 text:{
    color: '#000',
    marginBottom: 30
 },
 imageButton: {
   flex: 1,
   width: 240,
   height: 200,
   marginBottom: -15,
   marginTop: 10,
   resizeMode: 'cover'
 }
});

所以我的问题是如何在应用启动后阻止图像闪烁?

我为显示我的问题而构建的小演示应用程序的完整版可在我的Github Repository上找到

【问题讨论】:

    标签: android ios react-native


    【解决方案1】:

    加载不同分辨率的图像时可能会出现性能问题。您可以使用https://github.com/DylanVann/react-native-fast-image 模块来加载图片。

    您可以如下添加和链接它

    # Install
    yarn add react-native-fast-image
    
    # Automatic linking. (other linking methods listed below)
    react-native link react-native-fast-image
    

    之后你可以像下面的例子一样导入并使用它

    import FastImage from 'react-native-fast-image'
    
        const YourImage = () =>
          <FastImage
            style={styles.image}
            source={{
              uri: 'https://unsplash.it/400/400?image=1',
              headers:{ Authorization: 'someAuthToken' },
              priority: FastImage.priority.normal,
            }}
            resizeMode={FastImage.resizeMode.contain}
          />
    

    我从那个 repo 中复制了这个例子。你也可以在那里找到文档。尝试一下。它将提高图像加载性能。然后很可能会解决闪烁问题。

    【讨论】:

    • 感谢您的提示。问题是我似乎无法在这个模块中使用本地图像,这对我来说非常重要。
    • @frankenapps 据我所知,本地图像也需要相关设备的相关分辨率。否则,图像将被转换为相关类型并显示。也许它会导致你的问题。
    【解决方案2】:

    对我来说,当我将 Image 组件放入 FlatList ListHeaderComponent 组件时,它会导致闪烁问题。所以,

    • 导致闪烁的代码:

      ListHeaderComponent={HeadComponent}

    HeadComponent 基本上在render 内部,代码为const HeadComponent = () =&gt; { return (&lt;Image...

    • 修复闪烁的代码:

      ListHeaderComponent={this.renderHeader}

    renderHeader 是一个函数,它使用代码 renderHeader () { return (&lt;Image... 返回与 HeadComponent 相同的内容

    希望这对某人有所帮助。

    【讨论】:

      【解决方案3】:

      嗯,我有一个解决方法(有点..)。 在我的componentDidMount() 中,我现在将按钮设置为按下状态,等待一段时间直到图像显示并缩放,然后我再次将状态设置为关闭,如下所示:

      componentDidMount(){
         this.setState({alarm1: <Image source={require("./assets/alarmon.png")} style={styles.imageButton}/>})
         setTimeout(()=>{this.setState({alarm1: <Image source={require("./assets/alarmoff.png")} style={styles.imageButton}/>})}, 1000); 
      }
      

      我尝试将超时时间降低到不到一秒,但在我的旧(且速度较慢)手机上,应用加载后第一次按下时又开始闪烁。

      这显然会导致应用加载后按钮状态发生变化,但如果在应用启动后所有按钮都闪烁一次,我认为这比第一次按下时每个按钮都闪烁要好。

      如果有人能告诉我真正的方法,如何解决这个问题,我会很高兴。

      【讨论】:

        【解决方案4】:

        当我将 Image 组件放入 FlatList ListHeaderComponent 组件时,会导致闪烁问题

        为了解决这个问题,我添加了 useCallBack 钩子

        const ListComponent = useCallBack(() => {
        // your code
        }, [])
        
        ListHeaderComponent={ListComponent}
        

        对我来说,它解决了闪烁的问题

        【讨论】:

          【解决方案5】:

          如果您使用 expo,则可以使用Asset.loadAsync。见:https://docs.expo.io/versions/latest/sdk/asset

          App.js 中,我喜欢在显示任何屏幕之前等待所有静态资源加载完毕。

          【讨论】:

            猜你喜欢
            • 2020-06-22
            • 2018-09-26
            • 2018-12-14
            • 1970-01-01
            • 2019-11-28
            • 1970-01-01
            • 2016-03-17
            • 2011-12-23
            • 1970-01-01
            相关资源
            最近更新 更多