2222import android .content .ServiceConnection ;
2323import android .content .res .Configuration ;
2424import android .graphics .Color ;
25+ import android .graphics .RectF ;
2526import android .graphics .drawable .ColorDrawable ;
2627import android .net .Uri ;
2728import android .os .Build ;
3233import android .view .KeyEvent ;
3334import android .view .MotionEvent ;
3435import android .view .View ;
36+ import android .view .WindowManager ;
3537import android .widget .AdapterView ;
3638import android .widget .ArrayAdapter ;
39+ import android .widget .FrameLayout ;
3740import android .widget .ListView ;
3841import android .widget .Toast ;
3942
4043import androidx .annotation .Keep ;
4144import androidx .annotation .NonNull ;
45+ import androidx .annotation .Nullable ;
4246import androidx .annotation .RequiresApi ;
4347import androidx .core .content .ContextCompat ;
48+ import androidx .core .view .ViewCompat ;
49+ import androidx .core .view .WindowCompat ;
50+ import androidx .core .view .WindowInsetsAnimationCompat ;
51+ import androidx .core .view .WindowInsetsCompat ;
4452import androidx .drawerlayout .widget .DrawerLayout ;
4553
4654import com .kdt .LoggerView ;
7583
7684import java .io .File ;
7785import java .io .IOException ;
86+ import java .util .List ;
7887import java .util .Objects ;
7988
80- public class MainActivity extends BaseActivity implements ControlButtonMenuListener , EditorExitable , ServiceConnection {
89+ public class MainActivity extends BaseActivity implements ControlButtonMenuListener , EditorExitable , ServiceConnection , TouchControllerInputView . InputAreaRectListener {
8190 public static volatile ClipboardManager GLOBAL_CLIPBOARD ;
8291 public static final String TAG = "MainActivity" ;
8392 public static final String INTENT_MINECRAFT_VERSION = "intent_version" ;
@@ -96,6 +105,12 @@ public class MainActivity extends BaseActivity implements ControlButtonMenuListe
96105 private GyroControl mGyroControl = null ;
97106 private ControlLayout mControlLayout ;
98107 private HotbarView mHotbarView ;
108+ private FrameLayout contentFrame ;
109+
110+ @ Nullable
111+ private RectF inputAreaRect ;
112+ private int imeHeight ;
113+ private boolean hasOngoingImeAnimation ;
99114
100115 MinecraftProfile minecraftProfile ;
101116
@@ -110,6 +125,8 @@ public class MainActivity extends BaseActivity implements ControlButtonMenuListe
110125 @ Override
111126 public void onCreate (Bundle savedInstanceState ) {
112127 super .onCreate (savedInstanceState );
128+ WindowCompat .setDecorFitsSystemWindows (getWindow (), false );
129+
113130 if (LauncherPreferences .PREF_GAMEPAD_SDL_PASSTHRU ) {
114131 // TODO: Use lower level HID capture that needs a dialogue box from the user for the
115132 // app to fully take focus of the input devices. Might cause issues with older android
@@ -185,6 +202,39 @@ public void onCreate(Bundle savedInstanceState) {
185202 MCOptionUtils .addMCOptionListener (optionListener );
186203 mControlLayout .setModifiable (false );
187204
205+ // Listen to IME insets animation
206+ ViewCompat .setWindowInsetsAnimationCallback (contentFrame , new WindowInsetsAnimationCompat .Callback (WindowInsetsAnimationCompat .Callback .DISPATCH_MODE_STOP ) {
207+ @ Override
208+ public void onPrepare (@ NonNull WindowInsetsAnimationCompat animation ) {
209+ if ((animation .getTypeMask () & WindowInsetsCompat .Type .ime ()) != 0 ) {
210+ hasOngoingImeAnimation = true ;
211+ }
212+ }
213+
214+ @ NonNull
215+ @ Override
216+ public WindowInsetsCompat onProgress (@ NonNull WindowInsetsCompat insets , @ NonNull List <WindowInsetsAnimationCompat > runningAnimations ) {
217+ imeHeight = insets .getInsets (WindowInsetsCompat .Type .ime ()).bottom ;
218+ refreshImeTranslation ();
219+ return insets ;
220+ }
221+
222+ @ Override
223+ public void onEnd (@ NonNull WindowInsetsAnimationCompat animation ) {
224+ if ((animation .getTypeMask () & WindowInsetsCompat .Type .ime ()) != 0 ) {
225+ hasOngoingImeAnimation = false ;
226+ }
227+ }
228+ });
229+ ViewCompat .setOnApplyWindowInsetsListener (contentFrame , (v , insets ) -> {
230+ // Only refresh translation if IME change insets itself, not the animation
231+ if (!hasOngoingImeAnimation ) {
232+ imeHeight = insets .getInsets (WindowInsetsCompat .Type .ime ()).bottom ;
233+ refreshImeTranslation ();
234+ }
235+ return insets ;
236+ });
237+
188238 // Set the activity for the executor. Must do this here, or else Tools.showErrorRemote() may not
189239 // execute the correct method
190240 ContextExecutor .setActivity (this );
@@ -209,7 +259,7 @@ protected void initLayout(int resId) {
209259 GLOBAL_CLIPBOARD = (ClipboardManager ) getSystemService (CLIPBOARD_SERVICE );
210260 touchCharInput .setCharacterSender (new LwjglCharSender ());
211261
212- touchControllerInputView .setSize ( minecraftGLView . getWidth (), minecraftGLView . getHeight () );
262+ touchControllerInputView .setInputAreaRectListener ( this );
213263
214264 if (minecraftProfile .pojavRendererName != null ) {
215265 Log .i ("RdrDebug" ,"__P_renderer=" +minecraftProfile .pojavRendererName );
@@ -260,6 +310,9 @@ protected void initLayout(int resId) {
260310 touchpad .post (() -> touchpad .switchState ());
261311 }
262312
313+ // At this time, correct size is known
314+ touchControllerInputView .setSize (minecraftGLView .getWidth (), minecraftGLView .getHeight ());
315+
263316 runCraft (finalVersion , mVersionInfo );
264317 }catch (Throwable e ){
265318 Tools .showErrorRemote (e );
@@ -314,6 +367,7 @@ private void bindValues(){
314367 touchControllerInputView = findViewById (R .id .touch_controller_input );
315368 mDrawerPullButton = findViewById (R .id .drawer_button );
316369 mHotbarView = findViewById (R .id .hotbar_view );
370+ contentFrame = findViewById (R .id .content_frame );
317371 }
318372
319373 @ Override
@@ -700,4 +754,33 @@ public void onTrimMemory(int level) {
700754 public void onBackPressed () {
701755 super .onBackPressed ();
702756 }
757+
758+ @ Override
759+ public void updateInputAreaRect (@ Nullable RectF rect ) {
760+ inputAreaRect = rect ;
761+ refreshImeTranslation ();
762+ }
763+
764+ private void refreshImeTranslation () {
765+ if (imeHeight == 0 ) {
766+ // Early exit
767+ contentFrame .setTranslationY (0 );
768+ return ;
769+ }
770+
771+ int inputAreaBottom ;
772+ if (inputAreaRect != null ) {
773+ inputAreaBottom = (int ) inputAreaRect .bottom ;
774+ } else if (LauncherPreferences .PREF_KEYBOARD_PANNING ) {
775+ inputAreaBottom = contentFrame .getHeight ();
776+ } else {
777+ contentFrame .setTranslationY (0 );
778+ return ;
779+ }
780+
781+ int bottomDistance = contentFrame .getHeight () - inputAreaBottom ;
782+ int bottomPadding = Math .max (imeHeight - bottomDistance , 0 );
783+
784+ contentFrame .setTranslationY (-bottomPadding );
785+ }
703786}
0 commit comments