Skip to content

Commit

Permalink
Update useAnimatedKeyboard docs (#5866)
Browse files Browse the repository at this point in the history
<!-- Thanks for submitting a pull request! We appreciate you spending
the time to work on these changes. Please follow the template so that
the reviewers can easily understand what the code changes affect. -->

## Summary

This PR updates the `useAnimatedKeyboard` docs to current doc pattern +
add more detailed remarks discovered while doing #5851. It's pointing to
#5851 and assumes changes from that PR, so **should be merged after**.

## Test plan

```
cd docs
yarn
yarn start
```

and go to useAnimatedKeyboard section

<!-- Provide a minimal but complete code snippet that can be used to
test out this change along with instructions how to run it and a
description of the expected behavior. -->

---------

Co-authored-by: Tomek Zawadzki <tomasz.zawadzki@swmansion.com>
Co-authored-by: Kacper Kapuściak <39658211+kacperkapusciak@users.noreply.github.com>
  • Loading branch information
3 people committed May 9, 2024
1 parent 8a792b6 commit 637429d
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 47 deletions.
139 changes: 93 additions & 46 deletions docs/docs/device/useAnimatedKeyboard.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,72 +2,119 @@
sidebar_position: 1
---

:::info
This page was ported from an old version of the documentation.

As we're rewriting the documentation some of the pages might be a little outdated.
:::
`useAnimatedKeyboard` lets you create animations based on state and height of the virtual keyboard.

:::caution

Android implementation of `useAnimatedKeyboard` is an experimental feature.
Android implementation of `useAnimatedKeyboard` has drawbacks on Android SDK < 30, for more details see [remarks](/docs/device/useAnimatedKeyboard#remarks) section.

:::

With the `useAnimatedKeyboard` hook, you can create animations based on current keyboard position.
## Reference

```javascript
import { useAnimatedKeyboard, useAnimatedStyle } from 'react-native-reanimated';

export default function App() {
const keyboard = useAnimatedKeyboard();

const animatedStyles = useAnimatedStyle(() => ({
transform: [{ translateY: -keyboard.height.value }],
}));
}
```

<details>
<summary>Type definitions</summary>

```typescript
// --- Function declaration ---

function useAnimatedKeyboard(
options: AnimatedKeyboardOptions
): AnimatedKeyboardInfo;

// --- Configuration types ---

export interface AnimatedKeyboardOptions {
isStatusBarTranslucentAndroid?: boolean;
}

// --- Return types ---

On Android, make sure to set `android:windowSoftInputMode` in your `AndroidManifest.xml` to `adjustResize`. Then, using the `useAnimatedKeyboard` hook disables
the default Android behavior (resizing the view to accommodate keyboard) in the whole app. Using values from `useAnimatedKeyboard` hook you can handle the keyboard yourself. Unmounting all components that use `useAnimatedKeyboard` hook brings back the default Android behavior.
export type AnimatedKeyboardInfo = {
height: SharedValue<number>;
state: SharedValue<KeyboardState>;
};

export enum KeyboardState {
UNKNOWN = 0,
OPENING = 1,
OPEN = 2,
CLOSING = 3,
CLOSED = 4,
}
```

</details>

### Arguments

#### `options` [AnimatedKeyboardOptions]
#### `options` <Optional />

Optional object containing additional configuration.
Optional object containing additional configuration:

- `isStatusBarTranslucentAndroid` - removes top inset on Android i.e. to use translucent status bar on Android, set this option to `true`. Defaults to `false`. Ignored on iOS.

### Returns

Hook `useAnimatedKeyboard` returns an instance of [[AnimatedKeyboardInfo](#animatedkeyboard-object)];
Hook `useAnimatedKeyboard` returns an object containing these fields:

### Types
| Name | Type | Description |
| ------ | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| height | `SharedValue<number>` | A [shared value](/docs/fundamentals/glossary#shared-value) containing current height of the keyboard. |
| state | `SharedValue<KeyboardState>` | A [shared value](/docs/fundamentals/glossary#shared-value) containing current state of the keyboard. Possible states: `{ CLOSED, OPEN, CLOSING, OPENING }` |

#### `AnimatedKeyboardInfo: [object]`
## Example

Properties:
import useBaseUrl from '@docusaurus/useBaseUrl';
import AnimatedKeyboardSrc from '!!raw-loader!@site/src/examples/AnimatedKeyboard';

- `height`: [[SharedValue](/docs/core/useSharedValue)] contains `[number]`
contains current height of the keyboard
- `state`: [[SharedValue](/docs/core/useSharedValue)] contains `[enum]`
contains current state of the keyboard. Possible states: `{ CLOSED, OPEN, CLOSING, OPENING }`
<InteractiveExample
src={AnimatedKeyboardSrc}
component={
<ThemedVideo
center
width={300}
sources={{
light: '/recordings/useAnimatedKeyboard_light.mov',
dark: '/recordings/useAnimatedKeyboard_dark.mov',
}}
/>
}
/>

#### `AnimatedKeyboardOptions: [object]`
## Remarks

Properties:
- On Android, make sure to set `android:windowSoftInputMode` in your `AndroidManifest.xml` to `adjustResize`. Then, using the `useAnimatedKeyboard` hook disables
the default Android behavior (resizing the view to accommodate keyboard) in the whole app. Using values from `useAnimatedKeyboard` hook you can handle the keyboard yourself. Unmounting all components that use `useAnimatedKeyboard` hook brings back the default Android behavior.

- `isStatusBarTranslucentAndroid`[bool] - if you want to use translucent status bar on Android, set this option to `true`. Defaults to `false`. Ignored on iOS.
- On Android, using the `useAnimatedKeyboard` hook expands root view to full screen ([immersive mode](https://developer.android.com/develop/ui/views/layout/immersive)) and takes control over insets management.

### Example
- When `isStatusBarTranslucentAndroid` is `false` it applies the top and bottom margins according to the insets.

```jsx
function AnimatedKeyboardExample() {
const keyboard = useAnimatedKeyboard();
const translateStyle = useAnimatedStyle(() => {
return {
transform: [{ translateY: -keyboard.height.value }],
};
});

return (
<ScrollView
contentContainerStyle={{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
}}>
<Animated.View style={translateStyle}>
<TextInput />
</Animated.View>
</ScrollView>
);
}
```
- When `isStatusBarTranslucentAndroid` is `true` it applies bottom padding according to the navigation inset and sets top margin to `0`.

- On Android, when using navigation with native header, `isStatusBarTranslucentAndroid` doesn't affect the top inset.

- On Android SDK < 30, when status bar is hidden, the keyboard reverts to the default Android behavior.

## Platform compatibility

<div className="platform-compatibility">

| Android | iOS | Web |
| ------- | --- | --- |
||||

</div>
6 changes: 5 additions & 1 deletion docs/src/components/ThemedVideo/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,21 @@ interface Props {
light: string;
dark: string;
};
center?: boolean;
width?: number;
}

export default function ThemedVideo(props: Props) {
const { sources } = props;

return (
<div className={styles.container}>
<div className={clsx(styles.container, props.center && styles.center)}>
<video
playsInline
autoPlay
muted
loop
width={props.width}
className={clsx(styles.themedVideo, styles[`themedVideo--dark`])}>
<source src={useBaseUrl(sources.dark)} />
</video>
Expand All @@ -28,6 +31,7 @@ export default function ThemedVideo(props: Props) {
autoPlay
muted
loop
width={props.width}
className={clsx(styles.themedVideo, styles[`themedVideo--light`])}>
<source src={useBaseUrl(sources.light)} />
</video>
Expand Down
5 changes: 5 additions & 0 deletions docs/src/components/ThemedVideo/styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
margin: '16px 0';
}

.center {
display: flex;
justify-content: center;
}

.themedVideo {
display: none;
}
Expand Down
46 changes: 46 additions & 0 deletions docs/src/examples/AnimatedKeyboard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React from 'react';
import Animated, {
useAnimatedKeyboard,
useAnimatedStyle,
} from 'react-native-reanimated';
import { StyleSheet, TextInput, View, useColorScheme } from 'react-native';

export default function App() {
const colorScheme = useColorScheme();
const keyboard = useAnimatedKeyboard();

const animatedStyles = useAnimatedStyle(() => ({
transform: [{ translateY: -keyboard.height.value }],
}));

return (
<Animated.View
style={[
styles.container,
animatedStyles,
{ backgroundColor: colorScheme === 'light' ? '#fff' : '#000' },
]}>
<View style={styles.box}>
<TextInput placeholder="Text Input" />
</View>
</Animated.View>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
borderWidth: 5,
borderColor: '#782aeb',
borderRadius: 2,
},
box: {
justifyContent: 'center',
alignItems: 'center',
height: 200,
backgroundColor: '#b58df1',
borderRadius: 5,
margin: 20,
},
});
Binary file not shown.
Binary file not shown.

0 comments on commit 637429d

Please sign in to comment.