在ReactNative的首次加载中图像闪烁

时间:2018-11-03 10:32:35

标签: android ios react-native

我试图用一个动画按钮来构建一个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 Repository上提供了我为演示问题而构建的小演示应用程序的完整版。

4 个答案:

答案 0 :(得分: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}
      />

我从那个仓库复制了这个例子。您也可以在此处找到文档。尝试一下。它将提高图像加载性能。然后很可能会出现闪烁的问题。

答案 1 :(得分:0)

好吧,我有一种解决方法。 现在,在我的S1 = [20 32 44 56 68 80 92 104 116 128 140 152 164 176 188 200]; P = [16.82 26.93 37.01 47.1 57.21 67.32 77.41 87.5 97.54 107.7 117.8 127.9 138 148 158.2 168.3]; X = [0.119 0.191 0.262 0.334 0.405 0.477 0.548 0.620 0.691 0.763 0.835 0.906 0.978 1.049 1.120 1.192]; S = [2.3734 3.6058 5.0256 6.6854 8.6413 10.978 13.897 17.396 21.971 28.040 36.475 49.065 69.736 110.20 224.69 2779.1]; objective = @(x) sum( ((1250.*x(3).*S-(S+x(2)).*(P+x(1)))./(1250.*(S+x(2)).*(P+x(1)))-x(5)).^2+((x(2).*(P.^2+x(1).*P))./(1250.*x(4).*X.*x(3)-P.^2-x(1).*P)-S).^2+(74000./3.*((X.*x(3).*S)./S1.*(S+x(2)))-P).^2 ); %x0 = [Kp Ks mu.m Yp mu.d] x0 = [7.347705469 14.88611028 1.19747242 16.65696429 6.01E-03]; x = fminunc(objective,x0); disp(x) 中,将按钮设置为按下状态,等待一段时间直到图像显示并缩放,然后再次将状态设置为关闭,如下所示:

componentDidMount()

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

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

但是,如果有人能告诉我真实的方式以及解决方法的方法,我将感到很高兴。

答案 2 :(得分:0)

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

App.js中,我想等待所有静态资产加载后再显示任何屏幕。

答案 3 :(得分:0)

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

  • 导致闪烁的代码:

    ListHeaderComponent={HeadComponent}

HeadComponent基本上位于render内部,并且代码为const HeadComponent = () => { return (<Image...

  • 解决闪烁的代码:

    ListHeaderComponent={this.renderHeader}

renderHeader是使用代码HeadComponent返回与renderHeader () { return (<Image...相同的函数

希望这对某人有帮助。