WindowSoftInputMode = "adjustResize" no funciona con la acción translúcida / navbar

Tengo problemas con la barra de acción translúcida / navbar en el nuevo KitKat de Android (4.4) y el windowSoftInputMode="adjustResize" .

Normalmente cambiando el InputMode a adjustResize, la aplicación debe cambiar el tamaño cuando el teclado se muestra … pero aquí no lo hará! Si elimino las líneas para el efecto transparente, el cambio de tamaño está funcionando.

Así que si el teclado es visible, mi ListView está debajo de él y no puedo acceder a los últimos artículos. (Sólo ocultando el teclado manualmente)

AndroidManifest.xml

 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="XYZ" android:versionCode="23" android:versionName="0.1" > <uses-sdk android:minSdkVersion="9" android:targetSdkVersion="19" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/Theme.XYZStyle" > <activity android:name="XYZ" android:label="@string/app_name" android:windowSoftInputMode="adjustResize" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> 

Values-v19 / styles.xml

 <?xml version="1.0" encoding="utf-8"?> <resources> <style name="Theme.XYZStyle" parent="@style/Theme.AppCompat.Light"> <item name="android:windowTranslucentStatus">true</item> <item name="android:windowTranslucentNavigation">true</item> </style> </resources> 

Fragmento.xml

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ListView android:id="@+id/listView_contacts" android:layout_width="match_parent" android:layout_height="match_parent" android:clipToPadding="false" android:divider="@null" android:dividerHeight="0dp" android:drawSelectorOnTop="true" android:fastScrollAlwaysVisible="true" android:fastScrollEnabled="true" android:paddingBottom="@dimen/navigationbar__height" > </ListView> </RelativeLayout> 

Alguien ideas para arreglar esto?

Te pierdes la siguiente propiedad:

 android:fitsSystemWindows="true" 

En la raíz RelativeLayout del diseño fragment.xml (o, posiblemente, en el diseño de la actividad, no estoy seguro, ya que no tenemos la estructura completa de la aplicación)

Hay un informe de error relacionado aquí . He encontrado una solución que, a partir de pruebas limitadas, parece hacer el truco sin repercusiones. Añadir una implementación personalizada de su ViewGroup raíz (casi siempre estoy usando FrameLayout , por lo que esto es lo que he probado con) con la lógica a continuación. A continuación, utilice esta disposición personalizada en lugar de su diseño raíz, y asegúrese de establecer android:fitsSystemWindows="true" . A continuación, puede llamar a getInsets() cualquier momento después del diseño (por ejemplo, agregue un OnPreDrawListener ) para ajustar el resto de su diseño para tener en cuenta las inserciones del sistema, si lo desea.

 import android.content.Context; import android.graphics.Rect; import android.os.Build; import android.util.AttributeSet; import android.widget.FrameLayout; import org.jetbrains.annotations.NotNull; /** * @author Kevin * Date Created: 3/7/14 * * https://code.google.com/p/android/issues/detail?id=63777 * * When using a translucent status bar on API 19+, the window will not * resize to make room for input methods (ie * {@link android.view.WindowManager.LayoutParams#SOFT_INPUT_ADJUST_RESIZE} and * {@link android.view.WindowManager.LayoutParams#SOFT_INPUT_ADJUST_PAN} are * ignored). * * To work around this; override {@link #fitSystemWindows(android.graphics.Rect)}, * capture and override the system insets, and then call through to FrameLayout's * implementation. * * For reasons yet unknown, modifying the bottom inset causes this workaround to * fail. Modifying the top, left, and right insets works as expected. */ public final class CustomInsetsFrameLayout extends FrameLayout { private int[] mInsets = new int[4]; public CustomInsetsFrameLayout(Context context) { super(context); } public CustomInsetsFrameLayout(Context context, AttributeSet attrs) { super(context, attrs); } public CustomInsetsFrameLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public final int[] getInsets() { return mInsets; } @Override protected final boolean fitSystemWindows(@NotNull Rect insets) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // Intentionally do not modify the bottom inset. For some reason, // if the bottom inset is modified, window resizing stops working. // TODO: Figure out why. mInsets[0] = insets.left; mInsets[1] = insets.top; mInsets[2] = insets.right; insets.left = 0; insets.top = 0; insets.right = 0; } return super.fitSystemWindows(insets); } } 

Debido a que fitSystemWindow s estaba obsoleto, consulte la respuesta a continuación para completar la solución.

@kcoppock respuesta es realmente útil, pero fitSystemWindows fue obsoleto en el nivel de API 20

Así que desde la API 20 (KITKAT_WATCH) debe anular onApplyWindowInsets

 @Override public final WindowInsets onApplyWindowInsets(WindowInsets insets) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) { mInsets[0] = insets.getSystemWindowInsetLeft(); mInsets[1] = insets.getSystemWindowInsetTop(); mInsets[2] = insets.getSystemWindowInsetRight(); return super.onApplyWindowInsets(insets.replaceSystemWindowInsets(0, 0, 0, insets.getSystemWindowInsetBottom())); } else { return insets; } } 

Esto trabajó para mí para tener la barra de estado translúcida y adjustResize en el fragmento:

  1. Hacer una costumbre RelativeLayout as @ Victor91 y @kcoppock dijo.

  2. Utilice CustomRelativeLayout como diseño principal para su fragmento.

  3. Declare el tema con android: windowTranslucentStatus = true

  4. La actividad del contenedor debe declararse en Manifest con android: windowSoftInputMode = "adjustResize" y utilizar el tema declarado

  5. Por favor, use fitsSystemWindows en el diseño de la raíz de fragmento!

    Public class CustomRelativeLayout extends RelativeLayout {private int [] mInsets = nuevo int [4];

     public CustomRelativeLayout(Context context) { super(context); } public CustomRelativeLayout(Context context, AttributeSet attrs) { super(context, attrs); } public CustomRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } public CustomRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } @Override public final WindowInsets onApplyWindowInsets(WindowInsets insets) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) { mInsets[0] = insets.getSystemWindowInsetLeft(); mInsets[1] = insets.getSystemWindowInsetTop(); mInsets[2] = insets.getSystemWindowInsetRight(); return super.onApplyWindowInsets(insets.replaceSystemWindowInsets(0, 0, 0, insets.getSystemWindowInsetBottom())); } else { return insets; } } 

    }

     <com.blah.blah.CustomRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true"> 

Tuve el mismo problema, Mi Actividad tenía un ScrollView como vista de raíz y con la barra de estado translúcida activada no cambió de tamaño correctamente cuando el teclado mostró … y consecuently la pantalla no se desplazó ocultando las vistas de entrada.

Solución: Movió todo (lógica de la disposición y de la actividad) dentro de un nuevo fragmento. Luego cambió la Actividad para incluir solamente este Fragmento. ¡Ahora todo funciona como se esperaba!

Esta es la distribución de la actividad:

 <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/contentView" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" /> 

Basado en la solución de Joseph Johnson en Android Cómo ajustar el diseño en modo de pantalla completa cuando el teclado virtual está visible

Llame a esto en onCreate() después de setContentView() en su actividad.

AndroidBug5497Workaround.assistActivity(this);

Un litte diferente del original replace return (r.bottom - r.top); Con return r.bottom; En computeUsableHeight()

Por alguna razón, debo establecer mi actividad fitsSystemWindows atributo a false .

Esta solución me salvó. Funciona bien para mí. La esperanza puede ayudarle.

La clase de implementación es:

 public class AndroidBug5497Workaround { // 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. public static void assistActivity (Activity activity) { new AndroidBug5497Workaround(activity); } private View mChildOfContent; private int usableHeightPrevious; private FrameLayout.LayoutParams frameLayoutParams; private AndroidBug5497Workaround(Activity activity) { FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content); mChildOfContent = content.getChildAt(0); mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { public void onGlobalLayout() { possiblyResizeChildOfContent(); } }); frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams(); } private void possiblyResizeChildOfContent() { int usableHeightNow = computeUsableHeight(); if (usableHeightNow != usableHeightPrevious) { int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight(); int heightDifference = usableHeightSansKeyboard - usableHeightNow; if (heightDifference > (usableHeightSansKeyboard/4)) { // keyboard probably just became visible frameLayoutParams.height = usableHeightSansKeyboard - heightDifference; } else { // keyboard probably just became hidden frameLayoutParams.height = usableHeightSansKeyboard; } mChildOfContent.requestLayout(); usableHeightPrevious = usableHeightNow; } } private int computeUsableHeight() { Rect r = new Rect(); mChildOfContent.getWindowVisibleDisplayFrame(r); return r.bottom; } } 

AndroidBug5497Workaround.java cuidar la pérdida de memoria. Necesita debajo del código

 getViewTreeObserver().removeOnGlobalLayoutListener(listener); 

Mi muestra usando RxJava que llama automáticamente a removeOnGlobalLayoutListener () cuando onPause () en el ciclo de vida de la actividad

 public class MyActivity extends RxAppCompatActivity { // ... protected void onStart(){ super.onStart(); TRSoftKeyboardVisibility .changes(this) // activity .compose(this.<TRSoftKeyboardVisibility.ChangeEvent>bindUntilEvent(ActivityEvent.PAUSE)) .subscribe(keyboardEvent -> { FrameLayout content = (FrameLayout) findViewById(android.R.id.content); View firstChildView = content.getChildAt(0); firstChildView.getLayoutParams().height = keyboardEvent.viewHeight(); firstChildView.requestLayout(); // keyboardEvent.isVisible = keyboard visible or not // keyboardEvent.keyboardHeight = keyboard height // keyboardEvent.viewHeight = fullWindowHeight - keyboardHeight }); //... } package commonlib.rxjava.keyboard; import android.app.Activity; import android.view.View; import android.widget.FrameLayout; import kr.ohlab.android.util.Assert; import rx.Observable; public class TRSoftKeyboardVisibility { public static Observable<ChangeEvent> changes(Activity activity) { Assert.notNull(activity, "activity == null"); FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content); View childOfContent = content.getChildAt(0); return Observable.create( new TRSoftKeyboardVisibilityEventOnSubscribe(childOfContent)); } public static final class ChangeEvent { private final int keyboardHeight; private final boolean visible; private final int viewHeight; public static ChangeEvent create(boolean visible, int keyboardHeight, int windowDisplayHeight) { return new ChangeEvent(visible, keyboardHeight, windowDisplayHeight); } private ChangeEvent(boolean visible, int keyboardHeight, int viewHeight) { this.keyboardHeight = keyboardHeight; this.visible = visible; this.viewHeight = viewHeight; } public int keyboardHeight() { return keyboardHeight; } public boolean isVisible() { return this.visible; } public int viewHeight() { return viewHeight; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof ChangeEvent)) return false; ChangeEvent that = (ChangeEvent) o; if (keyboardHeight != that.keyboardHeight) return false; if (visible != that.visible) return false; return viewHeight == that.viewHeight; } @Override public int hashCode() { int result = keyboardHeight; result = 31 * result + (visible ? 1 : 0); result = 31 * result + viewHeight; return result; } @Override public String toString() { return "ChangeEvent{" + "keyboardHeight=" + keyboardHeight + ", visible=" + visible + ", viewHeight=" + viewHeight + '}'; } } } package commonlib.rxjava.keyboard; import android.graphics.Rect; import android.view.View; import android.view.ViewTreeObserver; import kr.ohlab.android.util.Assert; import rx.Observable; import rx.Subscriber; import rx.android.MainThreadSubscription; import timber.log.Timber; public class TRSoftKeyboardVisibilityEventOnSubscribe implements Observable.OnSubscribe<TRSoftKeyboardVisibility.ChangeEvent> { private final View mTopView; private int mLastVisibleDecorViewHeight; private final Rect mWindowVisibleDisplayFrame = new Rect(); public TRSoftKeyboardVisibilityEventOnSubscribe(View topView) { mTopView = topView; } private int computeWindowFrameHeight() { mTopView.getWindowVisibleDisplayFrame(mWindowVisibleDisplayFrame); return (mWindowVisibleDisplayFrame.bottom - mWindowVisibleDisplayFrame.top); } private TRSoftKeyboardVisibility.ChangeEvent checkKeyboardVisibility() { int windowFrameHeightNow = computeWindowFrameHeight(); TRSoftKeyboardVisibility.ChangeEvent event = null; if (windowFrameHeightNow != mLastVisibleDecorViewHeight) { int mTopViewHeight = mTopView.getHeight(); int heightDiff = mTopViewHeight - windowFrameHeightNow; Timber.e("XXX heightDiff=" + heightDiff); if (heightDiff > (mTopViewHeight / 4)) { event = TRSoftKeyboardVisibility.ChangeEvent.create(true, heightDiff, windowFrameHeightNow); } else { event = TRSoftKeyboardVisibility.ChangeEvent.create(false, 0, windowFrameHeightNow); } mLastVisibleDecorViewHeight = windowFrameHeightNow; return event; } return null; } public void call(final Subscriber<? super TRSoftKeyboardVisibility.ChangeEvent> subscriber) { Assert.checkUiThread(); final ViewTreeObserver.OnGlobalLayoutListener listener = new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { TRSoftKeyboardVisibility.ChangeEvent event = checkKeyboardVisibility(); if( event == null) return; if (!subscriber.isUnsubscribed()) { subscriber.onNext(event); } } }; mTopView.getViewTreeObserver().addOnGlobalLayoutListener(listener); subscriber.add(new MainThreadSubscription() { @Override protected void onUnsubscribe() { mTopView.getViewTreeObserver().removeOnGlobalLayoutListener(listener); } }); } } 

Tenía como un problema.

Establecer windowDrawsSystemBarBackgrounds a 'true' y mi aplicación debe mostrar en la barra de estado.

Es mi tema de actividad.

 <item name="android:windowTranslucentStatus" tools:targetApi="KITKAT">false</item> <item name="android:windowDrawsSystemBarBackgrounds">true</item> <item name="android:windowTranslucentNavigation">true</item> <item name="android:statusBarColor">@android:color/transparent</item> 

Y recibí ayuda del blog de jianshu . Usted puede leer el código pero el texto como mí. Añado poco código más.

 public final class ZeroInsetsFrameLayout extends FrameLayout { private int[] mInsets = new int[4]; public ZeroInsetsFrameLayout(Context context) { super(context); } public ZeroInsetsFrameLayout(Context context, AttributeSet attrs) { super(context, attrs); } public ZeroInsetsFrameLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public final int[] getInsets() { return mInsets; } @Override public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) { outLocalInsets.left = 0; outLocalInsets.top = 0; outLocalInsets.right = 0; return super.computeSystemWindowInsets(in, outLocalInsets); } @Override protected final boolean fitSystemWindows(@NonNull Rect insets) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { // Intentionally do not modify the bottom inset. For some reason, // if the bottom inset is modified, window resizing stops working. // TODO: Figure out why. mInsets[0] = insets.left; mInsets[1] = insets.top; mInsets[2] = insets.right; insets.left = 0; insets.top = 0; insets.right = 0; } return super.fitSystemWindows(insets); } } 

Este es mi diseño de fragmento.

 <com.dhna.widget.ZeroInsetsFrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" android:background="@color/white"> <!-- your xml code --> </ZeroInsetsFrameLayout> 

Quiero que sea útil para usted. ¡buena suerte!

  • Nuevo WebView en los problemas de Android KitKat
  • Cómo evitar el "permiso EACCES negado" en SDCARD con KITKAT 4.4.2 Versión. Nueva política de google
  • Theme.AppCompat.Light.NoActionBar.FullScreen No funciona con Android 4.4
  • La búsqueda global no funciona como se esperaba en Android 4.4
  • Entrada de archivo HTML en android webview (android 4.4, kitkat)
  • Android Material Design en los dispositivos KitKat (e inferior)
  • Problemas con Fast Scroll en Android 4.4
  • En android 4.4 webView.getHitTestResult () devuelve null
  • Activación de KioskMode en Android 4.4.2 con Root
  • ConsumerIrManager API 19
  • Obtener 'Permiso denegado (13)' al intentar usar systrace en Moto X con KitKat
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.