iOS 中使用 SafeAreaView 和 KeyboardAvoidingView 导致底部过多空白

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

我在使用 SafeAreaView、KeyboardAvoidingView 和 ScrollView 时遇到 iOS 屏幕底部空白过多的问题。该布局在 Android 上运行良好,但在 iOS 上,内容下方有一个不需要的空白区域。

这是我当前对该组件的实现:

import React from "react";
import { SafeAreaView } from "react-native-safe-area-context";
import {
  ScrollView,
  KeyboardAvoidingView,
  RefreshControl,
  Platform,
} from "react-native";
import { StatusBar } from "expo-status-bar";

const MainView = ({
  style,
  children,
  fixedHeader,
  loading,
  hasRefresh = false,
  refreshing = false,
  onRefresh,
  onScroll,
  needScrollView = true,
  needTopEdge = true,
  theme,
  insets,
}) => {
  return (
    <SafeAreaView
      style={[
        styles.safeAreaView,
        style,
        { paddingBottom: insets.bottom, marginBottom: 0 }, // Adjusting padding
      ]}
      edges={
        needTopEdge ? ["bottom", "left", "right", "top"] : ["bottom", "left", "right"]
      }
    >
      {fixedHeader}
      <KeyboardAvoidingView
        style={{ flex: 1 }}
        behavior={Platform.OS === "ios" ? "padding" : undefined}
        keyboardVerticalOffset={insets.top + 10} // Setting offset
      >
        {needScrollView ? (
          <ScrollView
            onScroll={onScroll}
            automaticallyAdjustKeyboardInsets={true}
            contentContainerStyle={[
              styles.scrollViewContent,
              { paddingBottom: insets.bottom }, // Adding bottom padding
            ]}
            showsVerticalScrollIndicator={false}
            refreshControl={
              hasRefresh ? (
                <RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
              ) : undefined
            }
          >
            {loading ? <ThemedActiveIndicator /> : children}
          </ScrollView>
        ) : (
          <>{loading ? <ThemedActiveIndicator /> : children}</>
        )}
      </KeyboardAvoidingView>
      <StatusBar
        style={theme === "dark" ? "light" : "dark"}
        backgroundColor={"black"}
      />
    </SafeAreaView>
  );
};

const styles = {
  safeAreaView: {
    flex: 1,
    backgroundColor: "white",
  },
  scrollViewContent: {
    flexGrow: 1,
    paddingBottom: 20, // Adding padding
  },
};

export default MainView;

#此代码也遇到相同的空白问题

import { SafeAreaView, useSafeAreaInsets } from "react-native-safe-area-context";
import { StatusBar } from "expo-status-bar";
import React, { ReactNode } from "react";
import { ScrollView, StyleSheet, RefreshControl, NativeSyntheticEvent, NativeScrollEvent } from "react-native";
import { StyleProps } from "react-native-reanimated";
import { ThemedView } from "@/components/ThemedView";
import { useGlobalContext } from "@/context/GlobalProvider";
import ThemedActiveIndicator from "../themedActiveIndicator/ThemedActiveIndicator";

interface Props {
  children: React.ReactNode;
  style?: StyleProps;
  needTopEdge?: boolean;
  hasRefresh?: boolean;
  refreshing?: boolean;
  onRefresh?: () => void;
  fixedHeader?: ReactNode;
  onScroll?: (e: NativeSyntheticEvent<NativeScrollEvent>) => void;
  loading?:boolean;
  needScrollView?:boolean;
  addBottomMargin?:boolean;
}

const MainView = ({
  children,
  style,
  needTopEdge = false,
  hasRefresh = false,
  refreshing = false,
  loading=false,
  fixedHeader,
  onScroll,
  onRefresh = () => {},
  needScrollView=true,
  addBottomMargin=false
}: Props) => {
  const { theme } = useGlobalContext();
  const inserts = useSafeAreaInsets()
  return (
    <ThemedView style={{ height: "100%" }}>
      <SafeAreaView
        style={[
          styles.safeAreaView,
          style,
          addBottomMargin ? { marginBottom: inserts.top +60 } : {},
        ]}
        edges={
          needTopEdge
            ? ["bottom", "left", "right", "top"]
            : ["bottom", "left", "right"]
        }
      >
        {fixedHeader}
        {needScrollView ? (
          <ScrollView
            onScroll={onScroll}
            automaticallyAdjustKeyboardInsets={true}
            contentContainerStyle={styles.scrollViewContent}
            showsVerticalScrollIndicator={false}
            refreshControl={
              hasRefresh ? (
                <RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
              ) : undefined
            }
          >
            {loading ? <ThemedActiveIndicator /> : children}
          </ScrollView>
        ) : (
          <>{loading ? <ThemedActiveIndicator /> : children}</>
        )}

        <StatusBar
          style={theme == "dark" ? "light" : "dark"}
          backgroundColor={"black"}
        />
      </SafeAreaView>
    </ThemedView>
  );
};

const styles = StyleSheet.create({
  safeAreaView: { flex: 1, padding: 0, margin: 0 },
  keyboardAvoidingView: { flex: 1 },
  scrollViewContent: { flexGrow: 1 },
});

export default React.memo(MainView);

问题:

在 iOS 上:

  • 屏幕底部出现大量空白,尤其是当键盘关闭时。

到目前为止我尝试过的:

  1. keyboardVerticalOffset
    中调整
    KeyboardAvoidingView
  2. paddingBottom
    contentContainerStyle
    中添加/删除
    ScrollView
  3. 确保仅在必要时应用
    flexGrow: 1
  4. 使用
    console.log(insets.bottom)
    进行调试,以确保正确计算安全区域插入。

问题:

  1. 为什么这个空白专门出现在 iOS 上?
  2. 是否有更好的方法来组合
    SafeAreaView
    KeyboardAvoidingView
    ScrollView
    来避免此问题?
  3. 我应该考虑任何特定于平台的怪癖或替代方案吗?

任何帮助或见解将不胜感激! 😊

ios react-native scrollview safeareaview keyboardavoidingview
1个回答
0
投票

这是针对您的问题的解决方案,基于平台应用填充。

const styles = {
  safeAreaView: {
    flex: 1,
    backgroundColor: "white",
  },
  scrollViewContent: {
    flexGrow: 1, //removed paddingBottom from here.
  },
};

像这样添加平台检查:

 <ScrollView
            onScroll={onScroll}
            automaticallyAdjustKeyboardInsets={true}
            contentContainerStyle={[
              styles.scrollViewContent,
              { paddingBottom: Platform.OS === 'android' ? 20 : insets.bottom}, // padding according to OS.
            ]}
            showsVerticalScrollIndicator={false}
            refreshControl={
              hasRefresh ? (
                <RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
              ) : undefined
            }
          >
© www.soinside.com 2019 - 2024. All rights reserved.