1

我在顶部标签栏导航中有三个标签,其中包含不同宽度的文本。是否可以使指示器宽度与文本匹配?在类似的说明中,如何使选项卡也与文本的宽度匹配,而不会使其显示奇怪。我试过自动宽度,但它没有保持中心。

这是自动宽度的外观: 在此处输入图像描述

    <Tab.Navigator 
                initialRouteName="Open"
                tabBarOptions={{
                    style: { 
                      backgroundColor: "white", 
                      paddingTop: 20, 
                      paddingHorizontal: 25
                      },
                    indicatorStyle: {
                      borderBottomColor: colorScheme.teal,
                      borderBottomWidth: 2,
                      width: '30%',
                      left:"9%"
                    },
                    tabStyle : {
                      justifyContent: "center",
                      width: tabBarWidth/3,
                    }
                  }}
            >
                <Tab.Screen 
                    name="Open" 
                    component={WriterRequestScreen} 
                    initialParams={{ screen: 'Open' }} 
                    options={{ 
                      tabBarLabel: ({focused}) => <Text style = {{fontSize: 18, fontWeight: 'bold', color: focused? colorScheme.teal : colorScheme.grey}}> Open </Text>, 
                   }}
                    />
               <Tab.Screen 
                    name="In Progress" 
                    component={WriterRequestScreen} 
                    initialParams={{ screen: 'InProgress' }}
                    options={{ 
                      tabBarLabel: ({focused}) => <Text style = {{fontSize: 18, fontWeight: 'bold', color: focused? colorScheme.teal : colorScheme.grey}}> In Progress </Text>}}
                    />
               <Tab.Screen 
                name="Completed" 
                component={WriterRequestScreen} 
                initialParams={{ screen: 'Completed' }}
                options={{ tabBarLabel: ({focused}) => <Text style = {{fontSize: 18, fontWeight: 'bold', color: focused? colorScheme.teal : colorScheme.grey}}> Completed </Text>}}
                />
            </Tab.Navigator>
4

3 回答 3

0

从 indicatorStyle 中删除宽度并使用 flex:1

indicatorStyle: {    borderBottomColor: colorScheme.teal,
                      borderBottomWidth: 2,
                      flex:1,
                      left:"9%"
                    },
于 2021-02-07T14:04:42.890 回答
0

我已经使用 onLayout 周围的一些技巧实现了这一点,请注意我是在假设两个选项卡的情况下做到这一点的,并且第二个选项卡的宽度大于第一个。它可能需要针对其他用例进行调整。

在此处输入图像描述

import React, { useEffect, useState } from 'react'
import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs'
import { Animated, Text, TouchableOpacity, View } from 'react-native'

const Stack = createMaterialTopTabNavigator()

const DISTANCE_BETWEEN_TABS = 25

function MyTabBar ({ state, descriptors, navigation, position }) {
  const [widths, setWidths] = useState([])
  const [transform, setTransform] = useState([])

  const inputRange = state.routes.map((_, i) => i)

  useEffect(() => {
    if (widths.length === 2) {
      const [startingWidth, transitionWidth] = widths
      const translateX = position.interpolate({
        inputRange,
        outputRange: [0, startingWidth + DISTANCE_BETWEEN_TABS + (transitionWidth - startingWidth) / 2]
      })
      const scaleX = position.interpolate({
        inputRange,
        outputRange: [1, transitionWidth / startingWidth]
      })
      setTransform([{ translateX }, { scaleX }])
    }
  }, [widths])

  return (
    <View style={{ flexDirection: 'row' }}>
      {state.routes.map((route, index) => {
        const { options } = descriptors[route.key]
        const label =
          options.tabBarLabel !== undefined
            ? options.tabBarLabel
            : options.title !== undefined
              ? options.title
              : route.name

        const isFocused = state.index === index

        const onPress = () => {
          const event = navigation.emit({
            type: 'tabPress',
            target: route.key,
            canPreventDefault: true
          })

          if (!isFocused && !event.defaultPrevented) {
            // The `merge: true` option makes sure that the params inside the tab screen are preserved
            navigation.navigate({ name: route.name, merge: true })
          }
        }

        const onLayout = event => {
          const { width } = event.nativeEvent.layout
          setWidths([...widths, width])
        }

        const opacity = position.interpolate({
          inputRange,
          outputRange: inputRange.map(i => (i === index ? 0.87 : 0.53))
        })

        return (
          <TouchableOpacity
            key={index}
            accessibilityRole='button'
            accessibilityState={isFocused ? { selected: true } : {}}
            accessibilityLabel={options.tabBarAccessibilityLabel}
            testID={options.tabBarTestID}
            onPress={onPress}
            style={{ marginRight: DISTANCE_BETWEEN_TABS }}
          >
            <Animated.Text
              onLayout={onLayout}
              style={{
                opacity,
                color: '#000',
                fontSize: 18,
                fontFamily: 'OpenSans-Bold',
                marginBottom: 15
              }}
            >
              {label}
            </Animated.Text>
          </TouchableOpacity>
        )
      })}
      <View style={{ backgroundColor: '#DDD', height: 2, position: 'absolute', bottom: 0, left: 0, right: 0 }} />
      <Animated.View style={{ position: 'absolute', bottom: 0, left: 0, width: widths.length ? widths[0] : 0, backgroundColor: '#222', height: 2, transform }} />
    </View>
  )
}

export default () => {
  return (
    <>
      <Stack.Navigator tabBar={props => <MyTabBar {...props} />} style={{ paddingHorizontal: 25 }}>
        <Stack.Screen name='Orders' component={() => <Text>A</Text>} />
        <Stack.Screen name='Reviews' component={() => <Text>B</Text>} />
      </Stack.Navigator>
    </>
  )
}

更新:

如果菜单名称是静态的,那么硬编码 内部的宽度可能是一种更强大的解决方案widths,尽管维护成本更高。

资源:

于 2021-10-29T05:01:18.500 回答
0

您必须添加width:auto到 tabStyle 以使选项卡宽度灵活。

然后在每个 tabBarLabel<Text>组件内添加样式textAlign: "center"width: YOUR_WIDTH.

YOUR_WIDTH每个选项卡可以不同,可以是你的 text.length * 10 (如果你想让它取决于你的文本长度)或从尺寸中获取屏幕宽度并将其除以任何其他数字以使其在屏幕中的宽度相等。例子:

const win = Dimensions.get('window');

...

bigTab: {
    fontFamily: "Mulish-Bold",
    fontSize: 11,
    color: "#fff",
    textAlign: "center",
    width: win.width/2 - 40
},
smallTab: {
    fontFamily: "Mulish-Bold",
    fontSize: 11,
    color: "#fff",
    textAlign: "center",
    width: win.width / 5 + 10
}
于 2021-01-27T21:11:15.123 回答