From 360310e99ffc7b1c47e63904580e7215ddc23310 Mon Sep 17 00:00:00 2001 From: le king fu Date: Sun, 1 Mar 2026 14:40:58 -0500 Subject: [PATCH] fix: replace KeyboardAvoidingView with manual keyboard padding (#6) KeyboardAvoidingView does not work with edgeToEdgeEnabled on Android. New approach: listen to Keyboard events, dynamically set spacer height to actual keyboard height, and scrollToEnd when subtask input is focused. Co-Authored-By: Claude Opus 4.6 --- app.json | 2 +- app/task/[id].tsx | 22 ++++++++++------------ app/task/new.tsx | 22 ++++++++++------------ package.json | 2 +- 4 files changed, 22 insertions(+), 26 deletions(-) diff --git a/app.json b/app.json index 7fed122..3d6a6ac 100644 --- a/app.json +++ b/app.json @@ -2,7 +2,7 @@ "expo": { "name": "Simpl-Liste", "slug": "simpl-liste", - "version": "1.2.1", + "version": "1.2.2", "orientation": "portrait", "icon": "./assets/images/icon.png", "scheme": "simplliste", diff --git a/app/task/[id].tsx b/app/task/[id].tsx index be8e859..c01630b 100644 --- a/app/task/[id].tsx +++ b/app/task/[id].tsx @@ -8,7 +8,6 @@ import { useColorScheme, Alert, Platform, - KeyboardAvoidingView, Keyboard, } from 'react-native'; import { useRouter, useLocalSearchParams } from 'expo-router'; @@ -83,16 +82,20 @@ export default function TaskDetailScreen() { const [selectedListId, setSelectedListId] = useState(''); const [saving, setSaving] = useState(false); const scrollRef = useRef(null); - const subtaskInputY = useRef(0); const subtaskFocused = useRef(false); + const [keyboardHeight, setKeyboardHeight] = useState(0); useEffect(() => { - const sub = Keyboard.addListener('keyboardDidShow', () => { + const showSub = Keyboard.addListener('keyboardDidShow', (e) => { + setKeyboardHeight(e.endCoordinates.height); if (subtaskFocused.current) { - scrollRef.current?.scrollTo({ y: subtaskInputY.current - 80, animated: true }); + setTimeout(() => scrollRef.current?.scrollToEnd({ animated: true }), 100); } }); - return () => sub.remove(); + const hideSub = Keyboard.addListener('keyboardDidHide', () => { + setKeyboardHeight(0); + }); + return () => { showSub.remove(); hideSub.remove(); }; }, []); useEffect(() => { @@ -223,7 +226,6 @@ export default function TaskDetailScreen() { - {/* Title */} { subtaskInputY.current = e.nativeEvent.layout.y; }} - > + - + - ); } diff --git a/app/task/new.tsx b/app/task/new.tsx index 91be103..d37aa95 100644 --- a/app/task/new.tsx +++ b/app/task/new.tsx @@ -7,7 +7,6 @@ import { ScrollView, useColorScheme, Platform, - KeyboardAvoidingView, Keyboard, } from 'react-native'; import { useRouter, useLocalSearchParams } from 'expo-router'; @@ -61,16 +60,20 @@ export default function NewTaskScreen() { const [pendingSubtasks, setPendingSubtasks] = useState([]); const [newSubtask, setNewSubtask] = useState(''); const scrollRef = useRef(null); - const subtaskInputY = useRef(0); const subtaskFocused = useRef(false); + const [keyboardHeight, setKeyboardHeight] = useState(0); useEffect(() => { - const sub = Keyboard.addListener('keyboardDidShow', () => { + const showSub = Keyboard.addListener('keyboardDidShow', (e) => { + setKeyboardHeight(e.endCoordinates.height); if (subtaskFocused.current) { - scrollRef.current?.scrollTo({ y: subtaskInputY.current - 80, animated: true }); + setTimeout(() => scrollRef.current?.scrollToEnd({ animated: true }), 100); } }); - return () => sub.remove(); + const hideSub = Keyboard.addListener('keyboardDidHide', () => { + setKeyboardHeight(0); + }); + return () => { showSub.remove(); hideSub.remove(); }; }, []); useEffect(() => { @@ -150,7 +153,6 @@ export default function NewTaskScreen() { - {/* Title */} { subtaskInputY.current = e.nativeEvent.layout.y; }} - > + - + - ); } diff --git a/package.json b/package.json index c8e7699..19652d6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "simpl-liste", "main": "index.js", - "version": "1.2.1", + "version": "1.2.2", "scripts": { "start": "expo start", "android": "expo start --android",