|
34 | 34 | import android.media.AudioManager; |
35 | 35 | import android.net.Uri; |
36 | 36 | import android.os.Build; |
| 37 | +import android.view.WindowInsets; |
37 | 38 | import android.os.Debug; |
38 | 39 | import android.os.Handler; |
39 | 40 | import android.os.Message; |
|
51 | 52 | import android.view.HapticFeedbackConstants; |
52 | 53 | import android.view.KeyEvent; |
53 | 54 | import android.view.View; |
| 55 | +import android.view.ViewGroup; |
54 | 56 | import android.view.Window; |
55 | 57 | import android.view.WindowManager; |
56 | 58 | import android.view.inputmethod.CompletionInfo; |
@@ -543,6 +545,11 @@ public void onConfigurationChanged(Configuration conf) { |
543 | 545 | mConfigurationChanging = true; |
544 | 546 | super.onConfigurationChanged(conf); |
545 | 547 | mConfigurationChanging = false; |
| 548 | + // Re-apply nav bar padding after orientation change; post it so the |
| 549 | + // new window layout has settled before we read the insets. |
| 550 | + mHandler.post(new Runnable() { |
| 551 | + @Override public void run() { scheduleApplyNavBarInsetsToInputViewLayout(); } |
| 552 | + }); |
546 | 553 | } |
547 | 554 |
|
548 | 555 | @Override |
@@ -628,6 +635,7 @@ public void onStartInputView(EditorInfo attribute, boolean restarting) { |
628 | 635 | checkReCorrectionOnStart(); |
629 | 636 |
|
630 | 637 | tryKp2aAutoFill(attribute); |
| 638 | + scheduleApplyNavBarInsetsToInputViewLayout(); |
631 | 639 |
|
632 | 640 | if (TRACE) Debug.startMethodTracing("/data/trace/latinime"); |
633 | 641 | } |
@@ -1036,6 +1044,62 @@ public void setCandidatesViewShown(boolean shown) { |
1036 | 1044 | setCandidatesViewShownInternal(shown, true /* needsInputViewShown */); |
1037 | 1045 | } |
1038 | 1046 |
|
| 1047 | + @Override |
| 1048 | + public void onWindowShown() { |
| 1049 | + super.onWindowShown(); |
| 1050 | + scheduleApplyNavBarInsetsToInputViewLayout(); |
| 1051 | + } |
| 1052 | + |
| 1053 | + private void scheduleApplyNavBarInsetsToInputViewLayout() { |
| 1054 | + applyNavBarInsetsToInputViewLayout(); |
| 1055 | + mHandler.postDelayed(new Runnable() { |
| 1056 | + @Override |
| 1057 | + public void run() { |
| 1058 | + applyNavBarInsetsToInputViewLayout(); |
| 1059 | + } |
| 1060 | + }, 100); |
| 1061 | + } |
| 1062 | + |
| 1063 | + private void applyNavBarInsetsToInputViewLayout() { |
| 1064 | + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) return; |
| 1065 | + final View inputView = mKeyboardSwitcher.getInputView(); |
| 1066 | + if (inputView == null) return; |
| 1067 | + |
| 1068 | + WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE); |
| 1069 | + android.view.WindowMetrics metrics = wm.getCurrentWindowMetrics(); |
| 1070 | + android.graphics.Insets nav = |
| 1071 | + metrics.getWindowInsets().getInsets(WindowInsets.Type.navigationBars()); |
| 1072 | + |
| 1073 | + android.view.Window win = getWindow() != null ? getWindow().getWindow() : null; |
| 1074 | + View decor = win != null ? win.getDecorView() : null; |
| 1075 | + int decorWidth = decor != null ? decor.getWidth() : 0; |
| 1076 | + int decorHeight = decor != null ? decor.getHeight() : 0; |
| 1077 | + int displayWidth = metrics.getBounds().width(); |
| 1078 | + int displayHeight = metrics.getBounds().height(); |
| 1079 | + |
| 1080 | + final int tolerancePx = 2; |
| 1081 | + boolean windowAlreadyExcludesHorizontalNav = decorWidth > 0 |
| 1082 | + && decorWidth <= (displayWidth - nav.left - nav.right + tolerancePx); |
| 1083 | + |
| 1084 | + int effectiveLeft = windowAlreadyExcludesHorizontalNav ? 0 : nav.left; |
| 1085 | + int effectiveRight = windowAlreadyExcludesHorizontalNav ? 0 : nav.right; |
| 1086 | + // Do not infer bottom-nav exclusion from decor height: IME windows are naturally |
| 1087 | + // shorter than display height, so that heuristic wrongly drops bottom inset. |
| 1088 | + int effectiveBottom = nav.bottom; |
| 1089 | + |
| 1090 | + ViewGroup.LayoutParams lp = inputView.getLayoutParams(); |
| 1091 | + if (lp instanceof ViewGroup.MarginLayoutParams) { |
| 1092 | + ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams) lp; |
| 1093 | + if (mlp.leftMargin != effectiveLeft || mlp.rightMargin != effectiveRight |
| 1094 | + || mlp.bottomMargin != effectiveBottom) { |
| 1095 | + mlp.leftMargin = effectiveLeft; |
| 1096 | + mlp.rightMargin = effectiveRight; |
| 1097 | + mlp.bottomMargin = effectiveBottom; |
| 1098 | + inputView.setLayoutParams(mlp); |
| 1099 | + } |
| 1100 | + } |
| 1101 | + } |
| 1102 | + |
1039 | 1103 | @Override |
1040 | 1104 | public void onComputeInsets(InputMethodService.Insets outInsets) { |
1041 | 1105 | super.onComputeInsets(outInsets); |
|
0 commit comments