From 908fdd2e4162bcc5ba9bd1b3411776321b023861 Mon Sep 17 00:00:00 2001 From: Jacek Pudysz Date: Fri, 30 Aug 2024 13:41:24 +0200 Subject: [PATCH] feat: add option to disable animated insets --- android/src/main/cxx/platform.cpp | 18 ++++++++++++++++++ android/src/main/cxx/platform.h | 1 + .../src/main/java/com/unistyles/Platform.kt | 13 ++++++++++++- .../main/java/com/unistyles/UnistylesModule.kt | 2 +- cxx/UnistylesImpl.cpp | 10 ++++++++++ cxx/UnistylesModel.h | 4 ++++ cxx/UnistylesRuntime.h | 4 +++- docs/.astro/settings.json | 2 +- examples/expo/src/examples/HomeScreen.tsx | 3 ++- src/core/UnistyleRegistry.ts | 6 +++++- src/types/unistyles.ts | 6 +++++- 11 files changed, 62 insertions(+), 7 deletions(-) diff --git a/android/src/main/cxx/platform.cpp b/android/src/main/cxx/platform.cpp index 9b640608..6acec15f 100644 --- a/android/src/main/cxx/platform.cpp +++ b/android/src/main/cxx/platform.cpp @@ -49,6 +49,10 @@ void makeShared(JNIEnv *env, jobject unistylesModule, std::shared_ptrsetDisableAnimatedInsetsAndroidCallback([=]() { + disableAnimatedInsets(env, unistylesModule); + }); + Screen screen = getScreenDimensions(env, unistylesModule); unistylesRuntime->screen = Dimensions{screen.width, screen.height}; @@ -62,6 +66,20 @@ void makeShared(JNIEnv *env, jobject unistylesModule, std::shared_ptrrtl = getIsRTL(env, unistylesModule); } +void disableAnimatedInsets(JNIEnv *env, jobject unistylesModule) { + jclass cls = env->GetObjectClass(unistylesModule); + jfieldID platformFieldId = env->GetFieldID(cls, "platform", "Lcom/unistyles/Platform;"); + jobject platformInstance = env->GetObjectField(unistylesModule, platformFieldId); + jclass platformClass = env->GetObjectClass(platformInstance); + jmethodID methodId = env->GetMethodID(platformClass, "disableAnimatedInsets", "()V"); + + env->CallVoidMethod(platformInstance, methodId); + + env->DeleteLocalRef(cls); + env->DeleteLocalRef(platformInstance); + env->DeleteLocalRef(platformClass); +} + Screen getScreenDimensions(JNIEnv *env, jobject unistylesModule) { jobject result = JNI_callPlatform(env, unistylesModule, "getScreenDimensions", "()Lcom/unistyles/Screen;"); Screen screenDimensions = jobjectToScreen(env, result); diff --git a/android/src/main/cxx/platform.h b/android/src/main/cxx/platform.h index 78aed71b..8e534d99 100644 --- a/android/src/main/cxx/platform.h +++ b/android/src/main/cxx/platform.h @@ -17,3 +17,4 @@ bool getIsRTL(JNIEnv *env, jobject unistylesModule); std::string getContentSizeCategory(JNIEnv *env, jobject unistylesModule); void setNavigationBarColor(JNIEnv *env, jobject unistylesModule, std::string color, float alpha); void setStatusBarColor(JNIEnv *env, jobject unistylesModule, std::string color, float alpha); +void disableAnimatedInsets(JNIEnv *env, jobject unistylesModule); diff --git a/android/src/main/java/com/unistyles/Platform.kt b/android/src/main/java/com/unistyles/Platform.kt index 575be05d..7161265f 100644 --- a/android/src/main/java/com/unistyles/Platform.kt +++ b/android/src/main/java/com/unistyles/Platform.kt @@ -20,12 +20,17 @@ import java.util.Locale import kotlin.math.roundToInt class Platform(private val reactApplicationContext: ReactApplicationContext) { + var hasAnimatedInsets = true private var insets: Insets = Insets(0, 0, 0, 0) private var defaultNavigationBarColor: Int = -1 private var defaultStatusBarColor: Int = -1 var orientation: Int = reactApplicationContext.resources.configuration.orientation + fun disableAnimatedInsets() { + this.hasAnimatedInsets = false + } + @Suppress("DEPRECATION") fun getScreenDimensions(): Screen { // function takes in count edge-to-edge layout @@ -140,10 +145,16 @@ class Platform(private val reactApplicationContext: ReactApplicationContext) { } val insets = insetsCompat.getInsets(WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout()) - val imeInsets = insetsCompat.getInsets(WindowInsetsCompat.Type.ime()) + + if (!hasAnimatedInsets) { + this.insets = Insets(statusBarTopInset, insets.bottom, insets.left, insets.right) + + return + } // Android 10 and below - set bottom insets to 0 while keyboard is visible and use default bottom insets otherwise // Android 11 and above - animate bottom insets while keyboard is appearing and disappearing + val imeInsets = insetsCompat.getInsets(WindowInsetsCompat.Type.ime()) val insetBottom = when(imeInsets.bottom > 0) { true -> { if (Build.VERSION.SDK_INT >= 30 && animatedBottomInsets != null) { diff --git a/android/src/main/java/com/unistyles/UnistylesModule.kt b/android/src/main/java/com/unistyles/UnistylesModule.kt index b4986e44..b54faa7d 100644 --- a/android/src/main/java/com/unistyles/UnistylesModule.kt +++ b/android/src/main/java/com/unistyles/UnistylesModule.kt @@ -154,7 +154,7 @@ class UnistylesModule(reactContext: ReactApplicationContext) : ReactContextBaseJ insets } - if (Build.VERSION.SDK_INT >= 30) { + if (platform.hasAnimatedInsets && Build.VERSION.SDK_INT >= 30) { ViewCompat.setWindowInsetsAnimationCallback( mainView, object : WindowInsetsAnimationCompat.Callback(DISPATCH_MODE_STOP) { diff --git a/cxx/UnistylesImpl.cpp b/cxx/UnistylesImpl.cpp index 98d24ecb..e3c2a674 100644 --- a/cxx/UnistylesImpl.cpp +++ b/cxx/UnistylesImpl.cpp @@ -298,3 +298,13 @@ jsi::Value UnistylesRuntime::setRootBackgroundColor(jsi::Runtime& rt, std::strin jsi::Value UnistylesRuntime::getIsRtl(jsi::Runtime& rt, std::string fnName) { return jsi::Value(this->rtl); } + +jsi::Value UnistylesRuntime::disableAnimatedInsets(jsi::Runtime& rt, std::string fnName) { + return HOST_FN(fnName, 1, { + if (this->disableAnimatedInsetsAndroid.has_value()) { + this->disableAnimatedInsetsAndroid.value()(); + } + + return jsi::Value::undefined(); + }); +} diff --git a/cxx/UnistylesModel.h b/cxx/UnistylesModel.h index 85b6817d..cb00ffb6 100644 --- a/cxx/UnistylesModel.h +++ b/cxx/UnistylesModel.h @@ -66,6 +66,7 @@ struct UnistylesModel { std::optional> setStatusBarHidden; std::optional> setImmersiveMode; std::optional> setRootViewBackgroundColor; + std::optional> disableAnimatedInsetsAndroid; void setScreenDimensionsCallback(std::function callback) { this->getScreenDimensions = callback; @@ -103,6 +104,9 @@ struct UnistylesModel { void setRootViewBackgroundColorCallback(std::function callback) { this->setRootViewBackgroundColor = callback; } + void setDisableAnimatedInsetsAndroidCallback(std::function callback) { + this->disableAnimatedInsetsAndroid = callback; + } Dimensions screen = {0, 0}; Dimensions statusBar = {0, 0}; diff --git a/cxx/UnistylesRuntime.h b/cxx/UnistylesRuntime.h index 3586f19a..eed620b5 100644 --- a/cxx/UnistylesRuntime.h +++ b/cxx/UnistylesRuntime.h @@ -35,7 +35,8 @@ struct JSI_EXPORT UnistylesRuntime : public jsi::HostObject, UnistylesModel { {"fontScale", BIND_FN(getFontScale)}, {"setRootViewBackgroundColor", BIND_FN(setRootBackgroundColor)}, {"setImmersiveMode", BIND_FN(setImmersiveModeEnabled)}, - {"rtl", BIND_FN(getIsRtl)} + {"rtl", BIND_FN(getIsRtl)}, + {"disableAnimatedInsets", BIND_FN(disableAnimatedInsets)} }; this->setters = { @@ -66,6 +67,7 @@ struct JSI_EXPORT UnistylesRuntime : public jsi::HostObject, UnistylesModel { jsi::Value setRootBackgroundColor(jsi::Runtime&, std::string); jsi::Value setImmersiveModeEnabled(jsi::Runtime&, std::string); jsi::Value getIsRtl(jsi::Runtime&, std::string); + jsi::Value disableAnimatedInsets(jsi::Runtime&, std::string); std::optional setThemes(jsi::Runtime&, const jsi::Value&); diff --git a/docs/.astro/settings.json b/docs/.astro/settings.json index 122d80d3..89040243 100644 --- a/docs/.astro/settings.json +++ b/docs/.astro/settings.json @@ -1,5 +1,5 @@ { "_variables": { - "lastUpdateCheck": 1720447718845 + "lastUpdateCheck": 1725018017706 } } \ No newline at end of file diff --git a/examples/expo/src/examples/HomeScreen.tsx b/examples/expo/src/examples/HomeScreen.tsx index b90d046a..c9079e1d 100644 --- a/examples/expo/src/examples/HomeScreen.tsx +++ b/examples/expo/src/examples/HomeScreen.tsx @@ -501,7 +501,8 @@ export const HomeScreen = () => { }) .addBreakpoints(breakpoints) .addConfig({ - initialTheme: 'light' + initialTheme: 'light', + disableAnimatedInsets: true }) navigation.navigate(DemoNames.Keyboard) diff --git a/src/core/UnistyleRegistry.ts b/src/core/UnistyleRegistry.ts index 2c9528fa..f9b49d7c 100644 --- a/src/core/UnistyleRegistry.ts +++ b/src/core/UnistyleRegistry.ts @@ -1,6 +1,6 @@ import type { UnistylesBridge, UnistylesConfig, UnistylesPlugin } from '../types' import type { UnistylesBreakpoints, UnistylesThemes } from '../global' -import { isDev, isWeb, UnistylesError } from '../common' +import { isAndroid, isDev, isWeb, UnistylesError } from '../common' import { cssMediaQueriesPlugin, normalizeWebStylesPlugin } from '../plugins' export class UnistyleRegistry { @@ -64,6 +64,10 @@ export class UnistyleRegistry { this.unistylesBridge.setWindowResizeDebounceTimeMs(config.windowResizeDebounceTimeMs) } + if (isAndroid && config.disableAnimatedInsets) { + this.unistylesBridge.disableAnimatedInsets() + } + return { addBreakpoints: this.addBreakpoints, addThemes: this.addThemes diff --git a/src/types/unistyles.ts b/src/types/unistyles.ts index 7fab3f19..5d1c0d9b 100644 --- a/src/types/unistyles.ts +++ b/src/types/unistyles.ts @@ -32,7 +32,8 @@ export type UnistylesConfig = { initialTheme?: keyof UnistylesThemes, plugins?: Array, experimentalCSSMediaQueries?: boolean, - windowResizeDebounceTimeMs?: number + windowResizeDebounceTimeMs?: number, + disableAnimatedInsets?: boolean } export type UnistylesBridge = { @@ -66,6 +67,9 @@ export type UnistylesBridge = { // web only setWindowResizeDebounceTimeMs(timeMs: number): void + + // android only + disableAnimatedInsets(): void } export type UnistylesThemeEvent = {