【问题标题】:borderRadius doesn't work on image when resizeMode is set to 'contain'当 resizeMode 设置为“包含”时,borderRadius 对图像不起作用
【发布时间】:2020-12-23 02:29:14
【问题描述】:

我一直在尝试用一堆随机选择的图像构建一个图像轮播。我想保持它们的纵横比,所以我将 resizeMode 设置为“包含”。不知何故,这一步会导致任何设置的边界半径的丢失!可能是什么原因?如果该步骤根本不起作用,关于如何保持正确的纵横比 + 圆角还有其他想法吗?

非常感谢您的帮助!

代码如下:

import React, { useCallback, memo, useRef, useState } from "react";
import {
  FlatList,
  View,
  Dimensions,
  Text,
  StyleSheet,
  Image,
} from "react-native";


const images = [
  Image1,
  Image2,
  Image3,
  Image4,
  Image5,
  Image6,
  Image7,
  Image8,
  Image9,
  Image10,
  Image11,
  Image12,
  Image13,
  Image14,
  Image15,
  Image16,
  Image17,
  Image18,
  Image19,
  Image20,
  Image21,
  Image22,
  Image23,
  Image24,
  Image25,
  Image26,
  Image27,
  Image28,
  Image29,
  Image30,
  Image31,
  Image32,
  Image33,
  Image34,
  Image35,
  Image36,
  Image37,
  Image38,
  Image39,
  Image40,
  Image41,
]


const { width: windowWidth, height: windowHeight } = Dimensions.get("window");



const randomImage = () =>
images[Math.floor(Math.random() * images.length)];
  



const styles = StyleSheet.create({
  slide: {
    height: windowHeight,
    width: windowWidth,
    //justifyContent: "center",
    alignItems: "center",
  },
  slideImage: { 
    height: '70%',
    width: '90%',
    borderRadius: 20,
    marginTop: 20,
    
   },
 
  slideTitle: { 
    fontSize: 24,
    marginTop: 0,
  },
  slideSubtitle: {
    fontSize: 18,
    marginTop: 10,
  },

  pagination: {
    position: "absolute",
    bottom: 8,
    justifyContent: "center",
    flexDirection: "row",
    marginBottom: 12
  },
  paginationDot: {
    width: 8,
    height: 8,
    borderRadius: 4,
    marginHorizontal: 2,
  },
  paginationDotActive: { backgroundColor: "lightblue" },
  paginationDotInactive: { backgroundColor: "gray" },

  carousel: {},
});

const slideList = Array.from({ length: 999 }).map((_, i) => {
  return {
    id: i,
    image: randomImage,
    title: `This is the title ${i + 1}!`,
    subtitle: `This is the subtitle ${i + 1}!`,
  };
});

const Slide = memo(function Slide({ data }) {
  return (
    <View style={styles.slide}>
      <Image resizeMode = 'contain' source = {randomImage()} style={styles.slideImage}></Image>
      <Text style={styles.slideTitle}>{data.title}</Text>
      <Text style={styles.slideSubtitle}>{data.subtitle}</Text>
    </View>
  );
});

function Pagination({ index }) {
  return (
    <View style={styles.pagination} pointerEvents="none">
      {slideList.map((_, i) => {
        return (
          <View
            key={i}
            style={[
              styles.paginationDot,
              index === i
                ? styles.paginationDotActive
                : styles.paginationDotInactive,
            ]}
          />
        );
      })}
    </View>
  );
}

export default function Carousel() {
  const [index, setIndex] = useState(0);
  const indexRef = useRef(index);
  indexRef.current = index;
  const onScroll = useCallback((event) => {
    const slideSize = event.nativeEvent.layoutMeasurement.width;
    const index = event.nativeEvent.contentOffset.x / slideSize;
    const roundIndex = Math.round(index);

    const distance = Math.abs(roundIndex - index);

    // Prevent one pixel triggering setIndex in the middle
    // of the transition. With this we have to scroll a bit
    // more to trigger the index change.
    const isNoMansLand = 0.4 < distance;

    if (roundIndex !== indexRef.current && !isNoMansLand) {
      setIndex(roundIndex);
    }
  }, []);

  const flatListOptimizationProps = {
    initialNumToRender: 0,
    maxToRenderPerBatch: 1,
    removeClippedSubviews: true,
    scrollEventThrottle: 16,
    windowSize: 2,
    keyExtractor: useCallback(s => String(s.id), []),
    getItemLayout: useCallback(
      (_, index) => ({
        index,
        length: windowWidth,
        offset: index * windowWidth,
      }),
      []
    ),
  };

  const renderItem = useCallback(function renderItem({ item }) {
    return <Slide data={item} />;
  }, []);

  return (
    <>
      <FlatList
        data={slideList}
        style={styles.carousel}
        renderItem={renderItem}
        pagingEnabled
        horizontal
        showsHorizontalScrollIndicator={false}
        bounces={false}
        onScroll={onScroll}
        {...flatListOptimizationProps}
      />
      <Pagination index={index}></Pagination>
    </>
  );
}
 ``

【问题讨论】:

    标签: javascript react-native


    【解决方案1】:

    实际上borderRadius 有效,但由于比例不正确,您看不到它。

    如果您的图片比例为 16:9,例如 1600x900 尺寸,那么您需要将 widthheight 设置为相同的比例。

    <Image
        source={ 1600x900 }
        resizeMode="contain"
        style={{
            width: 300,
            height: 300,
            borderRadius: 15,
            backgroundColor: 'red'
        }} />
    

    结果将是:

    因为图像的宽高为 300,即 1:1 的比例。如果将widthheight修改为320180,即16:9,则图像会填满所有空间,并且边框将可见。

    【讨论】:

    • 非常感谢您的详尽回答!很有帮助,很有意义!当我导入的图像具有不同的纵横比时,您知道我可以做些什么来保持圆角吗?在横向或纵向模式下,它们基本上是 3/4!
    • cover 看起来很糟糕?
    • cover 会剪掉不适合图像的给定样式(宽度/高度)的部分图像:/。是否有可能以某种方式将 If 语句连接到样式?因此,如果它是风景照片之一,那么高度/宽度会相应设置,而肖像照片也一样吗?感谢您的宝贵时间!:)
    • 风景照片如何判断?
    • 我把照片放在一个文件夹里,我会检查哪些是横向的,哪些是纵向的:D
    猜你喜欢
    • 2016-07-01
    • 2016-07-26
    • 2018-09-13
    • 1970-01-01
    • 2017-02-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-09
    • 1970-01-01
    相关资源
    最近更新 更多