React Native 图片背景方向更改

8
尽管我可以通过屏幕方向更改来更新状态并重新渲染,但是ImageBackground组件仍然不会更新其宽度。
我有以下代码:
<View
  onLayout={event => this.mylayoutchange(event)}
  style={{ flex: 1, backgroundColor: 'green' }}
>
  <ImageBackground
    style={{ flex: 1, width: this.state.width, height: this.state.height }}
    imageStyle={{ resizeMode: 'repeat' }}
    source={require('../assets/images/my_background.jpg')}
  >
    <View>
      <Text>.... Other code here....</Text>
    </View>
  </ImageBackground>
</View>;

当用户改变设备的方向时,mylayoutchange()函数会被调用。它正确地更新了状态,render函数也会更新。可以在console.log()中看到宽度和高度已正确更改。然而,出于某种原因,<ImageBackground>没有更新其正确的宽度和高度。
当屏幕旋转时,背景图片不再填充整个屏幕大小,我只能看到绿色的背景颜色。
我做错了什么?
我的环境:
"react": "16.13.1",
"react-native": "0.63.2",

如果您可以的话,请在 Snack 上分享您的问题重现。我们肯定能够提供更好的帮助。 - user14415508
3个回答

6
你需要使用resize作为resizeMethod的机制,以便使图像获得实际缩放:

resizeMethod

当图像尺寸与图像视图尺寸不同时应使用的机制。默认为auto

  • auto: 使用启发式方法在resizescale之间进行选择。

  • resize: 一种软件操作,它在图像解码之前更改内存中的编码图像。当图像比视图大很多时,应使用此选项而不是scale

  • scale: 图像被绘制缩小或放大。与resize相比,scale速度更快(通常是硬件加速的),并且产生更高质量的图像。如果图像比视图小,则应使用此选项。如果图像略大于视图,则也应使用此选项。

显然,在你的情况下,RN会选择scale,因此你必须将它显式设置为resize,以便在方向更改和弹性样式变化时它能够正常工作:
return (
  <View
    style={{ flex: 1, backgroundColor: 'blue' }}
  >
    <ImageBackground
      // All props other than children, style, imageStyle, imageRef,
      // will be passed to the inner Image component,
      // so, we can use resizeMethod that will be passed to the Image component

      resizeMethod="resize"

      style={{
        flex: 1,
        borderWidth: 1,
        borderColor: 'red'
      }}
      imageStyle={{
        resizeMode: 'repeat',
      }}
      source={require('../assets/images/my_background.jpg')}
    >
      <View>
        <Text style={{
          backgroundColor: 'white'
        }}>.... Other code here....</Text>
      </View>
      <View style={{
        position: 'absolute',
        right: 0,
        bottom: 0
      }}>
        <Text style={{
          backgroundColor: 'white'
        }}>Absolute bottom-right text</Text>
      </View>
    </ImageBackground>
  </View>
);

结果截图:

屏幕截图

测试环境:

"react": "16.13.1",
"react-native": "0.63.2",

用于平铺背景的示例瓷砖图像(400 X 400像素):

背景平铺图像

Expo Snack:

RN ImageBackground方向更改


嗯,它确实有效。奇怪的是它说如果图像比视图小,应该使用“scale”。我的图像比视图小,所以使用“resize”是违反直觉的。 - kojow7
@kojow7,你试图在现有代码中使用此属性,该代码使用onLayout内部计算的widthheight,很可能你正在使用扩展语法将{...dimensionsSize}应用于ImageBackground样式中,这当然不起作用,因为Dimentions助手类对象还返回fontScalescale以及widthheight(截图:https://prnt.sc/v8ivzq),其中`fontScale`和`scale`不是有效的样式属性。请注意我的代码,因为我根本不使用`onLayout`。 - Christos Lytras
@kojow7 你说这是“违反直觉的”,但任何软件都不是完美的,这就是为什么你在这里试图解决这个问题的原因。事实是,如果图片没有 resizeresizeMethod,它将无法在原始肖像大小上呈现,并具有适当的 resizeMode: "repeat" 绘制。祝你好运找到更好的解决方案。 - Christos Lytras
@ChristosLytras 我也尝试过使用width: '100%'和height: '100%',但仍然遇到了同样的问题。我认为你误解了我的意思。我所说的“违反直觉”是指文档似乎与我们实际看到的不符。我并没有说我在寻找更好的解决方案。你的解决方案很好,所以我正在使用它。 - kojow7
@kojow7 是的,看起来我误解了它。这不仅是文档,还有 RN 使用 auto resizeMethod 做出的“决定”,它将其设置为 scale,当然是因为图像源比视图小。我认为这可能是一个问题,但我不确定(也许是 Fresco 的问题,你在 iOS 上运行时遇到了相同的问题吗?我只在 Android 模拟器上测试过)。我也不确定这如何影响性能,特别是在使用旧设备时。 - Christos Lytras
1
你总是给我惊喜的回答,就像现在这样。这正是重点。 - AmerllicA

0

我刚遇到了类似的问题。我找到的一个解决方法是在每次方向改变时生成一个唯一的ID(UUID),并将该UUID用作ImageBackground的键。这将重新加载图像并解决该bug。


这对我似乎不起作用。谢谢你的帮助。 - kojow7

0

您可以使用CSS自动指定宽度和高度,这将确保您的视图在每个大小/布局下都占据整个宽度/高度。

     <View
        onLayout={(event) => this.mylayoutchange(event)}
        style={{flex: 1, backgroundColor: 'green'}}>
        <ImageBackground
          style={{
            flex: 1,
            width: '100%',
            height: '100%',
          }}
          imageStyle={{resizeMode: 'repeat'}}
          source={require('../assets/images/my_background.jpg')}>
          <View>
            <Text>.... Other code here....</Text>
          </View>
        </ImageBackground>
      </View>

注意事项:

  • React Native 中存在一个错误,可能仍然存在于您的 RN 版本中,您可以查看 问题
  • 如果您仍然需要使用 this.state.widththis.state.height 指定宽度和高度,请考虑使用 usewindowdimensions,因为它会自动更新,更加适合。

我最初将其设置为100%,但在旋转时仍然出现相同的问题。这就是为什么我切换到基于状态的选项,因为我认为重新渲染会更新它。但它仍然没有更新。 - kojow7
@kojow7,此答案中提到的错误绝对是你遇到问题的原因,由于它已被关闭,你可以在 GitHub 中打开一个新问题,以便再次引起注意。 - diedu

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