javascript - 我们如何根据 React Native 中的列表项内容为 FlatList 提供自动高度

标签 javascript css reactjs react-native react-native-flatlist

我在我的组件中使用 FlatList,它工作正常。所需要的是我的整个屏幕应该有一个自动高度,并且 FlatList 内容永远不会超出屏幕高度。

此外,FlatList 的高度应根据其中的内容/元素进行更改,而不是给出任何固定高度。

如何实现自动屏幕高度和 FlatList 内容自动高度等两种情况?

代码:

import React, { useState, useEffect } from 'react';
import {
  View,
  StyleSheet,
  useWindowDimensions,
  Text,
  FlatList,
  SafeAreaView,
  TouchableOpacity,
} from 'react-native';
import { LinearGradient as LinearGradientView } from 'expo-linear-gradient';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { ActivityIndicator, ThemeProvider } from 'react-native-paper';
import { ScrollView } from 'react-native-gesture-handler';
import { useIsFocused, useNavigation } from '@react-navigation/native';
import Svg, { Path } from 'react-native-svg';
import { BASE_GRADIENT_HEAVY } from '../rooms/Background';
import { useResolution } from '../browse/useResolution';
import { OnboardingNavigationProp } from '../navigation/LinkingConfiguration';
import { LIGHT_THEME } from '../Theme';
import { OnboardingBack } from './OnboardingBack';
import {
  useOnboardingYearsOfExperiencePage,
  useOnboardingYearsOfExperienceSubmit,
} from './useOnboardingYearsOfExperiencePage';

export function OnboardingYearsOfExperience({ route }: { route?: any }) {
  const { height } = useWindowDimensions();
  const { top: safeAreaTop } = useSafeAreaInsets();

  const [selectedId, setSelectedId] = useState<{ id: string }>();
  const [role_id, setRoleId] = useState<number>();
  const { navigate } =
    useNavigation<OnboardingNavigationProp<'OnboardingConfirmAllDetails'>>();

  const parentUrl = route?.params.result.onboarding._links;
  const initialUrl = parentUrl.onboarding_years_of_experience.href;
  const onboardingUrl = parentUrl.self.href;

  useEffect(() => {
    setRoleId(route?.params.role_id);
  }, []);

  const isFocused = useIsFocused();
  const { contentType } = useResolution();

  const {
    data: result,
    isLoading,
    error,
  } = useOnboardingYearsOfExperiencePage(initialUrl, contentType, role_id, {
    enabled: isFocused,
    notifyOnChangeProps: ['data', 'isLoading', 'error'],
  });

  const {
    mutateAsync: updateYearsOfExperience,
    isLoading: isUpdatingYearsOfExperience,
    error: yearsOfExperienceUpdateError,
  } = useOnboardingYearsOfExperienceSubmit(onboardingUrl);

  const Arrow = ({ style }: { style: object }) => {
    return (
      <Svg width="7" height="11" viewBox="0 0 7 11" fill="none" style={style}>
        <Path
          d="M6.28711 5.53931C6.28711 5.31649 6.19783 5.12476 6.02452 4.95376L1.9911 1.07251C1.85455 0.937781 1.68649 0.865234 1.48692 0.865234C1.07728 0.865234 0.751664 1.18651 0.751664 1.58552C0.751664 1.78243 0.830441 1.96898 0.977493 2.11407L4.54875 5.53413L0.977492 8.95937C0.835692 9.10446 0.751663 9.28583 0.751662 9.48792C0.751662 9.88693 1.07728 10.2082 1.48692 10.2082C1.68649 10.2082 1.85455 10.1357 1.99635 10.0009L6.02452 6.11968C6.20308 5.93832 6.28711 5.75695 6.28711 5.53931Z"
          fill="#4D4D4D"
        />
      </Svg>
    );
  };

  const Item = ({
    item,
    onPress,
  }: {
    item?: { id: string; title: string };
    onPress: () => void;
  }) => (
    <TouchableOpacity onPress={onPress}>
      <Text
        style={{
          color: '#4D4D4D',
          fontFamily: 'Inter_400Regular',
          fontStyle: 'normal',
          fontWeight: '400',
          fontSize: 16,
          lineHeight: 32,
          padding: 3,
          margin: 2,
        }}
      >
        {item?.title}
      </Text>
    </TouchableOpacity>
  );

  const renderItem = ({ item }: { item: { id: string; title: string } }) => {
    return (
      <React.Fragment>
        <View
          style={{
            flexDirection: 'row',
            justifyContent: 'space-between',
            borderRadius: 5,
            backgroundColor:
              selectedId?.id === item?.id ? '#F2F2F2' : 'transparent',
          }}
        >
          <View style={{ width: '90%' }}>
            <Item
              item={item}
              onPress={() => {
                setSelectedId({ id: item.id });
                updateYearsOfExperience({ id: item.id, role_id })
                  .then((result) => {
                    navigate('Onboarding', {
                      screen: 'OnboardingConfirmAllDetails',
                      params: { result },
                    });
                  })
                  .catch(() => {});
              }}
            />
          </View>
          <View style={{ width: '10%' }}>
            <Arrow style={{ position: 'absolute', top: 16, right: 10 }} />
          </View>
        </View>
      </React.Fragment>
    );
  };

  return (
    <ThemeProvider theme={LIGHT_THEME}>
      <View style={{ height: safeAreaTop }} />
      <View style={styles.topHeader}>
        <LinearGradientView
          {...BASE_GRADIENT_HEAVY}
          style={[styles.gradiantStyle]}
        />
      </View>
      <View style={styles.innerContainer}>
        <ScrollView
          contentContainerStyle={{
            marginHorizontal: 'auto',
            alignSelf: 'center',
            width: '100%',
            backgroundColor: '#ffffff',
            height: '100%',
          }}
        >
          <OnboardingBack
            style={{
              left: -10,
            }}
          />
          <Text style={styles.topHeadline}>
            How many years of experience do you have?
          </Text>
          <Text style={styles.middleHeadline}>
            Jump-start the conversation by sharing your years of experience
            within healthcare.
          </Text>
          {isLoading || isUpdatingYearsOfExperience ? (
            <ActivityIndicator size="large" />
          ) : (
            <SafeAreaView>
              <FlatList
                contentContainerStyle={{ flexGrow: 1 }}
                data={Object.values(
                  result!['years_of_experiences']['years_of_experiences_list']
                )}
                renderItem={renderItem}
                keyExtractor={(item) => item.id}
                extraData={selectedId}
                style={{
                  borderWidth: 1,
                  borderStyle: 'solid',
                  borderColor: '#D7D7D7',
                  borderRadius: 5,
                  padding: 12,
                  height: '27%',
                }}
                ListEmptyComponent={
                  <View>
                    <Text>No data found</Text>
                  </View>
                }
              />
            </SafeAreaView>
          )}
        </ScrollView>
      </View>
    </ThemeProvider>
  );
}

const styles = StyleSheet.create({
  innerContainer: {
    display: 'flex',
    position: 'relative',
    backgroundColor: 'white',
    padding: 18,
  },

  topHeader: {
    backgroundColor: '#e5dede',
    padding: 0,
    width: '100%',
  },

  topHeadline: {
    fontSize: 24,
    fontFamily: 'CircularStd_Medium',
    fontStyle: 'normal',
    fontWeight: '500',
    color: '#222222',
    marginTop: 40.6,
    marginBottom: 14.6,
    display: 'flex',
    alignItems: 'center',
    lineHeight: 32,
  },

  middleHeadline: {
    fontSize: 16,
    fontFamily: 'Inter_400Regular',
    fontStyle: 'normal',
    fontWeight: '400',
    lineHeight: 24,
    color: '#4D4D4D',
    marginBottom: 30,
  },

  gradiantStyle: {
    width: 248.4,
    height: 4.71,
  },
});

最佳答案

将以下样式添加到您的 flatList =>

style={{maxHeight:'你想要什么',flexGrow:0}}

关于javascript - 我们如何根据 React Native 中的列表项内容为 FlatList 提供自动高度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73398168/

相关文章:

javascript - 如何检测元素右半部分和左半部分的点击

java - 如何在javascript中动态加载选择选项值

html - 如何制作粘性页眉、页脚和侧边栏?

css - 属性选择器中未加引号的连字符

javascript - React - 使用map()时设置默认属性

javascript - 获取没有子元素文本的父元素文本

javascript - 无法显示在不同 div 中搜索的 Mysql 搜索结果

html - 如何在响应式跨浏览器安全的图像网格上精确弹出气球?

javascript - 将 createStore 替换为 configureStore

javascript - 如何返回数字 A 除以数字 B 的次数,直到它包含余数?