├── .eslintignore
├── .eslintrc.js
├── .gitattributes
├── .gitignore
├── .prettierrc.js
├── LICENSE
├── README.md
├── RNKeyboardInsets.podspec
├── android
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ └── java
│ └── com
│ └── reactnative
│ └── keyboardinsets
│ ├── EdgeInsets.java
│ ├── KeyboardAutoHandler.java
│ ├── KeyboardInsetsCallback.java
│ ├── KeyboardInsetsModule.java
│ ├── KeyboardInsetsPackage.java
│ ├── KeyboardInsetsView.java
│ ├── KeyboardInsetsViewManager.java
│ ├── KeyboardManualHandler.java
│ ├── KeyboardPositionChangedEvent.java
│ ├── KeyboardStatusChangedEvent.java
│ └── SystemUI.java
├── babel.config.js
├── example
├── App.tsx
├── KeyboardChat
│ ├── Message
│ │ ├── data.ts
│ │ ├── index.tsx
│ │ ├── styles.ts
│ │ └── types.ts
│ ├── driver
│ │ ├── Driver.ts
│ │ ├── KeyboardDriver.ts
│ │ └── ViewDriver.ts
│ ├── icon
│ │ ├── emoji@2x.png
│ │ ├── emoji@3x.png
│ │ ├── keyboard@2x.png
│ │ ├── keyboard@3x.png
│ │ ├── plus@2x.png
│ │ └── plus@3x.png
│ ├── index.tsx
│ └── styles.ts
├── android
│ ├── app
│ │ ├── build.gradle
│ │ ├── debug.keystore
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ │ ├── debug
│ │ │ └── AndroidManifest.xml
│ │ │ └── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java
│ │ │ └── com
│ │ │ │ └── reactnative
│ │ │ │ └── keyboardinsets
│ │ │ │ └── example
│ │ │ │ ├── MainActivity.java
│ │ │ │ └── MainApplication.java
│ │ │ └── res
│ │ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ └── values
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ ├── build.gradle
│ ├── gradle.properties
│ ├── gradle
│ │ └── wrapper
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ ├── gradlew
│ ├── gradlew.bat
│ └── settings.gradle
├── index.js
└── ios
│ ├── KeyboardInsetsExample.xcodeproj
│ ├── project.pbxproj
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── KeyboardInsetsExample.xcscheme
│ ├── KeyboardInsetsExample.xcworkspace
│ └── contents.xcworkspacedata
│ ├── KeyboardInsetsExample
│ ├── AppDelegate.h
│ ├── AppDelegate.m
│ ├── Assets.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ └── Contents.json
│ │ └── Contents.json
│ ├── Base.lproj
│ │ └── LaunchScreen.storyboard
│ ├── Info.plist
│ └── main.m
│ ├── Podfile
│ └── Podfile.lock
├── ios
├── KeyboardInsets.xcodeproj
│ └── project.pbxproj
└── KeyboardInsets
│ ├── HBDKeyboardAutoHandler.h
│ ├── HBDKeyboardAutoHandler.m
│ ├── HBDKeyboardInsetsModule.h
│ ├── HBDKeyboardInsetsModule.m
│ ├── HBDKeyboardInsetsView.h
│ ├── HBDKeyboardInsetsView.m
│ ├── HBDKeyboardInsetsViewManager.h
│ ├── HBDKeyboardInsetsViewManager.m
│ ├── HBDKeyboardManualHandler.h
│ └── HBDKeyboardManualHandler.m
├── metro.config.js
├── package.json
├── react-native.config.js
├── src
├── KeyboardInsetsView.tsx
├── hook.ts
├── index.ts
└── native.ts
├── tsconfig.build.json
├── tsconfig.json
└── yarn.lock
/.eslintignore:
--------------------------------------------------------------------------------
1 | ios/
2 | android/
3 | builds/
4 | */build/
5 | lib/
6 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | extends: ['@gfez/react-native', 'plugin:prettier/recommended', 'prettier/react'],
4 | }
5 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.pbxproj -text
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # Xcode
6 | #
7 | build/
8 | *.pbxuser
9 | !default.pbxuser
10 | *.mode1v3
11 | !default.mode1v3
12 | *.mode2v3
13 | !default.mode2v3
14 | *.perspectivev3
15 | !default.perspectivev3
16 | xcuserdata
17 | *.xccheckout
18 | *.moved-aside
19 | DerivedData
20 | *.hmap
21 | *.ipa
22 | *.xcuserstate
23 | project.xcworkspace
24 | IDEWorkspaceChecks.plist
25 |
26 | # Android/IntelliJ
27 | #
28 | build/
29 | .idea
30 | .gradle
31 | local.properties
32 | *.iml
33 | .project
34 | .settings/
35 |
36 | # node.js
37 | #
38 | node_modules/
39 | npm-debug.log
40 | yarn-error.log
41 |
42 | # BUCK
43 | buck-out/
44 | \.buckd/
45 | *.keystore
46 | !debug.keystore
47 |
48 | # fastlane
49 | #
50 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
51 | # screenshots whenever they are needed.
52 | # For more information about the recommended setup visit:
53 | # https://docs.fastlane.tools/best-practices/source-control/
54 |
55 | */fastlane/report.xml
56 | */fastlane/Preview.html
57 | */fastlane/screenshots
58 |
59 | # Bundle artifact
60 | *.jsbundle
61 |
62 | # CocoaPods
63 | Pods/
64 |
65 | # lib
66 | lib/
67 |
68 |
--------------------------------------------------------------------------------
/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | semi: false,
3 | trailingComma: 'all',
4 | jsxBracketSameLine: true,
5 | singleQuote: true,
6 | printWidth: 120,
7 | tabWidth: 2,
8 | arrowParens: 'avoid'
9 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 listenzz@163.com
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-native-keyboard-insets
2 |
3 | 本库已迁移至 [react-native-troika/keyboard-insets](https://github.com/sdcxtech/react-native-troika/blob/master/packages/keyboard-insets/README.md)
4 |
5 | A powerful Keyboard Aware View for React Native.
6 |
7 | 使用简单,自动模式下不需要额外代码来处理键盘。
8 |
9 | | 自动模式 | 手动模式 |
10 | | ---------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
11 | |  |  |
12 |
13 | 本库主要依据 Android 官方指南 [Synchronize animation with the software keyboard](https://developer.android.com/develop/ui/views/layout/sw-keyboard#synchronize-animation) 来实现,同时参考了 [react-native-keyboard-controller](https://github.com/kirillzyusko/react-native-keyboard-controller)。因为该库不是很符合我的需求,所以我自己写了一个。
14 |
15 | ## Installation
16 |
17 | ```bash
18 | yarn add react-native-keyboard-insets
19 | ```
20 |
21 | ### iOS
22 |
23 | ```sh
24 | cd ios
25 | pod install
26 | ```
27 |
28 | ### Android
29 |
30 | 开启 [edge-to-edge](https://developer.android.com/develop/ui/views/layout/edge-to-edge)。 这将使得 APP 的 UI 撑满整个屏幕,而不是被系统 UI(譬如虚拟导航键)遮挡,从而实现更摩登的 UI 效果。
31 |
32 | ```java
33 | // MainActivity.java
34 | import androidx.core.view.WindowCompat;
35 |
36 | public class MainActivity extends ReactActivity {
37 | @Override
38 | protected void onCreate(Bundle savedInstanceState) {
39 | super.onCreate(null);
40 | // enable Edge-to-Edge
41 | WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
42 | }
43 | }
44 | ```
45 |
46 | 为了更好的向后(Android 10 以前)兼容, 在 AndroidManifest 中设置 `android:windowSoftInputMode="adjustResize"`。
47 |
48 | ```xml
49 |
50 |
54 |
55 | ...
56 |
57 |
58 | ```
59 |
60 | 开启 Edge-to-Edge 后,你的 UI 会撑满整个屏幕,可使用 [react-native-safe-area-context](https://github.com/th3rdwave/react-native-safe-area-context) 来处理和系统 UI (譬如虚拟导航键) 重叠的部分。
61 |
62 | 可参考以下代码进行全局处理,也可以每个页面单独处理,以实现更美观更摩登的 UI 效果。
63 |
64 | ```tsx
65 | import { Platform } from 'react-native'
66 | import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context'
67 |
68 | function App() {
69 | return (
70 |
71 | ...
72 | {Platform.OS === 'android' && }
73 |
74 | )
75 | }
76 | ```
77 |
78 | > 如果使用 [hybrid-navigation](https://github.com/listenzz/hybrid-navigation) 作为导航组件,则不需要做任何事情,因为它已经帮你处理好了。
79 |
80 | ## Usage
81 |
82 | 使用 `KeyboardInsetsView` 代替 `View` 作为容器,或者使用 `KeyboardInsetsView` 将 `ScrollView` 包裹起来。当键盘显示或隐藏时,`KeyboardInsetsView` 会自动调整自身的位置,以保证输入框不被键盘遮挡。
83 |
84 | ```tsx
85 | import { KeyboardInsetsView } from 'react-native-keyboard-insets'
86 |
87 | function MyComponent() {
88 | return (
89 |
90 |
91 | ...
92 |
93 | ...
94 |
95 |
96 | )
97 | }
98 | ```
99 |
100 | Support Nested.
101 |
102 | ```tsx
103 | import { KeyboardInsetsView } from 'react-native-keyboard-insets'
104 |
105 | function MyComponent() {
106 | return (
107 |
108 | ...
109 |
110 |
111 |
112 | ...
113 |
114 | )
115 | }
116 | ```
117 |
118 | `KeyboardInsetsView` 本质上是个 `View`,所以你可以使用 `View` 的所有属性,也可以和 `View` 互相替换。
119 |
120 | `KeyboardInsetsView` 有两个额外的属性:
121 |
122 | - `extraHeight`:自动模式下,键盘总是紧贴着输入框的下边缘,这个属性设置输入框距离键盘的额外高度。KeyboardInsetsView 的最大偏移受键盘高度限制,若加入额外高度后,KeyboardInsetsView 偏移距离大于键盘高度,将产生截断,此时 KeyboardInsetsView 偏移距离等于键盘高度,底部将与键盘顶部相贴
123 |
124 | - `onKeyboard`:是个回调函数,一旦设置,就进入手动模式,`KeyboardInsetsView` 不会帮你调整输入框的位置。你需要利用这个回调函数实现自己想要的效果。
125 |
126 | `onKeyboard` 的参数声明如下:
127 |
128 | ```tsx
129 | interface KeyboardState {
130 | height: number // 键盘的高度,不会因为键盘隐藏而变为 0
131 | shown: boolean // 当键盘将隐已隐时,这个值为 false;当键盘将显已显时,这个值为 true
132 | transitioning: boolean // 键盘是否正在显示或隐藏
133 | position: Animated.Value // 键盘的位置,从 0 到 height,可以用来实现动画效果
134 | }
135 | ```
136 |
137 | ## API
138 |
139 | - `useKeyboard`
140 |
141 | 为了方便用户编写 `onKeyboard` 回调,keyboard-insets 提供了一个 `useKeyboard` hook,使用方法如下:
142 |
143 | ```tsx
144 | import { useKeyboard } from 'react-native-keyboard-insets'
145 |
146 | function MyComponent() {
147 | const { keyboard, onKeyboard } = useKeyboard()
148 |
149 | console.log(keyboard.height), // 键盘的高度
150 |
151 | return (
152 |
153 |
154 |
155 | )
156 | }
157 | ```
158 |
159 | - `getEdgeInsetsForView`
160 |
161 | 有时候你需要知道某个 `View` 距离屏幕四边的距离,这个时候就可以使用 `getEdgeInsetsForView` 方法。
162 |
163 | ```tsx
164 | import { getEdgeInsetsForView } from 'react-native-keyboard-insets'
165 |
166 | function MyComponent() {
167 | const inputRef = useRef(null)
168 |
169 | const onLayout = useCallback(() => {
170 | const viewTag = findNodeHandle(inputRef.current)
171 | if (viewTag === null) {
172 | return
173 | }
174 |
175 | // 获得 TextInput 距离屏幕四边的距离
176 | getEdgeInsetsForView(viewTag, insets => {
177 | console.log('insets', insets)
178 | })
179 | }, [])
180 |
181 | return (
182 |
183 |
184 |
185 | )
186 | }
187 | ```
188 |
189 | ## 运行 example 项目
190 |
191 | 首先 clone 本项目
192 |
193 | ```shell
194 | git clone git@github.com:listenzz/react-native-keyboard-insets.git
195 | cd react-native-keyboard-insets
196 | ```
197 |
198 | 然后在项目根目录下运行如下命令:
199 |
200 | ```shell
201 | yarn install
202 | # &
203 | yarn start
204 | ```
205 |
206 | ### 在 Android 上运行
207 |
208 | 首先,确保你有一个模拟器或设备
209 |
210 | 如果熟悉原生开发,使用 Android Studio 打开 example/android,像运行原生应用那样运行它,也可以使用命令行:
211 |
212 | ```sh
213 | # 在项目根目录下运行
214 | yarn android
215 | ```
216 |
217 | 你可能需要运行如下命令,才可以使用 Hot Reload 功能
218 |
219 | ```sh
220 | adb reverse tcp:8081 tcp:8081
221 | ```
222 |
223 | ### 在 iOS 上运行
224 |
225 | 首先安装 cocoapods 依赖,在项目根目录下运行如下命令:
226 |
227 | ```sh
228 | cd example/ios && pod install
229 | # 成功安装依赖后,回到根目录
230 | cd -
231 | ```
232 |
233 | 如果熟悉原生开发,使用 Xcode 打开 example/ios,像运行原生应用那样运行它,或者使用命令行:
234 |
235 | ```sh
236 | # 在项目根目录下运行
237 | yarn ios
238 | ```
239 |
--------------------------------------------------------------------------------
/RNKeyboardInsets.podspec:
--------------------------------------------------------------------------------
1 | require "json"
2 |
3 | package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4 |
5 | Pod::Spec.new do |s|
6 | s.name = "RNKeyboardInsets"
7 | s.version = package["version"]
8 | s.summary = package["description"]
9 |
10 | s.homepage = package["homepage"]
11 | s.license = package["license"]
12 | s.authors = package["author"]
13 | s.platforms = { :ios => "10.0" }
14 | s.source = { :git => "https://github.com/github-account/react-native-keyboard-insets.git", :tag => "#{s.version}" }
15 |
16 | s.source_files = "ios/KeyboardInsets/**/*.{h,m,mm}"
17 | s.dependency "React-Core"
18 | end
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | // android/build.gradle
2 |
3 | def safeExtGet(prop, fallback) {
4 | rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
5 | }
6 |
7 | apply plugin: 'com.android.library'
8 |
9 | android {
10 | compileOptions {
11 | sourceCompatibility JavaVersion.VERSION_1_8
12 | targetCompatibility JavaVersion.VERSION_1_8
13 | }
14 |
15 | compileSdkVersion safeExtGet('compileSdkVersion', 30)
16 | buildToolsVersion safeExtGet('buildToolsVersion', '30.0.2')
17 |
18 | defaultConfig {
19 | minSdkVersion safeExtGet('minSdkVersion', 21)
20 | targetSdkVersion safeExtGet('targetSdkVersion', 30)
21 | versionCode 1
22 | versionName "1.0.0"
23 | }
24 |
25 | buildTypes {
26 | release {
27 | consumerProguardFiles 'proguard-rules.pro'
28 | }
29 | }
30 | }
31 |
32 | dependencies {
33 | implementation fileTree(dir: 'libs', include: ['*.jar'])
34 | implementation "androidx.appcompat:appcompat:1.3.1"
35 | implementation 'com.facebook.react:react-native:+'
36 | }
37 |
--------------------------------------------------------------------------------
/android/proguard-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/listenzz/react-native-keyboard-insets/7bc81ed8f6434afc4321b71fbf33cfcff20fbde4/android/proguard-rules.pro
--------------------------------------------------------------------------------
/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/android/src/main/java/com/reactnative/keyboardinsets/EdgeInsets.java:
--------------------------------------------------------------------------------
1 | package com.reactnative.keyboardinsets;
2 |
3 | public class EdgeInsets {
4 | public int left;
5 | public int top;
6 | public int right;
7 | public int bottom;
8 |
9 | public EdgeInsets() {
10 |
11 | }
12 |
13 | public EdgeInsets(int left, int top, int right, int bottom) {
14 | this.left = left;
15 | this.top = top;
16 | this.right = right;
17 | this.bottom = bottom;
18 | }
19 |
20 | @Override
21 | public String toString() {
22 | return "EdgeInsets{" +
23 | "left=" + left +
24 | ", top=" + top +
25 | ", right=" + right +
26 | ", bottom=" + bottom +
27 | '}';
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/android/src/main/java/com/reactnative/keyboardinsets/KeyboardAutoHandler.java:
--------------------------------------------------------------------------------
1 | package com.reactnative.keyboardinsets;
2 |
3 | import android.graphics.Rect;
4 | import android.view.View;
5 | import android.view.ViewParent;
6 |
7 | import androidx.core.graphics.Insets;
8 | import androidx.core.view.WindowInsetsCompat;
9 |
10 | import com.facebook.react.uimanager.PixelUtil;
11 | import com.facebook.react.uimanager.ThemedReactContext;
12 | import com.facebook.react.views.scroll.ReactScrollView;
13 |
14 | public class KeyboardAutoHandler {
15 |
16 | private final KeyboardInsetsView view;
17 | private final ThemedReactContext reactContext;
18 |
19 | public KeyboardAutoHandler(KeyboardInsetsView view, ThemedReactContext reactContext) {
20 | this.view = view;
21 | this.reactContext = reactContext;
22 | }
23 |
24 | private int keyboardHeight;
25 | private boolean forceUpdated = false;
26 |
27 | void onStart(View focusView, int keyboardHeight) {
28 | adjustScrollViewOffsetIfNeeded(focusView);
29 |
30 | if (keyboardHeight != this.keyboardHeight) {
31 | forceUpdated = true;
32 | }
33 | this.keyboardHeight = keyboardHeight;
34 | }
35 |
36 | void onEnd(View focusView, int keyboardHeight) {
37 |
38 | }
39 |
40 | void onApplyWindowInsets(WindowInsetsCompat insets, View focusView, int keyboardHeight) {
41 | if (focusView == null) {
42 | view.setTranslationY(0);
43 | return;
44 | }
45 |
46 | adjustScrollViewOffsetIfNeeded(focusView);
47 |
48 | if (keyboardHeight != this.keyboardHeight) {
49 | forceUpdated = true;
50 | }
51 | this.keyboardHeight = keyboardHeight;
52 |
53 | handleKeyboardTransition(insets, focusView);
54 | }
55 |
56 | void handleKeyboardTransition(WindowInsetsCompat insets, View focusView) {
57 | Insets imeInsets = insets.getInsets(WindowInsetsCompat.Type.ime());
58 | EdgeInsets edge = SystemUI.getEdgeInsetsForView(focusView);
59 | float extraHeight = PixelUtil.toPixelFromDIP(view.getExtraHeight());
60 | float translationY = 0;
61 | if (imeInsets.bottom > 0) {
62 | float bottomInset = Math.max(edge.bottom - extraHeight, 0);
63 | translationY = -Math.max(imeInsets.bottom - bottomInset, 0);
64 | }
65 |
66 | if (forceUpdated) {
67 | forceUpdated = false;
68 | view.setTranslationY(translationY);
69 | }
70 |
71 | if (SystemUI.isImeVisible(view) && view.getTranslationY() < translationY) {
72 | return;
73 | }
74 |
75 | view.setTranslationY(translationY);
76 | }
77 |
78 | private void adjustScrollViewOffsetIfNeeded(View focusView) {
79 | ReactScrollView scrollView = findClosestScrollView(focusView);
80 | if (scrollView != null) {
81 | Rect offset = new Rect();
82 | focusView.getDrawingRect(offset);
83 | scrollView.offsetDescendantRectToMyCoords(focusView, offset);
84 | float extraHeight = PixelUtil.toPixelFromDIP(view.getExtraHeight());
85 | float dy = scrollView.getHeight() + scrollView.getScrollY() - offset.bottom - extraHeight;
86 | if (dy < 0) {
87 | scrollView.scrollTo(0, (int) (scrollView.getScrollY() - dy));
88 | scrollView.requestLayout();
89 | }
90 | }
91 | }
92 |
93 | private static ReactScrollView findClosestScrollView(View view) {
94 | ViewParent viewParent = view.getParent();
95 | if (viewParent instanceof ReactScrollView) {
96 | return (ReactScrollView) viewParent;
97 | }
98 |
99 | if (viewParent instanceof View) {
100 | return findClosestScrollView((View) viewParent);
101 | }
102 |
103 | return null;
104 | }
105 |
106 | }
107 |
--------------------------------------------------------------------------------
/android/src/main/java/com/reactnative/keyboardinsets/KeyboardInsetsCallback.java:
--------------------------------------------------------------------------------
1 | package com.reactnative.keyboardinsets;
2 |
3 | import android.view.View;
4 | import android.view.ViewParent;
5 |
6 | import androidx.annotation.NonNull;
7 | import androidx.core.graphics.Insets;
8 | import androidx.core.view.OnApplyWindowInsetsListener;
9 | import androidx.core.view.WindowInsetsAnimationCompat;
10 | import androidx.core.view.WindowInsetsCompat;
11 |
12 | import com.facebook.common.logging.FLog;
13 | import com.facebook.react.uimanager.ThemedReactContext;
14 |
15 | import java.util.List;
16 |
17 | public class KeyboardInsetsCallback extends WindowInsetsAnimationCompat.Callback implements OnApplyWindowInsetsListener {
18 |
19 | private final KeyboardInsetsView view;
20 | private final KeyboardAutoHandler autoHandler;
21 | private final KeyboardManualHandler manualHandler;
22 |
23 | public KeyboardInsetsCallback(KeyboardInsetsView view, ThemedReactContext reactContext) {
24 | super(WindowInsetsAnimationCompat.Callback.DISPATCH_MODE_CONTINUE_ON_SUBTREE);
25 | this.view = view;
26 | this.autoHandler = new KeyboardAutoHandler(view, reactContext);
27 | this.manualHandler = new KeyboardManualHandler(view, reactContext);
28 | }
29 |
30 | public View focusView;
31 | private boolean transitioning;
32 | private int keyboardHeight;
33 |
34 | @Override
35 | public void onPrepare(@NonNull WindowInsetsAnimationCompat animation) {
36 | transitioning = true;
37 | }
38 |
39 | @NonNull
40 | @Override
41 | public WindowInsetsAnimationCompat.BoundsCompat onStart(@NonNull WindowInsetsAnimationCompat animation, @NonNull WindowInsetsAnimationCompat.BoundsCompat bounds) {
42 | if (SystemUI.isImeVisible(view)) {
43 | focusView = view.findFocus();
44 | }
45 |
46 | if (!shouldHandleKeyboardTransition(focusView)) {
47 | return super.onStart(animation, bounds);
48 | }
49 |
50 | if (SystemUI.isImeVisible(view)) {
51 | keyboardHeight = SystemUI.imeHeight(view);
52 | }
53 |
54 | FLog.i("KeyboardInsets", "WindowInsetsAnimation.Callback onStart");
55 | if (view.isAutoMode()) {
56 | autoHandler.onStart(focusView, keyboardHeight);
57 | } else {
58 | manualHandler.onStart(focusView, keyboardHeight);
59 | }
60 |
61 | return super.onStart(animation, bounds);
62 | }
63 |
64 | @Override
65 | public void onEnd(@NonNull WindowInsetsAnimationCompat animation) {
66 | super.onEnd(animation);
67 | transitioning = false;
68 |
69 | if (!shouldHandleKeyboardTransition(focusView)) {
70 | return;
71 | }
72 |
73 | if (!SystemUI.isImeVisible(view)) {
74 | focusView = null;
75 | }
76 |
77 | FLog.i("KeyboardInsets", "WindowInsetsAnimation.Callback onEnd");
78 | if (view.isAutoMode()) {
79 | autoHandler.onEnd(focusView, keyboardHeight);
80 | } else {
81 | manualHandler.onEnd(focusView, keyboardHeight);
82 | }
83 | }
84 |
85 | @NonNull
86 | @Override
87 | public WindowInsetsCompat onProgress(@NonNull WindowInsetsCompat insets, @NonNull List runningAnimations) {
88 | if (!shouldHandleKeyboardTransition(focusView)) {
89 | return insets;
90 | }
91 | handleKeyboardTransition(insets);
92 | return WindowInsetsCompat.CONSUMED;
93 | }
94 |
95 | @Override
96 | public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) {
97 | if (transitioning) {
98 | return insets;
99 | }
100 |
101 | if (focusView == null) {
102 | // Android 10 以下,首次弹出键盘时,不会触发 WindowInsetsAnimationCompat.Callback
103 | focusView = view.findFocus();
104 | }
105 |
106 | if (!shouldHandleKeyboardTransition(focusView)) {
107 | return insets;
108 | }
109 |
110 | Insets imeInsets = insets.getInsets(WindowInsetsCompat.Type.ime());
111 | FLog.i("KeyboardInsets", "onApplyWindowInsets imeInsets" + imeInsets);
112 |
113 | if (SystemUI.isImeVisible(view)) {
114 | keyboardHeight = SystemUI.imeHeight(view);
115 | }
116 |
117 | if (view.isAutoMode()) {
118 | View focusView = view.findFocus();
119 | if (focusView != null && focusView != this.focusView) {
120 | KeyboardInsetsView insetsView = findClosestKeyboardInsetsView(focusView);
121 | if (insetsView != view) {
122 | focusView = null;
123 | }
124 | }
125 | this.focusView = focusView;
126 | autoHandler.onApplyWindowInsets(insets, focusView, keyboardHeight);
127 | } else {
128 | manualHandler.onApplyWindowInsets(insets, focusView, keyboardHeight);
129 | }
130 |
131 | return insets;
132 | }
133 |
134 | private void handleKeyboardTransition(WindowInsetsCompat insets) {
135 | if (view.isAutoMode()) {
136 | autoHandler.handleKeyboardTransition(insets, focusView);
137 | } else {
138 | manualHandler.handleKeyboardTransition(insets, focusView);
139 | }
140 | }
141 |
142 | private boolean shouldHandleKeyboardTransition(View focus) {
143 | if (focus != null) {
144 | KeyboardInsetsView insetsView = findClosestKeyboardInsetsView(focus);
145 | return insetsView == view;
146 | }
147 | return false;
148 | }
149 |
150 | private static KeyboardInsetsView findClosestKeyboardInsetsView(View focus) {
151 | ViewParent viewParent = focus.getParent();
152 | if (viewParent instanceof KeyboardInsetsView) {
153 | return (KeyboardInsetsView) viewParent;
154 | }
155 |
156 | if (viewParent instanceof View) {
157 | return findClosestKeyboardInsetsView((View) viewParent);
158 | }
159 |
160 | return null;
161 | }
162 |
163 | }
164 |
--------------------------------------------------------------------------------
/android/src/main/java/com/reactnative/keyboardinsets/KeyboardInsetsModule.java:
--------------------------------------------------------------------------------
1 | package com.reactnative.keyboardinsets;
2 |
3 | import android.view.View;
4 |
5 | import androidx.annotation.NonNull;
6 |
7 | import com.facebook.react.bridge.Arguments;
8 | import com.facebook.react.bridge.ReactApplicationContext;
9 | import com.facebook.react.bridge.ReactContextBaseJavaModule;
10 | import com.facebook.react.bridge.ReactMethod;
11 | import com.facebook.react.bridge.Callback;
12 | import com.facebook.react.bridge.UiThreadUtil;
13 | import com.facebook.react.bridge.WritableMap;
14 | import com.facebook.react.uimanager.PixelUtil;
15 | import com.facebook.react.uimanager.UIManagerModule;
16 |
17 | public class KeyboardInsetsModule extends ReactContextBaseJavaModule {
18 |
19 | public KeyboardInsetsModule(ReactApplicationContext reactContext) {
20 | super(reactContext);
21 | }
22 |
23 | @NonNull
24 | @Override
25 | public String getName() {
26 | return "KeyboardInsetsModule";
27 | }
28 |
29 | @ReactMethod
30 | public void getEdgeInsetsForView(int viewTag, Callback callback) {
31 | UiThreadUtil.runOnUiThread(() -> {
32 | UIManagerModule uiManagerModule = getReactApplicationContext().getNativeModule(UIManagerModule.class);
33 | View view = uiManagerModule.resolveView(viewTag);
34 | WritableMap map = Arguments.createMap();
35 | map.putDouble("top", 0);
36 | map.putDouble("left", 0);
37 | map.putDouble("right", 0);
38 | map.putDouble("bottom", 0);
39 | if (view != null) {
40 | EdgeInsets insets = SystemUI.getEdgeInsetsForView(view);
41 | map.putDouble("top", PixelUtil.toDIPFromPixel(insets.top));
42 | map.putDouble("left", PixelUtil.toDIPFromPixel(insets.left));
43 | map.putDouble("right", PixelUtil.toDIPFromPixel(insets.right));
44 | map.putDouble("bottom", PixelUtil.toDIPFromPixel(insets.bottom));
45 | }
46 | callback.invoke(map);
47 | });
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/android/src/main/java/com/reactnative/keyboardinsets/KeyboardInsetsPackage.java:
--------------------------------------------------------------------------------
1 | package com.reactnative.keyboardinsets;
2 |
3 | import androidx.annotation.NonNull;
4 |
5 | import java.util.Collections;
6 | import java.util.List;
7 |
8 | import com.facebook.react.ReactPackage;
9 | import com.facebook.react.bridge.NativeModule;
10 | import com.facebook.react.bridge.ReactApplicationContext;
11 | import com.facebook.react.uimanager.ViewManager;
12 |
13 | public class KeyboardInsetsPackage implements ReactPackage {
14 | @NonNull
15 | @Override
16 | public List createNativeModules(@NonNull ReactApplicationContext reactContext) {
17 | return Collections.singletonList(new KeyboardInsetsModule(reactContext));
18 | }
19 |
20 | @NonNull
21 | @Override
22 | public List createViewManagers(@NonNull ReactApplicationContext reactContext) {
23 | return Collections.singletonList(new KeyboardInsetsViewManager());
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/android/src/main/java/com/reactnative/keyboardinsets/KeyboardInsetsView.java:
--------------------------------------------------------------------------------
1 | package com.reactnative.keyboardinsets;
2 |
3 | import android.content.Context;
4 | import android.view.View;
5 |
6 | import com.facebook.react.views.view.ReactViewGroup;
7 |
8 | public class KeyboardInsetsView extends ReactViewGroup {
9 |
10 | private String mode = "auto";
11 |
12 | private float extraHeight = 0.0f;
13 |
14 | public KeyboardInsetsView(Context context) {
15 | super(context);
16 | }
17 |
18 | public void setMode(String mode) {
19 | this.mode = mode;
20 | }
21 |
22 | public boolean isAutoMode() {
23 | return this.mode.equals("auto");
24 | }
25 |
26 | public void setExtraHeight(float extraHeight) {
27 | this.extraHeight = extraHeight;
28 | }
29 |
30 | public float getExtraHeight() {
31 | return this.extraHeight;
32 | }
33 |
34 |
35 | @Override
36 | public void requestChildFocus(View child, View focused) {
37 | super.requestChildFocus(child, focused);
38 | requestApplyInsets();
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/android/src/main/java/com/reactnative/keyboardinsets/KeyboardInsetsViewManager.java:
--------------------------------------------------------------------------------
1 | package com.reactnative.keyboardinsets;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.annotation.Nullable;
5 | import androidx.core.view.ViewCompat;
6 |
7 | import com.facebook.react.common.MapBuilder;
8 | import com.facebook.react.uimanager.ThemedReactContext;
9 | import com.facebook.react.uimanager.ViewGroupManager;
10 | import com.facebook.react.uimanager.annotations.ReactProp;
11 |
12 | import java.util.Map;
13 |
14 | public class KeyboardInsetsViewManager extends ViewGroupManager {
15 |
16 | public static final String REACT_CLASS = "KeyboardInsetsView";
17 |
18 | @NonNull
19 | @Override
20 | public String getName() {
21 | return REACT_CLASS;
22 | }
23 |
24 | @NonNull
25 | @Override
26 | protected KeyboardInsetsView createViewInstance(@NonNull ThemedReactContext themedReactContext) {
27 | KeyboardInsetsView view = new KeyboardInsetsView(themedReactContext);
28 | KeyboardInsetsCallback callback = new KeyboardInsetsCallback(view, themedReactContext);
29 | ViewCompat.setWindowInsetsAnimationCallback(view, callback);
30 | ViewCompat.setOnApplyWindowInsetsListener(view, callback);
31 | return view;
32 | }
33 |
34 | @ReactProp(name = "mode")
35 | public void setMode(KeyboardInsetsView view, String mode) {
36 | view.setMode(mode);
37 | }
38 |
39 | @ReactProp(name = "extraHeight")
40 | public void setExtraHeight(KeyboardInsetsView view, float extraHeight) {
41 | view.setExtraHeight(extraHeight);
42 | }
43 |
44 | @Nullable
45 | @Override
46 | public Map getExportedCustomDirectEventTypeConstants() {
47 | return MapBuilder.of(
48 | "topStatusChanged", MapBuilder.of("registrationName", "onStatusChanged"),
49 | "topPositionChanged", MapBuilder.of("registrationName", "onPositionChanged")
50 | );
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/android/src/main/java/com/reactnative/keyboardinsets/KeyboardManualHandler.java:
--------------------------------------------------------------------------------
1 | package com.reactnative.keyboardinsets;
2 |
3 | import android.util.Log;
4 | import android.view.View;
5 |
6 | import androidx.core.graphics.Insets;
7 | import androidx.core.view.WindowInsetsCompat;
8 |
9 | import com.facebook.react.uimanager.ThemedReactContext;
10 | import com.facebook.react.uimanager.UIManagerHelper;
11 | import com.facebook.react.uimanager.events.Event;
12 | import com.facebook.react.uimanager.events.EventDispatcher;
13 |
14 | public class KeyboardManualHandler {
15 |
16 | private final KeyboardInsetsView view;
17 | private final ThemedReactContext reactContext;
18 |
19 | public KeyboardManualHandler(KeyboardInsetsView view, ThemedReactContext reactContext) {
20 | this.view = view;
21 | this.reactContext = reactContext;
22 | }
23 |
24 | void onStart(View focusView, int keyboardHeight) {
25 | sendEvent(new KeyboardStatusChangedEvent(view.getId(), keyboardHeight, SystemUI.isImeVisible(view), true));
26 | }
27 |
28 | void onEnd(View focusView, int keyboardHeight) {
29 | sendEvent(new KeyboardStatusChangedEvent(view.getId(), keyboardHeight, SystemUI.isImeVisible(view), false));
30 | }
31 |
32 | void onApplyWindowInsets(WindowInsetsCompat insets, View focusView, int keyboardHeight) {
33 | sendEvent(new KeyboardStatusChangedEvent(view.getId(), keyboardHeight, SystemUI.isImeVisible(view), true));
34 | handleKeyboardTransition(insets, focusView);
35 | sendEvent(new KeyboardStatusChangedEvent(view.getId(), keyboardHeight, SystemUI.isImeVisible(view), false));
36 | }
37 |
38 | void handleKeyboardTransition(WindowInsetsCompat insets, View focusView) {
39 | Insets imeInsets = insets.getInsets(WindowInsetsCompat.Type.ime());
40 | Log.d("KeyboardInsets", "imeInsets.bottom:" + imeInsets.bottom);
41 | sendEvent(new KeyboardPositionChangedEvent(view.getId(), imeInsets.bottom));
42 | }
43 |
44 | private void sendEvent(Event> event) {
45 | EventDispatcher eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, view.getId());
46 | eventDispatcher.dispatchEvent(event);
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/android/src/main/java/com/reactnative/keyboardinsets/KeyboardPositionChangedEvent.java:
--------------------------------------------------------------------------------
1 | package com.reactnative.keyboardinsets;
2 |
3 | import androidx.core.graphics.Insets;
4 |
5 | import com.facebook.react.bridge.Arguments;
6 | import com.facebook.react.bridge.WritableMap;
7 | import com.facebook.react.uimanager.PixelUtil;
8 | import com.facebook.react.uimanager.events.Event;
9 | import com.facebook.react.uimanager.events.RCTEventEmitter;
10 |
11 | public class KeyboardPositionChangedEvent extends Event {
12 |
13 | private final int position;
14 |
15 | public KeyboardPositionChangedEvent(int viewId, int position) {
16 | super(viewId);
17 | this.position = position;
18 | }
19 |
20 | @Override
21 | public String getEventName() {
22 | return "topPositionChanged";
23 | }
24 |
25 | @Override
26 | public void dispatch(RCTEventEmitter rctEventEmitter) {
27 | WritableMap map = Arguments.createMap();
28 | map.putDouble("position", PixelUtil.toDIPFromPixel(position));
29 | rctEventEmitter.receiveEvent(getViewTag(), getEventName(), map);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/android/src/main/java/com/reactnative/keyboardinsets/KeyboardStatusChangedEvent.java:
--------------------------------------------------------------------------------
1 | package com.reactnative.keyboardinsets;
2 |
3 | import com.facebook.react.bridge.Arguments;
4 | import com.facebook.react.bridge.WritableMap;
5 | import com.facebook.react.uimanager.PixelUtil;
6 | import com.facebook.react.uimanager.events.Event;
7 | import com.facebook.react.uimanager.events.RCTEventEmitter;
8 |
9 | public class KeyboardStatusChangedEvent extends Event {
10 |
11 | private final int height;
12 | private final boolean shown;
13 | private final boolean transitioning;
14 |
15 | public KeyboardStatusChangedEvent(int viewTag, int height, boolean shown, boolean transitioning) {
16 | super(viewTag);
17 | this.height = height;
18 | this.shown = shown;
19 | this.transitioning = transitioning;
20 | }
21 |
22 | @Override
23 | public String getEventName() {
24 | return "topStatusChanged";
25 | }
26 |
27 | @Override
28 | public void dispatch(RCTEventEmitter rctEventEmitter) {
29 | WritableMap map = Arguments.createMap();
30 | map.putDouble("height", PixelUtil.toDIPFromPixel(height));
31 | map.putBoolean("transitioning", transitioning);
32 | map.putBoolean("shown", shown);
33 | rctEventEmitter.receiveEvent(getViewTag(), getEventName(), map);
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/android/src/main/java/com/reactnative/keyboardinsets/SystemUI.java:
--------------------------------------------------------------------------------
1 | package com.reactnative.keyboardinsets;
2 |
3 | import android.graphics.Rect;
4 | import android.view.View;
5 | import android.view.ViewGroup;
6 |
7 | import androidx.annotation.NonNull;
8 | import androidx.core.view.ViewCompat;
9 | import androidx.core.view.WindowInsetsCompat;
10 |
11 | public class SystemUI {
12 |
13 | public static boolean isImeVisible(@NonNull View view) {
14 | WindowInsetsCompat insetsCompat = ViewCompat.getRootWindowInsets(view);
15 | assert insetsCompat != null;
16 | return insetsCompat.isVisible(WindowInsetsCompat.Type.ime());
17 | }
18 |
19 | public static int imeHeight(@NonNull View view) {
20 | WindowInsetsCompat insetsCompat = ViewCompat.getRootWindowInsets(view);
21 | assert insetsCompat != null;
22 | return insetsCompat.getInsets(WindowInsetsCompat.Type.ime()).bottom;
23 | }
24 |
25 | public static EdgeInsets getEdgeInsetsForView(@NonNull View view) {
26 | ViewGroup root = (ViewGroup) view.getRootView();
27 |
28 | int windowHeight = root.getHeight();
29 | int windowWidth = root.getWidth();
30 |
31 | Rect offset = new Rect();
32 | view.getDrawingRect(offset);
33 | root.offsetDescendantRectToMyCoords(view, offset);
34 |
35 | int leftMargin = 0;
36 | int topMargin = 0;
37 | int rightMargin = 0;
38 | int bottomMargin = 0;
39 |
40 | if (view.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {
41 | ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
42 | leftMargin = lp.leftMargin;
43 | topMargin = lp.topMargin;
44 | rightMargin = lp.rightMargin;
45 | bottomMargin = lp.bottomMargin;
46 | }
47 |
48 | EdgeInsets insets = new EdgeInsets();
49 | insets.left = Math.max(offset.left - leftMargin, 0);
50 | insets.top = Math.max(offset.top - topMargin, 0);
51 | insets.right = Math.max(windowWidth - offset.right - rightMargin, 0);
52 | insets.bottom = Math.max(windowHeight - offset.bottom - bottomMargin, 0);
53 | return insets;
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ['module:metro-react-native-babel-preset'],
3 | }
4 |
--------------------------------------------------------------------------------
/example/App.tsx:
--------------------------------------------------------------------------------
1 | import React, { Fragment, useRef } from 'react'
2 | import { withNavigationItem } from 'hybrid-navigation'
3 | import { StyleSheet, TextInput, ScrollView } from 'react-native'
4 | import { KeyboardInsetsView } from 'react-native-keyboard-insets'
5 | import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context'
6 |
7 | function App() {
8 | return (
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | {Array.from({ length: 10 }).map((item, index) => (
17 |
24 | ))}
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | )
33 | }
34 |
35 | const inputLength = 9
36 | function SubmitToNextInputFragment() {
37 | const inputRef = useRef<(TextInput | null)[]>([...Array(inputLength)])
38 | const goNextInput = (index: number) => {
39 | if (index !== inputLength - 1) {
40 | inputRef.current[index + 1]?.focus()
41 | }
42 | }
43 | return (
44 |
45 | {Array.from({ length: inputLength }).map((_, index) => (
46 | (inputRef.current[index] = ref)}
48 | key={index}
49 | style={styles.input}
50 | placeholder={index === inputLength - 1 ? 'submit' : `current:${index} => submit and next`}
51 | textAlignVertical="center"
52 | blurOnSubmit={index === inputLength - 1}
53 | autoCorrect={false}
54 | returnKeyType={index === inputLength - 1 ? 'done' : 'next'}
55 | onSubmitEditing={() => goNextInput(index)}
56 | />
57 | ))}
58 |
59 | )
60 | }
61 |
62 | export default withNavigationItem({
63 | titleItem: {
64 | title: 'KeyboardInsets 演示',
65 | },
66 | rightBarButtonItem: {
67 | title: 'chat',
68 | action: navigator => {
69 | navigator.push('Chat')
70 | },
71 | },
72 | })(App)
73 |
74 | const styles = StyleSheet.create({
75 | flex1: {
76 | flex: 1,
77 | },
78 | backgroundLime: {
79 | backgroundColor: 'lime',
80 | },
81 | container: {
82 | justifyContent: 'flex-start',
83 | alignItems: 'stretch',
84 | paddingBottom: 16,
85 | },
86 |
87 | input: {
88 | height: 100,
89 | marginHorizontal: 48,
90 | marginTop: 16,
91 | marginBottom: 0,
92 | paddingLeft: 8,
93 | paddingRight: 8,
94 | borderColor: '#cccccc',
95 | borderWidth: 1,
96 | },
97 |
98 | keyboard: {
99 | paddingBottom: 16,
100 | backgroundColor: 'bisque',
101 | },
102 | })
103 |
--------------------------------------------------------------------------------
/example/KeyboardChat/Message/data.ts:
--------------------------------------------------------------------------------
1 | import type { MessageProps } from './types'
2 |
3 | export const history: MessageProps[] = [
4 | { text: 'Hmmmm🤔' },
5 | { text: 'It looks like it still will be laggy...' },
6 | { text: "But I don't know what should I try next" },
7 | { text: 'Reanimated?', sender: true },
8 | { text: 'A little bit disappointed 😔' },
9 | { text: '🤯' },
10 | { text: 'Try to check it. I hope it helps you...', sender: true },
11 | { text: 'It really pushes you to think twice on how to design it first' },
12 | {
13 | text: 'Looks promising!😎 I was always looking for a solution that would allow us to run animations on native thread and provide at least stable 60 FPS',
14 | },
15 | { text: 'You have to check it!!!', sender: true },
16 | { text: "Ha-ha! I'm definitely going to check it!" },
17 | { text: 'Hello! How are you?' },
18 | { text: "Hi! I'm good. How are you?", sender: true },
19 | {
20 | text: "I'm fine, thank you! Have you seen new keyboard animation library?",
21 | },
22 | { text: 'No! Let me check.', sender: true },
23 | {
24 | text: "Wow! I've been looking for it for a while. It's awesome!",
25 | sender: true,
26 | },
27 | ]
28 |
--------------------------------------------------------------------------------
/example/KeyboardChat/Message/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { Text, View } from 'react-native'
3 | import styles from './styles'
4 |
5 | import type { MessageProps } from './types'
6 |
7 | export default function Message({ text, sender }: MessageProps) {
8 | return (
9 |
10 | {text}
11 |
12 | )
13 | }
14 |
--------------------------------------------------------------------------------
/example/KeyboardChat/Message/styles.ts:
--------------------------------------------------------------------------------
1 | import { StyleSheet } from 'react-native'
2 |
3 | const container = {
4 | borderRadius: 10,
5 | padding: 10,
6 | margin: 10,
7 | marginVertical: 5,
8 | }
9 | export default StyleSheet.create({
10 | senderContainer: {
11 | alignSelf: 'flex-end',
12 | backgroundColor: '#e0e0e0',
13 | ...container,
14 | },
15 | recipientContainer: {
16 | alignSelf: 'flex-start',
17 | backgroundColor: '#50FF00',
18 | ...container,
19 | },
20 | message: {
21 | color: '#000000',
22 | },
23 | })
24 |
--------------------------------------------------------------------------------
/example/KeyboardChat/Message/types.ts:
--------------------------------------------------------------------------------
1 | export type MessageProps = {
2 | text: string
3 | sender?: boolean
4 | }
5 |
--------------------------------------------------------------------------------
/example/KeyboardChat/driver/Driver.ts:
--------------------------------------------------------------------------------
1 | import { Animated } from 'react-native'
2 |
3 | export interface DriverState {
4 | // sender bottom
5 | bottom: number
6 | driver: Driver | undefined
7 | setDriver: React.Dispatch>
8 | setTranslateY: React.Dispatch>
9 | }
10 |
11 | export interface Driver {
12 | show: (state: DriverState) => void
13 | hide: (state: DriverState) => void
14 | toggle: (state: DriverState) => void
15 | shown: boolean
16 | height: number
17 | name: string
18 | }
19 |
--------------------------------------------------------------------------------
/example/KeyboardChat/driver/KeyboardDriver.ts:
--------------------------------------------------------------------------------
1 | import { TextInput, Keyboard, Animated } from 'react-native'
2 | import { KeyboardState } from 'react-native-keyboard-insets'
3 | import { Driver, DriverState } from './Driver'
4 |
5 | export class KeyboardDriver implements Driver {
6 | constructor(private inputRef: React.RefObject) {}
7 | // 输入框距屏幕底部的距离
8 | private senderBottom = 0
9 | private y = 0
10 | private position = new Animated.Value(0)
11 |
12 | name = 'keyboard'
13 | shown = false
14 | height = 0
15 |
16 | show = () => {
17 | this.inputRef.current?.focus()
18 | }
19 |
20 | hide = () => {
21 | Keyboard.dismiss()
22 | }
23 |
24 | toggle = () => {
25 | this.shown ? this.hide() : this.show()
26 | }
27 |
28 | createCallback = (state: DriverState) => {
29 | return (keyboard: KeyboardState) => {
30 | const { shown, height, position } = keyboard
31 |
32 | const { bottom, driver, setDriver, setTranslateY } = state
33 | const heightChanged = height !== this.height
34 |
35 | this.height = height
36 | this.position = position
37 | this.senderBottom = bottom
38 |
39 | if (shown && (!this.shown || heightChanged)) {
40 | this.shown = true
41 | if (driver && driver !== this) {
42 | // 记录主界面当前位置
43 | this.y = driver.shown ? driver.height : 0
44 | // 隐藏前一个 driver
45 | driver.hide({ bottom, driver: this, setDriver, setTranslateY })
46 | }
47 | setDriver(this)
48 | setTranslateY(this.translateY)
49 | }
50 |
51 | if (!shown && this.shown) {
52 | this.shown = false
53 | this.y = 0
54 | if (driver === this) {
55 | setDriver(undefined)
56 | setTranslateY(this.translateY)
57 | }
58 | }
59 | }
60 | }
61 |
62 | private get translateY() {
63 | const extraHeight = this.senderBottom
64 | console.log(this.name, 'height', this.height, 'y', this.y, 'extraHeight', extraHeight)
65 |
66 | if (!this.shown || this.y === 0) {
67 | return this.position.interpolate({
68 | inputRange: [extraHeight, this.height],
69 | outputRange: [0, extraHeight - this.height],
70 | extrapolate: 'clamp',
71 | }) as Animated.Value
72 | } else {
73 | return this.position.interpolate({
74 | inputRange: [0, this.height],
75 | outputRange: [extraHeight - this.y, extraHeight - this.height],
76 | extrapolate: 'clamp',
77 | }) as Animated.Value
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/example/KeyboardChat/driver/ViewDriver.ts:
--------------------------------------------------------------------------------
1 | import { Animated, LayoutChangeEvent } from 'react-native'
2 | import { Driver, DriverState } from './Driver'
3 |
4 | export class ViewDriver implements Driver {
5 | constructor(public name: string) {}
6 |
7 | // 输入框距屏幕底部的距离
8 | private senderBottom = 0
9 |
10 | private y = 0
11 | private animation = new Animated.Value(0)
12 |
13 | shown = false
14 | height = 0
15 |
16 | show = (state: DriverState) => {
17 | const { bottom, driver, setDriver, setTranslateY } = state
18 |
19 | if (driver && driver !== this) {
20 | // 记录主界面当前位置
21 | this.y = driver.shown ? driver.height : 0
22 | // 隐藏前一个 driver
23 | driver.hide({ bottom, driver: this, setDriver, setTranslateY })
24 | }
25 |
26 | this.shown = true
27 | this.senderBottom = bottom
28 | setDriver(this)
29 | setTranslateY(this.translateY)
30 |
31 | Animated.timing(this.animation, {
32 | toValue: 0,
33 | duration: 200,
34 | useNativeDriver: true,
35 | }).start()
36 | }
37 |
38 | hide = (state: DriverState) => {
39 | const { bottom, driver, setDriver, setTranslateY } = state
40 |
41 | this.shown = false
42 | this.y = 0
43 | this.senderBottom = bottom
44 |
45 | if (driver === this) {
46 | setDriver(undefined)
47 | setTranslateY(this.translateY)
48 | Animated.timing(this.animation, {
49 | toValue: this.height,
50 | duration: 200,
51 | useNativeDriver: true,
52 | }).start()
53 | } else {
54 | this.animation.setValue(this.height)
55 | }
56 | }
57 |
58 | toggle = (state: DriverState) => {
59 | this.shown ? this.hide(state) : this.show(state)
60 | }
61 |
62 | style = {
63 | transform: [
64 | {
65 | translateY: this.animation,
66 | },
67 | ],
68 | }
69 |
70 | private get position() {
71 | return this.animation.interpolate({
72 | inputRange: [0, this.height],
73 | outputRange: [this.height, 0],
74 | })
75 | }
76 |
77 | private get translateY() {
78 | const extraHeight = this.senderBottom
79 | console.log(this.name, 'height', this.height, 'y', this.y, 'extraHeight', extraHeight)
80 | if (!this.shown || this.y === 0) {
81 | return this.position.interpolate({
82 | inputRange: [extraHeight, this.height],
83 | outputRange: [0, extraHeight - this.height],
84 | extrapolate: 'clamp',
85 | }) as Animated.Value
86 | } else {
87 | return this.position.interpolate({
88 | inputRange: [0, this.height],
89 | outputRange: [extraHeight - this.y, extraHeight - this.height],
90 | extrapolate: 'clamp',
91 | }) as Animated.Value
92 | }
93 | }
94 |
95 | onLayout = (event: LayoutChangeEvent) => {
96 | this.animation.setValue(event.nativeEvent.layout.height)
97 | this.height = event.nativeEvent.layout.height
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/example/KeyboardChat/icon/emoji@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/listenzz/react-native-keyboard-insets/7bc81ed8f6434afc4321b71fbf33cfcff20fbde4/example/KeyboardChat/icon/emoji@2x.png
--------------------------------------------------------------------------------
/example/KeyboardChat/icon/emoji@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/listenzz/react-native-keyboard-insets/7bc81ed8f6434afc4321b71fbf33cfcff20fbde4/example/KeyboardChat/icon/emoji@3x.png
--------------------------------------------------------------------------------
/example/KeyboardChat/icon/keyboard@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/listenzz/react-native-keyboard-insets/7bc81ed8f6434afc4321b71fbf33cfcff20fbde4/example/KeyboardChat/icon/keyboard@2x.png
--------------------------------------------------------------------------------
/example/KeyboardChat/icon/keyboard@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/listenzz/react-native-keyboard-insets/7bc81ed8f6434afc4321b71fbf33cfcff20fbde4/example/KeyboardChat/icon/keyboard@3x.png
--------------------------------------------------------------------------------
/example/KeyboardChat/icon/plus@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/listenzz/react-native-keyboard-insets/7bc81ed8f6434afc4321b71fbf33cfcff20fbde4/example/KeyboardChat/icon/plus@2x.png
--------------------------------------------------------------------------------
/example/KeyboardChat/icon/plus@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/listenzz/react-native-keyboard-insets/7bc81ed8f6434afc4321b71fbf33cfcff20fbde4/example/KeyboardChat/icon/plus@3x.png
--------------------------------------------------------------------------------
/example/KeyboardChat/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { useCallback, useRef, useState } from 'react'
2 | import { Animated, findNodeHandle, Image, Pressable, ScrollView, Text, TextInput, View } from 'react-native'
3 |
4 | import Message from './Message'
5 | import { history } from './Message/data'
6 | import styles from './styles'
7 | import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context'
8 | import { KeyboardInsetsView, getEdgeInsetsForView } from 'react-native-keyboard-insets'
9 | import { withNavigationItem } from 'hybrid-navigation'
10 | import { ViewDriver } from './driver/ViewDriver'
11 | import { Driver } from './driver/Driver'
12 | import { KeyboardDriver } from './driver/KeyboardDriver'
13 |
14 | function KeyboardChat() {
15 | const inputRef = useRef(null)
16 | const senderRef = useRef(null)
17 | const [bottom, setBottom] = useState(0)
18 |
19 | const onLayout = useCallback(() => {
20 | const viewTag = findNodeHandle(senderRef.current)
21 | if (viewTag === null) {
22 | return
23 | }
24 |
25 | getEdgeInsetsForView(viewTag, insets => {
26 | setBottom(insets.bottom!)
27 | })
28 | }, [])
29 |
30 | const emoji = useRef(new ViewDriver('emoji')).current
31 | const toolbox = useRef(new ViewDriver('toolbox')).current
32 | const keyboard = useRef(new KeyboardDriver(inputRef)).current
33 |
34 | const [driver, setDriver] = useState()
35 | const [translateY, setTranslateY] = useState(new Animated.Value(0))
36 | const driverState = { bottom, driver, setDriver, setTranslateY }
37 |
38 | const mainStyle = {
39 | transform: [
40 | {
41 | translateY: translateY,
42 | },
43 | ],
44 | }
45 |
46 | return (
47 |
48 |
49 |
50 |
51 | {history.map((message, index) => (
52 |
53 | ))}
54 |
55 |
56 |
57 |
58 | (emoji.shown ? keyboard.show() : emoji.show(driverState))}>
59 |
60 |
61 | toolbox.toggle(driverState)}>
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | 表情包
71 |
72 |
73 |
74 |
75 |
76 | 工具箱
77 |
78 |
79 |
80 |
81 | )
82 | }
83 |
84 | export default withNavigationItem({
85 | titleItem: {
86 | title: '聊天键盘处理',
87 | },
88 | })(KeyboardChat)
89 |
--------------------------------------------------------------------------------
/example/KeyboardChat/styles.ts:
--------------------------------------------------------------------------------
1 | import { StyleSheet } from 'react-native'
2 |
3 | export default StyleSheet.create({
4 | provider: {
5 | backgroundColor: '#FFFFFF',
6 | },
7 | fill: {
8 | flex: 1,
9 | },
10 | header: {
11 | marginRight: 12,
12 | },
13 | inverted: {
14 | transform: [
15 | {
16 | scaleY: -1,
17 | },
18 | ],
19 | },
20 | sender: {
21 | flexDirection: 'row',
22 | backgroundColor: 'white',
23 | alignItems: 'center',
24 | borderTopColor: '#DDDDDD',
25 | borderTopWidth: 1,
26 | paddingRight: 6,
27 | paddingVertical: 6,
28 | },
29 | input: {
30 | borderWidth: 1,
31 | borderColor: '#DDDDDD',
32 | backgroundColor: '#F5F5F5',
33 | flex: 1,
34 | minHeight: 36,
35 | maxHeight: 80,
36 | fontSize: 14,
37 | paddingTop: 10,
38 | paddingBottom: 10,
39 | paddingHorizontal: 6,
40 | marginHorizontal: 6,
41 | },
42 | button: {
43 | width: 36,
44 | height: 36,
45 | justifyContent: 'center',
46 | alignItems: 'center',
47 | },
48 | absolute: {
49 | position: 'absolute',
50 | bottom: 0,
51 | left: 0,
52 | right: 0,
53 | },
54 | red: {
55 | backgroundColor: 'cadetblue',
56 | },
57 | emoji: {
58 | height: 300,
59 | justifyContent: 'center',
60 | alignItems: 'center',
61 | },
62 | blue: {
63 | backgroundColor: 'darkkhaki',
64 | },
65 | toolbox: {
66 | height: 200,
67 | justifyContent: 'center',
68 | alignItems: 'center',
69 | },
70 | text: {
71 | fontSize: 48,
72 | color: 'darkgray',
73 | },
74 | })
75 |
--------------------------------------------------------------------------------
/example/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | project.ext.react = [
3 | root : "../../../",
4 | entryFile : "example/index.js",
5 | cliPath : "../../../node_modules/react-native/cli.js",
6 | bundleInRelease: true,
7 | bundleInDebug : true,
8 | enableHermes : false,
9 | hermesCommand : "../../../node_modules/hermes-engine/%OS-BIN%/hermesc",
10 | ]
11 |
12 | apply from: "../../../node_modules/react-native/react.gradle"
13 |
14 | def enableHermes = project.ext.react.get("enableHermes", false)
15 | def enableSeparateBuildPerCPUArchitecture = false
16 | def enableProguardInReleaseBuilds = false
17 | def jscFlavor = 'org.webkit:android-jsc:+'
18 |
19 | android {
20 | compileSdkVersion rootProject.ext.compileSdkVersion
21 |
22 | compileOptions {
23 | sourceCompatibility JavaVersion.VERSION_1_8
24 | targetCompatibility JavaVersion.VERSION_1_8
25 | }
26 |
27 | defaultConfig {
28 | applicationId "com.reactnative.keyboardinsets.example"
29 | minSdkVersion rootProject.ext.minSdkVersion
30 | targetSdkVersion rootProject.ext.targetSdkVersion
31 | versionCode 1
32 | versionName "1.0"
33 | }
34 | splits {
35 | abi {
36 | reset()
37 | enable enableSeparateBuildPerCPUArchitecture
38 | universalApk false // If true, also generate a universal APK
39 | include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
40 | }
41 | }
42 | signingConfigs {
43 | debug {
44 | storeFile file('debug.keystore')
45 | storePassword 'android'
46 | keyAlias 'androiddebugkey'
47 | keyPassword 'android'
48 | }
49 | }
50 | buildTypes {
51 | debug {
52 | signingConfig signingConfigs.debug
53 | }
54 | release {
55 | // Caution! In production, you need to generate your own keystore file.
56 | // see https://facebook.github.io/react-native/docs/signed-apk-android.
57 | signingConfig signingConfigs.debug
58 | minifyEnabled enableProguardInReleaseBuilds
59 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
60 | }
61 | }
62 | }
63 |
64 | dependencies {
65 | implementation fileTree(dir: "libs", include: ["*.jar"])
66 | implementation 'com.facebook.react:react-native:+'
67 | implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
68 | if (enableHermes) {
69 | def hermesPath = "../../../node_modules/hermes-engine/android/"
70 | debugImplementation files(hermesPath + "hermes-debug.aar")
71 | releaseImplementation files(hermesPath + "hermes-release.aar")
72 | } else {
73 | implementation jscFlavor
74 | }
75 | implementation project(':react-native-keyboard-insets')
76 | }
77 |
78 | task copyDownloadableDepsToLibs(type: Copy) {
79 | from configurations.implementation
80 | into 'libs'
81 | }
82 |
83 | apply from: file("../../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle");
84 | applyNativeModulesAppBuildGradle(project, "../..")
--------------------------------------------------------------------------------
/example/android/app/debug.keystore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/listenzz/react-native-keyboard-insets/7bc81ed8f6434afc4321b71fbf33cfcff20fbde4/example/android/app/debug.keystore
--------------------------------------------------------------------------------
/example/android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
--------------------------------------------------------------------------------
/example/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
16 |
17 |
20 |
23 |
26 |
27 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/reactnative/keyboardinsets/example/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.reactnative.keyboardinsets.example;
2 |
3 | import com.reactnative.hybridnavigation.ReactAppCompatActivity;
4 |
5 | public class MainActivity extends ReactAppCompatActivity {
6 |
7 | }
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/reactnative/keyboardinsets/example/MainApplication.java:
--------------------------------------------------------------------------------
1 | package com.reactnative.keyboardinsets.example;
2 |
3 | import android.app.Application;
4 |
5 | import com.facebook.common.logging.FLog;
6 | import com.facebook.react.PackageList;
7 | import com.facebook.react.ReactApplication;
8 | import com.facebook.react.ReactNativeHost;
9 | import com.facebook.react.ReactPackage;
10 | import com.facebook.soloader.SoLoader;
11 | import java.util.List;
12 | import com.reactnative.hybridnavigation.ReactBridgeManager;
13 | import com.reactnative.keyboardinsets.KeyboardInsetsPackage;
14 |
15 | public class MainApplication extends Application implements ReactApplication {
16 |
17 | private final ReactNativeHost mReactNativeHost =
18 | new ReactNativeHost(this) {
19 | @Override
20 | public boolean getUseDeveloperSupport() {
21 | return BuildConfig.DEBUG;
22 | }
23 |
24 | @Override
25 | protected List getPackages() {
26 | @SuppressWarnings("UnnecessaryLocalVariable")
27 | List packages = new PackageList(this).getPackages();
28 | packages.add(new KeyboardInsetsPackage());
29 | return packages;
30 | }
31 |
32 | @Override
33 | protected String getJSMainModuleName() {
34 | return "example/index";
35 | }
36 | };
37 |
38 | @Override
39 | public ReactNativeHost getReactNativeHost() {
40 | return mReactNativeHost;
41 | }
42 |
43 | @Override
44 | public void onCreate() {
45 | super.onCreate();
46 | SoLoader.init(this, /* native exopackage */ false);
47 | ReactBridgeManager bridgeManager = ReactBridgeManager.get();
48 | bridgeManager.install(getReactNativeHost());
49 | FLog.setMinimumLoggingLevel(FLog.INFO);
50 | }
51 | }
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/listenzz/react-native-keyboard-insets/7bc81ed8f6434afc4321b71fbf33cfcff20fbde4/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/listenzz/react-native-keyboard-insets/7bc81ed8f6434afc4321b71fbf33cfcff20fbde4/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/listenzz/react-native-keyboard-insets/7bc81ed8f6434afc4321b71fbf33cfcff20fbde4/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/listenzz/react-native-keyboard-insets/7bc81ed8f6434afc4321b71fbf33cfcff20fbde4/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/listenzz/react-native-keyboard-insets/7bc81ed8f6434afc4321b71fbf33cfcff20fbde4/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/listenzz/react-native-keyboard-insets/7bc81ed8f6434afc4321b71fbf33cfcff20fbde4/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/listenzz/react-native-keyboard-insets/7bc81ed8f6434afc4321b71fbf33cfcff20fbde4/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/listenzz/react-native-keyboard-insets/7bc81ed8f6434afc4321b71fbf33cfcff20fbde4/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/listenzz/react-native-keyboard-insets/7bc81ed8f6434afc4321b71fbf33cfcff20fbde4/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/listenzz/react-native-keyboard-insets/7bc81ed8f6434afc4321b71fbf33cfcff20fbde4/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | KeyboardInsetsExample
3 |
4 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/example/android/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext {
5 | buildToolsVersion = "30.0.2"
6 | minSdkVersion = 21
7 | compileSdkVersion = 30
8 | targetSdkVersion = 30
9 | }
10 | repositories {
11 | google()
12 | mavenCentral()
13 | }
14 | dependencies {
15 | classpath("com.android.tools.build:gradle:7.3.1")
16 | // NOTE: Do not place your application dependencies here; they belong
17 | // in the individual module build.gradle files
18 | }
19 | }
20 |
21 | allprojects {
22 | repositories {
23 | maven {
24 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
25 | url("$rootDir/../../node_modules/react-native/android")
26 | }
27 | maven {
28 | // Android JSC is installed from npm
29 | url("$rootDir/../../node_modules/jsc-android/dist")
30 | }
31 | mavenCentral {
32 | // We don't want to fetch react-native from Maven Central as there are
33 | // older versions over there.
34 | content {
35 | excludeGroup "com.facebook.react"
36 | }
37 | }
38 | google()
39 | maven { url 'https://www.jitpack.io' }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/example/android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx1024m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
20 | android.useAndroidX=true
21 | android.enableJetifier=true
22 |
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/listenzz/react-native-keyboard-insets/7bc81ed8f6434afc4321b71fbf33cfcff20fbde4/example/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip
--------------------------------------------------------------------------------
/example/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/example/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/example/android/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'KeyboardInsetsExample'
2 | apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle")
3 | applyNativeModulesSettingsGradle(settings, "../..")
4 |
5 | include ':app'
6 |
7 | include ':react-native-keyboard-insets'
8 | project(':react-native-keyboard-insets').projectDir = new File(rootProject.projectDir, '../../android')
--------------------------------------------------------------------------------
/example/index.js:
--------------------------------------------------------------------------------
1 | import { Platform } from 'react-native'
2 | import Navigation, { BarStyleDarkContent } from 'hybrid-navigation'
3 | import App from './App'
4 | import KeyboardChat from './KeyboardChat'
5 |
6 | Navigation.setDefaultOptions({
7 | screenBackgroundColor: '#F8F8F8',
8 | topBarStyle: BarStyleDarkContent,
9 | statusBarColorAndroid: Platform.Version > 21 ? undefined : '#4A4A4A',
10 | navigationBarColorAndroid: '#FFFFFF',
11 | })
12 |
13 | Navigation.startRegisterComponent()
14 | Navigation.registerComponent('KeyboardInsets', () => App)
15 | Navigation.registerComponent('Chat', () => KeyboardChat)
16 | Navigation.endRegisterComponent()
17 |
18 | Navigation.setRoot({
19 | stack: {
20 | children: [
21 | {
22 | screen: {
23 | moduleName: 'KeyboardInsets',
24 | },
25 | },
26 | ],
27 | },
28 | })
29 |
--------------------------------------------------------------------------------
/example/ios/KeyboardInsetsExample.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 55;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 047B8517EA7B5047F0A2DD5B /* libPods-KeyboardInsetsExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E122DC6660A2FD7515F28ED7 /* libPods-KeyboardInsetsExample.a */; };
11 | 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
12 | 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
13 | 91459E512605ACD000EFBE6E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 91459E502605ACD000EFBE6E /* Assets.xcassets */; };
14 | 91459E552605ACE600EFBE6E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 91459E532605ACE600EFBE6E /* LaunchScreen.storyboard */; };
15 | /* End PBXBuildFile section */
16 |
17 | /* Begin PBXFileReference section */
18 | 075B3E117F0418BAAAC1F540 /* Pods-KeyboardInsetsExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-KeyboardInsetsExample.release.xcconfig"; path = "Target Support Files/Pods-KeyboardInsetsExample/Pods-KeyboardInsetsExample.release.xcconfig"; sourceTree = ""; };
19 | 13B07F961A680F5B00A75B9A /* KeyboardInsetsExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = KeyboardInsetsExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
20 | 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = KeyboardInsetsExample/AppDelegate.h; sourceTree = ""; };
21 | 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = KeyboardInsetsExample/AppDelegate.m; sourceTree = ""; };
22 | 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = KeyboardInsetsExample/Info.plist; sourceTree = ""; };
23 | 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = KeyboardInsetsExample/main.m; sourceTree = ""; };
24 | 514699031AF404FCBE8E8782 /* Pods-KeyboardInsetsExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-KeyboardInsetsExample.debug.xcconfig"; path = "Target Support Files/Pods-KeyboardInsetsExample/Pods-KeyboardInsetsExample.debug.xcconfig"; sourceTree = ""; };
25 | 91459E502605ACD000EFBE6E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = KeyboardInsetsExample/Assets.xcassets; sourceTree = ""; };
26 | 91459E542605ACE600EFBE6E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = KeyboardInsetsExample/Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
27 | E122DC6660A2FD7515F28ED7 /* libPods-KeyboardInsetsExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-KeyboardInsetsExample.a"; sourceTree = BUILT_PRODUCTS_DIR; };
28 | ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
29 | /* End PBXFileReference section */
30 |
31 | /* Begin PBXFrameworksBuildPhase section */
32 | 13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
33 | isa = PBXFrameworksBuildPhase;
34 | buildActionMask = 2147483647;
35 | files = (
36 | 047B8517EA7B5047F0A2DD5B /* libPods-KeyboardInsetsExample.a in Frameworks */,
37 | );
38 | runOnlyForDeploymentPostprocessing = 0;
39 | };
40 | /* End PBXFrameworksBuildPhase section */
41 |
42 | /* Begin PBXGroup section */
43 | 13B07FAE1A68108700A75B9A /* KeyboardInsetsExample */ = {
44 | isa = PBXGroup;
45 | children = (
46 | 91459E532605ACE600EFBE6E /* LaunchScreen.storyboard */,
47 | 91459E502605ACD000EFBE6E /* Assets.xcassets */,
48 | 13B07FAF1A68108700A75B9A /* AppDelegate.h */,
49 | 13B07FB01A68108700A75B9A /* AppDelegate.m */,
50 | 13B07FB61A68108700A75B9A /* Info.plist */,
51 | 13B07FB71A68108700A75B9A /* main.m */,
52 | );
53 | name = KeyboardInsetsExample;
54 | sourceTree = "";
55 | };
56 | 244BF2D3CD7C5A603856DFAB /* Pods */ = {
57 | isa = PBXGroup;
58 | children = (
59 | 514699031AF404FCBE8E8782 /* Pods-KeyboardInsetsExample.debug.xcconfig */,
60 | 075B3E117F0418BAAAC1F540 /* Pods-KeyboardInsetsExample.release.xcconfig */,
61 | );
62 | path = Pods;
63 | sourceTree = "";
64 | };
65 | 2D16E6871FA4F8E400B85C8A /* Frameworks */ = {
66 | isa = PBXGroup;
67 | children = (
68 | ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
69 | E122DC6660A2FD7515F28ED7 /* libPods-KeyboardInsetsExample.a */,
70 | );
71 | name = Frameworks;
72 | sourceTree = "";
73 | };
74 | 832341AE1AAA6A7D00B99B32 /* Libraries */ = {
75 | isa = PBXGroup;
76 | children = (
77 | );
78 | name = Libraries;
79 | sourceTree = "";
80 | };
81 | 83CBB9F61A601CBA00E9B192 = {
82 | isa = PBXGroup;
83 | children = (
84 | 13B07FAE1A68108700A75B9A /* KeyboardInsetsExample */,
85 | 832341AE1AAA6A7D00B99B32 /* Libraries */,
86 | 83CBBA001A601CBA00E9B192 /* Products */,
87 | 2D16E6871FA4F8E400B85C8A /* Frameworks */,
88 | 244BF2D3CD7C5A603856DFAB /* Pods */,
89 | );
90 | indentWidth = 4;
91 | sourceTree = "";
92 | tabWidth = 4;
93 | usesTabs = 0;
94 | };
95 | 83CBBA001A601CBA00E9B192 /* Products */ = {
96 | isa = PBXGroup;
97 | children = (
98 | 13B07F961A680F5B00A75B9A /* KeyboardInsetsExample.app */,
99 | );
100 | name = Products;
101 | sourceTree = "";
102 | };
103 | /* End PBXGroup section */
104 |
105 | /* Begin PBXNativeTarget section */
106 | 13B07F861A680F5B00A75B9A /* KeyboardInsetsExample */ = {
107 | isa = PBXNativeTarget;
108 | buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "KeyboardInsetsExample" */;
109 | buildPhases = (
110 | 0B094BC46D5831EE808180B5 /* [CP] Check Pods Manifest.lock */,
111 | 13B07F871A680F5B00A75B9A /* Sources */,
112 | 13B07F8C1A680F5B00A75B9A /* Frameworks */,
113 | 13B07F8E1A680F5B00A75B9A /* Resources */,
114 | 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
115 | 1D167FDFE527CD5394527AC6 /* [CP] Copy Pods Resources */,
116 | );
117 | buildRules = (
118 | );
119 | dependencies = (
120 | );
121 | name = KeyboardInsetsExample;
122 | productName = KeyboardInsetsExample;
123 | productReference = 13B07F961A680F5B00A75B9A /* KeyboardInsetsExample.app */;
124 | productType = "com.apple.product-type.application";
125 | };
126 | /* End PBXNativeTarget section */
127 |
128 | /* Begin PBXProject section */
129 | 83CBB9F71A601CBA00E9B192 /* Project object */ = {
130 | isa = PBXProject;
131 | attributes = {
132 | LastUpgradeCheck = 1320;
133 | TargetAttributes = {
134 | 13B07F861A680F5B00A75B9A = {
135 | LastSwiftMigration = 1120;
136 | };
137 | };
138 | };
139 | buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "KeyboardInsetsExample" */;
140 | compatibilityVersion = "Xcode 13.0";
141 | developmentRegion = en;
142 | hasScannedForEncodings = 0;
143 | knownRegions = (
144 | en,
145 | Base,
146 | );
147 | mainGroup = 83CBB9F61A601CBA00E9B192;
148 | productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
149 | projectDirPath = "";
150 | projectRoot = "";
151 | targets = (
152 | 13B07F861A680F5B00A75B9A /* KeyboardInsetsExample */,
153 | );
154 | };
155 | /* End PBXProject section */
156 |
157 | /* Begin PBXResourcesBuildPhase section */
158 | 13B07F8E1A680F5B00A75B9A /* Resources */ = {
159 | isa = PBXResourcesBuildPhase;
160 | buildActionMask = 2147483647;
161 | files = (
162 | 91459E512605ACD000EFBE6E /* Assets.xcassets in Resources */,
163 | 91459E552605ACE600EFBE6E /* LaunchScreen.storyboard in Resources */,
164 | );
165 | runOnlyForDeploymentPostprocessing = 0;
166 | };
167 | /* End PBXResourcesBuildPhase section */
168 |
169 | /* Begin PBXShellScriptBuildPhase section */
170 | 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = {
171 | isa = PBXShellScriptBuildPhase;
172 | buildActionMask = 2147483647;
173 | files = (
174 | );
175 | inputPaths = (
176 | );
177 | name = "Bundle React Native code and images";
178 | outputPaths = (
179 | );
180 | runOnlyForDeploymentPostprocessing = 0;
181 | shellPath = /bin/sh;
182 | shellScript = "set -e\n\nexport NODE_BINARY=node\n../../node_modules/react-native/scripts/react-native-xcode.sh example/index.js\n";
183 | };
184 | 0B094BC46D5831EE808180B5 /* [CP] Check Pods Manifest.lock */ = {
185 | isa = PBXShellScriptBuildPhase;
186 | buildActionMask = 2147483647;
187 | files = (
188 | );
189 | inputFileListPaths = (
190 | );
191 | inputPaths = (
192 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
193 | "${PODS_ROOT}/Manifest.lock",
194 | );
195 | name = "[CP] Check Pods Manifest.lock";
196 | outputFileListPaths = (
197 | );
198 | outputPaths = (
199 | "$(DERIVED_FILE_DIR)/Pods-KeyboardInsetsExample-checkManifestLockResult.txt",
200 | );
201 | runOnlyForDeploymentPostprocessing = 0;
202 | shellPath = /bin/sh;
203 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
204 | showEnvVarsInLog = 0;
205 | };
206 | 1D167FDFE527CD5394527AC6 /* [CP] Copy Pods Resources */ = {
207 | isa = PBXShellScriptBuildPhase;
208 | buildActionMask = 2147483647;
209 | files = (
210 | );
211 | inputFileListPaths = (
212 | "${PODS_ROOT}/Target Support Files/Pods-KeyboardInsetsExample/Pods-KeyboardInsetsExample-resources-${CONFIGURATION}-input-files.xcfilelist",
213 | );
214 | name = "[CP] Copy Pods Resources";
215 | outputFileListPaths = (
216 | "${PODS_ROOT}/Target Support Files/Pods-KeyboardInsetsExample/Pods-KeyboardInsetsExample-resources-${CONFIGURATION}-output-files.xcfilelist",
217 | );
218 | runOnlyForDeploymentPostprocessing = 0;
219 | shellPath = /bin/sh;
220 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-KeyboardInsetsExample/Pods-KeyboardInsetsExample-resources.sh\"\n";
221 | showEnvVarsInLog = 0;
222 | };
223 | /* End PBXShellScriptBuildPhase section */
224 |
225 | /* Begin PBXSourcesBuildPhase section */
226 | 13B07F871A680F5B00A75B9A /* Sources */ = {
227 | isa = PBXSourcesBuildPhase;
228 | buildActionMask = 2147483647;
229 | files = (
230 | 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,
231 | 13B07FC11A68108700A75B9A /* main.m in Sources */,
232 | );
233 | runOnlyForDeploymentPostprocessing = 0;
234 | };
235 | /* End PBXSourcesBuildPhase section */
236 |
237 | /* Begin PBXVariantGroup section */
238 | 91459E532605ACE600EFBE6E /* LaunchScreen.storyboard */ = {
239 | isa = PBXVariantGroup;
240 | children = (
241 | 91459E542605ACE600EFBE6E /* Base */,
242 | );
243 | name = LaunchScreen.storyboard;
244 | sourceTree = "";
245 | };
246 | /* End PBXVariantGroup section */
247 |
248 | /* Begin XCBuildConfiguration section */
249 | 13B07F941A680F5B00A75B9A /* Debug */ = {
250 | isa = XCBuildConfiguration;
251 | baseConfigurationReference = 514699031AF404FCBE8E8782 /* Pods-KeyboardInsetsExample.debug.xcconfig */;
252 | buildSettings = {
253 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
254 | CLANG_ENABLE_MODULES = YES;
255 | CURRENT_PROJECT_VERSION = 1;
256 | ENABLE_BITCODE = NO;
257 | INFOPLIST_FILE = KeyboardInsetsExample/Info.plist;
258 | LD_RUNPATH_SEARCH_PATHS = (
259 | "$(inherited)",
260 | "@executable_path/Frameworks",
261 | );
262 | OTHER_LDFLAGS = (
263 | "$(inherited)",
264 | "-ObjC",
265 | "-lc++",
266 | );
267 | PRODUCT_BUNDLE_IDENTIFIER = com.reactnative.keyboardinsets.example;
268 | PRODUCT_NAME = KeyboardInsetsExample;
269 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
270 | SWIFT_VERSION = 5.0;
271 | VERSIONING_SYSTEM = "apple-generic";
272 | };
273 | name = Debug;
274 | };
275 | 13B07F951A680F5B00A75B9A /* Release */ = {
276 | isa = XCBuildConfiguration;
277 | baseConfigurationReference = 075B3E117F0418BAAAC1F540 /* Pods-KeyboardInsetsExample.release.xcconfig */;
278 | buildSettings = {
279 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
280 | CLANG_ENABLE_MODULES = YES;
281 | CURRENT_PROJECT_VERSION = 1;
282 | INFOPLIST_FILE = KeyboardInsetsExample/Info.plist;
283 | LD_RUNPATH_SEARCH_PATHS = (
284 | "$(inherited)",
285 | "@executable_path/Frameworks",
286 | );
287 | OTHER_LDFLAGS = (
288 | "$(inherited)",
289 | "-ObjC",
290 | "-lc++",
291 | );
292 | PRODUCT_BUNDLE_IDENTIFIER = com.reactnative.keyboardinsets.example;
293 | PRODUCT_NAME = KeyboardInsetsExample;
294 | SWIFT_VERSION = 5.0;
295 | VERSIONING_SYSTEM = "apple-generic";
296 | };
297 | name = Release;
298 | };
299 | 83CBBA201A601CBA00E9B192 /* Debug */ = {
300 | isa = XCBuildConfiguration;
301 | buildSettings = {
302 | ALWAYS_SEARCH_USER_PATHS = NO;
303 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
304 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
305 | CLANG_CXX_LIBRARY = "libc++";
306 | CLANG_ENABLE_MODULES = YES;
307 | CLANG_ENABLE_OBJC_ARC = YES;
308 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
309 | CLANG_WARN_BOOL_CONVERSION = YES;
310 | CLANG_WARN_COMMA = YES;
311 | CLANG_WARN_CONSTANT_CONVERSION = YES;
312 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
313 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
314 | CLANG_WARN_EMPTY_BODY = YES;
315 | CLANG_WARN_ENUM_CONVERSION = YES;
316 | CLANG_WARN_INFINITE_RECURSION = YES;
317 | CLANG_WARN_INT_CONVERSION = YES;
318 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
319 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
320 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
321 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
322 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
323 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
324 | CLANG_WARN_STRICT_PROTOTYPES = YES;
325 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
326 | CLANG_WARN_UNREACHABLE_CODE = YES;
327 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
328 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
329 | COPY_PHASE_STRIP = NO;
330 | ENABLE_STRICT_OBJC_MSGSEND = YES;
331 | ENABLE_TESTABILITY = YES;
332 | "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
333 | GCC_C_LANGUAGE_STANDARD = gnu99;
334 | GCC_DYNAMIC_NO_PIC = NO;
335 | GCC_NO_COMMON_BLOCKS = YES;
336 | GCC_OPTIMIZATION_LEVEL = 0;
337 | GCC_PREPROCESSOR_DEFINITIONS = (
338 | "DEBUG=1",
339 | "$(inherited)",
340 | );
341 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
342 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
343 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
344 | GCC_WARN_UNDECLARED_SELECTOR = YES;
345 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
346 | GCC_WARN_UNUSED_FUNCTION = YES;
347 | GCC_WARN_UNUSED_VARIABLE = YES;
348 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
349 | LD_RUNPATH_SEARCH_PATHS = (
350 | /usr/lib/swift,
351 | "$(inherited)",
352 | );
353 | LIBRARY_SEARCH_PATHS = (
354 | "$(SDKROOT)/usr/lib/swift",
355 | "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"",
356 | "\"$(inherited)\"",
357 | );
358 | MTL_ENABLE_DEBUG_INFO = YES;
359 | ONLY_ACTIVE_ARCH = YES;
360 | SDKROOT = iphoneos;
361 | };
362 | name = Debug;
363 | };
364 | 83CBBA211A601CBA00E9B192 /* Release */ = {
365 | isa = XCBuildConfiguration;
366 | buildSettings = {
367 | ALWAYS_SEARCH_USER_PATHS = NO;
368 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
369 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
370 | CLANG_CXX_LIBRARY = "libc++";
371 | CLANG_ENABLE_MODULES = YES;
372 | CLANG_ENABLE_OBJC_ARC = YES;
373 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
374 | CLANG_WARN_BOOL_CONVERSION = YES;
375 | CLANG_WARN_COMMA = YES;
376 | CLANG_WARN_CONSTANT_CONVERSION = YES;
377 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
378 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
379 | CLANG_WARN_EMPTY_BODY = YES;
380 | CLANG_WARN_ENUM_CONVERSION = YES;
381 | CLANG_WARN_INFINITE_RECURSION = YES;
382 | CLANG_WARN_INT_CONVERSION = YES;
383 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
384 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
385 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
386 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
387 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
388 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
389 | CLANG_WARN_STRICT_PROTOTYPES = YES;
390 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
391 | CLANG_WARN_UNREACHABLE_CODE = YES;
392 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
393 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
394 | COPY_PHASE_STRIP = YES;
395 | ENABLE_NS_ASSERTIONS = NO;
396 | ENABLE_STRICT_OBJC_MSGSEND = YES;
397 | "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
398 | GCC_C_LANGUAGE_STANDARD = gnu99;
399 | GCC_NO_COMMON_BLOCKS = YES;
400 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
401 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
402 | GCC_WARN_UNDECLARED_SELECTOR = YES;
403 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
404 | GCC_WARN_UNUSED_FUNCTION = YES;
405 | GCC_WARN_UNUSED_VARIABLE = YES;
406 | IPHONEOS_DEPLOYMENT_TARGET = 11.0;
407 | LD_RUNPATH_SEARCH_PATHS = (
408 | /usr/lib/swift,
409 | "$(inherited)",
410 | );
411 | LIBRARY_SEARCH_PATHS = (
412 | "$(SDKROOT)/usr/lib/swift",
413 | "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"",
414 | "\"$(inherited)\"",
415 | );
416 | MTL_ENABLE_DEBUG_INFO = NO;
417 | SDKROOT = iphoneos;
418 | VALIDATE_PRODUCT = YES;
419 | };
420 | name = Release;
421 | };
422 | /* End XCBuildConfiguration section */
423 |
424 | /* Begin XCConfigurationList section */
425 | 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "KeyboardInsetsExample" */ = {
426 | isa = XCConfigurationList;
427 | buildConfigurations = (
428 | 13B07F941A680F5B00A75B9A /* Debug */,
429 | 13B07F951A680F5B00A75B9A /* Release */,
430 | );
431 | defaultConfigurationIsVisible = 0;
432 | defaultConfigurationName = Release;
433 | };
434 | 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "KeyboardInsetsExample" */ = {
435 | isa = XCConfigurationList;
436 | buildConfigurations = (
437 | 83CBBA201A601CBA00E9B192 /* Debug */,
438 | 83CBBA211A601CBA00E9B192 /* Release */,
439 | );
440 | defaultConfigurationIsVisible = 0;
441 | defaultConfigurationName = Release;
442 | };
443 | /* End XCConfigurationList section */
444 | };
445 | rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;
446 | }
447 |
--------------------------------------------------------------------------------
/example/ios/KeyboardInsetsExample.xcodeproj/xcshareddata/xcschemes/KeyboardInsetsExample.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
45 |
51 |
52 |
53 |
54 |
60 |
62 |
68 |
69 |
70 |
71 |
73 |
74 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/example/ios/KeyboardInsetsExample.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/example/ios/KeyboardInsetsExample/AppDelegate.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | @interface AppDelegate : UIResponder
4 |
5 | @property (strong, nonatomic) UIWindow *window;
6 |
7 | @end
--------------------------------------------------------------------------------
/example/ios/KeyboardInsetsExample/AppDelegate.m:
--------------------------------------------------------------------------------
1 | #import "AppDelegate.h"
2 | #import
3 | #import
4 | #import
5 |
6 | @interface AppDelegate ()
7 |
8 | @end
9 |
10 | @implementation AppDelegate
11 |
12 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
13 |
14 | RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
15 | [[HBDReactBridgeManager get] installWithBridge:bridge];
16 |
17 | UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"LaunchScreen" bundle:nil];
18 | UIViewController *rootViewController = [storyboard instantiateInitialViewController];
19 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
20 | self.window.windowLevel = UIWindowLevelStatusBar + 1;
21 | self.window.rootViewController = rootViewController;
22 | [self.window makeKeyAndVisible];
23 | return YES;
24 | }
25 |
26 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge {
27 | #if DEBUG
28 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"example/index" fallbackResource:nil];
29 | #else
30 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
31 | #endif
32 | }
33 |
34 | @end
35 |
--------------------------------------------------------------------------------
/example/ios/KeyboardInsetsExample/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/example/ios/KeyboardInsetsExample/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/example/ios/KeyboardInsetsExample/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/example/ios/KeyboardInsetsExample/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | $(PRODUCT_NAME)
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | LSRequiresIPhoneOS
26 |
27 | NSAppTransportSecurity
28 |
29 | NSAllowsArbitraryLoads
30 |
31 | NSExceptionDomains
32 |
33 | localhost
34 |
35 | NSExceptionAllowsInsecureHTTPLoads
36 |
37 |
38 |
39 |
40 | UILaunchStoryboardName
41 | LaunchScreen
42 | UIRequiredDeviceCapabilities
43 |
44 | armv7
45 |
46 | UIStatusBarHidden
47 |
48 | UISupportedInterfaceOrientations
49 |
50 | UIInterfaceOrientationPortrait
51 |
52 |
53 |
--------------------------------------------------------------------------------
/example/ios/KeyboardInsetsExample/main.m:
--------------------------------------------------------------------------------
1 | #import
2 | #import "AppDelegate.h"
3 |
4 | int main(int argc, char * argv[]) {
5 | NSString * appDelegateClassName;
6 | @autoreleasepool {
7 | // Setup code that might create autoreleased objects goes here.
8 | appDelegateClassName = NSStringFromClass([AppDelegate class]);
9 | }
10 | return UIApplicationMain(argc, argv, nil, appDelegateClassName);
11 | }
--------------------------------------------------------------------------------
/example/ios/Podfile:
--------------------------------------------------------------------------------
1 | platform :ios, '11.0'
2 | require_relative '../../node_modules/react-native/scripts/react_native_pods'
3 | require_relative '../../node_modules/@react-native-community/cli-platform-ios/native_modules'
4 |
5 | target 'KeyboardInsetsExample' do
6 | pod 'RNKeyboardInsets', :path => '../../'
7 |
8 | config = use_native_modules!
9 | use_react_native!(
10 | :path => config[:reactNativePath],
11 | :hermes_enabled => false
12 | )
13 | end
14 |
15 | post_install do |installer|
16 | react_native_post_install(installer)
17 | __apply_Xcode_12_5_M1_post_install_workaround(installer)
18 | end
19 |
--------------------------------------------------------------------------------
/example/ios/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - boost (1.76.0)
3 | - DoubleConversion (1.1.6)
4 | - FBLazyVector (0.67.4)
5 | - FBReactNativeSpec (0.67.4):
6 | - RCT-Folly (= 2021.06.28.00-v2)
7 | - RCTRequired (= 0.67.4)
8 | - RCTTypeSafety (= 0.67.4)
9 | - React-Core (= 0.67.4)
10 | - React-jsi (= 0.67.4)
11 | - ReactCommon/turbomodule/core (= 0.67.4)
12 | - fmt (6.2.1)
13 | - glog (0.3.5)
14 | - HybridNavigation (2.14.6):
15 | - React-Core
16 | - RCT-Folly (2021.06.28.00-v2):
17 | - boost
18 | - DoubleConversion
19 | - fmt (~> 6.2.1)
20 | - glog
21 | - RCT-Folly/Default (= 2021.06.28.00-v2)
22 | - RCT-Folly/Default (2021.06.28.00-v2):
23 | - boost
24 | - DoubleConversion
25 | - fmt (~> 6.2.1)
26 | - glog
27 | - RCTRequired (0.67.4)
28 | - RCTTypeSafety (0.67.4):
29 | - FBLazyVector (= 0.67.4)
30 | - RCT-Folly (= 2021.06.28.00-v2)
31 | - RCTRequired (= 0.67.4)
32 | - React-Core (= 0.67.4)
33 | - React (0.67.4):
34 | - React-Core (= 0.67.4)
35 | - React-Core/DevSupport (= 0.67.4)
36 | - React-Core/RCTWebSocket (= 0.67.4)
37 | - React-RCTActionSheet (= 0.67.4)
38 | - React-RCTAnimation (= 0.67.4)
39 | - React-RCTBlob (= 0.67.4)
40 | - React-RCTImage (= 0.67.4)
41 | - React-RCTLinking (= 0.67.4)
42 | - React-RCTNetwork (= 0.67.4)
43 | - React-RCTSettings (= 0.67.4)
44 | - React-RCTText (= 0.67.4)
45 | - React-RCTVibration (= 0.67.4)
46 | - React-callinvoker (0.67.4)
47 | - React-Core (0.67.4):
48 | - glog
49 | - RCT-Folly (= 2021.06.28.00-v2)
50 | - React-Core/Default (= 0.67.4)
51 | - React-cxxreact (= 0.67.4)
52 | - React-jsi (= 0.67.4)
53 | - React-jsiexecutor (= 0.67.4)
54 | - React-perflogger (= 0.67.4)
55 | - Yoga
56 | - React-Core/CoreModulesHeaders (0.67.4):
57 | - glog
58 | - RCT-Folly (= 2021.06.28.00-v2)
59 | - React-Core/Default
60 | - React-cxxreact (= 0.67.4)
61 | - React-jsi (= 0.67.4)
62 | - React-jsiexecutor (= 0.67.4)
63 | - React-perflogger (= 0.67.4)
64 | - Yoga
65 | - React-Core/Default (0.67.4):
66 | - glog
67 | - RCT-Folly (= 2021.06.28.00-v2)
68 | - React-cxxreact (= 0.67.4)
69 | - React-jsi (= 0.67.4)
70 | - React-jsiexecutor (= 0.67.4)
71 | - React-perflogger (= 0.67.4)
72 | - Yoga
73 | - React-Core/DevSupport (0.67.4):
74 | - glog
75 | - RCT-Folly (= 2021.06.28.00-v2)
76 | - React-Core/Default (= 0.67.4)
77 | - React-Core/RCTWebSocket (= 0.67.4)
78 | - React-cxxreact (= 0.67.4)
79 | - React-jsi (= 0.67.4)
80 | - React-jsiexecutor (= 0.67.4)
81 | - React-jsinspector (= 0.67.4)
82 | - React-perflogger (= 0.67.4)
83 | - Yoga
84 | - React-Core/RCTActionSheetHeaders (0.67.4):
85 | - glog
86 | - RCT-Folly (= 2021.06.28.00-v2)
87 | - React-Core/Default
88 | - React-cxxreact (= 0.67.4)
89 | - React-jsi (= 0.67.4)
90 | - React-jsiexecutor (= 0.67.4)
91 | - React-perflogger (= 0.67.4)
92 | - Yoga
93 | - React-Core/RCTAnimationHeaders (0.67.4):
94 | - glog
95 | - RCT-Folly (= 2021.06.28.00-v2)
96 | - React-Core/Default
97 | - React-cxxreact (= 0.67.4)
98 | - React-jsi (= 0.67.4)
99 | - React-jsiexecutor (= 0.67.4)
100 | - React-perflogger (= 0.67.4)
101 | - Yoga
102 | - React-Core/RCTBlobHeaders (0.67.4):
103 | - glog
104 | - RCT-Folly (= 2021.06.28.00-v2)
105 | - React-Core/Default
106 | - React-cxxreact (= 0.67.4)
107 | - React-jsi (= 0.67.4)
108 | - React-jsiexecutor (= 0.67.4)
109 | - React-perflogger (= 0.67.4)
110 | - Yoga
111 | - React-Core/RCTImageHeaders (0.67.4):
112 | - glog
113 | - RCT-Folly (= 2021.06.28.00-v2)
114 | - React-Core/Default
115 | - React-cxxreact (= 0.67.4)
116 | - React-jsi (= 0.67.4)
117 | - React-jsiexecutor (= 0.67.4)
118 | - React-perflogger (= 0.67.4)
119 | - Yoga
120 | - React-Core/RCTLinkingHeaders (0.67.4):
121 | - glog
122 | - RCT-Folly (= 2021.06.28.00-v2)
123 | - React-Core/Default
124 | - React-cxxreact (= 0.67.4)
125 | - React-jsi (= 0.67.4)
126 | - React-jsiexecutor (= 0.67.4)
127 | - React-perflogger (= 0.67.4)
128 | - Yoga
129 | - React-Core/RCTNetworkHeaders (0.67.4):
130 | - glog
131 | - RCT-Folly (= 2021.06.28.00-v2)
132 | - React-Core/Default
133 | - React-cxxreact (= 0.67.4)
134 | - React-jsi (= 0.67.4)
135 | - React-jsiexecutor (= 0.67.4)
136 | - React-perflogger (= 0.67.4)
137 | - Yoga
138 | - React-Core/RCTSettingsHeaders (0.67.4):
139 | - glog
140 | - RCT-Folly (= 2021.06.28.00-v2)
141 | - React-Core/Default
142 | - React-cxxreact (= 0.67.4)
143 | - React-jsi (= 0.67.4)
144 | - React-jsiexecutor (= 0.67.4)
145 | - React-perflogger (= 0.67.4)
146 | - Yoga
147 | - React-Core/RCTTextHeaders (0.67.4):
148 | - glog
149 | - RCT-Folly (= 2021.06.28.00-v2)
150 | - React-Core/Default
151 | - React-cxxreact (= 0.67.4)
152 | - React-jsi (= 0.67.4)
153 | - React-jsiexecutor (= 0.67.4)
154 | - React-perflogger (= 0.67.4)
155 | - Yoga
156 | - React-Core/RCTVibrationHeaders (0.67.4):
157 | - glog
158 | - RCT-Folly (= 2021.06.28.00-v2)
159 | - React-Core/Default
160 | - React-cxxreact (= 0.67.4)
161 | - React-jsi (= 0.67.4)
162 | - React-jsiexecutor (= 0.67.4)
163 | - React-perflogger (= 0.67.4)
164 | - Yoga
165 | - React-Core/RCTWebSocket (0.67.4):
166 | - glog
167 | - RCT-Folly (= 2021.06.28.00-v2)
168 | - React-Core/Default (= 0.67.4)
169 | - React-cxxreact (= 0.67.4)
170 | - React-jsi (= 0.67.4)
171 | - React-jsiexecutor (= 0.67.4)
172 | - React-perflogger (= 0.67.4)
173 | - Yoga
174 | - React-CoreModules (0.67.4):
175 | - FBReactNativeSpec (= 0.67.4)
176 | - RCT-Folly (= 2021.06.28.00-v2)
177 | - RCTTypeSafety (= 0.67.4)
178 | - React-Core/CoreModulesHeaders (= 0.67.4)
179 | - React-jsi (= 0.67.4)
180 | - React-RCTImage (= 0.67.4)
181 | - ReactCommon/turbomodule/core (= 0.67.4)
182 | - React-cxxreact (0.67.4):
183 | - boost (= 1.76.0)
184 | - DoubleConversion
185 | - glog
186 | - RCT-Folly (= 2021.06.28.00-v2)
187 | - React-callinvoker (= 0.67.4)
188 | - React-jsi (= 0.67.4)
189 | - React-jsinspector (= 0.67.4)
190 | - React-logger (= 0.67.4)
191 | - React-perflogger (= 0.67.4)
192 | - React-runtimeexecutor (= 0.67.4)
193 | - React-jsi (0.67.4):
194 | - boost (= 1.76.0)
195 | - DoubleConversion
196 | - glog
197 | - RCT-Folly (= 2021.06.28.00-v2)
198 | - React-jsi/Default (= 0.67.4)
199 | - React-jsi/Default (0.67.4):
200 | - boost (= 1.76.0)
201 | - DoubleConversion
202 | - glog
203 | - RCT-Folly (= 2021.06.28.00-v2)
204 | - React-jsiexecutor (0.67.4):
205 | - DoubleConversion
206 | - glog
207 | - RCT-Folly (= 2021.06.28.00-v2)
208 | - React-cxxreact (= 0.67.4)
209 | - React-jsi (= 0.67.4)
210 | - React-perflogger (= 0.67.4)
211 | - React-jsinspector (0.67.4)
212 | - React-logger (0.67.4):
213 | - glog
214 | - react-native-safe-area-context (4.5.0):
215 | - RCT-Folly
216 | - RCTRequired
217 | - RCTTypeSafety
218 | - React-Core
219 | - ReactCommon/turbomodule/core
220 | - React-perflogger (0.67.4)
221 | - React-RCTActionSheet (0.67.4):
222 | - React-Core/RCTActionSheetHeaders (= 0.67.4)
223 | - React-RCTAnimation (0.67.4):
224 | - FBReactNativeSpec (= 0.67.4)
225 | - RCT-Folly (= 2021.06.28.00-v2)
226 | - RCTTypeSafety (= 0.67.4)
227 | - React-Core/RCTAnimationHeaders (= 0.67.4)
228 | - React-jsi (= 0.67.4)
229 | - ReactCommon/turbomodule/core (= 0.67.4)
230 | - React-RCTBlob (0.67.4):
231 | - FBReactNativeSpec (= 0.67.4)
232 | - RCT-Folly (= 2021.06.28.00-v2)
233 | - React-Core/RCTBlobHeaders (= 0.67.4)
234 | - React-Core/RCTWebSocket (= 0.67.4)
235 | - React-jsi (= 0.67.4)
236 | - React-RCTNetwork (= 0.67.4)
237 | - ReactCommon/turbomodule/core (= 0.67.4)
238 | - React-RCTImage (0.67.4):
239 | - FBReactNativeSpec (= 0.67.4)
240 | - RCT-Folly (= 2021.06.28.00-v2)
241 | - RCTTypeSafety (= 0.67.4)
242 | - React-Core/RCTImageHeaders (= 0.67.4)
243 | - React-jsi (= 0.67.4)
244 | - React-RCTNetwork (= 0.67.4)
245 | - ReactCommon/turbomodule/core (= 0.67.4)
246 | - React-RCTLinking (0.67.4):
247 | - FBReactNativeSpec (= 0.67.4)
248 | - React-Core/RCTLinkingHeaders (= 0.67.4)
249 | - React-jsi (= 0.67.4)
250 | - ReactCommon/turbomodule/core (= 0.67.4)
251 | - React-RCTNetwork (0.67.4):
252 | - FBReactNativeSpec (= 0.67.4)
253 | - RCT-Folly (= 2021.06.28.00-v2)
254 | - RCTTypeSafety (= 0.67.4)
255 | - React-Core/RCTNetworkHeaders (= 0.67.4)
256 | - React-jsi (= 0.67.4)
257 | - ReactCommon/turbomodule/core (= 0.67.4)
258 | - React-RCTSettings (0.67.4):
259 | - FBReactNativeSpec (= 0.67.4)
260 | - RCT-Folly (= 2021.06.28.00-v2)
261 | - RCTTypeSafety (= 0.67.4)
262 | - React-Core/RCTSettingsHeaders (= 0.67.4)
263 | - React-jsi (= 0.67.4)
264 | - ReactCommon/turbomodule/core (= 0.67.4)
265 | - React-RCTText (0.67.4):
266 | - React-Core/RCTTextHeaders (= 0.67.4)
267 | - React-RCTVibration (0.67.4):
268 | - FBReactNativeSpec (= 0.67.4)
269 | - RCT-Folly (= 2021.06.28.00-v2)
270 | - React-Core/RCTVibrationHeaders (= 0.67.4)
271 | - React-jsi (= 0.67.4)
272 | - ReactCommon/turbomodule/core (= 0.67.4)
273 | - React-runtimeexecutor (0.67.4):
274 | - React-jsi (= 0.67.4)
275 | - ReactCommon/turbomodule/core (0.67.4):
276 | - DoubleConversion
277 | - glog
278 | - RCT-Folly (= 2021.06.28.00-v2)
279 | - React-callinvoker (= 0.67.4)
280 | - React-Core (= 0.67.4)
281 | - React-cxxreact (= 0.67.4)
282 | - React-jsi (= 0.67.4)
283 | - React-logger (= 0.67.4)
284 | - React-perflogger (= 0.67.4)
285 | - RNKeyboardInsets (1.3.2):
286 | - React-Core
287 | - Yoga (1.14.0)
288 |
289 | DEPENDENCIES:
290 | - boost (from `../../node_modules/react-native/third-party-podspecs/boost.podspec`)
291 | - DoubleConversion (from `../../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
292 | - FBLazyVector (from `../../node_modules/react-native/Libraries/FBLazyVector`)
293 | - FBReactNativeSpec (from `../../node_modules/react-native/React/FBReactNativeSpec`)
294 | - glog (from `../../node_modules/react-native/third-party-podspecs/glog.podspec`)
295 | - HybridNavigation (from `../../node_modules/hybrid-navigation`)
296 | - RCT-Folly (from `../../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`)
297 | - RCTRequired (from `../../node_modules/react-native/Libraries/RCTRequired`)
298 | - RCTTypeSafety (from `../../node_modules/react-native/Libraries/TypeSafety`)
299 | - React (from `../../node_modules/react-native/`)
300 | - React-callinvoker (from `../../node_modules/react-native/ReactCommon/callinvoker`)
301 | - React-Core (from `../../node_modules/react-native/`)
302 | - React-Core/DevSupport (from `../../node_modules/react-native/`)
303 | - React-Core/RCTWebSocket (from `../../node_modules/react-native/`)
304 | - React-CoreModules (from `../../node_modules/react-native/React/CoreModules`)
305 | - React-cxxreact (from `../../node_modules/react-native/ReactCommon/cxxreact`)
306 | - React-jsi (from `../../node_modules/react-native/ReactCommon/jsi`)
307 | - React-jsiexecutor (from `../../node_modules/react-native/ReactCommon/jsiexecutor`)
308 | - React-jsinspector (from `../../node_modules/react-native/ReactCommon/jsinspector`)
309 | - React-logger (from `../../node_modules/react-native/ReactCommon/logger`)
310 | - react-native-safe-area-context (from `../../node_modules/react-native-safe-area-context`)
311 | - React-perflogger (from `../../node_modules/react-native/ReactCommon/reactperflogger`)
312 | - React-RCTActionSheet (from `../../node_modules/react-native/Libraries/ActionSheetIOS`)
313 | - React-RCTAnimation (from `../../node_modules/react-native/Libraries/NativeAnimation`)
314 | - React-RCTBlob (from `../../node_modules/react-native/Libraries/Blob`)
315 | - React-RCTImage (from `../../node_modules/react-native/Libraries/Image`)
316 | - React-RCTLinking (from `../../node_modules/react-native/Libraries/LinkingIOS`)
317 | - React-RCTNetwork (from `../../node_modules/react-native/Libraries/Network`)
318 | - React-RCTSettings (from `../../node_modules/react-native/Libraries/Settings`)
319 | - React-RCTText (from `../../node_modules/react-native/Libraries/Text`)
320 | - React-RCTVibration (from `../../node_modules/react-native/Libraries/Vibration`)
321 | - React-runtimeexecutor (from `../../node_modules/react-native/ReactCommon/runtimeexecutor`)
322 | - ReactCommon/turbomodule/core (from `../../node_modules/react-native/ReactCommon`)
323 | - RNKeyboardInsets (from `../../`)
324 | - Yoga (from `../../node_modules/react-native/ReactCommon/yoga`)
325 |
326 | SPEC REPOS:
327 | trunk:
328 | - fmt
329 |
330 | EXTERNAL SOURCES:
331 | boost:
332 | :podspec: "../../node_modules/react-native/third-party-podspecs/boost.podspec"
333 | DoubleConversion:
334 | :podspec: "../../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec"
335 | FBLazyVector:
336 | :path: "../../node_modules/react-native/Libraries/FBLazyVector"
337 | FBReactNativeSpec:
338 | :path: "../../node_modules/react-native/React/FBReactNativeSpec"
339 | glog:
340 | :podspec: "../../node_modules/react-native/third-party-podspecs/glog.podspec"
341 | HybridNavigation:
342 | :path: "../../node_modules/hybrid-navigation"
343 | RCT-Folly:
344 | :podspec: "../../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec"
345 | RCTRequired:
346 | :path: "../../node_modules/react-native/Libraries/RCTRequired"
347 | RCTTypeSafety:
348 | :path: "../../node_modules/react-native/Libraries/TypeSafety"
349 | React:
350 | :path: "../../node_modules/react-native/"
351 | React-callinvoker:
352 | :path: "../../node_modules/react-native/ReactCommon/callinvoker"
353 | React-Core:
354 | :path: "../../node_modules/react-native/"
355 | React-CoreModules:
356 | :path: "../../node_modules/react-native/React/CoreModules"
357 | React-cxxreact:
358 | :path: "../../node_modules/react-native/ReactCommon/cxxreact"
359 | React-jsi:
360 | :path: "../../node_modules/react-native/ReactCommon/jsi"
361 | React-jsiexecutor:
362 | :path: "../../node_modules/react-native/ReactCommon/jsiexecutor"
363 | React-jsinspector:
364 | :path: "../../node_modules/react-native/ReactCommon/jsinspector"
365 | React-logger:
366 | :path: "../../node_modules/react-native/ReactCommon/logger"
367 | react-native-safe-area-context:
368 | :path: "../../node_modules/react-native-safe-area-context"
369 | React-perflogger:
370 | :path: "../../node_modules/react-native/ReactCommon/reactperflogger"
371 | React-RCTActionSheet:
372 | :path: "../../node_modules/react-native/Libraries/ActionSheetIOS"
373 | React-RCTAnimation:
374 | :path: "../../node_modules/react-native/Libraries/NativeAnimation"
375 | React-RCTBlob:
376 | :path: "../../node_modules/react-native/Libraries/Blob"
377 | React-RCTImage:
378 | :path: "../../node_modules/react-native/Libraries/Image"
379 | React-RCTLinking:
380 | :path: "../../node_modules/react-native/Libraries/LinkingIOS"
381 | React-RCTNetwork:
382 | :path: "../../node_modules/react-native/Libraries/Network"
383 | React-RCTSettings:
384 | :path: "../../node_modules/react-native/Libraries/Settings"
385 | React-RCTText:
386 | :path: "../../node_modules/react-native/Libraries/Text"
387 | React-RCTVibration:
388 | :path: "../../node_modules/react-native/Libraries/Vibration"
389 | React-runtimeexecutor:
390 | :path: "../../node_modules/react-native/ReactCommon/runtimeexecutor"
391 | ReactCommon:
392 | :path: "../../node_modules/react-native/ReactCommon"
393 | RNKeyboardInsets:
394 | :path: "../../"
395 | Yoga:
396 | :path: "../../node_modules/react-native/ReactCommon/yoga"
397 |
398 | SPEC CHECKSUMS:
399 | boost: a7c83b31436843459a1961bfd74b96033dc77234
400 | DoubleConversion: 831926d9b8bf8166fd87886c4abab286c2422662
401 | FBLazyVector: f7b0632c6437e312acf6349288d9aa4cb6d59030
402 | FBReactNativeSpec: 0f4e1f4cfeace095694436e7c7fcc5bf4b03a0ff
403 | fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
404 | glog: 85ecdd10ee8d8ec362ef519a6a45ff9aa27b2e85
405 | HybridNavigation: d54e779a0f7f1b2489be3d6b1a8ad3b7616dadbb
406 | RCT-Folly: 803a9cfd78114b2ec0f140cfa6fa2a6bafb2d685
407 | RCTRequired: 0aa6c1c27e1d65920df35ceea5341a5fe76bdb79
408 | RCTTypeSafety: d76a59d00632891e11ed7522dba3fd1a995e573a
409 | React: ab8c09da2e7704f4b3ebad4baa6cfdfcc852dcb5
410 | React-callinvoker: 216fb96b482da516b8aba4142b145938f6ea92f0
411 | React-Core: af99b93aff83599485e0e0879879aafa35ceae32
412 | React-CoreModules: 137a054ce8c547e81dc3502933b1bc0fd08df05d
413 | React-cxxreact: ec5ee6b08664f5b8ac71d8ad912f54d540c4f817
414 | React-jsi: 3e084c80fd364cee64668d5df46d40c39f7973e1
415 | React-jsiexecutor: cbdf37cebdc4f5d8b3d0bf5ccaa6147fd9de9f3d
416 | React-jsinspector: f4775ea9118cbe1f72b834f0f842baa7a99508d8
417 | React-logger: a1f028f6d8639a3f364ef80419e5e862e1115250
418 | react-native-safe-area-context: 39c2d8be3328df5d437ac1700f4f3a4f75716acc
419 | React-perflogger: 0afaf2f01a47fd0fc368a93bfbb5bd3b26db6e7f
420 | React-RCTActionSheet: 59f35c4029e0b532fc42114241a06e170b7431a2
421 | React-RCTAnimation: aae4f4bed122e78bdab72f7118d291d70a932ce2
422 | React-RCTBlob: f6fb23394b4f28cd86fa7e9f5f6ae45c23669fda
423 | React-RCTImage: 638815cf96124386dd296067246d91441932ae3f
424 | React-RCTLinking: 254dd06283dd6fdb784285f95e7cec8053c3270f
425 | React-RCTNetwork: 8a4c2d4f357268e520b060572d02bc69a9b991fb
426 | React-RCTSettings: 35d44cbb9972ab933bd0a59ea3e6646dcb030ba3
427 | React-RCTText: cc5315df8458cfa7b537e621271ef43273955a97
428 | React-RCTVibration: 3b52a7dced19cdb025b4f88ab26ceb2d85f30ba2
429 | React-runtimeexecutor: a9d3c82ddf7ffdad9fbe6a81c6d6f8c06385464d
430 | ReactCommon: 07d0c460b9ba9af3eaf1b8f5abe7daaad28c9c4e
431 | RNKeyboardInsets: beeec3dc406d040558bf8c9ba6a6c5f717a3268a
432 | Yoga: d6b6a80659aa3e91aaba01d0012e7edcbedcbecd
433 |
434 | PODFILE CHECKSUM: 5f8e27516be9e29e667680d1a90470ffeb5a4037
435 |
436 | COCOAPODS: 1.11.3
437 |
--------------------------------------------------------------------------------
/ios/KeyboardInsets.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 48;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 91C884A6202C3E8600EC0A20 /* undefined.m in Sources */ = {isa = PBXBuildFile; fileRef = 91C884A1202C3E8600EC0A20 /* undefined.m */; };
11 | /* End PBXBuildFile section */
12 |
13 | /* Begin PBXCopyFilesBuildPhase section */
14 | 910362D01FE9318600F4DA8E /* CopyFiles */ = {
15 | isa = PBXCopyFilesBuildPhase;
16 | buildActionMask = 2147483647;
17 | dstPath = "include/$(PRODUCT_NAME)";
18 | dstSubfolderSpec = 16;
19 | files = (
20 | );
21 | runOnlyForDeploymentPostprocessing = 0;
22 | };
23 | /* End PBXCopyFilesBuildPhase section */
24 |
25 | /* Begin PBXFileReference section */
26 | 910362D21FE9318600F4DA8E /* libKeyboardInsets.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libKeyboardInsets.a; sourceTree = BUILT_PRODUCTS_DIR; };
27 | 91C884A1202C3E8600EC0A20 /* undefined.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = undefined.m; sourceTree = ""; };
28 | 91C884A2202C3E8600EC0A20 /* undefined.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = undefined.h; sourceTree = ""; };
29 | /* End PBXFileReference section */
30 |
31 | /* Begin PBXFrameworksBuildPhase section */
32 | 910362CF1FE9318600F4DA8E /* Frameworks */ = {
33 | isa = PBXFrameworksBuildPhase;
34 | buildActionMask = 2147483647;
35 | files = (
36 | );
37 | runOnlyForDeploymentPostprocessing = 0;
38 | };
39 | /* End PBXFrameworksBuildPhase section */
40 |
41 | /* Begin PBXGroup section */
42 | 910362C91FE9318600F4DA8E = {
43 | isa = PBXGroup;
44 | children = (
45 | 910362D41FE9318600F4DA8E /* KeyboardInsets */,
46 | 910362D31FE9318600F4DA8E /* Products */,
47 | );
48 | sourceTree = "";
49 | };
50 | 910362D31FE9318600F4DA8E /* Products */ = {
51 | isa = PBXGroup;
52 | children = (
53 | 910362D21FE9318600F4DA8E /* libKeyboardInsets.a */,
54 | );
55 | name = Products;
56 | sourceTree = "";
57 | };
58 | 910362D41FE9318600F4DA8E /* KeyboardInsets */ = {
59 | isa = PBXGroup;
60 | children = (
61 | 91C884A2202C3E8600EC0A20 /* undefined.h */,
62 | 91C884A1202C3E8600EC0A20 /* undefined.m */,
63 | );
64 | path = KeyboardInsets;
65 | sourceTree = "";
66 | };
67 | /* End PBXGroup section */
68 |
69 | /* Begin PBXNativeTarget section */
70 | 910362D11FE9318600F4DA8E /* KeyboardInsets */ = {
71 | isa = PBXNativeTarget;
72 | buildConfigurationList = 910362DB1FE9318600F4DA8E /* Build configuration list for PBXNativeTarget "KeyboardInsets" */;
73 | buildPhases = (
74 | 910362CE1FE9318600F4DA8E /* Sources */,
75 | 910362CF1FE9318600F4DA8E /* Frameworks */,
76 | 910362D01FE9318600F4DA8E /* CopyFiles */,
77 | );
78 | buildRules = (
79 | );
80 | dependencies = (
81 | );
82 | name = KeyboardInsets;
83 | productName = KeyboardInsets;
84 | productReference = 910362D21FE9318600F4DA8E /* libKeyboardInsets.a */;
85 | productType = "com.apple.product-type.library.static";
86 | };
87 | /* End PBXNativeTarget section */
88 |
89 | /* Begin PBXProject section */
90 | 910362CA1FE9318600F4DA8E /* Project object */ = {
91 | isa = PBXProject;
92 | attributes = {
93 | LastUpgradeCheck = 0920;
94 | ORGANIZATIONNAME = Listen;
95 | TargetAttributes = {
96 | 910362D11FE9318600F4DA8E = {
97 | CreatedOnToolsVersion = 9.2;
98 | ProvisioningStyle = Automatic;
99 | };
100 | };
101 | };
102 | buildConfigurationList = 910362CD1FE9318600F4DA8E /* Build configuration list for PBXProject "KeyboardInsets" */;
103 | compatibilityVersion = "Xcode 8.0";
104 | developmentRegion = en;
105 | hasScannedForEncodings = 0;
106 | knownRegions = (
107 | en,
108 | );
109 | mainGroup = 910362C91FE9318600F4DA8E;
110 | productRefGroup = 910362D31FE9318600F4DA8E /* Products */;
111 | projectDirPath = "";
112 | projectRoot = "";
113 | targets = (
114 | 910362D11FE9318600F4DA8E /* KeyboardInsets */,
115 | );
116 | };
117 | /* End PBXProject section */
118 |
119 | /* Begin PBXSourcesBuildPhase section */
120 | 910362CE1FE9318600F4DA8E /* Sources */ = {
121 | isa = PBXSourcesBuildPhase;
122 | buildActionMask = 2147483647;
123 | files = (
124 | 91C884A6202C3E8600EC0A20 /* undefined.m in Sources */,
125 | );
126 | runOnlyForDeploymentPostprocessing = 0;
127 | };
128 | /* End PBXSourcesBuildPhase section */
129 |
130 | /* Begin XCBuildConfiguration section */
131 | 910362D91FE9318600F4DA8E /* Debug */ = {
132 | isa = XCBuildConfiguration;
133 | buildSettings = {
134 | ALWAYS_SEARCH_USER_PATHS = NO;
135 | CLANG_ANALYZER_NONNULL = YES;
136 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
137 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
138 | CLANG_CXX_LIBRARY = "libc++";
139 | CLANG_ENABLE_MODULES = YES;
140 | CLANG_ENABLE_OBJC_ARC = YES;
141 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
142 | CLANG_WARN_BOOL_CONVERSION = YES;
143 | CLANG_WARN_COMMA = YES;
144 | CLANG_WARN_CONSTANT_CONVERSION = YES;
145 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
146 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
147 | CLANG_WARN_EMPTY_BODY = YES;
148 | CLANG_WARN_ENUM_CONVERSION = YES;
149 | CLANG_WARN_INFINITE_RECURSION = YES;
150 | CLANG_WARN_INT_CONVERSION = YES;
151 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
152 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
153 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
154 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
155 | CLANG_WARN_STRICT_PROTOTYPES = YES;
156 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
157 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
158 | CLANG_WARN_UNREACHABLE_CODE = YES;
159 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
160 | CODE_SIGN_IDENTITY = "iPhone Developer";
161 | COPY_PHASE_STRIP = NO;
162 | DEBUG_INFORMATION_FORMAT = dwarf;
163 | ENABLE_STRICT_OBJC_MSGSEND = YES;
164 | ENABLE_TESTABILITY = YES;
165 | GCC_C_LANGUAGE_STANDARD = gnu11;
166 | GCC_DYNAMIC_NO_PIC = NO;
167 | GCC_NO_COMMON_BLOCKS = YES;
168 | GCC_OPTIMIZATION_LEVEL = 0;
169 | GCC_PREPROCESSOR_DEFINITIONS = (
170 | "DEBUG=1",
171 | "$(inherited)",
172 | );
173 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
174 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
175 | GCC_WARN_UNDECLARED_SELECTOR = YES;
176 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
177 | GCC_WARN_UNUSED_FUNCTION = YES;
178 | GCC_WARN_UNUSED_VARIABLE = YES;
179 | IPHONEOS_DEPLOYMENT_TARGET = 7.0;
180 | MTL_ENABLE_DEBUG_INFO = YES;
181 | ONLY_ACTIVE_ARCH = YES;
182 | SDKROOT = iphoneos;
183 | };
184 | name = Debug;
185 | };
186 | 910362DA1FE9318600F4DA8E /* Release */ = {
187 | isa = XCBuildConfiguration;
188 | buildSettings = {
189 | ALWAYS_SEARCH_USER_PATHS = NO;
190 | CLANG_ANALYZER_NONNULL = YES;
191 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
192 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
193 | CLANG_CXX_LIBRARY = "libc++";
194 | CLANG_ENABLE_MODULES = YES;
195 | CLANG_ENABLE_OBJC_ARC = YES;
196 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
197 | CLANG_WARN_BOOL_CONVERSION = YES;
198 | CLANG_WARN_COMMA = YES;
199 | CLANG_WARN_CONSTANT_CONVERSION = YES;
200 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
201 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
202 | CLANG_WARN_EMPTY_BODY = YES;
203 | CLANG_WARN_ENUM_CONVERSION = YES;
204 | CLANG_WARN_INFINITE_RECURSION = YES;
205 | CLANG_WARN_INT_CONVERSION = YES;
206 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
207 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
208 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
209 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
210 | CLANG_WARN_STRICT_PROTOTYPES = YES;
211 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
212 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
213 | CLANG_WARN_UNREACHABLE_CODE = YES;
214 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
215 | CODE_SIGN_IDENTITY = "iPhone Developer";
216 | COPY_PHASE_STRIP = NO;
217 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
218 | ENABLE_NS_ASSERTIONS = NO;
219 | ENABLE_STRICT_OBJC_MSGSEND = YES;
220 | GCC_C_LANGUAGE_STANDARD = gnu11;
221 | GCC_NO_COMMON_BLOCKS = YES;
222 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
223 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
224 | GCC_WARN_UNDECLARED_SELECTOR = YES;
225 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
226 | GCC_WARN_UNUSED_FUNCTION = YES;
227 | GCC_WARN_UNUSED_VARIABLE = YES;
228 | IPHONEOS_DEPLOYMENT_TARGET = 7.0;
229 | MTL_ENABLE_DEBUG_INFO = NO;
230 | SDKROOT = iphoneos;
231 | VALIDATE_PRODUCT = YES;
232 | };
233 | name = Release;
234 | };
235 | 910362DC1FE9318600F4DA8E /* Debug */ = {
236 | isa = XCBuildConfiguration;
237 | buildSettings = {
238 | CODE_SIGN_STYLE = Automatic;
239 | DEVELOPMENT_TEAM = 9H9696K6NL;
240 | OTHER_LDFLAGS = "-ObjC";
241 | PRODUCT_NAME = "$(TARGET_NAME)";
242 | SKIP_INSTALL = YES;
243 | TARGETED_DEVICE_FAMILY = "1,2";
244 | };
245 | name = Debug;
246 | };
247 | 910362DD1FE9318600F4DA8E /* Release */ = {
248 | isa = XCBuildConfiguration;
249 | buildSettings = {
250 | CODE_SIGN_STYLE = Automatic;
251 | DEVELOPMENT_TEAM = 9H9696K6NL;
252 | OTHER_LDFLAGS = "-ObjC";
253 | PRODUCT_NAME = "$(TARGET_NAME)";
254 | SKIP_INSTALL = YES;
255 | TARGETED_DEVICE_FAMILY = "1,2";
256 | };
257 | name = Release;
258 | };
259 | /* End XCBuildConfiguration section */
260 |
261 | /* Begin XCConfigurationList section */
262 | 910362CD1FE9318600F4DA8E /* Build configuration list for PBXProject "KeyboardInsets" */ = {
263 | isa = XCConfigurationList;
264 | buildConfigurations = (
265 | 910362D91FE9318600F4DA8E /* Debug */,
266 | 910362DA1FE9318600F4DA8E /* Release */,
267 | );
268 | defaultConfigurationIsVisible = 0;
269 | defaultConfigurationName = Release;
270 | };
271 | 910362DB1FE9318600F4DA8E /* Build configuration list for PBXNativeTarget "KeyboardInsets" */ = {
272 | isa = XCConfigurationList;
273 | buildConfigurations = (
274 | 910362DC1FE9318600F4DA8E /* Debug */,
275 | 910362DD1FE9318600F4DA8E /* Release */,
276 | );
277 | defaultConfigurationIsVisible = 0;
278 | defaultConfigurationName = Release;
279 | };
280 | /* End XCConfigurationList section */
281 | };
282 | rootObject = 910362CA1FE9318600F4DA8E /* Project object */;
283 | }
284 |
--------------------------------------------------------------------------------
/ios/KeyboardInsets/HBDKeyboardAutoHandler.h:
--------------------------------------------------------------------------------
1 | #import "HBDKeyboardInsetsView.h"
2 |
3 | NS_ASSUME_NONNULL_BEGIN
4 |
5 | @interface HBDKeyboardAutoHandler : NSObject
6 |
7 | - (instancetype)initWithKeyboardInsetsView:(HBDKeyboardInsetsView *)view;
8 |
9 | @end
10 |
11 | NS_ASSUME_NONNULL_END
12 |
--------------------------------------------------------------------------------
/ios/KeyboardInsets/HBDKeyboardAutoHandler.m:
--------------------------------------------------------------------------------
1 | #import "HBDKeyboardAutoHandler.h"
2 |
3 | #import
4 | #import
5 | #import
6 |
7 | @interface HBDKeyboardAutoHandler ()
8 |
9 | @property (nonatomic, weak) HBDKeyboardInsetsView *view;
10 | @property (nonatomic, assign) CGFloat keyboardHeight;
11 | @property (nonatomic, assign) BOOL forceUpdated;
12 | @property (nonatomic, assign) CGFloat edgeBottom;
13 | @property (nonatomic, assign) BOOL shown;
14 |
15 | @end
16 |
17 | @implementation HBDKeyboardAutoHandler
18 |
19 | - (instancetype)initWithKeyboardInsetsView:(HBDKeyboardInsetsView *)view {
20 | if (self = [super init]) {
21 | _view = view;
22 | }
23 | return self;
24 | }
25 |
26 | - (void)keyboardWillShow:(UIView *)focusView keyboardHeight:(CGFloat)keyboardHeight {
27 | self.shown = YES;
28 | if (self.keyboardHeight != keyboardHeight) {
29 | self.forceUpdated = YES;
30 | }
31 | self.keyboardHeight = keyboardHeight;
32 |
33 | [self adjustScrollViewOffsetIfNeeded:focusView];
34 | [self refreshEdgeBottom:focusView];
35 | }
36 |
37 | - (void)keyboardDidShow:(UIView *)focusView keyboardHeight:(CGFloat)keyboardHeight {
38 | if (focusView) {
39 | [self handleKeyboardTransition:keyboardHeight];
40 | } else {
41 | self.forceUpdated = YES;
42 | [self handleKeyboardTransition:0];
43 | }
44 | }
45 |
46 | - (void)keyboardWillHide:(UIView *)focusView keyboardHeight:(CGFloat)keyboardHeight {
47 | self.shown = NO;
48 | }
49 |
50 | - (void)keyboardDidHide:(UIView *)focusView keyboardHeight:(CGFloat)keyboardHeight {
51 | [self handleKeyboardTransition:0];
52 | self.edgeBottom = 0;
53 | }
54 |
55 | - (void)handleKeyboardTransition:(CGFloat)position {
56 | HBDKeyboardInsetsView *view = self.view;
57 |
58 | CGFloat translationY = 0;
59 | if (position > 0) {
60 | CGFloat edgeBottom = MAX(self.edgeBottom - view.extraHeight, 0);
61 | translationY = -MAX(position - edgeBottom, 0);
62 | }
63 |
64 | if (self.forceUpdated) {
65 | self.forceUpdated = NO;
66 | view.transform = CGAffineTransformMakeTranslation(0, translationY);
67 | }
68 |
69 | if (self.shown && view.transform.ty < translationY) {
70 | return;
71 | }
72 |
73 | view.transform = CGAffineTransformMakeTranslation(0, translationY);
74 | }
75 |
76 | - (void)refreshEdgeBottom:(UIView *)focusView {
77 | UIView *view = self.view;
78 | CGFloat translateY = view.transform.ty;
79 | CGRect windowFrame = [view.window convertRect:focusView.frame fromView:focusView.superview];
80 | CGFloat dy = CGRectGetMaxY(view.window.bounds) - CGRectGetMaxY(windowFrame);
81 | CGFloat newEdgeBottom = MAX(dy + translateY, 0);
82 | if (self.edgeBottom == 0 || self.edgeBottom != newEdgeBottom){
83 | self.edgeBottom = newEdgeBottom;
84 | }
85 | }
86 |
87 | - (void)adjustScrollViewOffsetIfNeeded:(UIView *)focusView {
88 | RCTScrollView *rct = [HBDKeyboardAutoHandler findClosetScrollView:focusView];
89 | if (rct) {
90 | UIScrollView *scrollView = rct.scrollView;
91 | CGRect frame = [rct.contentView convertRect:focusView.frame fromView:focusView.superview];
92 | CGFloat dy = CGRectGetHeight(rct.frame) + scrollView.contentOffset.y - CGRectGetMaxY(frame) - self.view.extraHeight;
93 | if (dy < 0) {
94 | CGFloat range = scrollView.contentSize.height - scrollView.frame.size.height;
95 | CGPoint offset = scrollView.contentOffset;
96 | offset.y = MIN(range, offset.y - dy);
97 | [rct scrollToOffset:offset animated:NO];
98 | }
99 | }
100 | }
101 |
102 | + (RCTScrollView *)findClosetScrollView:(UIView *)view {
103 | if ([view isKindOfClass:[RCTScrollView class]]) {
104 | return (RCTScrollView *)view;
105 | }
106 |
107 | if (view.superview) {
108 | return [self findClosetScrollView:view.superview];
109 | }
110 |
111 | return nil;
112 | }
113 |
114 | @end
115 |
--------------------------------------------------------------------------------
/ios/KeyboardInsets/HBDKeyboardInsetsModule.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | NS_ASSUME_NONNULL_BEGIN
4 |
5 | @interface HBDKeyboardInsetsModule : NSObject
6 |
7 | @end
8 |
9 | NS_ASSUME_NONNULL_END
10 |
--------------------------------------------------------------------------------
/ios/KeyboardInsets/HBDKeyboardInsetsModule.m:
--------------------------------------------------------------------------------
1 | #import "HBDKeyboardInsetsModule.h"
2 | #import
3 | #import
4 |
5 | @implementation HBDKeyboardInsetsModule
6 |
7 | RCT_EXPORT_MODULE(KeyboardInsetsModule)
8 |
9 | @synthesize bridge;
10 |
11 | + (BOOL)requiresMainQueueSetup {
12 | return YES;
13 | }
14 |
15 | - (dispatch_queue_t)methodQueue {
16 | return dispatch_get_main_queue();
17 | }
18 |
19 | RCT_EXPORT_METHOD(getEdgeInsetsForView:(nonnull NSNumber *)reactTag callback:(RCTResponseSenderBlock)callback) {
20 | RCTUIManager* uiManager = [self.bridge moduleForClass:[RCTUIManager class]];
21 | UIView* view = [uiManager viewForReactTag:reactTag];
22 | CGRect windowFrame = [view.window convertRect:view.frame fromView:view.superview];
23 |
24 | CGAffineTransform t = [self maybeTransform:view];
25 |
26 | callback(@[
27 | @{
28 | @"left": @(MAX(0, windowFrame.origin.x + t.tx)),
29 | @"top": @(MAX(0, windowFrame.origin.y + t.ty)),
30 | @"right": @(MAX(0, CGRectGetMaxX(view.window.bounds) - CGRectGetMaxX(windowFrame) + t.tx)),
31 | @"bottom": @(MAX(0, CGRectGetMaxY(view.window.bounds) - CGRectGetMaxY(windowFrame) + t.ty)),
32 | }
33 | ]);
34 | }
35 |
36 |
37 | - (CGAffineTransform)maybeTransform:(UIView *)view {
38 | if (view.transform.ty != 0) {
39 | return view.transform;
40 | }
41 |
42 | if (!view.superview) {
43 | return CGAffineTransformIdentity;
44 | }
45 |
46 | return [self maybeTransform:view.superview];
47 | }
48 |
49 |
50 | @end
51 |
--------------------------------------------------------------------------------
/ios/KeyboardInsets/HBDKeyboardInsetsView.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | NS_ASSUME_NONNULL_BEGIN
4 |
5 | @interface HBDKeyboardInsetsView : RCTView
6 |
7 | @property(nonatomic, copy) RCTDirectEventBlock onStatusChanged;
8 | @property(nonatomic, copy) RCTDirectEventBlock onPositionChanged;
9 |
10 | @property(nonatomic, copy) NSString *mode;
11 | @property(nonatomic, assign) CGFloat extraHeight;
12 |
13 | @end
14 |
15 | @protocol HBDKeyboardHandler
16 |
17 | - (void)keyboardWillShow:(UIView *)focusView keyboardHeight:(CGFloat)keyboardHeight;
18 |
19 | - (void)keyboardDidShow:(UIView *)focusView keyboardHeight:(CGFloat)keyboardHeight;
20 |
21 | - (void)keyboardWillHide:(UIView *)focusView keyboardHeight:(CGFloat)keyboardHeight;
22 |
23 | - (void)keyboardDidHide:(UIView *)focusView keyboardHeight:(CGFloat)keyboardHeight;
24 |
25 | - (void)handleKeyboardTransition:(CGFloat)position;
26 |
27 | @end
28 |
29 | NS_ASSUME_NONNULL_END
30 |
--------------------------------------------------------------------------------
/ios/KeyboardInsets/HBDKeyboardInsetsView.m:
--------------------------------------------------------------------------------
1 | #import "HBDKeyboardInsetsView.h"
2 | #import "HBDKeyboardAutoHandler.h"
3 | #import "HBDKeyboardManualHandler.h"
4 |
5 | #import
6 | #import
7 | #import
8 |
9 | @implementation HBDKeyboardInsetsView {
10 | UIView *_focusView;
11 |
12 | CADisplayLink *_displayLink;
13 | UIView *_keyboardView;
14 | CGFloat _keyboardHeight;
15 |
16 | HBDKeyboardAutoHandler *_autoHandler;
17 | HBDKeyboardManualHandler *_manualHandler;
18 | }
19 |
20 | - (instancetype)init {
21 | if (self = [super init]) {
22 | _mode = @"auto";
23 | }
24 | return self;
25 | }
26 |
27 | - (HBDKeyboardAutoHandler *)autoHandler {
28 | if (!_autoHandler) {
29 | _autoHandler = [[HBDKeyboardAutoHandler alloc] initWithKeyboardInsetsView:self];
30 | }
31 | return _autoHandler;
32 | }
33 |
34 | - (HBDKeyboardManualHandler *)manualHandler {
35 | if (!_manualHandler) {
36 | _manualHandler = [[HBDKeyboardManualHandler alloc] initWithKeyboardInsetsView:self];
37 | }
38 | return _manualHandler;
39 | }
40 |
41 | - (void)willMoveToWindow:(UIWindow *)newWindow {
42 | if (!newWindow) {
43 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
44 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidShowNotification object:nil];
45 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
46 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidHideNotification object:nil];
47 | [self stopWatchKeyboardTransition];
48 | }
49 | }
50 |
51 | - (void)didMoveToWindow {
52 | if (self.window) {
53 | [[NSNotificationCenter defaultCenter] addObserver:self
54 | selector:@selector(keyboardWillShow:)
55 | name:UIKeyboardWillShowNotification
56 | object:nil];
57 |
58 | [[NSNotificationCenter defaultCenter] addObserver:self
59 | selector:@selector(keyboardDidShow:)
60 | name:UIKeyboardDidShowNotification
61 | object:nil];
62 |
63 | [[NSNotificationCenter defaultCenter] addObserver:self
64 | selector:@selector(keyboardWillHide:)
65 | name:UIKeyboardWillHideNotification
66 | object:nil];
67 |
68 | [[NSNotificationCenter defaultCenter] addObserver:self
69 | selector:@selector(keyboardDidHide:)
70 | name:UIKeyboardDidHideNotification
71 | object:nil];
72 | }
73 | }
74 |
75 | - (void)keyboardWillShow:(NSNotification *)notification {
76 | UIView *focusView = [HBDKeyboardInsetsView findFocusView:self];
77 |
78 | if (![self shouldHandleKeyboardTransition:focusView]) {
79 | return;
80 | }
81 |
82 | _focusView = focusView;
83 | _keyboardView = [HBDKeyboardInsetsView findKeyboardView];
84 |
85 | NSDictionary *userInfo = [notification userInfo];
86 | CGRect keyboardRect = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
87 | CGFloat keyboardHeight = keyboardRect.size.height;
88 |
89 | _keyboardHeight = keyboardHeight;
90 |
91 | if ([self isAutoMode]) {
92 | [[self autoHandler] keyboardWillShow:focusView keyboardHeight:keyboardHeight];
93 | } else {
94 | [[self manualHandler] keyboardWillShow:focusView keyboardHeight:keyboardHeight];
95 | }
96 |
97 | RCTLogInfo(@"[KeyboardInsetsView] keyboardWillShow startWatchKeyboardTransition");
98 | [self startWatchKeyboardTransition];
99 | }
100 |
101 | - (void)keyboardDidShow:(NSNotification *)notification {
102 | if (![self shouldHandleKeyboardTransition:_focusView]) {
103 | return;
104 | }
105 |
106 | RCTLogInfo(@"[KeyboardInsetsView] keyboardDidShow stopWatchKeyboardTransition");
107 | [self stopWatchKeyboardTransition];
108 |
109 | if ([self isAutoMode]) {
110 | UIView *focusView = [HBDKeyboardInsetsView findFocusView:self];
111 | if (focusView && focusView != _focusView) {
112 | HBDKeyboardInsetsView *insetsView = [HBDKeyboardInsetsView findClosetKeyboardInsetsView:focusView];
113 | if (insetsView != self) {
114 | focusView = nil;
115 | }
116 | }
117 | _focusView = focusView;
118 | [[self autoHandler] keyboardDidShow:focusView keyboardHeight:_keyboardHeight];
119 | } else {
120 | [[self manualHandler] keyboardDidShow:_focusView keyboardHeight:_keyboardHeight];
121 | }
122 | }
123 |
124 | - (void)keyboardWillHide:(NSNotification *)notification {
125 | if (![self shouldHandleKeyboardTransition:_focusView]) {
126 | return;
127 | }
128 |
129 | _keyboardView = [HBDKeyboardInsetsView findKeyboardView];
130 |
131 | if ([self isAutoMode]) {
132 | [[self autoHandler] keyboardWillHide:_focusView keyboardHeight:_keyboardHeight];
133 | } else {
134 | [[self manualHandler] keyboardWillHide:_focusView keyboardHeight:_keyboardHeight];
135 | }
136 |
137 | RCTLogInfo(@"[KeyboardInsetsView] keyboardWillHide startWatchKeyboardTransition");
138 | [self startWatchKeyboardTransition];
139 | }
140 |
141 |
142 | - (void)keyboardDidHide:(NSNotification *)notification {
143 | UIView *focusView = _focusView;
144 | _focusView = nil;
145 |
146 | if (![self shouldHandleKeyboardTransition:focusView]) {
147 | return;
148 | }
149 |
150 | RCTLogInfo(@"[KeyboardInsetsView] keyboardDidHide stopWatchKeyboardTransition");
151 | [self stopWatchKeyboardTransition];
152 |
153 | if ([self isAutoMode]) {
154 | [[self autoHandler] keyboardDidHide:focusView keyboardHeight:_keyboardHeight];
155 | } else {
156 | [[self manualHandler] keyboardDidHide:focusView keyboardHeight:_keyboardHeight];
157 | }
158 | }
159 |
160 | - (BOOL)shouldHandleKeyboardTransition:(UIView *)focusView {
161 | if (focusView) {
162 | HBDKeyboardInsetsView *closet = [HBDKeyboardInsetsView findClosetKeyboardInsetsView:focusView];
163 | return closet == self;
164 | }
165 | return NO;
166 | }
167 |
168 |
169 | - (void)startWatchKeyboardTransition {
170 | [self stopWatchKeyboardTransition];
171 | _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(watchKeyboardTransition)];
172 | _displayLink.preferredFramesPerSecond = 120;
173 | [_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
174 | }
175 |
176 | - (void)stopWatchKeyboardTransition {
177 | if(_displayLink){
178 | [_displayLink invalidate];
179 | _displayLink = nil;
180 | }
181 | }
182 |
183 | - (void)watchKeyboardTransition {
184 | if (_keyboardView == nil) {
185 | return;
186 | }
187 |
188 | CGFloat keyboardFrameY = [_keyboardView.layer presentationLayer].frame.origin.y;
189 | CGFloat keyboardWindowH = _keyboardView.window.bounds.size.height;
190 | [self handleKeyboardTransition:(keyboardWindowH - keyboardFrameY)];
191 | }
192 |
193 | - (void)handleKeyboardTransition:(CGFloat)position {
194 | if ([self isAutoMode]) {
195 | if (_focusView) {
196 | [[self autoHandler] handleKeyboardTransition:position];
197 | }
198 | } else {
199 | [[self manualHandler] handleKeyboardTransition:position];
200 | }
201 | }
202 |
203 | - (BOOL)isAutoMode {
204 | return [self.mode isEqualToString:@"auto"];
205 | }
206 |
207 | + (UIView *)findKeyboardView {
208 | NSArray *windows = UIApplication.sharedApplication.windows;
209 | for (UIWindow *window in windows) {
210 | if ([window.description hasPrefix:@"
2 |
3 | NS_ASSUME_NONNULL_BEGIN
4 |
5 | @interface HBDKeyboardInsetsViewManager : RCTViewManager
6 |
7 | @end
8 |
9 | NS_ASSUME_NONNULL_END
10 |
--------------------------------------------------------------------------------
/ios/KeyboardInsets/HBDKeyboardInsetsViewManager.m:
--------------------------------------------------------------------------------
1 | #import "HBDKeyboardInsetsViewManager.h"
2 | #import "HBDKeyboardInsetsView.h"
3 |
4 | @implementation HBDKeyboardInsetsViewManager
5 |
6 | RCT_EXPORT_MODULE(KeyboardInsetsView)
7 |
8 | - (UIView *)view {
9 | return [[HBDKeyboardInsetsView alloc] init];
10 | }
11 |
12 | RCT_EXPORT_VIEW_PROPERTY(mode, NSString)
13 | RCT_EXPORT_VIEW_PROPERTY(extraHeight, CGFloat)
14 |
15 | RCT_EXPORT_VIEW_PROPERTY(onStatusChanged, RCTDirectEventBlock)
16 | RCT_EXPORT_VIEW_PROPERTY(onPositionChanged, RCTDirectEventBlock)
17 |
18 | @end
19 |
--------------------------------------------------------------------------------
/ios/KeyboardInsets/HBDKeyboardManualHandler.h:
--------------------------------------------------------------------------------
1 | #import "HBDKeyboardInsetsView.h"
2 |
3 | NS_ASSUME_NONNULL_BEGIN
4 |
5 | @interface HBDKeyboardManualHandler : NSObject
6 |
7 | - (instancetype)initWithKeyboardInsetsView:(HBDKeyboardInsetsView *)view;
8 |
9 | @end
10 |
11 | NS_ASSUME_NONNULL_END
12 |
--------------------------------------------------------------------------------
/ios/KeyboardInsets/HBDKeyboardManualHandler.m:
--------------------------------------------------------------------------------
1 | #import "HBDKeyboardManualHandler.h"
2 |
3 | #import
4 | #import
5 | #import
6 |
7 | @interface HBDKeyboardManualHandler ()
8 |
9 | @property (nonatomic, weak) HBDKeyboardInsetsView *view;
10 |
11 | @end
12 |
13 | @implementation HBDKeyboardManualHandler
14 |
15 | - (instancetype)initWithKeyboardInsetsView:(HBDKeyboardInsetsView *)view {
16 | if (self = [super init]) {
17 | _view = view;
18 | }
19 | return self;
20 | }
21 |
22 | - (void)keyboardWillShow:(UIView *)focusView keyboardHeight:(CGFloat)keyboardHeight {
23 | self.view.onStatusChanged(@{
24 | @"height": @(keyboardHeight),
25 | @"shown": @(YES),
26 | @"transitioning": @(YES),
27 | });
28 | }
29 |
30 | - (void)keyboardDidShow:(UIView *)focusView keyboardHeight:(CGFloat)keyboardHeight {
31 | [self handleKeyboardTransition:keyboardHeight];
32 | self.view.onStatusChanged(@{
33 | @"height": @(keyboardHeight),
34 | @"shown": @(YES),
35 | @"transitioning": @(NO),
36 | });
37 | }
38 |
39 | - (void)keyboardWillHide:(UIView *)focusView keyboardHeight:(CGFloat)keyboardHeight {
40 | self.view.onStatusChanged(@{
41 | @"height": @(keyboardHeight),
42 | @"shown": @(NO),
43 | @"transitioning": @(YES),
44 | });
45 | }
46 |
47 | - (void)keyboardDidHide:(UIView *)focusView keyboardHeight:(CGFloat)keyboardHeight {
48 | [self handleKeyboardTransition:0];
49 | self.view.onStatusChanged(@{
50 | @"height": @(keyboardHeight),
51 | @"shown": @(NO),
52 | @"transitioning": @(NO),
53 | });
54 | }
55 |
56 | - (void)handleKeyboardTransition:(CGFloat)position {
57 | RCTLogInfo(@"[KeyboardInsetsView] keyboard position: %f", position);
58 | self.view.onPositionChanged(@{
59 | @"position": @(position)
60 | });
61 | }
62 |
63 | @end
64 |
--------------------------------------------------------------------------------
/metro.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Metro configuration for React Native
3 | * https://github.com/facebook/react-native
4 | *
5 | * @format
6 | */
7 |
8 | module.exports = {
9 | transformer: {
10 | getTransformOptions: async () => ({
11 | transform: {
12 | experimentalImportSupport: false,
13 | inlineRequires: false,
14 | },
15 | }),
16 | },
17 | }
18 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-keyboard-insets",
3 | "description": "A powerful Keyboard Aware View for React Native",
4 | "version": "1.3.5",
5 | "main": "./lib/index.js",
6 | "typings": "./lib/index.d.ts",
7 | "react-native": "src/index",
8 | "nativePackage": true,
9 | "files": [
10 | "src",
11 | "lib",
12 | "android",
13 | "ios",
14 | "RNKeyboardInsets.podspec",
15 | "!android/build",
16 | "!android/.gradle",
17 | "!android/.idea",
18 | "!android/local.properties",
19 | "!ios/build",
20 | "!**/__tests__"
21 | ],
22 | "repository": "https://github.com/listenzz/react-native-keyboard-insets",
23 | "homepage": "https://github.com/listenzz/react-native-keyboard-insets#readme",
24 | "author": "listenzz (https://github.com/listenzz)",
25 | "license": "MIT",
26 | "keywords": [
27 | "react-native"
28 | ],
29 | "scripts": {
30 | "build": "rm -rf ./lib && tsc -p tsconfig.build.json",
31 | "prepare": "npm run build",
32 | "tsc": "tsc",
33 | "start": "watchman watch-del-all && react-native start --reset-cache",
34 | "android": "react-native run-android",
35 | "ios": "react-native run-ios",
36 | "test": "jest",
37 | "lint": "eslint . --fix --ext .js,.jsx,.ts,.tsx"
38 | },
39 | "peerDependencies": {
40 | "react": ">=16.8",
41 | "react-native": ">=0.60"
42 | },
43 | "devDependencies": {
44 | "@babel/core": "^7.13.10",
45 | "@babel/runtime": "^7.13.10",
46 | "@gfez/eslint-config-react-native": "^1.0.0",
47 | "@types/jest": "^26.0.21",
48 | "@types/react": "^17.0.2",
49 | "@types/react-native": "^0.67.0",
50 | "@types/react-test-renderer": "17.0.2",
51 | "babel-jest": "^26.6.3",
52 | "hybrid-navigation": "^2.15.1",
53 | "jest": "^26.6.3",
54 | "metro-react-native-babel-preset": "^0.66.2",
55 | "react": "17.0.2",
56 | "react-native": "0.67.4",
57 | "react-native-safe-area-context": "^4.5.0",
58 | "react-test-renderer": "17.0.2",
59 | "typescript": "^4.6.4"
60 | },
61 | "jest": {
62 | "preset": "react-native",
63 | "moduleFileExtensions": [
64 | "ts",
65 | "tsx",
66 | "js",
67 | "jsx",
68 | "json",
69 | "node"
70 | ]
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/react-native.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | project: {
3 | ios: {
4 | project: './example/ios/RNKeyboardInsets.xcworkspace',
5 | },
6 | android: {
7 | sourceDir: './example/android/',
8 | },
9 | },
10 | }
11 |
--------------------------------------------------------------------------------
/src/KeyboardInsetsView.tsx:
--------------------------------------------------------------------------------
1 | import React, { useCallback, useMemo, useRef } from 'react'
2 | import { Animated, NativeSyntheticEvent, ViewProps } from 'react-native'
3 | import { KeyboardStatus, NativeKeyboardInsetsView } from './native'
4 |
5 | export interface KeyboardState {
6 | height: number
7 | shown: boolean
8 | transitioning: boolean
9 | position: Animated.Value
10 | }
11 |
12 | const NativeKeyboardInsetsViewAnimated = Animated.createAnimatedComponent(NativeKeyboardInsetsView)
13 |
14 | interface KeyboardInsetsViewProps extends Animated.AnimatedProps {
15 | extraHeight?: number
16 | onKeyboard?: (status: KeyboardState) => void
17 | }
18 |
19 | export function KeyboardInsetsView(props: KeyboardInsetsViewProps) {
20 | const { children, onKeyboard, ...rest } = props
21 |
22 | const position = useRef(new Animated.Value(0)).current
23 |
24 | const onPositionChanged = useMemo(
25 | () =>
26 | Animated.event(
27 | [
28 | {
29 | nativeEvent: {
30 | position,
31 | },
32 | },
33 | ],
34 | {
35 | useNativeDriver: true,
36 | },
37 | ),
38 | [position],
39 | )
40 |
41 | const onStatusChanaged = useCallback(
42 | (event: NativeSyntheticEvent) => {
43 | onKeyboard?.({ ...event.nativeEvent, position })
44 | },
45 | [position, onKeyboard],
46 | )
47 |
48 | if (onKeyboard) {
49 | return (
50 |
55 | {children}
56 |
57 | )
58 | }
59 |
60 | return {children}
61 | }
62 |
--------------------------------------------------------------------------------
/src/hook.ts:
--------------------------------------------------------------------------------
1 | import { useCallback, useState } from 'react'
2 | import { Animated } from 'react-native'
3 |
4 | interface KeyboardState {
5 | height: number
6 | shown: boolean
7 | transitioning: boolean
8 | position: Animated.Value
9 | }
10 |
11 | export function useKeyboard() {
12 | const [keyboard, setKeyboard] = useState({
13 | height: 0,
14 | shown: false,
15 | transitioning: false,
16 | position: new Animated.Value(0),
17 | })
18 |
19 | const onKeyboard = useCallback((state: KeyboardState) => {
20 | setKeyboard(state)
21 | }, [])
22 |
23 | return { keyboard, onKeyboard }
24 | }
25 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import { KeyboardInsetsView, KeyboardState } from './KeyboardInsetsView'
2 | import { getEdgeInsetsForView } from './native'
3 | import { useKeyboard } from './hook'
4 |
5 | export { KeyboardInsetsView, KeyboardState, useKeyboard, getEdgeInsetsForView }
6 |
--------------------------------------------------------------------------------
/src/native.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Insets,
3 | NativeModule,
4 | NativeModules,
5 | NativeSyntheticEvent,
6 | requireNativeComponent,
7 | ViewProps,
8 | Animated,
9 | } from 'react-native'
10 |
11 | export interface KeyboardStatus {
12 | height: number
13 | shown: boolean
14 | transitioning: boolean
15 | }
16 |
17 | interface KeyboardPosition {
18 | position: number
19 | }
20 |
21 | interface NativeKeyboardInsetsViewProps {
22 | mode?: 'auto' | 'manual'
23 | extraHeight?: number
24 | onStatusChanged?: (event: NativeSyntheticEvent) => void
25 | onPositionChanged?: (event: NativeSyntheticEvent) => void
26 | }
27 |
28 | export const NativeKeyboardInsetsView = requireNativeComponent<
29 | NativeKeyboardInsetsViewProps & Animated.AnimatedProps
30 | >('KeyboardInsetsView')
31 |
32 | interface KeyboardInsetsModuleInterface extends NativeModule {
33 | getEdgeInsetsForView(viewTag: number, callback: (insets: Insets) => void): void
34 | }
35 |
36 | const KeyboardInsetsModule: KeyboardInsetsModuleInterface = NativeModules.KeyboardInsetsModule
37 |
38 | export function getEdgeInsetsForView(viewTag: number, callback: (insets: Insets) => void) {
39 | KeyboardInsetsModule.getEdgeInsetsForView(viewTag, callback)
40 | }
41 |
--------------------------------------------------------------------------------
/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "noEmit": false
5 | },
6 | "exclude": ["./example/**/*"]
7 | }
8 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "resolveJsonModule": true,
4 | "skipLibCheck": true,
5 | "target": "esnext",
6 | "module": "esnext",
7 | "lib": ["esnext"],
8 | "jsx": "react-native",
9 | "moduleResolution": "node",
10 | "declaration": true,
11 | "outDir": "./lib",
12 | "noEmit": true,
13 | "strict": true,
14 | "noImplicitAny": true,
15 | "baseUrl": "./",
16 | "paths": {
17 | "react-native-keyboard-insets": ["src/index"]
18 | },
19 | "allowSyntheticDefaultImports": true,
20 | "esModuleInterop": true,
21 | "useUnknownInCatchVariables": false
22 | },
23 | "include": ["./src/**/*", "./example/**/*"]
24 | }
25 |
--------------------------------------------------------------------------------