Android Come regolare il layout in modalità schermo intero quando è visibile la tastiera


178

Ho fatto molte ricerche per adattare il layout quando il softkeyboard è attivo e l'ho implementato con successo, ma il problema si presenta quando lo uso android:theme="@android:style/Theme.NoTitleBar.Fullscreen"nel mio tag attività nel file manifest.

Per questo ho usato android:windowSoftInputMode="adjustPan|adjustResize|stateHidden"con diverse opzioni ma senza fortuna.

Successivamente ho implementato a livello di FullScreencodice e ho provato vari layout con cui lavorare, FullScreenma invano.

Ho fatto riferimento a questi collegamenti e ho cercato molti post qui relativi a questo 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/

Ecco il codice 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>

inserisci qui la descrizione dell'immagine

Voglio che i 2 pulsanti in basso vadano verso l'alto quando la tastiera viene visualizzata in figura.

inserisci qui la descrizione dell'immagine


1
Penso che devi aggiungere pulsanti all'interno di ScrollView e sotto EditText.
Balaji Khadake,

Ho già provato molte opzioni che non funzionano ...
Vineet Shukla,

1
metti i tuoi pulsanti in un framelayout e imposta il peso del framelayout su 1 e infine usa android:windowSoftInputMode="adjustPan"dimmi solo se questo funziona ..
Sherif elKhatib

@VineetShukla hai trovato qualche allenamento a schermo intero ??
Muhammad Babar,

2
Nota che non dovresti usare adjustResizee adjustPanallo stesso tempo, dal javadoc di android.view.WindowManager.LayoutParams#SOFT_INPUT_ADJUST_RESIZE: "Questo non può essere combinato con {@link SOFT_INPUT_ADJUST_PAN}"
Denis Kniazhev,

Risposte:


257

Sulla base della soluzione di yghm, ho codificato una classe di convenienza che mi consente di risolvere il problema con una riga (ovviamente dopo aver aggiunto la nuova classe al mio codice sorgente). Il one-liner è:

     AndroidBug5497Workaround.assistActivity(this);

E la classe di implementazione è:


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

Spero che questo aiuti qualcuno.


8
Grazie! Non ho idea del perché, ma ho dovuto sostituirlo return (r.bottom - r.top); con return r.bottomper farlo funzionare sul mio HTC One Mini, altrimenti la visualizzazione dell'attività verrebbe spinta troppo in alto dalle dimensioni della barra di stato. Non l'ho ancora testato su un altro dispositivo. Spero che possa essere d'aiuto.
Joan,

4
Ciao Joseph John, ho usato il tuo codice e ha funzionato perfettamente. Ma ora alcuni giorni affrontano un problema su alcuni piccoli dispositivi che mostra il divario (schermo vuoto) tra tastiera e layout. Hai qualche idea su questo problema? Ho anche provato a restituire r.bottom.
Pankaj,

2
Joseph Johnson: Ho implementato il tuo metodo, funziona benissimo quando facciamo clic sul testo di modifica in alto, ma quando facciamo clic sul pulsante in basso tutto il design aumenta
ranjith

3
Sfortunatamente non funziona su Nexus 7 (2013). Fa una panoramica anche con un set di Nulla.
Le-roy Staines,

4
Risposta fantastica, grazie mille. Funziona su un Nexus 6 ma invece di usare frameLayoutParams.height = usableHeightSansKeyboard;devo usare frameLayoutParams.height = usableHeightNow; Se non lo faccio, alcuni elementi non rientrano nello schermo.
Roberto Allende,

37

Poiché la risposta è già stata scelta e il problema è noto per essere un bug, ho pensato di aggiungere un "Possibile soluzione".

È possibile attivare o disattivare la modalità schermo intero quando viene visualizzata la tastiera virtuale. Ciò consente a "adjustPan" di funzionare correttamente.

In altre parole, uso ancora @android: style / Theme.Black.NoTitleBar.Fullscreen come parte del tema dell'applicazione e stateVisible | AdjustResize come parte della modalità di input soft della finestra attività ma per farli lavorare insieme devo attivare la modalità a schermo intero prima che arrivi la tastiera.

Usa il seguente codice:

Disattiva la modalità a schermo intero

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

Attiva la modalità a schermo intero

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

Nota: l'ispirazione è venuta da: Nascondere il titolo in modalità a schermo intero


1
Apprezzo che tu abbia dato tempo al problema, +1 per quello. Sicuramente testerò questo approccio e ti informerò presto se ha funzionato per me, grazie.
Vineet Shukla,

1
Funziona come sospettato! Davvero un'ottima soluzione! +1 dalla mia parte.
Mike,


1
la tastiera scatta, rendendo nero lo sfondo della tastiera. L'effetto snapping non sembra buono :(
nibz il

wow grazie ... funziona davvero bene combinando Workaround menzionato da AndroidBug5497Workaround ... Ho caricato la fonte combinata su GitHub ... github.com/CrandellWS/AndroidBug5497Workaround/blob/master/…
CrandellWS

23

Ho provato la soluzione di Joseph Johnson , ma come altri ho riscontrato il problema del gap tra contenuto e tastiera. Il problema si verifica perché la modalità di input soft è sempre panoramica quando si utilizza la modalità a schermo intero. Questa panoramica interferisce con la soluzione di Joseph quando si attiva un campo di input che sarebbe nascosto dall'input soft.

Quando viene visualizzato l'input software, il contenuto viene prima spostato in base alla sua altezza originale, quindi ridimensionato dal layout richiesto dalla soluzione di Joseph. Il ridimensionamento e il layout successivo non annullano il pan, il che si traduce in uno spazio vuoto. L'ordine completo degli eventi è:

  1. Listener di layout globale
  2. panoramica
  3. Layout del contenuto (= ridimensionamento effettivo del contenuto)

Non è possibile disabilitare la panoramica, ma è possibile forzare l'offset della panoramica su 0 modificando l'altezza del contenuto. Questo può essere fatto nel listener, perché viene eseguito prima che avvenga il panning. Impostando l'altezza del contenuto all'altezza disponibile si ottiene un'esperienza utente fluida, cioè senza sfarfallio.

Ho anche apportato queste modifiche. Se qualcuno di questi problemi presenta, fammi sapere:

  • Determinazione commutata dell'altezza disponibile da utilizzare getWindowVisibleDisplayFrame. IlRect viene memorizzato nella cache per evitare un po 'di spazzatura non necessari.
  • Consenti anche al listener di essere rimosso. Ciò è utile quando si riutilizza un'attività per frammenti diversi con requisiti a schermo intero diversi.
  • Non distinguere tra tastiera mostrata o nascosta, ma imposta sempre l'altezza del contenuto all'altezza del riquadro di visualizzazione visibile.

È stato testato su un Nexus 5 ed emulatori con livelli API 16-24 con dimensioni dello schermo che vanno da minuscole a grandi.

Il codice è stato portato su Kotlin, ma riportare le mie modifiche su Java è semplice. Fammi sapere se hai bisogno di aiuto:

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
Questa sembra essere la risposta migliore. Ho effettuato il porting su java qui gist.github.com/grennis/2e3cd5f7a9238c59861015ce0a7c5584 . Nota che stavo ottenendo eccezioni per cui l'osservatore non era vivo e dovevo verificare anche quello.
Greg Ennis,

Oh mio Dio! attraversando la gerarchia di tutte le viste di sistema alla ricerca di quello spazio fantasma. Ero vicino ai computer abbandonati per un camion di cibo ma ho visto la tua risposta all'ultimo minuto. Funziona :)
rupps

1
@Greg Ennis Grazie per la porta Java. Risparmiato un sacco di sforzi e tempo.
Ikun,

@GregEnnis, grazie, la tua soluzione funziona con onResume (), onPause (), onDestroy () (vedi commenti nel codice GitHub).
CoolMind,

Questo funziona per me, tranne per il fatto che la chiamata removeListener non sembra funzionare. Ho inserito i punti di interruzione sia nella possiblyResizeChildOfContentchiamata che nella removeListenerchiamata e, anche dopo aver toccato il removeListenerpunto di interruzione, possiblyResizeChildOfContentviene ancora chiamato. Qualcun altro ha questo problema?
Quinn,

14

Ho appena trovato una soluzione semplice e affidabile se stai usando l'approccio UI di sistema ( https://developer.android.com/training/system-ui/immersive.html ).

Funziona nel caso in cui si sta utilizzando View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN , ad esempio se si sta utilizzando CoordinatorLayout.

Non funzionerà per WindowManager.LayoutParams.FLAG_FULLSCREEN(quello con cui puoi anche impostare il tema android:windowFullscreen), ma puoi ottenere un effetto simile con SYSTEM_UI_FLAG_LAYOUT_STABLE(che "ha lo stesso effetto visivo" secondo i documenti ) e questa soluzione dovrebbe funzionare di nuovo.

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)

L'ho provato sul mio dispositivo con Marshmallow.

La chiave è che le tastiere software sono anche una delle finestre di sistema (come la barra di stato e la barra di navigazione), quindi la WindowInsetsspedizione inviata dal sistema contiene informazioni accurate e affidabili al riguardo.

Per il caso d'uso come in DrawerLayout cui stiamo provando a disegnare dietro la barra di stato, possiamo creare un layout che ignori solo l'inserto superiore e applichi l'inserto inferiore che rappresenta la tastiera software.

Ecco la mia abitudine 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 per 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>

Questo dovrebbe teoricamente funzionare per qualsiasi dispositivo senza modifiche folli, molto meglio di qualsiasi hack che provi a prendere una dimensione casuale 1/3o 1/4di schermo come riferimento.

(Richiede API 16+, ma sto usando lo schermo intero solo su Lollipop + per disegnare dietro la barra di stato, quindi è la soluzione migliore in questo caso.)


@Dilip Funziona su API 16+, purché siano soddisfatte le condizioni di cui sopra.
Hai Zhang,

10

Si noti che android:windowSoftInputMode="adjustResize"non funziona quando WindowManager.LayoutParams.FLAG_FULLSCREENè impostato per un'attività. Hai due opzioni.

  1. Disattiva la modalità a schermo intero per la tua attività. L'attività non viene ridimensionata in modalità schermo intero. Puoi farlo in XML (modificando il tema dell'attività) o nel codice Java. Aggiungi le seguenti righe nel tuo metodo onCreate ().

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

O

  1. Utilizzare un modo alternativo per ottenere la modalità a schermo intero. Aggiungi il seguente codice nel tuo metodo 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);`

Si noti che il metodo 2 funziona solo su Android 4.1 e versioni successive.


@AnshulTyagi method-2 funziona solo su Android 4.1 e versioni successive.
Abhinav Chauhan,

4
Testato su 5.0 e 4.4.2, Nexus 9 e Samsung s4 rispettivamente, il 2o metodo non funziona.
RobVoisey,

1
Il secondo metodo semplicemente non funziona e ho perso molto tempo.
Greg Ennis,

Grazie, salva la mia giornata.
Deni Rohimat,

9

Ho dovuto affrontare anche questo problema e ho avuto un lavoro intorno al quale ho controllato su HTC one, galaxy s1, s2, s3, note e sensazione HTC.

mettere un listener di layout globale nella vista principale del layout

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

e lì ho controllato la differenza di altezza e se la differenza di altezza dello schermo è maggiore di un terzo dell'altezza dello schermo, possiamo supporre che la tastiera sia aperta. preso da questa risposta .

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

questo probabilmente non è a prova di proiettile e forse su alcuni dispositivi non funzionerà ma ha funzionato per me e spero che possa aiutare anche te.


1
Aveva bisogno di alcuni aggiustamenti, ma ha funzionato. Nel Nexus 7 2013 ho dovuto ridurre l'altezza della tastiera (screenHeight / 3) di alcuni pixel. Bella idea, grazie!
Joao Sousa,

7

Ho implementato la soluzione Joseph Johnson e ha funzionato bene, ho notato che dopo aver usato questa soluzione a volte il cassetto sull'applicazione non si chiudeva correttamente. Ho aggiunto una funzionalità per rimuovere il listener removeOnGlobalLayoutListener quando l'utente chiude il frammento in cui si trovano gli edittexts.

    //when the application uses full screen theme and the keyboard is shown the content not scrollable! 
//with this util it will be scrollable once again
//http://stackoverflow.com/questions/7417123/android-how-to-adjust-layout-in-full-screen-mode-when-softkeyboard-is-visible
public class AndroidBug5497Workaround {


    private static AndroidBug5497Workaround mInstance = null;
    private View mChildOfContent;
    private int usableHeightPrevious;
    private FrameLayout.LayoutParams frameLayoutParams;
    private ViewTreeObserver.OnGlobalLayoutListener _globalListener;

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

    public static AndroidBug5497Workaround getInstance (Activity activity) {
        if(mInstance==null)
        {
            synchronized (AndroidBug5497Workaround.class)
            {
                mInstance = new AndroidBug5497Workaround(activity);
            }
        }
        return mInstance;
    }

    private AndroidBug5497Workaround(Activity activity) {
        FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);
        mChildOfContent = content.getChildAt(0);
        frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();

        _globalListener = new ViewTreeObserver.OnGlobalLayoutListener()
        {

            @Override
            public void onGlobalLayout()
            {
                 possiblyResizeChildOfContent();
            }
        };
    }

    public void setListener()
    {
         mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(_globalListener);
    }

    public void removeListener()
    {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            mChildOfContent.getViewTreeObserver().removeOnGlobalLayoutListener(_globalListener);
        } else {
            mChildOfContent.getViewTreeObserver().removeGlobalOnLayoutListener(_globalListener);
        }
    }

    private void possiblyResizeChildOfContent() {
        int usableHeightNow = computeUsableHeight();
        if (usableHeightNow != usableHeightPrevious) {
            int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();
            int heightDifference = usableHeightSansKeyboard - usableHeightNow;
            if (heightDifference > (usableHeightSansKeyboard/4)) {
                // keyboard probably just became visible
                frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
            } else {
                // keyboard probably just became hidden
                frameLayoutParams.height = usableHeightSansKeyboard;
            }
            mChildOfContent.requestLayout();
            usableHeightPrevious = usableHeightNow;
        }
    }

    private int computeUsableHeight() {
        Rect r = new Rect();
        mChildOfContent.getWindowVisibleDisplayFrame(r);
        return (r.bottom - r.top);
    } 
}

usa la classe in cui si trova il mio edittexts

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

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

7

Aggiungi android:fitsSystemWindows="true"al layout e questo layout verrà ridimensionato.


Questo è ciò che ha risolto per me. Inoltre, assicurati di impostarlo sulla vista giusta. Se hai uno sfondo che dovrebbe andare sotto la barra di stato, non impostarlo lì, ma su un layout all'interno. Probabilmente le viste EditText ecc. Dovrebbero essere all'interno del secondo layout all'interno. Guarda anche questo discorso, in quanto rende le cose più chiare: youtube.com/watch?v=_mGDMVRO3iE
Stan,

Ha funzionato anche per me. Grazie al commento @Stan sono stato anche in grado di farlo funzionare con il tema FULLSCREEN posizionando quell'attributo sul ViewPager anziché sul layout di attività / frammento.
marcouberti

5

Per farlo funzionare con FullScreen:

Usa il plugin della tastiera ionica. Ciò ti consente di ascoltare quando appare e scompare la tastiera.

OnDeviceReady aggiungi questi listener di eventi:

// 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 logica:

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

Fondamentalmente se la loro differenza è meno, allora è la quantità di pixel che copre la tastiera del tuo input. Quindi, se modifichi il div del tuo genitore con questo, dovresti contrastarlo.

L'aggiunta di timeout alla logica indica che 300 ms dovrebbero anche ottimizzare le prestazioni (poiché ciò consentirà di visualizzare il tempo della tastiera.


3

Ho provato la lezione di Joseph Johnson, e ha funzionato, ma non ha soddisfatto le mie esigenze. Invece di emulare android: windowSoftInputMode = "AdjustResize", dovevo emulare android: windowSoftInputMode = "AdjustPan".

Lo sto usando per una visualizzazione web a schermo intero. Per spostare la visualizzazione del contenuto nella posizione corretta, ho bisogno di utilizzare un'interfaccia javascript che fornisca dettagli sulla posizione dell'elemento della pagina che ha lo stato attivo e quindi riceve l'input da tastiera. Ho omesso quei dettagli, ma ho fornito la mia riscrittura della lezione di Joseph Johnson. Ti fornirà una base molto solida per implementare una panoramica personalizzata rispetto al suo ridimensionamento.

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

}

sembra essere quello di cui ho bisogno, potresti per favore aggiungere un campione completo? grazie per il tuo lavoro!
vilicvane,

Non volevo pubblicare un intero progetto. Ciò che ti ho fornito ti porterà molto lontano verso una soluzione perfettamente funzionante. Cosa devi definire tu stesso: crea una classe "JavaScriptObject" e iniettala nella tua webview come interfaccia js (controlla la documentazione della webview per questo). Ci sono già buone probabilità che tu l'abbia già fatto se scrivi qualcosa che utilizza una visualizzazione Web in modo completo. Aggiungi JavaScript nella visualizzazione Web per ascoltare gli eventi di messa a fuoco e inserire i dati nella tua classe JavaScriptObject sul posizionamento degli elementi di messa a fuoco.
BuvinJ

2

In effetti l'aspetto della tastiera soft non sembra influenzare Activityin alcun modo, indipendentemente da ciò windowSoftInputModeche seleziono nella FullScreenmodalità.

Sebbene non sia stato possibile trovare molta documentazione su questa proprietà, penso che la FullScreenmodalità sia stata progettata per applicazioni di gioco che non richiedono un uso eccessivo della tastiera software. Se la tua è un'attività che richiede l'interazione dell'utente tramite la tastiera software, ti preghiamo di riconsiderare utilizzando un tema non FullScreen. È possibile disattivare la barra del titolo utilizzando un NoTitleBartema. Perché dovresti nascondere la barra delle notifiche?


2

Continua come android:windowSoftInputMode="adjustResize". Perché è dato per mantenere solo uno fuori "adjustResize"e "adjustPan"(La modalità di regolazione della finestra è specificata con AdjustResize o AdjustPan. Si consiglia vivamente di specificare sempre l'uno o l'altro). Puoi trovarlo qui: http://developer.android.com/resources/articles/on-screen-inputs.html

Funziona perfettamente per me.


Non sto riscontrando alcun problema ... Ho provato anche il tuo XML. Anche questo funziona ... sto usando Os versione 2.2
Balaji Khadake,

Ho provato solo con la modalità a schermo intero ... m testandolo sul mio Nexus One e Nexus S .... Funziona.
Balaji Khadake,

1
Ho provato con Galaxy S, HTC Wildfire, HTC Hero, Motorola Deify e Sony XPeria. Non funziona su nessun singolo dispositivo.
Vineet Shukla,


2

Attualmente sto usando questo approccio e funziona come un fascino. Il trucco è che otteniamo l' altezza della tastiera da diversi metodi su 21 sopra e sotto e quindi usiamola come riempimento inferiore della nostra vista radice nella nostra attività. Presumo che il tuo layout non abbia bisogno di un'imbottitura superiore (va sotto la barra di stato) ma, nel caso, informami per aggiornare la mia risposta.

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

Non dimenticare di indirizzare la vista radice con un 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">

Spero che aiuti qualcuno.


1
Non riesco a capire, perché questa risposta non è ancora in cima. Che gli altri glitch, flash, ma questo è geniale, specialmente se hai 5+ api.
Anton Shkurenko,

1

usa solo android:windowSoftInputMode="adjustResize|stateHiddenmentre usi AdjustPan, quindi disabilita la proprietà di ridimensionamento


L'ho usato anch'io .... ti prego di farlo in modalità a schermo intero e su quale dispositivo stai testando?
Vineet Shukla,

HTC NEXUS uno, ok ho aggiunto schermo intero
Mohammed Azharuddin Shaikh

puoi usare getWindow (). requestFeature (Window.FEATURE_NO_TITLE); onCreate () invece usa il tema?
Mohammed Azharuddin Shaikh,

10
il codice sopra funziona senza schermo intero ma aggiungendo schermo intero da XML o da codice ... Non funziona ... Leggere attentamente la domanda.
Vineet Shukla,

1

Ho usato Joseph Johnson creato AndroidBug5497Workaround class ma ottenendo uno spazio nero tra la tastiera e la vista. Ho indicato questo link Greg Ennis . Dopo aver apportato alcune modifiche a quanto sopra, questo è il mio codice di lavoro finale.

 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

basato su https://stackoverflow.com/a/19494006/1815624 e desiderio di farlo accadere ...

idea aggiornata


combinando le risposte di

Codice pertinente:

        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 su https://github.com/CrandellWS/AndroidBug5497Workaround/blob/master/AndroidBug5497Workaround.java

vecchia idea

Creare un valore statico dell'altezza del contenitore prima di aprire la tastiera Impostare l'altezza del contenitore in base usableHeightSansKeyboard - heightDifferenceall'apertura della tastiera e riportarla al valore salvato quando si chiude

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

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

    });

}

Esempio di contenitore 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">

allo stesso modo è possibile aggiungere margini se necessario ...

Un'altra considerazione è l'uso del riempimento, un esempio di questo può essere trovato su:

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


1

1) Crea 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) Lascia che la tua attività sia a schermo intero:

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

3) Ascolta le modifiche dell'altezza della tastiera e aggiungi un'imbottitura inferiore per la visualizzazione:

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

Quindi , ogni volta che la tastiera apparirà sullo schermo - il padding inferiore per la tua vista cambierà e il contenuto verrà riorganizzato.


0

Vuoi che la barra in basso si attacchi alla parte inferiore della vista, ma quando viene visualizzata la tastiera, dovrebbero spostarsi verso l'alto per essere posizionati sopra la tastiera, giusto?

Puoi provare questo frammento di codice:

<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 inferiore si attaccherà nella parte inferiore della vista e il LinearLayout contenente lo ScrollView prenderà ciò che resta della vista dopo la visualizzazione della barra superiore / inferiore e della tastiera. Fammi sapere se funziona anche per te.


1
Molto strano come ha funzionato più volte nelle mie app. A proposito, RelativeLayout non ha orientamento, quindi puoi eliminare questi attributi nel tuo codice. Ho appena riconosciuto che avrei potuto ridurre lo snippet di codice sulla riga: android: layout_below = "@ + id / scoringContainerView" che devi aggiungere a ScrollView
banzai86,

A schermo intero? Intendi senza un layout in alto?
banzai86,

no ..... Voglio dire nessuna barra di stato che mostra la durata della batteria, la connettività per il dispositivo ecc ....
Vineet Shukla,

no, la barra di stato è visibile nella mia app. puoi provare a cambiare l'ordine dei tuoi layout, il che significa che inserisci il codice per il tuo layout con i pulsanti sopra l'altro codice e poi riprova? forse devi prima definirli per usare layout_below
banzai86,

1
per favore leggi attentamente la domanda ...... Ho menzionato che sto avendo problemi con la modalità a schermo intero ......
Vineet Shukla,

0

Grazie Giuseppe per la tua risposta. Tuttavia, nel metodo eventualmenteResizeChildOfContent (), la porzione

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

non funzionava per me, poiché la parte inferiore della vista veniva nascosta. Quindi ho dovuto eseguire un ripristino della variabile globaleHeight e nel costruttore ho inserito l'ultima riga

restoreHeight = frameLayoutParams.height;

e poi ho sostituito la parte precedentemente menzionata con

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

Ma non ho idea del perché il tuo codice non abbia funzionato per me. Sarebbe di grande aiuto se qualcuno potesse far luce su questo.


0

Stavo solo usando la modalità a schermo intero per nascondere la barra di stato. Tuttavia, desidero ridimensionare l'app quando viene visualizzata la tastiera. Tutte le altre soluzioni (probabilmente a causa dell'età dei post) erano complicate o non possibili per il mio uso (voglio evitare di cambiare il codice Java per il sacco di PhoneGap Build).

Invece di utilizzare lo schermo intero, ho modificato la mia configurazione per Android in modo che non fosse a schermo intero:

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

E aggiunto il cordova-plugin-statusbar, tramite riga di comando:

cordova plugin add cordova-plugin-statusbar

Quando l'app è stata caricata, chiamo semplicemente un metodo sul plug-in per nascondersi, come:

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

Funziona come un fascino. L'unico aspetto negativo è che la barra di stato è facilmente visibile mentre l'app viene caricata. Per le mie esigenze, non è stato un problema.


0

Ho provato tutte le possibili risposte da stackOverflow, finalmente ho risolto dopo una settimana di ricerca lunga. Ho usato il layout delle coordinate e l'ho modificato con linearLayout e il mio problema è stato risolto. Probabilmente non so che il layout delle coordinate ha dei bug o qualcos'altro del mio errore.


0

Ho provato molte soluzioni tra cui Joseph Johnson e Johan Stuyts. Ma di conseguenza ho ottenuto uno spazio bianco tra contenuto e tastiera su alcuni dispositivi (come Lenovo s820) in tutti i casi. Quindi ho apportato alcune modifiche ai loro codici e finalmente ho ottenuto una soluzione funzionante.

La mia idea si basa sull'aggiunta di margine all'inizio del contenuto quando viene mostrata la tastiera.

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

Come puoi vedere, aggiungo 30 px alla differenza perché c'è un piccolo spazio bianco tra la parte superiore dello schermo e l'area di contenuto con margine. E non so da dove appaia, quindi ho deciso di ridurre i margini e ora funziona esattamente come mi serviva.


0

Oggi non funziona AdjustResize sul problema dello schermo intero è reale per Android SDK.

Dalle risposte che ho trovato:
la soluzione - ma la soluzione presenta questo problema con l'immagine:

Quindi ho trovato la soluzione e ho rimosso l'unica azione non necessaria:

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

Quindi, vedi il mio codice di soluzione fissa su 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
        }
    }
}

Il mio codice dell'attrezzo per la correzione di 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

Non usare:

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

perché funziona male. Invece, usa:

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

Nel mio caso, questo problema è iniziato quando ho aggiunto Crosswalk alla mia applicazione Cordova. La mia app non viene utilizzata a schermo intero e Android: windowSoftInputMode = "AdjustPan".

Avevo già il plug-in ionico della tastiera nell'applicazione, quindi rilevare se la tastiera era su o giù era facile grazie ad esso:

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

Ho provato tutte le correzioni sopra, ma la semplice linea che ha finito per farlo per me era questo pezzo di CSS:

&.keyboardUp {
        overflow-y: scroll;
}

Spero che questo ti salvi i pochi giorni che ho trascorso su questo. :)


Sto usando Crosswalk con Cordova e anche con Android: windowSoftInputMode = "AdjustPan". Tuttavia, non funziona. Vedo che la classe viene aggiunta all'elemento html, ma il CSS non ha alcun effetto sullo schermo. Esistono altre impostazioni che consentono lo spostamento dello schermo?
disastro

Devo impostare la trasformazione add: translateY (0px) affinché funzioni. Tuttavia, lo scorrimento non funziona affatto. Qualche idea?
disastro
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.