反应本机矢量图标以适应父容器而不指定尺寸道具(Expo)

Nan*_*ndi 6 reactjs react-native expo

我正在使用 Expo 提供的矢量图标https://github.com/expo/vector-icons

所有图标都接受一个整数的 size 属性,我的用例是看看是否可以根据父容器自动调整图标大小,而不必担心每个设备上的大小(因为大小似乎会翻译尽管像素比、尺寸等不同,但每个设备上都相同)

<View style={{flex: 1}}>
  <Icon name="app-logo" size={30} color="white" />
</View>    
Run Code Online (Sandbox Code Playgroud)

我尝试将 style 属性设置为以下选项,但没有成功。我希望这不会起作用,因为毕竟它们只是字体,并且不需要支持widthheight

<Icon name="app-logo" style={{flex: 1}} color="white" />
Run Code Online (Sandbox Code Playgroud)
<Icon name="app-logo" style={{width: '100%', height: '100%' color="white" />
Run Code Online (Sandbox Code Playgroud)

有没有更干净或建议的方法来做到这一点?使用设备的尺寸和比例是我最后的手段。

pac*_*hun 0

这是我能得到的最接近的示例:

最佳博览会矢量图标大小到父尝试

import React from "react"
import { PixelRatio, StyleSheet, Text, View } from "react-native"
import { FontAwesome5 } from "@expo/vector-icons"

const getRandomNumber = (min: number, max: number) =>
  Math.random() * (max - min) + min

const App = () => {
  const [containerSize, setContainerSize] = React.useState<number>()

  const randomDimension = React.useMemo(() => getRandomNumber(100, 400), [])

  return (
    <View
      style={{
        flex: 1,
        backgroundColor: "green",
        justifyContent: "center",
        alignItems: "center",
      }}
    >
      <View
        style={{
          width: randomDimension,
          aspectRatio: 1,
          backgroundColor: "red",
        }}
        onLayout={layoutEvent =>
          setContainerSize(layoutEvent.nativeEvent.layout.width)
        }
      >
        <FontAwesome5
          name="app-store-ios"
          size={containerSize || 0}
          style={{
            textAlign: "center",
          }}
          color="blue"
        />
      </View>
    </View>
  )
}

export default App
Run Code Online (Sandbox Code Playgroud)

这里有一些代码,用于故意将图标的父容器设置为随机大小的正方形,并将其设置在父容器上,这不是您正在寻找的内容,但帮助我重新创建了问题。

onLayout我认为您想要的有趣的一点是传递给图标父容器的 prop 的值,它获取父容器的大小并将其置于状态。在第一次渲染和布局之前,该状态将为空,因此我们在发生这种情况之前默认设置矢量图标的大小0。一旦我们获得了状态中父级的大小,我们就可以设置矢量图标的大小。

矢量图标实际上并没有填充整个父级的空间,但它的缩放比例非常接近。我认为这是因为矢量图标本身是一种字体(?),我们试图将字体的大小(实际上以磅为单位(我认为?))设置为我们从父级获得的大小(以像素为单位)。可能有一种巧妙的方法可以使用 React Native 的 PixelRatio 来清理它- 我花了一些时间尝试但无法让它完美工作。

我需要做的最后一件事(因为矢量图标实际上并没有“填充”父视图,所以将style图标的支柱设置为{ textAlign: 'center' }使其在父视图中水平居中(它已经垂直居中)而不是关闭在父母的左侧。

你可以通过在大小上添加一个常量并在图标上放置一个负的上边距来让整个事情提交,但这有点像 PITA,显然不是一个很好的解决方案(每次你这样做都会很头疼,而且它可能无法跨平台/在不同的像素密度上工作)。


我实际上到达这篇文章的原因是因为我试图使图标与文本大小相同;我正在开发一个应用程序,它在一个小聊天气泡图标的左侧显示评论计数(整数),并且如果用户在系统设置中调整了该图标的大小,我希望图标的大小能够随着系统的字体大小而缩放。这实际上更容易(考虑到我关于矢量图标在引擎盖下表示为字体的理论是正确的,这是有道理的)。这是我的代码中实现这一目标的相关部分:

const StoryCommentsLabel = ({ story }: { story: HackerNewsItem }) => {
  const navigation = useNavigation()
  const numberOfComments = story.descendants || 0
  const doNotActTouchable = { activeOpacity: 1 }
  const fontScale = React.useMemo(() => PixelRatio.getFontScale(), [])
  const defaultFontSize = 14
  const iconSize = defaultFontSize * fontScale
  return (
    <TouchableOpacity
      style={{ flexDirection: "row", justifyContent: "flex-end" }}
      onPress={() => {
        if (numberOfComments > 0) {
          navigation.navigate("Story Comments", { story })
        }
      }}
      hitSlop={{ top: 20, left: 20, bottom: 20, right: 20 }}
      {...(numberOfComments === 0 ? doNotActTouchable : {})}
    >
      <Text
        style={{
          fontSize: 14,
          color: PlatformColor("secondaryLabel"),
        }}
      >
        {numberOfComments}
      </Text>
      <View style={{ width: 5 }} />
      <Ionicons
        name="chatbubble"
        size={iconSize}
        color={PlatformColor("secondaryLabel")}
      />
    </TouchableOpacity>
  )
}
Run Code Online (Sandbox Code Playgroud)

里面有比你需要的更多的东西,但重要的是:

  const fontScale = React.useMemo(() => PixelRatio.getFontScale(), [])
  const defaultFontSize = 14
  const iconSize = defaultFontSize * fontScale
Run Code Online (Sandbox Code Playgroud)