如何在底部对齐的视图避免键盘弹出时布局跳动?

huangapple go评论47阅读模式
英文:

How to avoid having the layout jump when avoiding the keyboard with a bottom aligned View?

问题

我有一个视图,我想将其定位在屏幕底部,使用 `position: absolute, bottom: 0`,并使其位于键盘的正上方。在 Android 上,我无法使其正常工作,否则会导致布局出现问题。

 iOS 上,通过 `react-native-reanimated`  `useAnimatedKeyboard`,可以轻松实现如下效果:
```tsx
const keyboard = useAnimatedKeyboard()

const bottomStyle = useAnimatedStyle(() => ({
  paddingBottom: keyboard.height.value,
}))

然而,在 Android 上,这种方法会出现问题,因为我需要在应用的其他部分保持 android:windowSoftInputMode 设置为 "adjustResize",而调用 useAnimatedKeyboard 会修改此设置,导致应用在瞬间向上移动一点,然后再重新适应新的设置。

当我禁用此功能时,我注意到视图在键盘第一次打开时会突然上移,然后迅速回到屏幕底部。在任何其他屏幕和任何其他时间,只要我不关闭应用再次操作,它就会正常工作(始终保持在屏幕底部,不会上移)。这是一个问题,因为如果我使用键盘事件监听器来监听 keyboardDidOpen 事件以获取键盘的高度,并将其用作视图的填充,这将导致视图在键盘首次打开时瞬间出现在键盘的整个高度之上,然后再次调整到正确的位置。


<details>
<summary>英文:</summary>

I have a View I want to position at the bottom of the screen with `position: absolute, bottom: 0`, and keep it just above the keyboard. I can&#39;t get this to work on Android without the layout breaking.

On iOS this was pretty easy with `react-native-reanimated`&#39;s `useAnimatedKeyboard` doing the following:
```tsx
const keyboard = useAnimatedKeyboard()

const bottomStyle = useAnimatedStyle(() =&gt; ({
  paddingBottom: keyboard.height.value,
}))

However, this breaks on Android, because I need to keep android:windowSoftInputMode set to &quot;adjustResize&quot; on the rest of the app, and when calling useAnimatedKeyboard this is modified, causing the app to shift slightly up for an instant, before the app readjusts to the new setting.

When I disabled this, I noticed the View would snap up to the keyboard for an instant, before shifting back to the bottom of the screen, on the first time the keyboard would open. On any other screen and any other time I did this again without closing the app, it would behave normally (stay at the bottom of the screen at all times, without shifting up). This was a problem because if I used the Keyboard event listener to watch for a keyboardDidOpen event to get the keyboard height, and use that as padding to the View, this would position the View correctly above the keyboard, but on the first time the keyboard was opened this would cause my View to appear an entire keyboard height above the keyboard for a moment, before settling back.

答案1

得分: 1

我想创建这个问题,以便将来的人不会陷入我所遇到的同样问题。

最终,我注意到渲染树上有一个 KeyboardAvoidingView,但由于它的 enabled 属性设置为 false,我没有认为这可能是个问题。

然而,我注意到即使禁用了该 KeyboardAvoidingView,它的 behavior 仍然会影响我的组件。因此,仅禁用 KeyboardAvoidingView 不足以解决问题,但当我完全删除 behavior 属性时,问题就得到了解决。

因此,以下代码会导致底部对齐的 View 在第一次打开键盘时瞬间"跳"到正确位置之前上移:

<KeyboardAvoidingView enabled={false} behavior="height">
{/* 其余部分 */}
</KeyboardAvoidingView>

但这将使 View 从第一次打开键盘时就表现正常:

<KeyboardAvoidingView enabled={false}>
{/* 其余部分 */}
</KeyboardAvoidingView>
英文:

I wanted to create this question so people in the future don't get stuck in the same issue I did.

Eventually, I was able to notice that there was a KeyboardAvoidingView on the render tree, but since it had enabled set to false, I didn't think that could be a problem.

However, what I noticed was that the behavior from that KeyboardAvoidingView was still impacting my component even though it was disabled. Therefore it wasn't enough to disable the KeyboardAvoidingView, but when I removed the behavior prop entirely, then this issue was resolved.

Therefore, the following would cause the bottom-aligned View to "jump" up for a moment, on the first time the keyboard was opened, before going back to the correct location:

&lt;KeyboardAvoidingView enabled={false} behavior=&quot;height&quot;&gt;
{/* Rest of the screen */}
&lt;/KeyboardAvoidingView&gt; 

But this would make the View behave correctly from the first time the keyboard opened:

&lt;KeyboardAvoidingView enabled={false}&gt;
{/* Rest of the screen */}
&lt;/KeyboardAvoidingView&gt;

huangapple
  • 本文由 发表于 2023年6月2日 02:04:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/76384571.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定