Fix layout jumps for images (#6474)

This commit is contained in:
dan
2024-11-18 21:42:32 +00:00
committed by GitHub
parent 924f1e0e7f
commit ec97352201
+15 -12
View File
@@ -1,4 +1,4 @@
import React from 'react'
import React, {useRef} from 'react'
import {DimensionValue, Pressable, View} from 'react-native'
import Animated, {AnimatedRef, useAnimatedRef} from 'react-native-reanimated'
import {Image} from 'expo-image'
@@ -79,15 +79,19 @@ export function AutoSizedImage({
const {_} = useLingui()
const largeAlt = useLargeAltBadgeEnabled()
const containerRef = useAnimatedRef()
const fetchedDimsRef = useRef<{width: number; height: number} | null>(null)
const [fetchedDims, setFetchedDims] = React.useState<Dimensions | null>(null)
const dims = fetchedDims ?? image.aspectRatio
let aspectRatio: number | undefined
const dims = image.aspectRatio
if (dims) {
aspectRatio = dims.width / dims.height
if (Number.isNaN(aspectRatio)) {
aspectRatio = undefined
}
} else {
// If we don't know it synchronously, treat it like a square.
// We won't use fetched dimensions to avoid a layout shift.
aspectRatio = 1
}
let constrained: number | undefined
@@ -113,13 +117,12 @@ export function AutoSizedImage({
accessibilityIgnoresInvertColors
accessibilityLabel={image.alt}
accessibilityHint=""
onLoad={
fetchedDims
? undefined
: e => {
setFetchedDims({width: e.source.width, height: e.source.height})
}
}
onLoad={e => {
fetchedDimsRef.current = {
width: e.source.width,
height: e.source.height,
}
}}
/>
<MediaInsetBorder />
@@ -191,7 +194,7 @@ export function AutoSizedImage({
if (cropDisabled) {
return (
<Pressable
onPress={() => onPress?.(containerRef, fetchedDims)}
onPress={() => onPress?.(containerRef, fetchedDimsRef.current)}
onLongPress={onLongPress}
onPressIn={onPressIn}
// alt here is what screen readers actually use
@@ -213,7 +216,7 @@ export function AutoSizedImage({
fullBleed={crop === 'square'}
aspectRatio={constrained ?? 1}>
<Pressable
onPress={() => onPress?.(containerRef, fetchedDims)}
onPress={() => onPress?.(containerRef, fetchedDimsRef.current)}
onLongPress={onLongPress}
onPressIn={onPressIn}
// alt here is what screen readers actually use