Android Cómo ajustar el diseño en el modo de pantalla completa cuando el teclado virtual está visible

He investigado mucho para ajustar el diseño cuando el softkeyboard está activo y lo he implementado con éxito pero el problema viene cuando uso android:theme="@android:style/Theme.NoTitleBar.Fullscreen" esto en mi etiqueta de actividad en el archivo de manifiesto .

Para esto he utilizado android:windowSoftInputMode="adjustPan|adjustResize|stateHidden" con diferentes opciones, pero no hay suerte.

Después de eso, implementé FullScreen programación y probé varios diseños para trabajar con FullScreen pero todo en vano.

Hice referencia a estos enlaces y he visto muchos mensajes relacionados con este tema:

Http://android-developers.blogspot.com/2009/04/updating-applications-for-on-screen.html

Http://davidwparker.com/2011/08/30/android-how-to-float-a-row-above-keyboard/

Aquí está el código xml:

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout android:id="@+id/masterContainerView" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android" android:background="#ffffff"> <ScrollView android:id="@+id/parentScrollView" android:layout_width="fill_parent" android:layout_height="wrap_content"> <LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <TextView android:id="@+id/setup_txt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Setup - Step 1 of 3" android:textColor="@color/top_header_txt_color" android:textSize="20dp" android:padding="8dp" android:gravity="center_horizontal" /> <TextView android:id="@+id/txt_header" android:layout_width="fill_parent" android:layout_height="40dp" android:text="AutoReply:" android:textColor="@color/top_header_txt_color" android:textSize="14dp" android:textStyle="bold" android:padding="10dp" android:layout_below="@+id/setup_txt" /> <EditText android:id="@+id/edit_message" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Some text here." android:textSize="16dp" android:textColor="@color/setting_editmsg_color" android:padding="10dp" android:minLines="5" android:maxLines="6" android:layout_below="@+id/txt_header" android:gravity="top" android:scrollbars="vertical" android:maxLength="132" /> <ImageView android:id="@+id/image_bottom" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_below="@+id/edit_message" /> </LinearLayout> </ScrollView> <RelativeLayout android:id="@+id/scoringContainerView" android:layout_width="fill_parent" android:layout_height="50px" android:orientation="vertical" android:layout_alignParentBottom="true" android:background="#535254"> <Button android:id="@+id/btn_save" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_marginTop="7dp" android:layout_marginRight="15dp" android:layout_below="@+id/edit_message" android:text = "Save" /> <Button android:id="@+id/btn_cancel" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="7dp" android:layout_marginRight="10dp" android:layout_below="@+id/edit_message" android:layout_toLeftOf="@+id/btn_save" android:text = "Cancel" /> </RelativeLayout> </RelativeLayout> 

Introduzca aquí la descripción de la imagen

Quiero que la parte inferior 2 botones debe ir hacia arriba cuando el softkeyboard viene en la imagen.

Introduzca aquí la descripción de la imagen

Basándome en la solución de yghm, codifiqué una clase de conveniencia que me permite resolver el problema con un solo forro (después de añadir la nueva clase a mi código fuente, por supuesto). El one-liner es:

  AndroidBug5497Workaround.assistActivity(this); 

Y 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 - r.top); } } 

Espero que esto ayude a alguien.

Dado que la respuesta ya ha sido escogida y el problema conocido como un error, pensé que iba a añadir un "trabajo posible alrededor".

Puede activar el modo de pantalla completa cuando se muestre el teclado virtual. Esto permite que el "adjustPan" funcione correctamente.

En otras palabras, todavía uso @android: style / Theme.Black.NoTitleBar.Fullscreen como parte del tema de la aplicación y stateVisible | adjustResize como parte del modo de entrada suave de la ventana de actividad, pero para que trabajen juntos Debo activar el modo de pantalla completa Antes de que aparezca el teclado.

Utilice el siguiente código:

Desactivar el modo de pantalla completa

 getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); 

Activar el modo de pantalla completa

 getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); 

Nota – la inspiración vino de: Ocultar título en un modo de pantalla completa

Tuve que hacer frente a este problema también y tenía un trabajo alrededor de lo que he comprobado en un HTC, galaxia s1, s2, s3, nota y la sensación de HTC.

Poner un oyente de diseño global en la vista raíz de su diseño

 mRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener(){ public void onGlobalLayout() { checkHeightDifference(); } }); 

Y en allí he comprobado la diferencia de altura y si la diferencia de altura de la pantalla es más grande que un tercio en la altura de la pantalla, entonces podemos suponer que el teclado está abierto. Lo tomó de esta respuesta .

 private void checkHeightDifference(){ // get screen frame rectangle Rect r = new Rect(); mRootView.getWindowVisibleDisplayFrame(r); // get screen height int screenHeight = mRootView.getRootView().getHeight(); // calculate the height difference int heightDifference = screenHeight - (r.bottom - r.top); // if height difference is different then the last height difference and // is bigger then a third of the screen we can assume the keyboard is open if (heightDifference > screenHeight/3 && heightDifference != mLastHeightDifferece) { // keyboard visiblevisible // get root view layout params FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mRootView.getLayoutParams(); // set the root view height to screen height minus the height difference lp.height = screenHeight - heightDifference; // call request layout so the changes will take affect .requestLayout(); // save the height difference so we will run this code only when a change occurs. mLastHeightDifferece = heightDifference; } else if (heightDifference != mLastHeightDifferece) { // keyboard hidden PFLog.d("[ChatroomActivity] checkHeightDifference keyboard hidden"); // get root view layout params and reset all the changes we have made when the keyboard opened. FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mRootView.getLayoutParams(); lp.height = screenHeight; // call request layout so the changes will take affect mRootView.requestLayout(); // save the height difference so we will run this code only when a change occurs. mLastHeightDifferece = heightDifference; } } 

Esto probablemente no es prueba de balas y tal vez en algunos dispositivos no funcionará, pero funcionó para mí y espero que te ayude también.

Sólo use android:windowSoftInputMode="adjustResize|stateHidden como se utiliza AdjustPan a continuación, deshabilitar la propiedad de cambio de tamaño

Para que funcione con FullScreen:

Utilice el complemento de teclado iónico. Esto le permite escuchar cuando el teclado aparece y desaparece.

OnDeviceReady agrega estos oyentes de eventos:

 // Allow Screen to Move Up when Keyboard is Present window.addEventListener('native.keyboardshow', onKeyboardShow); // Reset Screen after Keyboard hides window.addEventListener('native.keyboardhide', onKeyboardHide); 

La lógica:

 function onKeyboardShow(e) { // Get Focused Element var thisElement = $(':focus'); // Get input size var i = thisElement.height(); // Get Window Height var h = $(window).height() // Get Keyboard Height var kH = e.keyboardHeight // Get Focused Element Top Offset var eH = thisElement.offset().top; // Top of Input should still be visible (30 = Fixed Header) var vS = h - kH; i = i > vS ? (vS - 30) : i; // Get Difference var diff = (vS - eH - i); if (diff < 0) { var parent = $('.myOuter-xs.myOuter-md'); // Add Padding var marginTop = parseInt(parent.css('marginTop')) + diff - 25; parent.css('marginTop', marginTop + 'px'); } } function onKeyboardHide(e) { // Remove All Style Attributes from Parent Div $('.myOuter-xs.myOuter-md').removeAttr('style'); } 

Básicamente, si la diferencia es menos entonces que es la cantidad de píxeles que el teclado está cubriendo de su entrada. Así que si ajusta su div padre por esto que debe contrarrestarlo.

Añadiendo tiempos de espera a la lógica, digamos 300ms también debe optimizar el rendimiento (ya que esto permitirá que el tiempo del teclado aparezca.

He implementado la solución de Joseph Johnson y funcionó bien, me di cuenta después de usar esta solución a veces el cajón de la aplicación no se cerrará correctamente. He añadido una funcionalidad para eliminar el oyente removeOnGlobalLayoutListener cuando el usuario cierra el fragmento donde se encuentran edittexts.

  //when the application uses full screen theme and the keyboard is shown the content not scrollable! //with this util it will be scrollable once again //http://stackoverflow.com/questions/7417123/android-how-to-adjust-layout-in-full-screen-mode-when-softkeyboard-is-visible public class AndroidBug5497Workaround { private static AndroidBug5497Workaround mInstance = null; private View mChildOfContent; private int usableHeightPrevious; private FrameLayout.LayoutParams frameLayoutParams; private ViewTreeObserver.OnGlobalLayoutListener _globalListener; // 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 AndroidBug5497Workaround getInstance (Activity activity) { if(mInstance==null) { synchronized (AndroidBug5497Workaround.class) { mInstance = new AndroidBug5497Workaround(activity); } } return mInstance; } private AndroidBug5497Workaround(Activity activity) { FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content); mChildOfContent = content.getChildAt(0); frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams(); _globalListener = new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { possiblyResizeChildOfContent(); } }; } public void setListener() { mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(_globalListener); } public void removeListener() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { mChildOfContent.getViewTreeObserver().removeOnGlobalLayoutListener(_globalListener); } else { mChildOfContent.getViewTreeObserver().removeGlobalOnLayoutListener(_globalListener); } } 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 - r.top); } } 

Usa la clase donde se encuentra mi editexts

 @Override public void onStart() { super.onStart(); AndroidBug5497Workaround.getInstance(getActivity()).setListener(); } @Override public void onStop() { super.onStop(); AndroidBug5497Workaround.getInstance(getActivity()).removeListener(); } 

Tenga en cuenta que android:windowSoftInputMode="adjustResize" no funciona cuando WindowManager.LayoutParams.FLAG_FULLSCREEN está establecido para una actividad. Tienes dos opciones.

  1. Deshabilite el modo de pantalla completa para su actividad. La actividad no se vuelve a clasificar en el modo de pantalla completa. Puede hacerlo en xml (cambiando el tema de la actividad) o en código Java. Agregue las siguientes líneas en su método onCreate ().

     getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);` 

O

  1. Utilice una forma alternativa para lograr el modo de pantalla completa. Agregue el código siguiente en su método onCreate ().

     getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); View decorView = getWindow().getDecorView(); // Hide the status bar. int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN; decorView.setSystemUiVisibility(uiOptions);` 

Tenga en cuenta que method-2 sólo funciona en Android 4.1 o superior.

Intenté la solución de Joseph Johnson , pero como otros me encontré con el problema entre el contenido y el teclado. El problema se produce porque el modo de entrada suave es siempre pan cuando se utiliza el modo de pantalla completa. Esta panorámica interfiere con la solución de Joseph cuando se activa un campo de entrada que se oculta por la entrada suave.

Cuando aparece la entrada suave, el contenido se despliega primero en función de su altura original y se redimensiona según el diseño solicitado por la solución de Joseph. El cambio de tamaño y el diseño posterior no deshacen la panoramización, lo que resulta en la brecha. El orden completo de los eventos es:

  1. Oyente de diseño global
  2. Panning
  3. Diseño del contenido (= redimensionamiento real del contenido)

No es posible desactivar el panoramizado, pero es posible forzar el desplazamiento del panorámico a 0 cambiando la altura del contenido. Esto se puede hacer en el oyente, porque se ejecuta antes de que se realice el panoramizado. Ajustar la altura del contenido a la altura disponible resulta en una experiencia de usuario fluida, es decir, sin parpadeo.

También hice estos cambios. Si alguno de estos introduce problemas, hágamelo saber:

  • Determinación conmutada de altura disponible para usar getWindowVisibleDisplayFrame . El Rect se almacena en caché para evitar un poco de basura innecesaria.
  • Permita que el oyente también se elimine. Esto es útil cuando reutiliza una actividad para diferentes fragmentos que tienen diferentes requisitos de pantalla completa.
  • No distinga entre el teclado mostrado u oculto, pero siempre ajusta la altura del contenido a la altura visible del marco de visualización.

Se ha probado en un Nexus 5, y los emuladores que ejecutan los niveles API 16-24 con tamaños de pantalla que van desde pequeños a grandes.

El código se ha portado a Kotlin, pero portar mis cambios de nuevo a Java es simple. Déjame saber si necesitas ayuda:

 class AndroidBug5497Workaround constructor(activity: Activity) { private val contentContainer = activity.findViewById(android.R.id.content) as ViewGroup private val rootView = contentContainer.getChildAt(0) private val rootViewLayout = rootView.layoutParams as FrameLayout.LayoutParams private val viewTreeObserver = rootView.viewTreeObserver private val listener = { possiblyResizeChildOfContent() } private val contentAreaOfWindowBounds = Rect() private var usableHeightPrevious = 0 // I call this in "onResume()" of my fragment fun addListener() { viewTreeObserver.addOnGlobalLayoutListener(listener) } // I call this in "onPause()" of my fragment fun removeListener() { viewTreeObserver.removeOnGlobalLayoutListener(listener) } private fun possiblyResizeChildOfContent() { contentContainer.getWindowVisibleDisplayFrame(contentAreaOfWindowBounds) val usableHeightNow = contentAreaOfWindowBounds.height() if (usableHeightNow != usableHeightPrevious) { rootViewLayout.height = usableHeightNow // Change the bounds of the root view to prevent gap between keyboard and content, and top of content positioned above top screen edge. rootView.layout(contentAreaOfWindowBounds.left, contentAreaOfWindowBounds.top, contentAreaOfWindowBounds.right, contentAreaOfWindowBounds.bottom) rootView.requestLayout() usableHeightPrevious = usableHeightNow } } } 

De hecho, la apariencia de teclado suave no parece afectar a la Activity de ninguna manera, no importa lo que windowSoftInputMode seleccionar en el modo FullScreen .

Aunque no pude encontrar mucha documentación sobre esta propiedad, creo que el modo FullScreen fue diseñado para la aplicación de juegos que no requieren mucho uso del teclado suave. Si la suya es una actividad que requiere la interacción del usuario a través de un teclado virtual, reconsidere si utiliza un tema que no sea de pantalla completa. Puede desactivar el TitleBar utilizando un tema NoTitleBar . ¿Por qué desea ocultar la barra de notificación?

Intenté la clase de Joseph Johnson, y funcionó, pero no satisfizo mis necesidades. En lugar de emular android: windowSoftInputMode = "adjustResize", necesitaba emular android: windowSoftInputMode = "adjustPan".

Estoy usando esto para una vista en pantalla completa. Para desplazar la vista de contenido a la posición correcta, necesito usar una interfaz javascript que proporcione detalles sobre la posición del elemento de página que tiene el foco y por lo tanto está recibiendo la entrada del teclado. He omitido esos detalles, pero proporcioné mi reescritura de la clase de Joseph Johnson. Proporcionará una base muy sólida para que usted implemente una cacerola personalizada contra su redimensionar.

 package some.package.name; import some.package.name.JavaScriptObject; import android.app.Activity; import android.graphics.Rect; import android.view.View; import android.view.ViewTreeObserver; import android.widget.FrameLayout; //------------------------------------------------------- // ActivityPanner Class // // Convenience class to handle Activity attributes bug. // Use this class instead of windowSoftInputMode="adjustPan". // // To implement, call enable() and pass a reference // to an Activity which already has its content view set. // Example: // setContentView( R.layout.someview ); // ActivityPanner.enable( this ); //------------------------------------------------------- // // Notes: // // The standard method for handling screen panning // when the virtual keyboard appears is to set an activity // attribute in the manifest. // Example: // <activity // ... // android:windowSoftInputMode="adjustPan" // ... > // Unfortunately, this is ignored when using the fullscreen attribute: // android:theme="@android:style/Theme.NoTitleBar.Fullscreen" // //------------------------------------------------------- public class ActivityPanner { private View contentView_; private int priorVisibleHeight_; public static void enable( Activity activity ) { new ActivityPanner( activity ); } private ActivityPanner( Activity activity ) { FrameLayout content = (FrameLayout) activity.findViewById( android.R.id.content ); contentView_ = content.getChildAt( 0 ); contentView_.getViewTreeObserver().addOnGlobalLayoutListener( new ViewTreeObserver.OnGlobalLayoutListener() { public void onGlobalLayout() { panAsNeeded(); } }); } private void panAsNeeded() { // Get current visible height int currentVisibleHeight = visibleHeight(); // Determine if visible height changed if( currentVisibleHeight != priorVisibleHeight_ ) { // Determine if keyboard visiblity changed int screenHeight = contentView_.getRootView().getHeight(); int coveredHeight = screenHeight - currentVisibleHeight; if( coveredHeight > (screenHeight/4) ) { // Keyboard probably just became visible // Get the current focus elements top & bottom // using a ratio to convert the values // to the native scale. float ratio = (float) screenHeight / viewPortHeight(); int elTop = focusElementTop( ratio ); int elBottom = focusElementBottom( ratio ); // Determine the amount of the focus element covered // by the keyboard int elPixelsCovered = elBottom - currentVisibleHeight; // If any amount is covered if( elPixelsCovered > 0 ) { // Pan by the amount of coverage int panUpPixels = elPixelsCovered; // Prevent panning so much the top of the element // becomes hidden panUpPixels = ( panUpPixels > elTop ? elTop : panUpPixels ); // Prevent panning more than the keyboard height // (which produces an empty gap in the screen) panUpPixels = ( panUpPixels > coveredHeight ? coveredHeight : panUpPixels ); // Pan up contentView_.setY( -panUpPixels ); } } else { // Keyboard probably just became hidden // Reset pan contentView_.setY( 0 ); } // Save usabale height for the next comparison priorVisibleHeight_ = currentVisibleHeight; } } private int visibleHeight() { Rect r = new Rect(); contentView_.getWindowVisibleDisplayFrame( r ); return r.bottom - r.top; } // Customize this as needed... private int viewPortHeight() { return JavaScriptObject.viewPortHeight(); } private int focusElementTop( final float ratio ) { return (int) (ratio * JavaScriptObject.focusElementTop()); } private int focusElementBottom( final float ratio ) { return (int) (ratio * JavaScriptObject.focusElementBottom()); } } 

Sólo mantener como android:windowSoftInputMode="adjustResize" . Debido a que se le da a mantener sólo uno de "adjustResize" y "adjustPan" (El modo de ajuste de ventana se especifica con adjustResize o adjustPan. Es muy recomendable que siempre especifique uno o el otro). Puede encontrarlo aquí: http://developer.android.com/resources/articles/on-screen-inputs.html

Funciona perfectamente para mí.

Acabo de encontrar una solución simple y confiable si está utilizando el enfoque de interfaz de usuario del sistema ( https://developer.android.com/training/system-ui/immersive.html ).

Funciona en el caso cuando está utilizando View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN , por ejemplo, si está utilizando CoordinatorLayout .

No funcionará para WindowManager.LayoutParams.FLAG_FULLSCREEN (el que también se puede establecer en el tema con android:windowFullscreen ), pero se puede lograr un efecto similar con SYSTEM_UI_FLAG_LAYOUT_STABLE (que "tiene el mismo efecto visual" de acuerdo con los documentos ) y esto Solución debería funcionar de nuevo.

 getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION /* If you want to hide navigation */ | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE) 

Lo he probado en mi dispositivo con Marshmallow.

La clave es que los teclados suaves también son una de las ventanas del sistema (como la barra de estado y la barra de navegación), por lo que los WindowInsets enviados por el sistema contienen información precisa y confiable sobre ella.

Para el caso de uso, como en DrawerLayout donde estamos tratando de dibujar detrás de la barra de estado, podemos crear un diseño que ignora sólo el recuadro superior y aplica la inserción inferior que representa el teclado virtual.

Aquí está mi personalizado FrameLayout :

 /** * Implements an effect similar to {@code android:fitsSystemWindows="true"} on Lollipop or higher, * except ignoring the top system window inset. {@code android:fitsSystemWindows="true"} does not * and should not be set on this layout. */ public class FitsSystemWindowsExceptTopFrameLayout extends FrameLayout { public FitsSystemWindowsExceptTopFrameLayout(Context context) { super(context); } public FitsSystemWindowsExceptTopFrameLayout(Context context, AttributeSet attrs) { super(context, attrs); } public FitsSystemWindowsExceptTopFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @RequiresApi(Build.VERSION_CODES.LOLLIPOP) public FitsSystemWindowsExceptTopFrameLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } @Override public WindowInsets onApplyWindowInsets(WindowInsets insets) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { setPadding(insets.getSystemWindowInsetLeft(), 0, insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom()); return insets.replaceSystemWindowInsets(0, insets.getSystemWindowInsetTop(), 0, 0); } else { return super.onApplyWindowInsets(insets); } } } 

Y para usarlo:

 <com.example.yourapplication.FitsSystemWindowsExceptTopFrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- Your original layout here --> </com.example.yourapplication.FitsSystemWindowsExceptTopFrameLayout> 

Esto debería funcionar teóricamente para cualquier dispositivo sin modificación insana, mucho mejor que cualquier hack que intenta tomar un 1/3 o 1/4 azar del tamaño de la pantalla como referencia.

(Requiere API 16+, pero estoy usando la pantalla completa sólo en Lollipop + para dibujar detrás de la barra de estado por lo que es la mejor solución en este caso.)

You want the bottom bar to stick to the bottom of the view, but when the keyboard is displayed, they should move up to be placed above the keyboard, right?

You can try this code snippet:

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" ...> <RelativeLayout android:id="@+id/RelativeLayoutTopBar" ...> </RelativeLayout> <LinearLayout android:id="@+id/LinearLayoutBottomBar" android:layout_alignParentBottom = true ...> </LinearLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="390dp" android:orientation="vertical" android:layout_above="@+id/LinearLayoutBottomBar" android:layout_below="@+id/RelativeLayoutTopBar"> <ScrollView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:layout_marginBottom="10dp" android:id="@+id/ScrollViewBackground"> ... </ScrollView> </LinearLayout> </RelativeLayout> 

The BottomBar will stick to the bottom of the view and the LinearLayout containing the ScrollView will take what's left of the view after the top/bottom bar and the keyboard are displayed. Let me know if it works for you as well.

Thank you Joseph for your answer. However, in the method possiblyResizeChildOfContent(), the portion

 else { // keyboard probably just became hidden frameLayoutParams.height = usableHeightSansKeyboard; } 

was not working for me, as the lower portion of view became hidden. So I had to take a global variable restoreHeight, and in the constructor, I inserted the last line

 restoreHeight = frameLayoutParams.height; 

and then I replaced the former mentioned part with

 else { // keyboard probably just became hidden frameLayoutParams.height = restoreHeight; } 

But I have no idea why your code didn't work for me. It would be of great help, if someone can shed light on this.

I was only using full screen mode to hide the status bar. However, I want the app to resize when keyboard is shown. All of the other solutions (likely due to age of post) were complicated or not possible for my use (want to avoid change Java code for sack of PhoneGap Build).

Instead of using Full screen, I modified my configure for Android to be non-fullscreen:

  <preference name="fullscreen" value="false" /> 

And added the cordova-plugin-statusbar , via command line:

 cordova plugin add cordova-plugin-statusbar 

When app has loaded, I simple call a method on the plugin to hide itself, like:

  if (window.cordova && window.cordova.platformId == 'android' && window.StatusBar) window.StatusBar.hide(); 

Esto funciona como un encanto. Only real downside is that the status bar is breifly visible while the app loads. For my needs, that wasn't an issue.

I have tried out all the possible answers from stackOverflow, finally i solved after a week Long search . I have used the coordinate layout and i changed this with linearLayout and my problem is fixed. I dont know possibly the coordinate layout has bugs or anything my mistake.

In my case, this issue started happening once I added Crosswalk to my Cordova application. My app is not used in fullscreen and android:windowSoftInputMode="adjustPan".

I already had the ionic keyboard plugin in the application, so detecting if the keyboard was up or down was easy thanks to it:

 // Listen for events to when the keyboard is opened and closed window.addEventListener("native.keyboardshow", keyboardUp, false); window.addEventListener('native.keyboardhide', keyboardDown, false); function keyboardUp() { $('html').addClass('keyboardUp'); } function keyboardDown() { $('html').removeClass('keyboardUp'); } 

I tried all of the fixes above but the simple line that ended up doing it for me was this bit of css:

 &.keyboardUp { overflow-y: scroll; } 

Hope this saves you the few days I spent on this. 🙂

I used Joseph Johnson created AndroidBug5497Workaround class but getting black space between softkeyboard and the view. I referred this link Greg Ennis . After doing some changes to the above this is my final working code.

  public class SignUpActivity extends Activity { private RelativeLayout rlRootView; // this is my root layout private View rootView; private ViewGroup contentContainer; private ViewTreeObserver viewTreeObserver; private ViewTreeObserver.OnGlobalLayoutListener listener; private Rect contentAreaOfWindowBounds = new Rect(); private FrameLayout.LayoutParams rootViewLayout; private int usableHeightPrevious = 0; private View mDecorView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sign_up); mDecorView = getWindow().getDecorView(); contentContainer = (ViewGroup) this.findViewById(android.R.id.content); listener = new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { possiblyResizeChildOfContent(); } }; rootView = contentContainer.getChildAt(0); rootViewLayout = (FrameLayout.LayoutParams) rootView.getLayoutParams(); rlRootView = (RelativeLayout) findViewById(R.id.rlRootView); rlRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { int heightDiff = rlRootView.getRootView().getHeight() - rlRootView.getHeight(); if (heightDiff > Util.dpToPx(SignUpActivity.this, 200)) { // if more than 200 dp, it's probably a keyboard... // Logger.info("Soft Key Board ", "Key board is open"); } else { Logger.info("Soft Key Board ", "Key board is CLOSED"); hideSystemUI(); } } }); } // This snippet hides the system bars. protected void hideSystemUI() { // Set the IMMERSIVE flag. // Set the content to appear under the system bars so that the content // doesn't resize when the system bars hide and show. mDecorView.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 | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); } @Override protected void onPause() { super.onPause(); if (viewTreeObserver.isAlive()) { viewTreeObserver.removeOnGlobalLayoutListener(listener); } } @Override protected void onResume() { super.onResume(); if (viewTreeObserver == null || !viewTreeObserver.isAlive()) { viewTreeObserver = rootView.getViewTreeObserver(); } viewTreeObserver.addOnGlobalLayoutListener(listener); } @Override protected void onDestroy() { super.onDestroy(); rootView = null; contentContainer = null; viewTreeObserver = null; } private void possiblyResizeChildOfContent() { contentContainer.getWindowVisibleDisplayFrame(contentAreaOfWindowBounds); int usableHeightNow = contentAreaOfWindowBounds.height(); if (usableHeightNow != usableHeightPrevious) { rootViewLayout.height = usableHeightNow; rootView.layout(contentAreaOfWindowBounds.left, contentAreaOfWindowBounds.top, contentAreaOfWindowBounds.right, contentAreaOfWindowBounds.bottom); rootView.requestLayout(); usableHeightPrevious = usableHeightNow; } else { this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); } } } 

Full screen please use

“`java

 View decorView = getWindow().getDecorView(); int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN; decorView.setSystemUiVisibility(uiOptions); 

¡Bienvenido!

  • Cómo crear un widget Widget.Holo.Spinner-estilo en v7
  • Cómo configurar el texto en la vista de texto de un widget
  • Múltiples tamaños de widgets
  • Efecto extraño con ImageView startAnimation en ListView
  • ¿Por qué el teclado levanta el tabhost a la tapa?
  • Android: Agregar elementos de interfaz de usuario a una vista de forma programática
  • Android VideoView borrar la visualización después de stopPlayback ()
  • SearchView.OnCloseListener no se invoca
  • ¿Puedo actualizar el mensaje de cadena de un ProgressDialog?
  • Android Gallery Adaptador con MultiTouch? Galería personalizada o ImageView personalizado?
  • Mostrar SearchWidget en ActionBar si el usuario presiona el botón de búsqueda del dispositivo
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.