ReactNative中首次加载时图像闪烁

8

我正在尝试构建一个带有动画按钮的ReactNative应用程序。问题是在启动应用程序后第一次运行此动画时,它不会正确工作,会出现一些白色闪烁。但在第一次动画出错后,一切都如预期般工作:

Animation of the problem.

我已经尝试过多种预加载图片的方法,但都没有成功。
这是我的最小工作示例,请注意,如果有几个不同的图片,则在加载新图片时会出现闪烁(例如,我有两个蓝色按钮,如果我点击第一个按钮,第二个按钮将正常工作,但如果我然后点击一个橙色按钮,它就会再次闪烁,至少在应用程序启动后没有点击另一个橙色按钮的情况下)。
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存储库上找到。

https://github.com/facebook/react-native/issues/6971 - Scaraux
7个回答

3

在加载不同分辨率的图片时,可能会出现性能问题。你可以使用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
据我所知,本地图像也需要与相关设备相应的分辨率。否则,图像将被转换为相关类型并显示。这可能导致您的问题。 - PushpikaWan
react-native-fast-image 仓库看起来已经停止维护,请谨慎选择此路径 https://github.com/DylanVann/react-native-fast-image/issues/685 - cengaver

2
最初的回答:对我来说,在FlatList ListHeaderComponent组件中放置Image组件会导致闪烁问题。所以,

  • 引起闪烁的代码:

    ListHeaderComponent={HeadComponent}

HeadComponent基本上是在render内部,并具有以下代码:const HeadComponent =()=> { return(<Image...

  • 修复闪烁的代码:

    ListHeaderComponent={this.renderHeader}

renderHeader是一个函数,返回与HeadComponent相同的内容,使用以下代码 renderHeader(){return(<Image...

希望这能帮助某些人。


1
对于仍然遇到这个问题的任何人:这是另一种解决方法。
<Image
     source={{ uri: your_path }}
     defaultSource={{ uri: your_path }}
     resizeMode="cover"
     style={{width: 100,height: 100}} />

1

当我将Image组件放入FlatList ListHeaderComponent组件中时,会出现闪烁问题。

为了解决这个问题,我添加了useCallBack hook。

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

ListHeaderComponent={ListComponent}

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


1

一种愚蠢的方式:

<ImageBackground
  defaultSource={require('./ui/pay0.png')}
  source={require('./ui/pay0.png')}
  style={{flex: 1, position: 'relative', zIndex: 9999, elevation: 5}}
/>
{/* Cache the remaining pictures to prevent flickering */}
<ImageBackground
  source={require('./ui/pay1.png')}
  style={{position: 'absolute', width: 1, height: 1}}
/>


你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community

0

我有一个解决方法(有点儿..)。 在我的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); 
}

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

这显然导致了应用程序加载后按钮状态的改变,但如果所有按钮在应用程序启动后都闪烁一次,那么在我看来比每个按钮在第一次按下时闪烁要好。

但是,如果有人能告诉我真正的解决方法,我会很高兴的。


-2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接