Quickly solve the problem of Android adapting to virtual keyboards such as bottom return keys

  • 2021-09-24 23:33:12
  • OfStack

This problem has bothered me back and forth for a long time, and it has not been properly solved.

Scenario 1: Huawei mobile phone obscures the bottom of the screen.

Scenario 2: When entering the application, the virtual key automatically retracts, leaving a blank area.

Requirements:

Android needs to be able to adapt to the bottom virtual keys. When the user hides the virtual keys, the application should occupy the whole screen. When the user enables the virtual keys, the application can shrink up, which is equivalent to being pushed up by the bottom virtual keys.

The requirements are simple, but it is difficult to realize.

Perfect solution:

Explain the following code under 1, which is to monitor the change of a certain view, and rearrange the view when the visible height changes, so as to ensure that the view will not be blocked and the screen space will not be wasted. This point can be especially used on mobile phones such as Huawei mobile phones, which can hide and display screen changes caused by virtual keyboards.

First add the tool class AndroidBug54971Workaround


package com.xxxx.xxxx;

import android.graphics.Rect;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;

/**
 * Created by win7 on 2016/12/14.
 */

public class AndroidBug54971Workaround {
 // For more information, see https://code.google.com/p/android/issues/detail?id=5497
 // To use this class, simply invoke assistActivity() on an Activity that already has its content view set.

 /**
  *  Associate a view to listen to 
  *
  * @param viewObserving
  */
 public static void assistActivity(View viewObserving) {
  new AndroidBug54971Workaround(viewObserving);
 }

 private View mViewObserved;// Listened view 
 private int usableHeightPrevious;// Available height before view change 
 private ViewGroup.LayoutParams frameLayoutParams;

 private AndroidBug54971Workaround(View viewObserving) {
  mViewObserved = viewObserving;
  // To View Add a global layout listener 
  mViewObserved.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
   public void onGlobalLayout() {
    resetLayoutByUsableHeight(computeUsableHeight());
   }
  });
  frameLayoutParams = mViewObserved.getLayoutParams();
 }

 private void resetLayoutByUsableHeight(int usableHeightNow) {
  // Compare before and after layout changes View Available height of 
  if (usableHeightNow != usableHeightPrevious) {
   // If the height is not twice 1 To 
   // Will the current View The available height of is set to View Actual height of 
   frameLayoutParams.height = usableHeightNow;
   mViewObserved.requestLayout();// Request relayout 
   usableHeightPrevious = usableHeightNow;
  }
 }

 /**
  *  Calculate the visible height of the view 
  *
  * @return
  */
 private int computeUsableHeight() {
  Rect r = new Rect();
  mViewObserved.getWindowVisibleDisplayFrame(r);
  return (r.bottom - r.top);
 }
}

Then setContentView (R.layout.content_frame) of onCreate method of Activity that you need to solve this problem; Add on after


setContentView(R.layout.content_frame);
AndroidBug54971Workaround.assistActivity(findViewById(android.R.id.content));

If you understand the code, you must know that the View put in the assistActivity method is the view where you want to adjust the height.

Other imperfect schemes: they will not work in some cases more or less

I have one method:


android:fitsSystemWindows= " true "  

This sentence is written in the root directory of layout, and it is an adaptive system window by looking at the name. It is estimated that it can solve a large part of mobile phones, but it is useless under the colleague's nexus 4.

Method 2:

I removed android for each layout: fitsSystemWindows= "true"

This sentence was added to the style file.


<item name="android:windowTranslucentNavigation">false</item>

Note: You will find that the system reported an error, because this sentence came after API-19, so you can copy your style file and put it in the folder of API-19. This purpose is that if the mobile phone is greater than or equal to API19, it will use the contents under the folder of API-19. Otherwise, use the original style file. If you add the above sentence to the root theme of the style file under the API19 folder, it will be OK.

I thought it was a perfect solution to my problem. But I got hit in the face. Scenario 2 above will appear when you first enter App.

I look at setContentView of onCreate method in MainActivity (R. layout. xxxx); There is the following code before it


// Control the bottom virtual keyboard 
  getWindow().getDecorView().setSystemUiVisibility(
    View.SYSTEM_UI_FLAG_LAYOUT_STABLE
      | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
      | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
      | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
//      | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
      | View.SYSTEM_UI_FLAG_IMMERSIVE);

It is estimated that the former friends of this project added it to solve this problem.

After many debugs, I added a sentence


  // Control the bottom virtual keyboard 
  getWindow().getDecorView().setSystemUiVisibility(
    View.SYSTEM_UI_FLAG_LAYOUT_STABLE
      | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
      | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
      | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
//      | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
      | View.SYSTEM_UI_FLAG_IMMERSIVE);
  getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);

Scenario 2 is resolved. This is no problem when the virtual key 1 exists directly, because nexus can't hide the virtual keyboard manually, so I don't know whether it can run normally on Huawei and other mobile phones. TODO.

In addition, if you want to hide the virtual keyboard directly, and the click screen will not appear, replace the above code with:


  // Let the virtual keyboard 1 Direct display 
  Window window = getWindow();
  WindowManager.LayoutParams params = window.getAttributes();
  params.systemUiVisibility = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION|View.SYSTEM_UI_FLAG_IMMERSIVE;
  window.setAttributes(params);

Related articles: