fix: adjust layout for Android (#3548)

* fix: adjust tab bar height for Android to account for insets

* fix(mobile): onboarding screen layout adjustments

* fix(mobile): update header height calculation to use Constants for status bar height

* fix(mobile): remove unnecessary RootSiblingParent wrapper in Subscriptions component
This commit is contained in:
Whitewater 2025-04-22 18:14:45 +08:00 committed by GitHub
parent c3812be806
commit 3343ddb658
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 57 additions and 54 deletions

View File

@ -16,6 +16,7 @@ import { SetBottomTabBarHeightContext } from "@/src/components/layouts/tabbar/co
import { gentleSpringPreset, quickSpringPreset, softSpringPreset } from "@/src/constants/spring"
import { BottomTabContext } from "@/src/lib/navigation/bottom-tab/BottomTabContext"
import type { TabbarIconProps, TabScreenProps } from "@/src/lib/navigation/bottom-tab/types"
import { isAndroid } from "@/src/lib/platform"
import { PlayerTabBar } from "@/src/modules/player/PlayerTabBar"
import { accentColor } from "@/src/theme/colors"
@ -73,7 +74,8 @@ export const Tabbar: FC<{
transform: [{ translateY }],
}}
onLayout={(e) => {
setTabBarHeight(e.nativeEvent.layout.height)
const tabBarHeight = e.nativeEvent.layout.height + (isAndroid ? insets.bottom : 0)
setTabBarHeight(tabBarHeight)
}}
>
<TabBarBackground />

View File

@ -1,4 +1,5 @@
import { PixelRatio, Platform } from "react-native"
import Constants from "expo-constants"
import { Platform } from "react-native"
type Layout = { width: number; height: number }
/**
@ -14,7 +15,7 @@ export function getDefaultHeaderHeight(
// On models with Dynamic Island the status bar height is smaller than the safe area top inset.
const hasDynamicIsland = topInset > 50
const statusBarHeight = hasDynamicIsland ? topInset - (5 + 1 / PixelRatio.get()) : topInset
const topHeight = hasDynamicIsland ? Constants.statusBarHeight : topInset
const isLandscape = layout.width > layout.height
@ -36,5 +37,5 @@ export function getDefaultHeaderHeight(
}
}
return headerHeight + (!modalPresentation ? statusBarHeight : 0)
return headerHeight + (!modalPresentation ? topHeight : 0)
}

View File

@ -1,6 +1,5 @@
import type { FeedViewType } from "@follow/constants"
import { useMemo } from "react"
import { RootSiblingParent } from "react-native-root-siblings"
import { useColor } from "react-native-uikit-colors"
import { ErrorBoundary } from "@/src/components/common/ErrorBoundary"
@ -22,19 +21,17 @@ export default function Subscriptions() {
useResetTabOpacityWhenFocused()
return (
<EntryListContext.Provider value={useMemo(() => ({ type: "subscriptions" }), [])}>
<RootSiblingParent>
<TimelineHeader />
{whoami ? (
<PagerList
renderItem={renderItem}
style={{
backgroundColor: systemGroupedBackground,
}}
/>
) : (
<NoLoginInfo target="subscriptions" />
)}
</RootSiblingParent>
<TimelineHeader />
{whoami ? (
<PagerList
renderItem={renderItem}
style={{
backgroundColor: systemGroupedBackground,
}}
/>
) : (
<NoLoginInfo target="subscriptions" />
)}
</EntryListContext.Provider>
)
}

View File

@ -1,8 +1,9 @@
import { tracker } from "@follow/tracker"
import { useCallback, useEffect, useState } from "react"
import { useTranslation } from "react-i18next"
import { SafeAreaView, Text, TouchableOpacity, View } from "react-native"
import { Text, TouchableOpacity, View } from "react-native"
import Animated, { FadeInRight, FadeOutLeft } from "react-native-reanimated"
import { useSafeAreaInsets } from "react-native-safe-area-context"
import { kv } from "../lib/kv"
import { useNavigation } from "../lib/navigation/hooks"
@ -16,6 +17,7 @@ import { isNewUserQueryKey, isOnboardingFinishedStorageKey } from "../store/user
export const OnboardingScreen: NavigationControllerView = () => {
const { t } = useTranslation("common")
const insets = useSafeAreaInsets()
const [currentStep, setCurrentStep] = useState(1)
const totalSteps = 4
@ -39,43 +41,44 @@ export const OnboardingScreen: NavigationControllerView = () => {
}, [])
return (
<View className="bg-system-grouped-background flex-1 px-6">
<SafeAreaView className="flex-1">
<ProgressIndicator
currentStep={currentStep}
totalSteps={totalSteps}
setCurrentStep={setCurrentStep}
/>
<View
className="bg-system-grouped-background flex-1 px-6"
style={{ paddingTop: insets.top, paddingBottom: insets.bottom }}
>
<ProgressIndicator
currentStep={currentStep}
totalSteps={totalSteps}
setCurrentStep={setCurrentStep}
/>
<Animated.View
className={"flex-1"}
key={`step-${currentStep}`}
exiting={FadeOutLeft}
entering={FadeInRight}
<Animated.View
className={"flex-1"}
key={`step-${currentStep}`}
exiting={FadeOutLeft}
entering={FadeInRight}
>
{/* Content */}
{currentStep === 1 && <StepWelcome />}
{currentStep === 2 && <StepPreferences />}
{currentStep === 3 && <StepInterests />}
{currentStep === 4 && <StepFinished />}
</Animated.View>
{/* Navigation buttons */}
<View className="mb-6 px-6">
<TouchableOpacity
onPress={handleNext}
className="bg-accent w-full items-center rounded-xl py-4"
>
{/* Content */}
{currentStep === 1 && <StepWelcome />}
{currentStep === 2 && <StepPreferences />}
{currentStep === 3 && <StepInterests />}
{currentStep === 4 && <StepFinished />}
</Animated.View>
{/* Navigation buttons */}
<View className="mb-6 px-6">
<TouchableOpacity
onPress={handleNext}
className="bg-accent w-full items-center rounded-xl py-4"
>
<Text className="text-lg font-bold text-white">
{currentStep < totalSteps - 1
? t("words.next")
: currentStep === totalSteps - 1
? t("words.finishSetup")
: t("words.letsGo")}
</Text>
</TouchableOpacity>
</View>
</SafeAreaView>
<Text className="text-lg font-bold text-white">
{currentStep < totalSteps - 1
? t("words.next")
: currentStep === totalSteps - 1
? t("words.finishSetup")
: t("words.letsGo")}
</Text>
</TouchableOpacity>
</View>
</View>
)
}