Commit d1fb606
authored
## 📜 Description
Fixed `enabled` behavior for `KeyboardStickyView` on fabric.
## 💡 Motivation and Context
It looks like on fabric when we detach animated value we "break" graph
of native driver animations (sine we don't use Animated value anymore)
and animations becomes just frozen (element is not getting moved to its
initial position).
To overcome this problem I replaced plain `closed` value with `Animated`
one:
```ts
Animated.add(Animated.multiply(height, 0), closed);
```
Effectively we still consume `height`, but we multiply it by `0` (we get
`0` after that) and after that we make additions `0` + `closed` as
animated value. As a result we always switch between animated values and
we always use `height` value (it was critical, if we stop to use it we
get again the same bug).
I used this code for testing:
```tsx
import React, { useCallback, useEffect, useMemo, useState } from "react";
import { Button, Text, View } from "react-native";
import {
KeyboardAwareScrollView,
KeyboardController,
KeyboardStickyView,
} from "react-native-keyboard-controller";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import TextInput from "../../../components/TextInput";
import { styles } from "./styles";
import type { ExamplesStackParamList } from "../../../navigation/ExamplesStack";
import type { StackScreenProps } from "@react-navigation/stack";
import type { LayoutChangeEvent } from "react-native";
type Props = StackScreenProps<ExamplesStackParamList>;
const variants = ["v1", "v2", "v3"] as const;
type Variant = (typeof variants)[number];
export default function AwareScrollViewStickyFooter({ navigation }: Props) {
const { bottom } = useSafeAreaInsets();
const [footerHeight, setFooterHeight] = useState(0);
const [additionalHeight, setAdditionalHeight] = useState(0);
const [variant, setVariant] = useState<Variant>("v1");
const handleLayout = useCallback((evt: LayoutChangeEvent) => {
setFooterHeight(evt.nativeEvent.layout.height);
}, []);
const offset = useMemo(
() => ({ closed: 0, opened: variant === "v1" ? 0 : bottom }),
[bottom, variant],
);
const offsetV3 = useMemo(
() => ({ closed: -50, opened: bottom - 25 }),
[bottom],
);
const [enabled, setEnabled] = useState(true);
useEffect(() => {
navigation.setOptions({
headerRight: () => (
<Text
style={styles.header}
onPress={() => {
const index = variants.indexOf(variant);
setVariant(variants[index === variants.length - 1 ? 0 : index + 1]);
}}
>
{variant}
</Text>
),
});
}, [variant]);
const v1v2 = variant === "v1" || variant === "v2";
return (
<View
style={[
styles.pageContainer,
{ paddingBottom: variant === "v1" ? 0 : bottom },
]}
>
<KeyboardAwareScrollView
bottomOffset={(v1v2 ? footerHeight + additionalHeight : 0) + 50}
contentContainerStyle={styles.content}
keyboardShouldPersistTaps="handled"
style={styles.container}
testID="aware_scroll_sticky_view_scroll_container"
>
{new Array(10).fill(0).map((_, i) => (
<TextInput
key={i}
keyboardType={i % 2 === 0 ? "numeric" : "default"}
placeholder={`TextInput#${i}`}
/>
))}
</KeyboardAwareScrollView>
{v1v2 && (
<KeyboardStickyView offset={offset} enabled={enabled}>
<View
style={{ height: additionalHeight, backgroundColor: "magenta" }}
/>
<View style={styles.footer} onLayout={handleLayout}>
<Text style={styles.footerText}>A mocked sticky footer</Text>
<TextInput placeholder="Amount" style={styles.inputInFooter} />
<Button
testID="toggle_height"
title="Toggle height"
onPress={() => {
setEnabled(false);
setTimeout(() => {
KeyboardController.dismiss();
}, 500)
}}
/>
</View>
</KeyboardStickyView>
)}
{variant === "v3" && (
<KeyboardStickyView offset={offsetV3}>
<View style={styles.circle} />
</KeyboardStickyView>
)}
</View>
);
}
```
## 📢 Changelog
<!-- High level overview of important changes -->
<!-- For example: fixed status bar manipulation; added new types
declarations; -->
<!-- If your changes don't affect one of platform/language below - then
remove this platform/language -->
### JS
- don't break animated graph;
## 🤔 How Has This Been Tested?
Tested in example project manually.
## 📸 Screenshots (if appropriate):
|Before|After|
|-------|-----|
|<video
src="https://github.com/user-attachments/assets/6adbf44a-4256-4e1f-b842-d94284b1c8d9">|<video
src="https://github.com/user-attachments/assets/6026bd1b-c643-4be0-b331-ca0c1006e53f">|
## 📝 Checklist
- [x] CI successfully passed
- [x] I added new mocks and corresponding unit-tests if library API was
changed
1 parent 76056c3 commit d1fb606
1 file changed
Lines changed: 10 additions & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
58 | 58 | | |
59 | 59 | | |
60 | 60 | | |
61 | | - | |
62 | | - | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
63 | 66 | | |
64 | 67 | | |
65 | | - | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
66 | 71 | | |
67 | 72 | | |
68 | 73 | | |
69 | | - | |
70 | | - | |
71 | | - | |
| 74 | + | |
| 75 | + | |
72 | 76 | | |
73 | 77 | | |
74 | 78 | | |
| |||
0 commit comments