From c76523f1ad832cd3a32151e6a20d3a58bf09496f Mon Sep 17 00:00:00 2001 From: Janic Duplessis Date: Thu, 17 Mar 2016 16:59:33 -0700 Subject: [PATCH] Fix text input scroll when status bar is translucent Summary:Changed the implementation of `setTranslucent` because the old one used the view flag SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN which has the sad side effect of making the ScrollViews not adjust properly when the keyboard is opened. Instead I use `setOnApplyWindowInsetsListener` to hook in the insets calculation process and consume the top offset so the decor view doesn't add top padding for the status bar. I also limited the translucent prop to API 21+ because `setOnApplyWindowInsetsListener` is not available before that and anyway the translucent prop is only useful with a semi-transparent status bar color which only works on API 21+. **Test plan** Reproduced the bug using this code in UIExplorer. https://gist.github.com/janicduplessis/217b9994e35f960a1793 Tapping a text field that would be hidden by the soft keyboard should scroll the view so it is not hidden. Also tested that setting the translucent prop on and off still works as before. Fixes #6455 Closes https://github.com/facebook/react-native/pull/6481 Differential Revision: D3067199 Pulled By: mkonicek fb-gh-sync-id: aa115f8688ac7e461e62c18ebb8ab77350d000f8 shipit-source-id: aa115f8688ac7e461e62c18ebb8ab77350d000f8 --- .../modules/statusbar/StatusBarModule.java | 46 +++++++++++++------ 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/modules/statusbar/StatusBarModule.java b/ReactAndroid/src/main/java/com/facebook/react/modules/statusbar/StatusBarModule.java index efe9fc9206d642..76554b7e438505 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/modules/statusbar/StatusBarModule.java +++ b/ReactAndroid/src/main/java/com/facebook/react/modules/statusbar/StatusBarModule.java @@ -17,6 +17,7 @@ import android.os.Build; import android.support.v4.view.ViewCompat; import android.view.View; +import android.view.WindowInsets; import android.view.WindowManager; import java.util.Map; @@ -112,22 +113,39 @@ public void setTranslucent(final boolean translucent, final Promise res) { res.reject(ERROR_NO_ACTIVITY, ERROR_NO_ACTIVITY_MESSAGE); return; } - UiThreadUtil.runOnUiThread( - new Runnable() { - @Override - public void run() { - int flags = activity.getWindow().getDecorView().getSystemUiVisibility(); - if (translucent) { - flags |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; - } else { - flags &= ~(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + UiThreadUtil.runOnUiThread( + new Runnable() { + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + @Override + public void run() { + // If the status bar is translucent hook into the window insets calculations + // and consume all the top insets so no padding will be added under the status bar. + View decorView = activity.getWindow().getDecorView(); + if (translucent) { + decorView.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() { + @Override + public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) { + WindowInsets defaultInsets = v.onApplyWindowInsets(insets); + return defaultInsets.replaceSystemWindowInsets( + defaultInsets.getSystemWindowInsetLeft(), + 0, + defaultInsets.getSystemWindowInsetRight(), + defaultInsets.getSystemWindowInsetBottom() + ); + } + }); + } else { + decorView.setOnApplyWindowInsetsListener(null); + } + + ViewCompat.requestApplyInsets(decorView); + res.resolve(null); } - activity.getWindow().getDecorView().setSystemUiVisibility(flags); - ViewCompat.requestApplyInsets(activity.getWindow().getDecorView()); - res.resolve(null); } - } - ); + ); + } } @ReactMethod