Android Como ajustar o layout no modo de tela cheia quando o teclado virtual está visível


178

Eu pesquisei bastante para ajustar o layout quando o softkeyboard está ativo e o implementei com êxito, mas o problema ocorre quando eu o uso android:theme="@android:style/Theme.NoTitleBar.Fullscreen"na minha tag de atividade no arquivo de manifesto.

Para isso, usei android:windowSoftInputMode="adjustPan|adjustResize|stateHidden"com opções diferentes, mas sem sorte.

Depois disso, implementei FullScreenprogramaticamente e tentei vários layouts para trabalhar, FullScreenmas tudo em vão.

Consultei esses links e procurei muitas postagens aqui relacionadas a esse problema:

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/

Aqui está o 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>

insira a descrição da imagem aqui

Eu quero que os 2 botões inferiores subam quando a tecla programável aparecer na imagem.

insira a descrição da imagem aqui


1
Eu acho que você precisa adicionar botões dentro do ScrollView e abaixo do EditText.
Balaji Khadake

Eu já tentei muitas opções que não funciona ...
Vineet Shukla

1
colocar ur botões em uma FrameLayout e definir o peso do FrameLayout a 1 e, finalmente, usar somente android:windowSoftInputMode="adjustPan"me dizer se este trabalho ..
Sherif elKhatib

@VineetShukla você encontrou algum trabalho com tela cheia?
Muhammad Babar 29/04

2
Observe que você não deve usar adjustResizee adjustPan, ao mesmo tempo, no javadoc de android.view.WindowManager.LayoutParams#SOFT_INPUT_ADJUST_RESIZE: "Isso não pode ser combinado com {@link SOFT_INPUT_ADJUST_PAN}"
Denis Kniazhev

Respostas:


257

Com base na solução alternativa do yghm, codifiquei uma classe de conveniência que me permite resolver o problema com uma linha (depois de adicionar a nova classe ao meu código-fonte, é claro). O one-liner é:

     AndroidBug5497Workaround.assistActivity(this);

E a classe de implementação é:


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 isso ajude alguém.


8
Obrigado! Não tenho idéia do porquê, mas tive que substituir return (r.bottom - r.top); por return r.bottompara que ele funcionasse no meu HTC One Mini, caso contrário, a exibição da atividade seria muito alta pelo tamanho da barra de status. Ainda não testei em outro dispositivo. Espero que possa ajudar.
Joan

4
Oi Joseph Johnson, usei seu código e funcionou perfeitamente. Mas agora os dias enfrentam um problema em alguns dispositivos pequenos que mostra a diferença (tela em branco) entre o teclado e o layout. Você tem alguma idéia sobre esse problema? Eu também tentei retornar r.bottom.
Pankaj

2
Joseph Johnson: Eu tenho implementado o seu método, sua excelente trabalho quando clicar sobre o texto top edição, mas quando clicamos EditText fundo todo o projeto vai para cima
ranjith

3
Infelizmente, ele não funciona no Nexus 7 (2013). Ele ainda se move mesmo com o ajusteNenhum conjunto.
Le-Roy Staines

4
Resposta incrível, muito obrigado. Ele está trabalhando em um Nexus 6, mas, em vez de usar, frameLayoutParams.height = usableHeightSansKeyboard;tenho que usar. frameLayoutParams.height = usableHeightNow; Se não o fizer, alguns elementos ficam fora da tela.
RobertoAllende

36

Como a resposta já foi escolhida e o problema é conhecido como bug, pensei em adicionar uma "solução possível".

Você pode alternar para o modo tela cheia quando o teclado virtual é exibido. Isso permite que o "AdjustPan" funcione corretamente.

Em outras palavras, eu ainda uso @android: style / Theme.Black.NoTitleBar.Fullscreen como parte do tema do aplicativo e stateVisible | AdjustResize como parte do modo de entrada programável da janela de atividade, mas para que eles funcionem juntos, devo alternar o modo de tela cheia antes do teclado aparecer.

Use o seguinte código:

Desativar o modo de tela cheia

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

Ativar o modo de tela cheia

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

Nota - a inspiração veio de: Ocultando o título no modo de tela cheia


1
Compreendo que você tenha dedicado tempo ao problema, +1 para isso. Definitivamente vou testar essa abordagem e informar em breve se ela funcionou para mim, obrigado.
Vineet Shukla

1
Está funcionando como suspeito! Solução realmente boa! +1 do meu lado.
1276 Mike


1
o teclado se encaixa, deixando o fundo do teclado preto. O efeito de encaixe não parece bom :(
nibz

uau, obrigado ... ele funciona muito bem para mim combinando a solução alternativa mencionada pelo AndroidBug5497Workaround ... Fiz o upload da fonte combinada para o GitHub ... github.com/CrandellWS/AndroidBug5497Workaround/blob/master/…
CrandellWS

23

Tentei a solução com Joseph Johnson , mas, como outros, me deparei com o problema do espaço entre o conteúdo e o teclado. O problema ocorre porque o modo de entrada suave é sempre panorâmico ao usar o modo de tela cheia. Esse panorama interfere na solução de Joseph quando você ativa um campo de entrada que seria oculto pela entrada flexível.

Quando a entrada flexível é exibida, o conteúdo é exibido primeiro com base na sua altura original e depois redimensionado pelo layout solicitado pela solução de Joseph. O redimensionamento e o layout subsequente não desfazem o panorama, o que resulta na lacuna. A ordem completa dos eventos é:

  1. Ouvinte de layout global
  2. Panorâmica
  3. Layout do conteúdo (= redimensionamento real do conteúdo)

Não é possível desativar o panorama, mas é possível forçar o deslocamento do panorama para 0 alterando a altura do conteúdo. Isso pode ser feito no ouvinte, porque é executado antes do pan. Definir a altura do conteúdo para a altura disponível resulta em uma experiência suave do usuário, ou seja, sem tremulações.

Eu também fiz essas mudanças. Se algum deles apresentar problemas, informe-me:

  • Determinação comutada da altura disponível para uso getWindowVisibleDisplayFrame. O Recté armazenado em cache para evitar um pouco de lixo desnecessário.
  • Permita que o ouvinte seja removido também. Isso é útil quando você reutiliza uma atividade para diferentes fragmentos com diferentes requisitos de tela cheia.
  • Não faça distinção entre o teclado mostrado ou oculto, mas sempre defina a altura do conteúdo para a altura visível do quadro de exibição.

Foi testado em um Nexus 5 e emuladores executando os níveis de API 16-24 com tamanhos de tela variando de pequeno a grande.

O código foi portado para o Kotlin, mas transportar minhas alterações para Java é simples. Deixe-me saber se você precisar de ajuda:

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 a melhor resposta. Portado para java aqui gist.github.com/grennis/2e3cd5f7a9238c59861015ce0a7c5584 . Observe que eu estava obtendo exceções de que o observador não estava vivo e também tinha que verificar isso.
Greg Ennis

Oh meu Deus! percorreu toda a hierarquia de visualizações do sistema procurando pelo espaço Ghost. Eu estava perto de abandonar computadores para um caminhão de comida, mas vi sua resposta no último minuto. Funciona :)
rompe

1
@ Greg Ennis Obrigado pela porta Java. Economizou muito esforço e tempo.
Ikun

@GregEnnis, obrigado, sua solução funciona com onResume (), onPause (), onDestroy () (consulte os comentários no código do GitHub).
CoolMind

Isso está funcionando para mim, exceto que a chamada removeListener não parece estar funcionando. Eu coloquei pontos de interrupção tanto na possiblyResizeChildOfContentchamada quanto na removeListenerchamada e, mesmo depois de atingir o removeListenerponto de interrupção, possiblyResizeChildOfContentainda está sendo chamado. Alguém mais tendo esse problema?
Quinn

14

Acabei de encontrar uma solução simples e confiável se você estiver usando a abordagem da interface do sistema ( https://developer.android.com/training/system-ui/immersive.html ).

Isso funciona quando você estiver usando View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN, por exemplo, se estiver usando CoordinatorLayout.

Não funcionará para WindowManager.LayoutParams.FLAG_FULLSCREEN(Aquele com o qual você também pode definir um tema android:windowFullscreen), mas é possível obter um efeito semelhante com SYSTEM_UI_FLAG_LAYOUT_STABLE(que "tem o mesmo efeito visual" de acordo com os documentos ) e essa solução deve funcionar novamente.

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)

Eu testei no meu dispositivo executando o Marshmallow.

A chave é que os teclados programáveis ​​também são uma das janelas do sistema (como barra de status e barra de navegação); portanto, o WindowInsetsdespachado pelo sistema contém informações precisas e confiáveis ​​sobre ele.

Para o caso de uso, como DrawerLayoutonde estamos tentando desenhar atrás da barra de status, podemos criar um layout que ignore apenas a inserção superior e aplique a inserção inferior responsável pelo teclado virtual.

Aqui está o meu costume 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);
        }
    }
}

E para usá-lo:

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

Teoricamente, isso deve funcionar para qualquer dispositivo sem modificação insana, muito melhor do que qualquer invasão que tente usar um tamanho aleatório 1/3ou 1/4de tela como referência.

(Requer API 16+, mas eu estou usando a tela cheia apenas no Lollipop + para desenhar atrás da barra de status, por isso é a melhor solução nesse caso.)


@Dilip Funciona na API 16+, desde que as condições mencionadas sejam atendidas.
Hai Zhang

10

Observe que android:windowSoftInputMode="adjustResize"não funciona quando WindowManager.LayoutParams.FLAG_FULLSCREENestá definido para uma atividade. Você tem duas opções.

  1. Desative o modo de tela cheia para sua atividade. A atividade não é redimensionada no modo de tela cheia. Você pode fazer isso no xml (alterando o tema da atividade) ou no código Java. Adicione as seguintes linhas no seu método onCreate ().

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

OU

  1. Use uma maneira alternativa de obter o modo de tela cheia. Adicione o seguinte código ao seu 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);`

Observe que o método-2 funciona apenas no Android 4.1 e superior.


O método @AnshulTyagi-2 funciona apenas no Android 4.1 e superior.
Abhinav Chauhan

4
Testado em 5.0 e 4.4.2, Nexus 9 e Samsung s4, respectivamente, o segundo método não funciona.
RobVoisey

1
O segundo método simplesmente não funciona e eu perdi muito tempo nele.
Greg Ennis

Obrigado, salve o meu dia.
Deni Rohimat

9

Eu também tive que enfrentar esse problema e tive um trabalho em torno do qual verifiquei no HTC One, Galaxy S1, S2, S3, Note e HTC Sensation.

coloque um ouvinte de layout global na visualização raiz do seu layout

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

e lá verifiquei a diferença de altura e, se a diferença de altura da tela for maior que um terço da altura da tela, podemos assumir que o teclado está aberto. tirou desta resposta .

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

isso provavelmente não é à prova de balas e talvez em alguns dispositivos não funcione, mas funcionou para mim e espero que também o ajude.


1
Precisava de alguns ajustes, mas funcionou. No Nexus 7 2013, tive que diminuir a altura do teclado (screenHeight / 3) em alguns pixels. Boa ideia, obrigado!
Joao Sousa

7

Eu implementei a solução Joseph Johnson e funcionou bem, notei que depois de usar essa solução, às vezes a gaveta do aplicativo não fecha corretamente. Adicionei uma funcionalidade para remover o ouvinte removeOnGlobalLayoutListener quando o usuário fecha o fragmento em que os edittexts estão localizados.

    //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 a classe em que meus edittexts estão localizados

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

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

7

Adicione android:fitsSystemWindows="true"ao layout, e esse layout será redimensionado.


Foi isso que resolveu para mim. Além disso, pense em defini-lo na exibição correta. Se você tem um plano de fundo que deve ficar abaixo da barra de status, não o defina lá, mas em um layout interno. Provavelmente as visualizações EditText, etc, devem estar dentro desse segundo layout. Assista também a essa conversa, pois ela torna as coisas mais claras: youtube.com/watch?v=_mGDMVRO3iE
Stan

Trabalhou para mim também. Graças ao comentário do @Stan, também consegui fazê-lo funcionar com o tema FULLSCREEN, colocando esse atributo no ViewPager em vez do layout de atividade / fragmento.
marcouberti 03/03

5

Para que ele funcione com o FullScreen:

Use o plug-in do teclado iônico. Isso permite que você escute quando o teclado aparece e desaparece.

OnDeviceReady adicione estes ouvintes de evento:

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

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

Basicamente, se a diferença é menor, essa é a quantidade de pixels que o teclado está cobrindo da sua entrada. Portanto, se você ajustar sua div principal por isso, isso deve ser combatido.

Adicionar tempos limite à lógica diz que 300ms também devem otimizar o desempenho (pois isso permitirá que o tempo do teclado apareça.


3

Tentei a aula de Joseph Johnson, e funcionou, mas não atendeu às minhas necessidades. Em vez de emular o android: windowSoftInputMode = "AdjustResize", eu precisava emular o android: windowSoftInputMode = "AdjustPan".

Estou usando isso para uma visualização na web em tela cheia. Para deslocar a exibição do conteúdo para a posição correta, preciso usar uma interface javascript que forneça detalhes sobre a posição do elemento da página que está em foco e, portanto, esteja recebendo a entrada do teclado. Omiti esses detalhes, mas reescrevi a aula de Joseph Johnson. Ele fornecerá uma base muito sólida para você implementar uma panorâmica personalizada versus o redimensionamento.

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 o que eu preciso, você poderia adicionar uma amostra completa? obrigado pelo seu trabalho!
precisa saber é o seguinte

Eu não estava olhando para postar um projeto inteiro. O que eu forneci trará a você um longo caminho, porém, em direção a uma solução que funcione perfeitamente. O que você precisa para se definir: Crie uma classe "JavaScriptObject" e injete-a na sua webview como uma interface js (verifique a documentação da webview para isso). Há uma boa chance de que você já tenha feito isso se estiver escrevendo algo que usa uma visualização da web de maneira abrangente. Adicione JavaScript na visualização da web para ouvir eventos de foco e alimentar dados em sua classe JavaScriptObject sobre o posicionamento do elemento de foco.
precisa saber é o seguinte

2

Na verdade, a aparência do teclado virtual não parece afetar de Activityforma alguma, não importa o que windowSoftInputModeeu selecione no FullScreenmodo.

Embora eu não tenha conseguido encontrar muita documentação sobre essa propriedade, acho que o FullScreenmodo foi projetado para aplicativos de jogos que não exigem muito uso do teclado virtual. Se a sua atividade for uma que requer interação do usuário por meio do teclado virtual, reconsidere usar um tema que não seja o FullScreen. Você pode desativar a barra de título usando um NoTitleBartema. Por que você deseja ocultar a barra de notificação?


2

Apenas mantenha como android:windowSoftInputMode="adjustResize". Como ele é fornecido para manter apenas um fora de "adjustResize"e "adjustPan"(O modo de ajuste da janela é especificado com AdjustResize ou AdjustPan. É altamente recomendável que você sempre especifique um ou outro). Você pode encontrá-lo aqui: http://developer.android.com/resources/articles/on-screen-inputs.html

Funciona perfeitamente para mim.


Não estou tendo nenhum problema ... Eu tentei o seu XML também. Este também works..m usando o OS versão 2.2
Balaji Khadake

Eu tentei apenas no modo de tela cheia ... estou testando no meu Nexus One e Nexus S .... Funciona.
Balaji Khadake

1
Eu tentei com Galaxy S, HTC Wildfire, HTC Hero, Motorola Deify e Sony XPeria. Não está funcionando em um único dispositivo.
Vineet Shukla


2

Atualmente, estou usando essa abordagem e funciona como um encanto. O truque é obter a altura do teclado de diferentes métodos no 21 acima e abaixo e usá-lo como o preenchimento inferior da nossa visualização raiz em nossa atividade. Eu assumi que seu layout não precisa de um preenchimento superior (fica abaixo da barra de status), mas, se precisar, informe-me para atualizar minha resposta.

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

Não se esqueça de abordar sua visualização raiz com um ID:

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 ajude alguém.


1
Não consigo entender, por que essa resposta ainda não está no topo. Que outros falha, flash, mas este é brilhante, especialmente se você tiver mais de 5 api.
Anton Shkurenko 07/07

1

use apenas android:windowSoftInputMode="adjustResize|stateHiddencomo você usa o AdjustPan, em seguida, ele desativa a propriedade de redimensionamento


Eu também o usei .... por favor, faça-o no modo de tela cheia e em qual dispositivo você está testando?
Vineet Shukla

HTC NEXUS one, ok, eu não adicionei tela cheia
Mohammed Azharuddin Shaikh

você pode usar getWindow (). requestFeature (Window.FEATURE_NO_TITLE); onCreate () usando o tema?
Mohammed Azharuddin Shaikh

10
o código acima está funcionando bem sem tela cheia, mas adicionando tela cheia do xml ou do código ... Não está funcionando ... Por favor, leia a pergunta com atenção.
Vineet Shukla

1

Eu usei Joseph Johnson e criei a classe AndroidBug5497Workaround, mas obtendo espaço em branco entre a tecla programável e a exibição. Eu indiquei este link Greg Ennis . Depois de fazer algumas alterações no item acima, este é o meu código de trabalho 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

com base em https://stackoverflow.com/a/19494006/1815624 e desejo que isso aconteça ...

ideia atualizada


combinando respostas 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);

            }

Fonte completa em https://github.com/CrandellWS/AndroidBug5497Workaround/blob/master/AndroidBug5497Workaround.java

velha ideia

Crie um valor estático da altura dos contêineres antes de abrir o teclado Defina a altura do contêiner com base em usableHeightSansKeyboard - heightDifferencequando o teclado for aberto e retorne ao valor salvo ao fechar

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

    });

}

Exemplo de XML do Contêiner

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

da mesma forma, margens podem ser adicionadas, se necessário ...

Outra consideração é o uso de preenchimento. Um exemplo disso pode ser encontrado em:

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


1

1) Crie 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) Deixe sua atividade em tela cheia:

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

3) Ouça as alterações de altura do teclado e adicione preenchimento inferior à sua exibição:

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

Portanto , toda vez que o teclado aparecer na tela - o preenchimento inferior da sua visualização mudará e o conteúdo será reorganizado.


0

Você deseja que a barra inferior fique na parte inferior da visualização, mas quando o teclado for exibido, eles deverão se mover para cima e serem colocados acima do teclado, certo?

Você pode tentar este trecho 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>

A barra inferior ficará na parte inferior da visualização e o LinearLayout que contém o ScrollView reterá o que resta da visualização depois que a barra superior / inferior e o teclado forem exibidos. Deixe-me saber se funciona para você também.


1
Muito estranho, pois funcionou em meus aplicativos várias vezes. A propósito, RelativeLayout não tem orientação para que você possa excluir esses atributos no seu código. Eu só reconheceu que eu poderia ter cortar a parte do código na linha: android: layout_below = "@ + id / scoringContainerView", que você tem que adicionar à sua ScrollView
banzai86

Tela cheia? Você quer dizer sem um layout no topo?
banzai86

não ..... Quero dizer nenhuma barra de status que mostram a vida da bateria, conectividade para o dispositivo etc ....
Vineet Shukla

não, a barra de status está visível no meu aplicativo. você pode tentar alterar a ordem dos seus layouts, o que significa que você coloca o código do layout com os botões acima do outro código e tenta novamente? talvez você tem que defini-los primeiro para usar o layout_below
banzai86

1
leia a questão com cuidado ...... eu mencionei que eu estou tendo problemas com modo de tela cheia ......
Vineet Shukla

0

Obrigado Joseph pela sua resposta. No entanto, no método possivelmenteResizeChildOfContent (), a parte

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

não estava funcionando para mim, pois a parte inferior da vista ficou oculta. Então, eu tive que pegar uma variável global restoreHeight e, no construtor, inseri a última linha

restoreHeight = frameLayoutParams.height;

e então substituí a parte mencionada anterior por

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

Mas não tenho idéia do por que seu código não funcionou para mim. Seria de grande ajuda se alguém pudesse esclarecer isso.


0

Eu estava apenas usando o modo de tela cheia para ocultar a barra de status. No entanto, quero que o aplicativo seja redimensionado quando o teclado for mostrado. Todas as outras soluções (provavelmente devido à idade da publicação) foram complicadas ou não são possíveis para o meu uso (quero evitar alterar o código Java para o saco do PhoneGap Build).

Em vez de usar a tela cheia, modifiquei meu configure para Android para não ser de tela inteira:

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

E adicionou o cordova-plugin-statusbar, via linha de comando:

cordova plugin add cordova-plugin-statusbar

Quando o aplicativo é carregado, eu chamo um método no plugin para se esconder, como:

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

Isso funciona como um encanto. A única desvantagem real é que a barra de status é facilmente visível enquanto o aplicativo é carregado. Para minhas necessidades, isso não foi um problema.


0

Eu tentei todas as respostas possíveis do stackOverflow, finalmente resolvi depois de uma semana Pesquisa longa. Eu usei o layout de coordenadas e mudei isso com linearLayout e meu problema foi corrigido. Eu não sei, possivelmente, o layout de coordenadas tem bugs ou qualquer coisa meu erro.


0

Tentei muitas soluções, incluindo as de Joseph Johnson e Johan Stuyts. Mas, como resultado, tive um espaço em branco entre o conteúdo e o teclado em alguns dispositivos (como o Lenovo s820) em todos os casos. Então, eu fiz algumas alterações em seus códigos e finalmente obtive a solução de trabalho.

Minha ideia foi adicionar margem ao topo do conteúdo quando o teclado está sendo exibido.

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 você pode ver, adiciono 30 px à diferença porque há um pequeno espaço em branco entre a parte superior da tela e a zona de conteúdo com margem. E eu não sei de onde ela aparece, então decidi apenas reduzir as margens e agora funciona exatamente como eu precisava.


0

Hoje, não está funcionando o AdjustResize na edição de tela cheia é real para o Android sdk.

Das respostas que encontrei:
a solução - mas a solução mostra isso na questão da imagem:

Então eu encontrei a solução e remova a ação desnecessária:

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

Então, veja meu código de solução fixa no 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
        }
    }
}

Meu código de implementação de correção de bug:

 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

Não use:

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

porque funciona mal. Em vez disso, 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

No meu caso, esse problema começou a acontecer depois que adicionei o Crosswalk ao meu aplicativo Cordova. Meu aplicativo não é usado em tela cheia e no android: windowSoftInputMode = "AdjustPan".

Eu já tinha o plug-in do teclado iônico no aplicativo, portanto, foi fácil detectar se o teclado estava ativo ou inativo, graças a ele:

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

Eu tentei todas as correções acima, mas a linha simples que acabou fazendo isso por mim foi este pouco de css:

&.keyboardUp {
        overflow-y: scroll;
}

Espero que isso poupe os poucos dias que passei nisso. :)


Estou usando a faixa de pedestres com cordova e também com o android: windowSoftInputMode = "AdjustPan". No entanto, não está funcionando. Vejo que a classe está sendo adicionada ao elemento html, mas o css não tem efeito na tela. Existe alguma outra configuração que permita que a tela se mova?
darewreck

Eu tenho que definir a transformação add: translateY (0px) para que ele funcione. No entanto, a rolagem não funciona. Alguma ideia?
darewreck
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.