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
This commit is contained in:
parent
18f38ecdc0
commit
c76523f1ad
|
@ -17,6 +17,7 @@ import android.content.Context;
|
|||
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 class StatusBarModule extends ReactContextBaseJavaModule {
|
|||
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
|
||||
|
|
Loading…
Reference in New Issue