在 React Native Expo 中更新到 SDK 52 后,Carousel 中的图像大小调整错误

问题描述 投票:0回答:1

更新到

Expo SDK 52
后,轮播中的图像不再正确显示,经常出现裁剪或未对齐的情况,特别是对于纵向图像。此问题似乎源于新 SDK 版本中图像渲染或调整大小方式的变化。目标是通过确保所有图像完全适合轮播而没有任何裁剪或错位来解决此问题,但我在这样做时遇到了困难。 SDK的强制更新给我带来了很多问题。

The image how image is displayed

代码

    import * as React from "react";
    import { Animated, View } from "react-native";
    import { useSharedValue } from "react-native-reanimated";
    import Carousel, {
      ICarouselInstance,
      Pagination,
    } from "react-native-reanimated-carousel";
    
    import { window } from "../features/favourites/constants";
    
    const PAGE_WIDTH = window.width;
    
    function Test({
      images,
    }: {
      images: { original: string; thumbnail: string }[];
    }) {
      const progress = useSharedValue<number>(0);
      const ref = React.useRef<ICarouselInstance>(null);
    
      const onPressPagination = (index: number) => {
        ref.current?.scrollTo({
          count: index - progress.value,
          animated: true,
        });
      };
    
      return (
        <View style={{ flex: 1 }}>
          <Carousel
            ref={ref}
            vertical={false}
            width={PAGE_WIDTH}
            height={PAGE_WIDTH * 0.6}
            loop
            pagingEnabled
            snapEnabled
            autoPlay
            autoPlayInterval={2500}
            onProgressChange={(_, progressValue) => {
              progress.value = progressValue;
            }}
            mode="parallax"
            modeConfig={{
              parallaxScrollingScale: 0.9,
              parallaxScrollingOffset: 50,
            }}
            data={images}
            renderItem={({ index }) => (
              <View
                key={index}
                style={{
                  backgroundColor: "#fff",
                  borderRadius: 10,
                  width: PAGE_WIDTH / 1,
                  height: PAGE_WIDTH / 1.8,
                  shadowColor: "#000",
                  shadowOffset: {
                    width: 0,
                    height: 4,
                  },
                  shadowOpacity: 0.34,
                  shadowRadius: 10.32,
                  elevation: 16,
                  justifyContent: "center",
                  alignItems: "center",
                }}
              >
                <Animated.Image
                  source={{ uri: images[index].original }}
                  style={{
        width: PAGE_WIDTH / 1,
                height: PAGE_WIDTH / 1.8,
                borderRadius: 10,
                justifyContent: "center",
                alignItems: "center",
                  }}
                  resizeMode={"cover"}
                />
              </View>
            )}
          />
    
          {Pagination && Pagination.Basic && (
            <Pagination.Basic
              progress={progress}
              data={images}
              dotStyle={{ backgroundColor: "rgba(0,0,0,0.2)" }}
              containerStyle={{ gap: 5, marginBottom: 10 }}
              onPress={onPressPagination}
            />
          )}
        </View>
      );
    }
    
    export default Test;

我也尝试过

react-native-snap-carousel
,仍然是同样的问题。

这是package.json

    "react-native-reanimated": "^3.16.5",
    "react-native-reanimated-carousel": "^4.0.0-canary.20",
    "react-native": "0.76.5",
react-native expo sdk
1个回答
0
投票

我审查了代码的某些部分,发现一些 styling 属性可以更改,特别是 Animated.Image 中的属性,因为 Image 类似乎需要 root 类参数 的尺寸,这些可以在样式属性之外给出,也可以更改一些其他尺寸值,请查看下面修改行的注释:

  return (
    <View style={{ flex: 1 }}>
      <Carousel
        ref={ref}
        vertical={false}
        width={PAGE_WIDTH}
        height={PAGE_WIDTH} //*0.6 may resize the inner Image to the 60% of the size
        loop
        pagingEnabled
        snapEnabled
        autoPlay
        autoPlayInterval={2500}
        onProgressChange={(_, progressValue) => {
          progress.value = progressValue;
        }}
        mode="parallax"
        modeConfig={{
          parallaxScrollingScale: 0.9,
          parallaxScrollingOffset: 50,
        }}
        data={images}
        renderItem={({ index }) => (
          <View
            key={index}
            style={{
              backgroundColor: "#fff",
              borderRadius: 10,
              width: 'auto', //changing this to auto may help to fit entire width of screen
              height: PAGE_WIDTH, // this PAGE_WIDTH / 1.8 tells the child view of component to be 180% of screen width which if landscape it may not be desired
              shadowColor: "#000",
              shadowOffset: {
                width: 0,
                height: 4,
              },
              shadowOpacity: 0.34,
              shadowRadius: 10.32,
              elevation: 5,
              justifyContent: "center",
              alignItems: "center",
            }}
          >
            <Animated.Image
              source={{ uri: images[index].original }}
              width={PAGE_WIDTH}
              height={PAGE_WIDTH / 1.8}
              style={{
              borderRadius: 10,
              justifyContent: "center",
              alignItems: "center",
              }}
              resizeMode={"cover"}
            />
          </View>
        )}
      />

      {Pagination && Pagination.Basic && (
        <Pagination.Basic
          progress={progress}
          data={images}
          dotStyle={{ backgroundColor: "rgba(0,0,0,0.2)" }}
          containerStyle={{ gap: 5, marginBottom: 10 }}
          onPress={onPressPagination}
        />
      )}
    </View>
  );
}

export default Test;

模拟 Carousel 功能的另一种方法如下:

import { Dimensions, ScrollView } from 'react-native';  

const { height: SCREEN_HEIGHT, width: SCREEN_WIDTH } = Dimensions.get('window');  
const scrollViewRef = useRef(null); 

const carouselItems = [  
  { icon: faDollar, label: "Money" },  
  { icon: faLanguage, label: "Language" },  
  { icon: faToolbox, label: "Tools" },  
];  

const handleScroll = (event) => {  
  const contentOffsetX = event.nativeEvent.contentOffset.x;  
  const index = Math.floor(contentOffsetX / SCREEN_WIDTH);  
  setCurrentIndex(index);  
};  

提供flexGrow的样式:1,如下:

contentContainer: {
  flexGrow: 1,
  justifyContent: 'center',
  alignItems: 'center',
  paddingHorizontal: 70, // Adjust padding as needed
},

在这里您可以为轮播添加类似的动画行为:

<ScrollView  
  horizontal  
  pagingEnabled
  showsHorizontalScrollIndicator={false}
  onScroll={handleScroll}  
  scrollEventThrottle={16}  
  ref={scrollViewRef}  
  snapToAlignment="center"
  decelerationRate="fast"
  contentContainerStyle={styles.contentContainer}  
  >  
  {carouselItems.map((item, index) => renderItem(item, index))}  
</ScrollView>

这是渲染项功能:

const renderItem = (item, index) => {  
  let navigateTo;  
  switch (item.label) {  
    case "Money":  
      navigateTo = 'ScreenPage1'; //another ScreenPage1.tsx 
      break;  
    case "Language":  
      navigateTo = 'ScreenPage2';  //another ScreenPage2.tsx
      break;  
    case "Tools":  
      navigateTo = 'ScreenPage3';  //another ScreenPage3.tsx
      break;  
    default:  
      navigateTo = null;  
  }  
© www.soinside.com 2019 - 2024. All rights reserved.