React Native:Android 软键盘将 View 向上推
Posted
技术标签:
【中文标题】React Native:Android 软键盘将 View 向上推【英文标题】:React native: Android soft keyboard push the View up 【发布时间】:2021-11-28 10:53:48 【问题描述】:我制作了一张自定义动画底页。它有两个捕捉点。它从屏幕顶部开始,如果向下滚动动画卡片,它将来到屏幕中间,再次向下滚动卡片,它将来到屏幕底部。如果用户用力向下滚动动画卡片,那么它将一直向下滚动。我把这个组件做成了一个可重用的组件。
我制作了可重复使用的搜索组件。
我将这两个组件都导入到 main-app 组件中。在 Animated-Bottom-sheet 中,我放置了 Search-component。
我已经为 keyboard 和 Animated.View
设置了条件如果动画视图从屏幕中间移动到底部并搜索 onFocus(出现键盘),则 Keyboard 将关闭。
如果动画视图位于屏幕底部并搜索输入onfocus
(出现键盘),那么它会将动画视图移动到屏幕中间。对于这个逻辑,我做了Keyboard.addListener('keyboardDidHide',()=>....)
我的这个逻辑在 IOS 中完美运行,但在 Android 中,它将所有元素推送到屏幕顶部。
有很多关于 KeyboardAvoidingView 的建议,但就我而言,它不起作用。
在 react-native 的 android 的 AndroidManifest.xml 文件中。我制作了android:windowSoftInputMode="adjustPan"
,它听Keyboard.addListener('keyboardDidHide'
并将所有元素推到屏幕顶部,如果我制作android:windowSoftInputMode="adjustPan|adjustResize"
,那么它不会听Event-lister
。结果,我的逻辑不起作用,它隐藏了 Android 键盘下的动画视图。根据RN-documentation,Event-lister 只听adjustResize or adjustPan
。
问题:
我真的不知道如何解决这个问题
Android 设备行为
DEMO
代码演示
expo-snacks
这是我的动画视图组件
import React, useState from "react";
import StyleSheet, Dimensions, Platform, View, Keyboard from "react-native";
import
PanGestureHandler,
PanGestureHandlerGestureEvent,
from "react-native-gesture-handler";
import Animated,
useAnimatedGestureHandler,
useAnimatedStyle,
useSharedValue,
withTiming,
withSpring,
runOnJS,
Easing,
from "react-native-reanimated";
import styled from "styled-components/native";
interface Props
children: React.ReactNode;
const height: SCREEN_HEIGHT = Dimensions.get("screen");
const IPHONE_DEVICE_MIDDLE_SCREEN = Platform.OS === "ios" ? 4 : 4;
const IPHONE_DEVICE_BOTTOM_SCREEN = Platform.OS === "ios" ? 7.6 : 7.36;
const ANIMATED_DURATION = 300;
const LoadingContainer = styled.View`
height: $SCREEN_HEIGHT - 300px;
background-color: #fff;
justify-content: center;
`;
const ScrollBottomSheet = ( children : Props) =>
const contentTop = useSharedValue(SCREEN_HEIGHT);
const [bottomSheetState, setBottomSheetState] = useState("top");
// Event-listener
Keyboard.addListener("keyboardDidShow", () =>
if (bottomSheetState === "bottom")
contentTop.value = withSpring(
SCREEN_HEIGHT * IPHONE_DEVICE_MIDDLE_SCREEN
);
);
const animatedStyle = useAnimatedStyle(() =>
"worklet";
return
top: contentTop.value * 0.1,
bottom: 0,
;
);
const gestureHandler = useAnimatedGestureHandler(
onStart(_, context)
context.translateY = contentTop.value;
,
onActive(event, context)
contentTop.value = context.translateY + event.translationY;
,
onEnd(event, _)
if (event.y > 0 && event.y < 200)
// MIDDLE SCREEN LOGIC
contentTop.value = withTiming(
SCREEN_HEIGHT * IPHONE_DEVICE_MIDDLE_SCREEN,
duration: ANIMATED_DURATION,
easing: Easing.inOut(Easing.ease),
);
runOnJS(setBottomSheetState)("middle");
runOnJS(Keyboard.dismiss)(); // dismiss Keyboard
else if (event.y > 200)
// BOTTOM SCREEN LOGIC
contentTop.value = withTiming(
SCREEN_HEIGHT * IPHONE_DEVICE_BOTTOM_SCREEN,
duration: ANIMATED_DURATION,
easing: Easing.inOut(Easing.ease),
);
runOnJS(Keyboard.dismiss)();
runOnJS(setBottomSheetState)("bottom");
else if (event.translationY < 0)
contentTop.value = withTiming(SCREEN_HEIGHT,
duration: ANIMATED_DURATION,
easing: Easing.inOut(Easing.ease),
);
runOnJS(setBottomSheetState)("top");
,
,
[contentTop]
);
return (
<PanGestureHandler onGestureEvent=gestureHandler>
<Animated.View style=[styles.container, animatedStyle]>
<View style=styles.grbber />
children
</Animated.View>
</PanGestureHandler>
);
;
export default ScrollBottomSheet;
const styles = StyleSheet.create(
container:
position: "absolute",
left: 0,
right: 0,
top: 0,
backgroundColor: "#fff",
shadowOffset:
height: -6,
width: 0,
,
shadowOpacity: 0.1,
shadowRadius: 5,
borderTopEndRadius: 15,
borderTopLeftRadius: 15,
,
grbber:
width: 80,
height: 5,
marginBottom: 4,
alignSelf: "center",
marginTop: 5,
borderTopWidth: 5,
borderTopColor: "#aaa",
,
);
搜索组件
import React, useRef, useEffect from "react";
import
Animated,
KeyboardTypeOptions,
TextInputProps,
TextInput,
Text,
Keyboard,
from "react-native";
import styled from "styled-components/native";
type Props = TextInputProps &
text: string,
hint: string,
onChangeText?: ((text: string) => void) | undefined,
onClearText: () => void,
animatedStyle?: height: Animated.AnimatedInterpolation ,
keyboardType?: KeyboardTypeOptions,
autoFocus?: boolean,
;
const Container = styled(Animated.View)`
flex-direction: row;
background-color: grey;
border-radius: 6px;
align-items: center;
`;
const IconTouchableOpacity = styled.TouchableOpacity`
padding: 16px;
`;
const SearchInput = styled.TextInput`
flex: 1;
padding-right: 16px;
color: #fff;
font-size: 16px;
line-height: 20px;
height: 44px;
`;
const SearchBar = (
text,
hint,
onChangeText,
onClearText,
animatedStyle,
keyboardType,
maxLength,
autoFocus,
: Props) =>
const searchInput = useRef(null);
const onSearchPress = () =>
searchInput?.current?.focus();
;
useEffect(() =>
if (autoFocus)
onSearchPress();
, [autoFocus]);
return (
<Container accessible=false style=animatedStyle>
<SearchInput
ref=searchInput
onChangeText=onChangeText
value=text
placeholder=hint
maxLength=maxLength
underlineColorAndroid="transparent"
placeholderTextColor="grey"
keyboardType=keyboardType
autoFocus=autoFocus
onKeyPress=() => hideKeyBoard
/>
</Container>
);
;
export default SearchBar;
**应用组件
import React, useState, useEffect from "react";
import StyleSheet, Button from "react-native";
import TouchableHighlight from "react-native-gesture-handler";
import MapView from "react-native-maps";
import styled from "styled-components";
import ScrollBottomSheet from "./components/ActionSheet";
import SearchBar from "./components/SearchBar";
const initialRegion =
latitudeDelta: 15,
longitudeDelta: 15,
latitude: 60.1098678,
longitude: 24.7385084,
;
export default function App()
return (
<>
<MapView style=styles.mapStyle initialRegion=initialRegion />
<ScrollBottomSheet>
<SearchContainer>
<SearchBar hint="search" />
</SearchContainer>
</ScrollBottomSheet>
</>
);
const styles = StyleSheet.create(
mapStyle:
height: "100%",
,
);
const SearchContainer = styled.View`
padding: 10px;
`;
【问题讨论】:
您如何尝试使用KeyboardAvoidingView
?你定义了什么行为?我遇到了类似的问题,它帮助我将行为属性定义为高度 - <KeyboardAvoidingView behavior='height' enable=true>/*...*/</KeyboardAvoidingView>
KeyboardTypeOptions from 'react-native' ?
【参考方案1】:
您是否尝试过使用 Animated.ScrollView 代替 Animated.View?
【讨论】:
不,我没有使用Animated.ScrollView
。对我有什么帮助以上是关于React Native:Android 软键盘将 View 向上推的主要内容,如果未能解决你的问题,请参考以下文章
如何在带有 React Native Text 的 Android 中实现软连字符
如何在 react-native 应用程序中更改 android 的键盘主题?