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


178

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

Para esto lo he usado android:windowSoftInputMode="adjustPan|adjustResize|stateHidden"con diferentes opciones pero sin suerte.

Después de eso, implementé mediante FullScreenprogramación y probé varios diseños para trabajar, FullScreenpero todo fue en vano.

Hice referencia a estos enlaces y he buscado muchas publicaciones relacionadas 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>

ingrese la descripción de la imagen aquí

Quiero que los 2 botones inferiores deben ir hacia arriba cuando aparezca el teclado virtual en la imagen.

ingrese la descripción de la imagen aquí


1
Creo que debe agregar botones dentro de ScrollView y debajo de EditText.
Balaji Khadake

Ya he probado muchas opciones que no funcionan ...
Vineet Shukla

1
ur poner botones en un FrameLayout y establecer el peso de la FrameLayout a 1 y finalmente utilizar solamente android:windowSoftInputMode="adjustPan"dime si este trabajo ..
Sherif Elkhatib

@VineetShukla, ¿has encontrado algún trabajo con pantalla completa?
Muhammad Babar

2
Tenga en cuenta que no debe usar adjustResizey, adjustPanal mismo tiempo, del javadoc de android.view.WindowManager.LayoutParams#SOFT_INPUT_ADJUST_RESIZE: "Esto no se puede combinar con {@link SOFT_INPUT_ADJUST_PAN}"
Denis Kniazhev

Respuestas:


257

Basado en la solución de yghm, codifiqué una clase de conveniencia que me permite resolver el problema con una sola línea (después de agregar 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://issuetracker.google.com/issues/36911528
    // 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.


8
¡Gracias! No tengo ni idea de por qué, pero tenía que sustituir return (r.bottom - r.top); a return r.bottomconseguir que funcione en mi HTC uno mini, de lo contrario la vista de la actividad sería empujado demasiado alto por el tamaño de la barra de estado. Sin embargo, aún no lo he probado en otro dispositivo. Espero que pueda ayudar.
Joan

44
Hola Joseph Johnson, utilicé tu código y funcionó perfectamente. Pero ahora los días enfrentan un problema en algunos dispositivos pequeños que muestra la brecha (pantalla en blanco) entre el teclado y el diseño. ¿Tienes alguna idea sobre este tema? También intenté regresar r.bottom.
Pankaj

2
Joseph Johnson: He aplicado su método, su fina de trabajo cuando se hace clic en el texto superior de edición pero cuando se hace clic en EditarTexto abajo todo el diseño sube
ranjith

3
Desafortunadamente no funciona en Nexus 7 (2013). Todavía se desplaza incluso con el ajuste Ajustar nada.
Le-roy Staines

44
Impresionante respuesta, muchas gracias. Está funcionando en un Nexus 6, pero en lugar de usarlo, frameLayoutParams.height = usableHeightSansKeyboard;tengo que usarlo. frameLayoutParams.height = usableHeightNow; Si no lo hago, algunos elementos quedan fuera de la pantalla.
RobertoAllende

37

Como la respuesta ya ha sido elegida y se sabe que el problema es un error, pensé que agregaría un "Posible solución".

Puede alternar el modo de pantalla completa cuando se muestra el teclado virtual. Esto permite que el "ajustarPan" funcione correctamente.

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

Use 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 el título en modo de pantalla completa


1
Aprecio que hayas dado tiempo al problema, +1 por eso. Definitivamente probaré este enfoque y le haré saber pronto si funcionó para mí, gracias.
Vineet Shukla

1
Está funcionando como se sospecha! Muy buena solución! +1 de mi lado.
Mike


1
el teclado se rompe, haciendo que el fondo del teclado sea negro. El efecto de
ajuste

wow, gracias ... me funciona muy bien combinando la solución mencionada por AndroidBug5497Workaround ... Subí la fuente combinada a GitHub ... github.com/CrandellWS/AndroidBug5497Workaround/blob/master/…
CrandellWS el

23

Probé la solución de Joseph Johnson , pero al igual que otros, me encontré con el problema de la brecha entre el contenido y el teclado. El problema se produce porque el modo de entrada suave siempre se desplaza al usar el modo de pantalla completa. Esta panorámica interfiere con la solución de Joseph cuando activa un campo de entrada que estaría oculto por la entrada de software.

Cuando aparece la entrada de software, el contenido se desplaza primero en función de su altura original, y luego 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 panorámica, lo que da como resultado el espacio. El orden completo de los eventos es:

  1. Oyente de diseño global
  2. Paneo
  3. Diseño del contenido (= cambio de tamaño real del contenido)

No es posible deshabilitar la panorámica, pero es posible forzar el desplazamiento de la panorámica a 0 cambiando la altura del contenido. Esto se puede hacer en el oyente, ya que se ejecuta antes de que se realice la panorámica. Establecer la altura del contenido a la altura disponible da como resultado una experiencia de usuario fluida, es decir, sin parpadeos.

También hice estos cambios. Si alguno de estos presenta problemas, avíseme:

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

Se ha probado en un Nexus 5 y en emuladores con niveles de API 16-24 con tamaños de pantalla que varían de pequeño a grande.

El código ha sido portado a Kotlin, pero portar mis cambios 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 = ViewTreeObserver.OnGlobalLayoutListener { 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
        }
    }
}

9
Esta parece ser la mejor respuesta. Me porté a Java aquí gist.github.com/grennis/2e3cd5f7a9238c59861015ce0a7c5584 . Tenga en cuenta que estaba recibiendo excepciones de que el observador no estaba vivo, y tuve que verificar eso también.
Greg Ennis

¡Oh Dios mío! estado recorriendo todas las jerarquías de vistas del sistema buscando ese espacio fantasma. Estaba cerca de deshacerme de las computadoras por un camión de comida, pero vi su respuesta en el último minuto. Funciona :)
rompe el

1
@ Greg Ennis Gracias por el puerto Java. Ahorró mucho esfuerzo y tiempo.
Ikun

@GregEnnis, gracias, su solución funciona con onResume (), onPause (), onDestroy () (ver comentarios en el código de GitHub).
CoolMind

Esto está funcionando para mí, excepto que la llamada removeListener no parece estar funcionando. Puse puntos de interrupción dentro de la possiblyResizeChildOfContentllamada y la removeListenerllamada, e incluso después de alcanzar el removeListenerpunto de interrupción, possiblyResizeChildOfContenttodavía se está llamando. ¿Alguien más tiene este problema?
Quinn

14

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á usando View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN, por ejemplo, si está usandoCoordinatorLayout .

No funcionará para WindowManager.LayoutParams.FLAG_FULLSCREEN(El que también puede configurar en el tema android:windowFullscreen), pero puede lograr un efecto similar con SYSTEM_UI_FLAG_LAYOUT_STABLE(que "tiene el mismo efecto visual" según los documentos ) y esta solución debería funcionar nuevamente.

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 probé 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 el WindowInsetsenvío por el sistema contiene información precisa y confiable al respecto.

Para el caso de uso como en DrawerLayout cuando estamos tratando de dibujar detrás de la barra de estado, podemos crear un diseño que ignore solo el recuadro superior y aplique el recuadro inferior que representa el teclado virtual.

Aquí está mi costumbre 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>

Teóricamente, esto debería funcionar para cualquier dispositivo sin modificación loca, mucho mejor que cualquier hack que intente tomar un tamaño aleatorio 1/3o 1/4de pantalla como referencia.

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


@Dilip Funciona en API 16+, siempre que se cumplan las condiciones antes mencionadas.
Hai Zhang

10

Tenga en cuenta que android:windowSoftInputMode="adjustResize"no funciona cuando WindowManager.LayoutParams.FLAG_FULLSCREENse configura para una actividad. Tienes dos opciones.

  1. Desactive el modo de pantalla completa para su actividad. La actividad no se redimensiona en 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. Use una forma alternativa para lograr el modo de pantalla completa. Agregue el siguiente código 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 el método 2 solo funciona en Android 4.1 y superior.


@AnshulTyagi method-2 solo funciona en Android 4.1 y superior.
Abhinav Chauhan

44
Probado en 5.0 y 4.4.2, Nexus 9 y Samsung s4 respectivamente, el segundo método no funciona.
RobVoisey

1
El segundo método simplemente no funciona y perdí mucho tiempo en él.
Greg Ennis

Gracias, salva mi día.
Deni Rohimat

9

Tuve que enfrentar este problema también y tuve un trabajo en torno al cual revisé HTC uno, galaxy s1, s2, s3, nota y 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 allí comprobé la diferencia de altura y si la diferencia de altura de la pantalla es mayor que un tercio de la altura de la pantalla, 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 sea a prueba de balas y tal vez en algunos dispositivos no funcione, pero funcionó para mí y espero que también lo ayude.


1
Necesitaba algunos ajustes, pero funcionó. En el Nexus 7 2013 tuve que disminuir la altura del teclado (screenHeight / 3) en algunos píxeles. Buena idea, gracias!
Joao Sousa el

7

Implementé la solución Joseph Johnson y funcionó bien, noté que después de usar esta solución, a veces el cajón de la aplicación no se cierra correctamente. Agregué una funcionalidad para eliminar el escucha removeOnGlobalLayoutListener cuando el usuario cierra el fragmento donde se encuentran los textos de edición.

    //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);
    } 
}

utiliza la clase donde se encuentran mis textos de edición

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

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

7

Agregue android:fitsSystemWindows="true"al diseño, y este diseño cambiará de tamaño.


Eso fue lo que me resolvió. Además, pensó, asegúrese de configurarlo en la vista correcta. Si tiene un fondo que debería ir debajo de la barra de estado, no lo configure allí, sino en un diseño interior. Probablemente las vistas de EditText, etc., deberían estar dentro de ese segundo diseño dentro. También vea esta charla, ya que aclara las cosas: youtube.com/watch?v=_mGDMVRO3iE
Stan

Me funcionó a mi también. Gracias al comentario de @Stan también pude hacerlo funcionar con el tema FULLSCREEN colocando ese atributo en ViewPager en lugar del diseño de actividad / fragmento.
marcouberti

5

Para que funcione con FullScreen:

Use el complemento de teclado iónico. Esto le permite escuchar cuándo aparece y desaparece el teclado.

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 negativa, esa es la cantidad de píxeles que el teclado cubre de su entrada. Entonces, si ajusta su div padre por esto, eso debería contrarrestarlo.

Agregar tiempos de espera a la lógica dice que 300 ms también debería optimizar el rendimiento (ya que esto permitirá que aparezca el tiempo del teclado.


3

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

Estoy usando esto para una vista web a pantalla completa. Para desplazar la vista de contenido a la posición correcta, necesito usar una interfaz de 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 pueda implementar una panorámica personalizada frente a su cambio de tamaño.

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());
    }

}

parece ser lo que necesito, ¿podría agregar una muestra completa? ¡gracias por tu trabajo!
vilicvane

No estaba buscando publicar un proyecto completo. Lo que he proporcionado le traerá un largo camino hacia una solución que funcione perfectamente. Lo que necesita definirse: cree una clase "JavaScriptObject" e instálela en su vista web como una interfaz js (consulte la documentación de la vista web para eso). Hay una buena probabilidad de que ya lo haya hecho si escribe algo que usa una vista web de manera integral. Agregue JavaScript en la vista web para escuchar eventos de enfoque y alimentar datos en su clase JavaScriptObject sobre el posicionamiento del elemento de enfoque.
BuvinJ

2

De hecho, la apariencia del teclado suave no parece afectar Activityde ninguna manera, sin importar lo windowSoftInputModeque seleccione en el FullScreenmodo.

Aunque no pude encontrar mucha documentación sobre esta propiedad, creo que el FullScreenmodo fue diseñado para aplicaciones de juegos que no requieren mucho uso del teclado virtual. Si la suya es una actividad que requiere la interacción del usuario a través del teclado virtual, reconsidere el uso de un tema que no sea de pantalla completa. Puede apagar la barra de título usando un NoTitleBartema. ¿Por qué querrías ocultar la barra de notificaciones?


2

Solo mantenlo como android:windowSoftInputMode="adjustResize". Porque se da para mantener sólo uno de cada "adjustResize"y "adjustPan"(El modo de ajuste de la ventana se especifica, ya sea con o adjustResize adjustPan. Se recomienda que siempre se especifica una o la otra). Puede encontrarlo aquí: http://developer.android.com/resources/articles/on-screen-inputs.html

Funciona perfectamente para mí.


No tengo ningún problema ... También he probado tu XML. Este también funciona ... estoy usando Os versión 2.2
Balaji Khadake

Lo he intentado solo con el modo de pantalla completa ... lo estoy probando en mi Nexus One y Nexus S ... Funciona.
Balaji Khadake

1
He intentado con Galaxy S, HTC wildfire, HTC Hero, Motorola Deify y Sony XPeria. No funciona en ningún dispositivo individual.
Vineet Shukla


2

Actualmente estoy usando este enfoque y funciona de maravilla. El truco es que obtenemos la altura del teclado de diferentes métodos en 21 arriba y abajo y luego lo usamos como el relleno inferior de nuestra vista raíz en nuestra actividad. Supuse que su diseño no necesita un relleno superior (va debajo de la barra de estado) pero en caso de que lo haga, infórmeme para actualizar mi respuesta.

MainActivity.java

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        RelativeLayout mainLayout = findViewById(R.id.main_layout);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            ViewCompat.setOnApplyWindowInsetsListener(mainLayout , new OnApplyWindowInsetsListener() {
                @Override
                public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) {
                    v.setPadding(0, 0, 0, insets.getSystemWindowInsetBottom());
                    return insets;
                }
            });
        } else {
            View decorView = getWindow().getDecorView();
            final View contentView = mainLayout;
            decorView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    Rect r = new Rect();
                    //r will be populated with the coordinates of your view that area still visible.
                    decorView.getWindowVisibleDisplayFrame(r);

                    //get screen height and calculate the difference with the useable area from the r
                    int height = decorView.getContext().getResources().getDisplayMetrics().heightPixels;
                    int diff = height - r.bottom;

                    //if it could be a keyboard add the padding to the view
                    if (diff != 0) {
                        // if the use-able screen height differs from the total screen height we assume that it shows a keyboard now
                        //check if the padding is 0 (if yes set the padding for the keyboard)
                        if (contentView.getPaddingBottom() != diff) {
                            //set the padding of the contentView for the keyboard
                            contentView.setPadding(0, 0, 0, diff);
                        }
                    } else {
                        //check if the padding is != 0 (if yes reset the padding)
                        if (contentView.getPaddingBottom() != 0) {
                            //reset the padding of the contentView
                            contentView.setPadding(0, 0, 0, 0);
                        }
                    }
                }
            });
        }
    }
...
}

No olvide abordar su vista raíz con una identificación:

activity_main.xml

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/main_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

Espero que ayude a alguien.


1
No puedo entender por qué esta respuesta aún no está en la parte superior. Que otros fallan, destellan, pero este es brillante, especialmente si tienes más de 5 api.
Anton Shkurenko

1

solo use android:windowSoftInputMode="adjustResize|stateHiddenmientras usa AdjustPan y luego deshabilita la propiedad de cambio


También lo he usado ... por favor, haz que lo estés haciendo en modo de pantalla completa y ¿en qué dispositivo estás probando?
Vineet Shukla

HTC NEXUS one, ok, no debería agregar pantalla completa
Mohammed Azharuddin Shaikh

¿Puedes usar getWindow (). requestFeature (Window.FEATURE_NO_TITLE); onCreate () en lugar de usar el tema?
Mohammed Azharuddin Shaikh

10
el código anterior funciona bien sin pantalla completa pero agregando pantalla completa desde xml o desde código ... No funciona ... Lea la pregunta detenidamente.
Vineet Shukla

1

Utilicé Joseph Johnson, creé la clase AndroidBug5497Workaround pero obtuve un espacio negro entre el softkeyboard y la vista. Me referí a este enlace Greg Ennis . Después de hacer algunos cambios a lo anterior, este es mi código de trabajo final.

 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);
  }
 }
}

1

basado en https://stackoverflow.com/a/19494006/1815624 y deseo de que esto suceda ...

idea actualizada


combinando respuestas de

Código relevante:

        if (heightDifference > (usableHeightSansKeyboard / 4)) {

            // keyboard probably just became visible
            frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
            activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
        } else {

            // keyboard probably just became hidden
            if(usableHeightPrevious != 0) {
                frameLayoutParams.height = usableHeightSansKeyboard;
                activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
                activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

            }

Fuente completa en https://github.com/CrandellWS/AndroidBug5497Workaround/blob/master/AndroidBug5497Workaround.java

vieja idea

Cree un valor estático de la altura de los contenedores antes de abrir el teclado Establezca la altura del contenedor en función de usableHeightSansKeyboard - heightDifferencecuándo se abre el teclado y vuelva a establecer el valor guardado cuando se cierre

if (heightDifference > (usableHeightSansKeyboard / 4)) {
                // keyboard probably just became visible
                frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
                int mStatusHeight = getStatusBarHeight();
                frameLayoutParams.topMargin = mStatusHeight;
                ((MainActivity)activity).setMyMainHeight(usableHeightSansKeyboard - heightDifference);

                if(BuildConfig.DEBUG){
                    Log.v("aBug5497", "keyboard probably just became visible");
                }
            } else {
                // keyboard probably just became hidden
                if(usableHeightPrevious != 0) {
                    frameLayoutParams.height = usableHeightSansKeyboard;
                    ((MainActivity)activity).setMyMainHeight();    
                }
                frameLayoutParams.topMargin = 0;

                if(BuildConfig.DEBUG){
                    Log.v("aBug5497", "keyboard probably just became hidden");
                }
            }

Métodos en MainActivity

public void setMyMainHeight(final int myMainHeight) {

    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            ConstraintLayout.LayoutParams rLparams =  (ConstraintLayout.LayoutParams) myContainer.getLayoutParams();
            rLparams.height = myMainHeight;

            myContainer.setLayoutParams(rLparams);
        }

    });

}

int mainHeight = 0;
public void setMyMainHeight() {

    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            ConstraintLayout.LayoutParams rLparams =  (ConstraintLayout.LayoutParams) myContainer.getLayoutParams();
            rLparams.height = mainHeight;

            myContainer.setLayoutParams(rLparams);
        }

    });

}

Ejemplo de contenedor XML

<android.support.constraint.ConstraintLayout
    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.support.constraint.ConstraintLayout
            android:id="@+id/my_container"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            app:layout_constraintHeight_percent=".8">

de manera similar, se pueden agregar márgenes si es necesario ...

Otra consideración es el uso de relleno, un ejemplo de esto se puede encontrar en:

https://github.com/mikepenz/MaterialDrawer/issues/95#issuecomment-80519589


1

1) Crear KeyboardHeightHelper:

public class KeyboardHeightHelper {

    private final View decorView;
    private int lastKeyboardHeight = -1;

    public KeyboardHeightHelper(Activity activity, View activityRootView, OnKeyboardHeightChangeListener listener) {
        this.decorView = activity.getWindow().getDecorView();
        activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
            int keyboardHeight = getKeyboardHeight();
            if (lastKeyboardHeight != keyboardHeight) {
                lastKeyboardHeight = keyboardHeight;
                listener.onKeyboardHeightChange(keyboardHeight);
            }
        });
    }

    private int getKeyboardHeight() {
        Rect rect = new Rect();
        decorView.getWindowVisibleDisplayFrame(rect);
        return decorView.getHeight() - rect.bottom;
    }

    public interface OnKeyboardHeightChangeListener {
        void onKeyboardHeightChange(int keyboardHeight);
    }
}

2) Deja que tu actividad sea pantalla completa:

activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);

3) Escuche los cambios de altura del teclado y agregue el relleno inferior para su vista:

View rootView = activity.findViewById(R.id.root); // your root view or any other you want to resize
KeyboardHeightHelper effectiveHeightHelper = new KeyboardHeightHelper(
        activity, 
        rootView,
        keyboardHeight -> rootView.setPadding(0, 0, 0, keyboardHeight));

Por lo tanto , cada vez que aparezca el teclado en la pantalla, el relleno inferior para su vista cambiará y el contenido se reorganizará.


0

Desea que la barra inferior se adhiera a la parte inferior de la vista, pero cuando se muestra el teclado, deben moverse hacia arriba para colocarse encima del teclado, ¿verdad?

Puedes probar este fragmento de código:

<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>

La barra inferior se adherirá a la parte inferior de la vista y el diseño lineal que contiene la vista de desplazamiento tomará lo que quede de la vista después de que se muestren la barra superior / inferior y el teclado. Avísame si también te funciona.


1
Muy extraño ya que funcionó en mis aplicaciones varias veces. Por cierto, RelativeLayout no tiene orientación, por lo que puede eliminar estos atributos en su código. Yo sólo reconocido que podría haber cortado hacia abajo el fragmento de código a la línea: android: layout_below = "@ + / Identificación del scoringContainerView" que hay que añadir a su ScrollView
banzai86

¿Pantalla completa? ¿Quieres decir sin un diseño en la parte superior?
banzai86

sin ..... me refiero a ninguna barra de estado que muestran la vida de la batería, conectividad para el dispositivo, etc ....
Vineet Shukla

no, la barra de estado está visible en mi aplicación. ¿puedes intentar cambiar el orden de tus diseños, lo que significa que colocas el código para tu diseño con los botones sobre el otro código y luego lo intentas nuevamente? tal vez tengas que definirlos primero para usar el layout_below
banzai86

1
por favor lea la pregunta cuidadosamente ... He mencionado que tengo problemas con el modo de
pantalla

0

Gracias Joseph por tu respuesta. Sin embargo, en el método posiblementeResizeChildOfContent (), la porción

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

no funcionaba para mí, ya que la parte inferior de la vista se ocultó. Así que tuve que tomar una variable global restoreHeight, y en el constructor, inserté la última línea

restoreHeight = frameLayoutParams.height;

y luego reemplacé la parte mencionada anteriormente con

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

Pero no tengo idea de por qué su código no funcionó para mí. Sería de gran ayuda, si alguien puede arrojar luz sobre esto.


0

Solo estaba usando el modo de pantalla completa para ocultar la barra de estado. Sin embargo, quiero que la aplicación cambie de tamaño cuando se muestre el teclado. Todas las otras soluciones (probablemente debido a la antigüedad de la publicación) fueron complicadas o no fueron posibles para mi uso (quiero evitar cambiar el código Java para el saqueo de PhoneGap Build).

En lugar de usar Pantalla completa, modifiqué mi configuración para Android para que no sea de pantalla completa:

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

Y agregó el cordova-plugin-statusbar, a través de la línea de comando:

cordova plugin add cordova-plugin-statusbar

Cuando la aplicación se ha cargado, simplemente llamo a un método en el complemento para esconderse, como:

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

Esto funciona como un encanto. El único inconveniente real es que la barra de estado es brevemente visible mientras se carga la aplicación. Para mis necesidades, eso no fue un problema.


0

He probado todas las respuestas posibles de stackOverflow, finalmente resolví después de una semana de búsqueda. He usado el diseño de coordenadas y cambié esto con linearLayout y mi problema está solucionado. No sé, posiblemente, el diseño de coordenadas tiene errores o cualquier cosa, mi error.


0

Intenté muchas soluciones, incluidas las de Joseph Johnson y Johan Stuyts. Pero como resultado obtuve un espacio en blanco entre el contenido y el teclado en algunos dispositivos (como Lenovo s820) en todos los casos. Así que hice algunos cambios en sus códigos y finalmente obtuve una solución de trabajo.

Mi idea se basa en agregar margen a la parte superior del contenido cuando se muestra el teclado.

contentContainer.getWindowVisibleDisplayFrame(contentAreaOfWindowBounds);
    int usableHeightNow = contentAreaOfWindowBounds.height();

    if (usableHeightNow != usableHeightPrevious) {

        int difference = usableHeightNow - usableHeightPrevious;

        if (difference < 0 && difference < -150) {
            keyboardShowed = true;
            rootViewLayout.topMargin -= difference + 30;
            rootViewLayout.bottomMargin += 30;
        }
        else if (difference < 0 && difference > -150){
            rootViewLayout.topMargin -= difference + 30;
        }
        else if (difference > 0 && difference > 150) {
            keyboardShowed = false;
            rootViewLayout.topMargin = 0;
            rootViewLayout.bottomMargin = 0;
        }

        rootView.requestLayout();

        Log.e("Bug Workaround", "Difference: " + difference);

        usableHeightPrevious = usableHeightNow;
}

Como puede ver, agrego 30 px a la diferencia porque hay un pequeño espacio en blanco entre la parte superior de la pantalla y la zona de contenido con margen. Y no sé de dónde aparece, así que decidí reducir los márgenes y ahora funciona exactamente como lo necesitaba.


0

Hoy no funciona el ajuste de ajuste de tamaño en pantalla completa es real para Android SDK.

De las respuestas que encontré:
la solución , pero la solución muestra esto en el problema de la imagen:

Entonces encontré la solución y eliminé la única acción innecesaria:

this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);

Entonces, vea mi código de solución fija en Kotlin:

class AndroidBug5497Workaround constructor(val activity: Activity) {

    private val content = activity.findViewById<View>(android.R.id.content) as FrameLayout

    private val mChildOfContent = content.getChildAt(0)
    private var usableHeightPrevious: Int = 0
    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 listener = {
        possiblyResizeChildOfContent()
    }

    fun addListener() {
        mChildOfContent.apply {
            viewTreeObserver.addOnGlobalLayoutListener(listener)

        }
    }

    fun removeListener() {
        mChildOfContent.apply {
            viewTreeObserver.removeOnGlobalLayoutListener(listener)
        }
    }

    private fun possiblyResizeChildOfContent() {
        val contentAreaOfWindowBounds = Rect()
        mChildOfContent.getWindowVisibleDisplayFrame(contentAreaOfWindowBounds)
        val usableHeightNow = contentAreaOfWindowBounds.height()

        if (usableHeightNow != usableHeightPrevious) {
            rootViewLayout.height = usableHeightNow
            rootView.layout(contentAreaOfWindowBounds.left,
                    contentAreaOfWindowBounds.top, contentAreaOfWindowBounds.right, contentAreaOfWindowBounds.bottom);
            mChildOfContent.requestLayout()
            usableHeightPrevious = usableHeightNow
        }
    }
}

Mi código de implementación de corrección de errores:

 class LeaveDetailActivity : BaseActivity(){

    private val keyBoardBugWorkaround by lazy {
        AndroidBug5497Workaround(this)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

    }

    override fun onResume() {
        keyBoardBugWorkaround.addListener()
        super.onResume()
    }

    override fun onPause() {
        keyBoardBugWorkaround.removeListener()
        super.onPause()
    }
}

0

No utilizar:

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

porque funciona mal En lugar de eso, use:

fun setFullScreen(fullScreen: Boolean) {
        val decorView = getWindow().getDecorView()
        val uiOptions : Int
        if(fullScreen){
            uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN // this hide statusBar
            toolbar.visibility = View.GONE // if you use toolbar
            tabs.visibility = View.GONE // if you use tabLayout
        } else {
            uiOptions = View.SYSTEM_UI_FLAG_VISIBLE // this show statusBar
            toolbar.visibility = View.VISIBLE
            tabs.visibility = View.VISIBLE
        }
        decorView.setSystemUiVisibility(uiOptions)
    }

-1

En mi caso, este problema comenzó a suceder una vez que agregué Crosswalk a mi aplicación Cordova. Mi aplicación no se usa en pantalla completa y Android: windowSoftInputMode = "ajustarPan".

Ya tenía el complemento de teclado iónico en la aplicación, por lo que fue fácil detectar si el teclado estaba arriba o abajo:

// 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');
}

Intenté todas las soluciones anteriores, pero la línea simple que terminó haciéndolo fue este bit de css:

&.keyboardUp {
        overflow-y: scroll;
}

Espero que esto te salve los pocos días que pasé en esto. :)


Estoy usando el paso de peatones con cordova también con android: windowSoftInputMode = "ajustarPan". Sin embargo, no está funcionando. Veo que la clase se está agregando al elemento html, pero el CSS no tiene ningún efecto en la pantalla. ¿Hay alguna otra configuración que permita que la pantalla se mueva?
darewreck

Tengo que configurar la transformación add: translateY (0px) para que funcione. Sin embargo, el desplazamiento no funciona en absoluto. ¿Algunas ideas?
darewreck
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.