Android Comment régler la disposition en mode plein écran lorsque le clavier virtuel est visible

178

J'ai beaucoup recherché pour ajuster la mise en page lorsque le clavier logiciel est actif et je l'ai implémenté avec succès, mais le problème survient lorsque j'utilise android:theme="@android:style/Theme.NoTitleBar.Fullscreen"cette balise d'activité dans le fichier manifeste.

Pour cela, j'ai utilisé android:windowSoftInputMode="adjustPan|adjustResize|stateHidden"différentes options mais pas de chance.

Après cela, j'ai implémenté par FullScreenprogramme et essayé différentes mises en page avec lesquelles travailler, FullScreenmais en vain.

J'ai fait référence à ces liens et j'ai consulté de nombreux articles liés à ce problème:

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/

Voici le code 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>

entrez la description de l'image ici

Je veux que les 2 boutons inférieurs montent lorsque le clavier virtuel apparaît.

entrez la description de l'image ici

Vineet Shukla
la source
1
Je pense que vous devez ajouter des boutons à l'intérieur de ScrollView et sous EditText.
Balaji Khadake le
J'ai déjà essayé de nombreuses options qui ne fonctionnent pas ...
Vineet Shukla
1
mettre vos boutons dans un framelayout et régler le poids du framelayout à 1 et enfin utiliser seulement android:windowSoftInputMode="adjustPan"dites-moi si ce travail ..
Sherif elKhatib
@VineetShukla avez-vous trouvé un entraînement en plein écran ??
Muhammad Babar le
2
Notez que vous ne devez pas utiliser adjustResizeet adjustPanen même temps, à partir du javadoc de android.view.WindowManager.LayoutParams#SOFT_INPUT_ADJUST_RESIZE: "Cela ne peut pas être combiné avec {@link SOFT_INPUT_ADJUST_PAN}"
Denis Kniazhev

Réponses:

257

Sur la base de la solution de contournement de yghm, j'ai codé une classe de commodité qui me permet de résoudre le problème avec une ligne unique (après avoir ajouté la nouvelle classe à mon code source bien sûr). Le one-liner est:

     AndroidBug5497Workaround.assistActivity(this);

Et la classe d'implémentation est:


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

J'espère que cela aide quelqu'un.

Joseph Johnson
la source
8
Merci! Je ne sais pas pourquoi, mais j'ai dû remplacer return (r.bottom - r.top); par return r.bottompour le faire fonctionner sur mon HTC One Mini, sinon la vue d'activité serait poussée trop haut par la taille de la barre d'état. Cependant, je ne l'ai pas encore testé sur un autre appareil. J'espère que cela peut aider.
Joan le
4
Salut Joseph Johnson, j'ai utilisé votre code et cela a parfaitement fonctionné. Mais aujourd'hui, face à un problème sur certains petits appareils, il montre l'écart (écran vide) entre le clavier et la disposition. Avez-vous une idée de ce problème? J'ai aussi essayé de retourner r.bottom.
Pankaj du
2
Joseph Johnson: J'ai implémenté votre méthode, elle fonctionne très bien lorsque nous cliquons sur le texte d'édition du haut, mais lorsque nous cliquons sur edittext en bas, tout le design monte
ranjith
3
Malheureusement, cela ne fonctionne pas sur Nexus 7 (2013). Il effectue toujours un panoramique même avec le réglage AdjustNothing.
Le-roy Staines
4
Super réponse, merci beaucoup. Cela fonctionne sur un Nexus 6, mais au lieu d'utiliser, frameLayoutParams.height = usableHeightSansKeyboard;je dois utiliser frameLayoutParams.height = usableHeightNow; Si je ne le fais pas, certains éléments tombent en dehors de l'écran.
RobertoAllende
37

Étant donné que la réponse a déjà été choisie et que le problème est connu pour être un bogue, j'ai pensé ajouter un "Contournement possible".

Vous pouvez basculer en mode plein écran lorsque le clavier virtuel est affiché. Cela permet à "AdjustPan" de fonctionner correctement.

En d'autres termes, j'utilise toujours @android: style / Theme.Black.NoTitleBar.Fullscreen dans le cadre du thème de l'application et stateVisible | AdjustResize dans le cadre du mode de saisie de la fenêtre d'activité, mais pour les faire fonctionner ensemble, je dois basculer en mode plein écran avant que le clavier ne se lève.

Utilisez le code suivant:

Désactiver le mode plein écran

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

Activer le mode plein écran

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

Remarque - l'inspiration est venue de: Masquage du titre en mode plein écran

LEO
la source
1
J'apprécie que vous ayez accordé du temps au problème, +1 pour cela. Je vais certainement tester cette approche et vous faire savoir bientôt si cela a fonctionné pour moi, merci.
Vineet Shukla
1
Fonctionne comme on le soupçonne! Vraiment bonne solution! +1 de mon côté.
Mike
1
le clavier s'enclenche, rendant le fond du clavier noir. L'effet d'accrochage ne semble pas bon :(
nibz
wow merci ... cela fonctionne très bien pour moi en combinant la solution de contournement mentionnée par AndroidBug5497Workaround ... J'ai téléchargé la source combinée sur GitHub ... github.com/CrandellWS/AndroidBug5497Workaround/blob/master/…
CrandellWS
23

J'ai essayé la solution de Joseph Johnson , mais comme d'autres, j'ai rencontré le problème de l'écart entre le contenu et le clavier. Le problème se produit car le mode d'entrée logicielle est toujours panoramique lors de l'utilisation du mode plein écran. Ce panoramique interfère avec la solution de Joseph lorsque vous activez un champ de saisie qui serait masqué par l'entrée logicielle.

Lorsque l'entrée logicielle apparaît, le contenu est d'abord déplacé en fonction de sa hauteur d'origine, puis redimensionné selon la mise en page demandée par la solution de Joseph. Le redimensionnement et la mise en page ultérieure n'annulent pas le panoramique, ce qui entraîne un écart. L'ordre complet des événements est:

  1. Écouteur de disposition globale
  2. Panoramique
  3. Mise en page du contenu (= redimensionnement réel du contenu)

Il n'est pas possible de désactiver le panoramique, mais il est possible de forcer le décalage du panoramique à 0 en modifiant la hauteur du contenu. Cela peut être fait dans l'écouteur, car il est exécuté avant le panoramique. Le réglage de la hauteur du contenu à la hauteur disponible permet une expérience utilisateur fluide, c'est-à-dire sans scintillement.

J'ai également apporté ces modifications. Si l'un de ces problèmes pose problème, faites-le moi savoir:

  • Détermination commutée de la hauteur disponible à utiliser getWindowVisibleDisplayFrame. Le Rectest mis en cache pour éviter un peu de déchets inutiles.
  • Autorisez également l'auditeur à être supprimé. Cela est utile lorsque vous réutilisez une activité pour différents fragments ayant des exigences de plein écran différentes.
  • Ne faites pas la distinction entre le clavier affiché ou masqué, mais définissez toujours la hauteur du contenu sur la hauteur du cadre d'affichage visible.

Il a été testé sur un Nexus 5 et des émulateurs exécutant des niveaux d'API 16 à 24 avec des tailles d'écran allant de petit à grand.

Le code a été porté sur Kotlin, mais le portage de mes modifications vers Java est simple. Dis-moi si tu as besoin d'aide:

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
        }
    }
}
Johan Stuyts
la source
9
Cela semble être la meilleure réponse. J'ai porté sur java ici gist.github.com/grennis/2e3cd5f7a9238c59861015ce0a7c5584 . Remarquez que je recevais des exceptions indiquant que l'observateur n'était pas en vie et que je devais également le vérifier.
Greg Ennis
Oh mon Dieu! parcouru toute la hiérarchie des vues système à la recherche de cet espace Ghost. J'étais sur le point d'abandonner les ordinateurs pour un food truck mais j'ai vu votre réponse à la dernière minute. Ça marche :)
rupps
1
@Greg Ennis Merci pour le port Java. Économisé beaucoup d'efforts et de temps.
Ikun
@GregEnnis, merci, votre solution fonctionne avec onResume (), onPause (), onDestroy () (voir les commentaires dans le code GitHub).
CoolMind
Cela fonctionne pour moi, sauf que l'appel removeListener ne semble pas fonctionner. J'ai mis des points d'arrêt à la fois dans l' possiblyResizeChildOfContentappel et dans l' removeListenerappel, et même après avoir atteint le removeListenerpoint d'arrêt, il possiblyResizeChildOfContentest toujours appelé. Quelqu'un d'autre a-t-il ce problème?
Quinn
14

Je viens de trouver une solution simple et fiable si vous utilisez l'approche de l'interface utilisateur système ( https://developer.android.com/training/system-ui/immersive.html ).

Cela fonctionne dans le cas où vous utilisez View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN, par exemple si vous utilisez CoordinatorLayout.

Cela ne fonctionnera pas pour WindowManager.LayoutParams.FLAG_FULLSCREEN(celui android:windowFullscreenavec SYSTEM_UI_FLAG_LAYOUT_STABLElequel vous pouvez également définir le thème ), mais vous pouvez obtenir un effet similaire avec (qui "a le même effet visuel" selon la documentation ) et cette solution devrait fonctionner à nouveau.

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)

Je l'ai testé sur mon appareil exécutant Marshmallow.

La clé est que les claviers programmables sont également l'une des fenêtres du système (comme la barre d'état et la barre de navigation), de sorte que le WindowInsetssystème distribué par le système contient des informations précises et fiables à ce sujet.

Pour le cas d'utilisation comme celui DrawerLayoutoù nous essayons de dessiner derrière la barre d'état, nous pouvons créer une mise en page qui ignore uniquement l'encart supérieur et applique l'encart inférieur qui tient compte du clavier logiciel.

Voici ma coutume 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);
        }
    }
}

Et pour l'utiliser:

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

Cela devrait théoriquement fonctionner pour tout appareil sans modification insensée, bien mieux que tout piratage qui tente de prendre une taille d'écran aléatoire 1/3ou 1/4de référence.

(Cela nécessite l'API 16+, mais j'utilise le plein écran uniquement sur Lollipop + pour dessiner derrière la barre d'état, c'est donc la meilleure solution dans ce cas.)

Hai Zhang
la source
@Dilip Cela fonctionne sur l'API 16+, à condition que les conditions susmentionnées soient remplies.
Hai Zhang
10

Veuillez noter que android:windowSoftInputMode="adjustResize"cela ne fonctionne pas lorsque WindowManager.LayoutParams.FLAG_FULLSCREENest défini pour une activité. Vous avez deux options.

  1. Soit désactiver le mode plein écran pour votre activité. L'activité n'est pas redimensionnée en mode plein écran. Vous pouvez le faire soit en xml (en changeant le thème de l'activité) soit en code Java. Ajoutez les lignes suivantes dans votre méthode onCreate ().

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

OU

  1. Utilisez un autre moyen pour atteindre le mode plein écran. Ajoutez le code suivant dans votre méthode 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);`

Veuillez noter que la méthode 2 ne fonctionne que sous Android 4.1 et supérieur.

Abhinav Chauhan
la source
@AnshulTyagi method-2 ne fonctionne que sous Android 4.1 et supérieur.
Abhinav Chauhan
4
Testée sur 5.0 et 4.4.2, Nexus 9 et Samsung s4 respectivement, la 2ème méthode ne fonctionne pas.
RobVoisey
1
La 2ème méthode ne fonctionne tout simplement pas et j'ai perdu beaucoup de temps dessus.
Greg Ennis
Merci, sauve ma journée.
Deni Rohimat le
9

J'ai dû faire face à ce problème aussi et j'ai eu un travail autour duquel j'ai vérifié sur HTC One, Galaxy s1, s2, s3, note et HTC sensation.

mettre un écouteur de mise en page globale sur la vue racine de votre mise en page

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

et là-dedans, j'ai vérifié la différence de hauteur et si la différence de hauteur de l'écran est plus grande qu'un tiers de la hauteur de l'écran, nous pouvons supposer que le clavier est ouvert. l'a pris de cette réponse .

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

ce n'est probablement pas à l'épreuve des balles et peut-être que sur certains appareils, cela ne fonctionnera pas mais cela a fonctionné pour moi et j'espère que cela vous aidera aussi.

yghm
la source
1
Besoin de quelques ajustements, mais cela a fonctionné. Dans le Nexus 7 2013, j'ai dû diminuer la hauteur du clavier (screenHeight / 3) de quelques pixels. Bonne idée, merci!
Joao Sousa
7

J'ai implémenté la solution Joseph Johnson et cela a bien fonctionné, j'ai remarqué qu'après avoir utilisé cette solution, le tiroir de l'application ne se fermait pas correctement. J'ai ajouté une fonctionnalité pour supprimer l'écouteur removeOnGlobalLayoutListener lorsque l'utilisateur ferme le fragment où se trouvent les 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);
    } 
}

utilise la classe où se trouvent mes edittexts

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

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

Ajoutez android:fitsSystemWindows="true"à la mise en page, et cette mise en page sera redimensionnée.

Zayn
la source
C'est ce qui m'a résolu. De plus, assurez-vous de le définir sur la bonne vue. Si vous avez un arrière-plan qui devrait aller sous la barre d'état, ne le définissez pas ici, mais sur une disposition à l'intérieur. Les vues EditText, etc. devraient probablement être à l'intérieur de cette deuxième disposition. Regardez également cette conférence, car elle clarifie les choses: youtube.com/watch?v=_mGDMVRO3iE
Stan
A travaillé pour moi aussi. Grâce au commentaire @Stan, j'ai également pu le faire fonctionner avec le thème FULLSCREEN en plaçant cet attribut sur le ViewPager au lieu de la mise en page activité / fragment.
marcouberti
5

Pour le faire fonctionner avec FullScreen:

Utilisez le plugin de clavier ionique. Cela vous permet d'écouter quand le clavier apparaît et disparaît.

OnDeviceReady ajoute ces écouteurs d'événements:

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

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

Fondamentalement, si leur différence est moins, c'est la quantité de pixels que le clavier couvre de votre entrée. Donc, si vous ajustez votre div parent par cela, cela devrait le neutraliser.

L'ajout de délais d'attente à la logique dit que 300 ms devrait également optimiser les performances (car cela permettra au clavier d'apparaître.

tyler_mitchell
la source
3

J'ai essayé le cours de Joseph Johnson et cela a fonctionné, mais n'a pas tout à fait répondu à mes besoins. Plutôt que d'émuler android: windowSoftInputMode = "AdjustResize", j'avais besoin d'émuler android: windowSoftInputMode = "AdjustPan".

J'utilise ceci pour une vue Web en plein écran. Pour faire un panoramique de la vue de contenu à la bonne position, je dois utiliser une interface javascript qui fournit des détails sur la position de l'élément de page qui a le focus et qui reçoit donc l'entrée du clavier. J'ai omis ces détails, mais j'ai fourni ma réécriture de la classe de Joseph Johnson. Il vous fournira une base très solide pour implémenter un panoramique personnalisé par rapport à son redimensionnement.

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

}
BuvinJ
la source
semble être ce dont j'ai besoin, pourriez-vous s'il vous plaît ajouter un échantillon complet? merci pour votre travail!
vilicvane
Je ne cherchais pas à publier un projet entier. Ce que j'ai fourni vous apportera cependant un très long chemin vers une solution parfaitement fonctionnelle. Ce dont vous avez besoin pour vous définir: Créez une classe "JavaScriptObject" et injectez-la dans votre webview en tant qu'interface js (consultez la documentation webview pour cela). Il y a de fortes chances que vous ayez déjà fait cela si vous écrivez quelque chose qui utilise une vue Web de manière complète. Ajoutez JavaScript dans la vue Web pour écouter les événements de focus et pour alimenter votre classe JavaScriptObject sur le positionnement de l'élément de focus.
BuvinJ
2

En effet, l'apparence du clavier souple ne semble pas affecter le Activityen aucune façon, peu importe ce que windowSoftInputModeje sélectionne dans le FullScreenmode.

Bien que je n'ai pas pu trouver beaucoup de documentation sur cette propriété, je pense que le FullScreenmode a été conçu pour les applications de jeu qui ne nécessitent pas beaucoup d'utilisation du clavier logiciel. Si la vôtre est une activité qui nécessite une interaction de l'utilisateur via un clavier logiciel, veuillez reconsidérer l'utilisation d'un thème non plein écran. Vous pouvez désactiver la barre de titre à l'aide d'un NoTitleBarthème. Pourquoi voudriez-vous masquer la barre de notification?

Arnab Chakraborty
la source
2

Continuez comme ça android:windowSoftInputMode="adjustResize". Parce qu'il est donné de ne garder qu'un seul hors de "adjustResize"et "adjustPan"(Le mode de réglage de la fenêtre est spécifié avec AdjustResize ou AdjustPan. Il est fortement recommandé de toujours spécifier l'un ou l'autre). Vous pouvez le découvrir ici: http://developer.android.com/resources/articles/on-screen-inputs.html

Cela fonctionne parfaitement pour moi.

Balaji Khadake
la source
Je ne reçois aucun problème ... J'ai également essayé votre XML. Celui-ci fonctionne également..m en utilisant la version 2.2 d'Os
Balaji Khadake
J'ai essayé avec le mode plein écran seulement ... je le teste sur mon Nexus One et Nexus S .... Cela fonctionne.
Balaji Khadake
1
J'ai essayé avec Galaxy S, HTC wildfire, HTC Hero, Motorola Deify et Sony XPeria. Ne fonctionne pas sur un seul appareil.
Vineet Shukla
2

J'utilise actuellement cette approche et cela fonctionne comme un charme. L'astuce est que nous obtenons la hauteur du clavier du partir de différentes méthodes sur 21 ci-dessus et ci-dessous, puis nous l'utilisons comme remplissage inférieur de notre vue racine dans notre activité. J'ai supposé que votre mise en page n'avait pas besoin d'un rembourrage supérieur (va sous la barre d'état) mais dans le cas où vous le faites, informez-moi pour mettre à jour ma réponse.

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'oubliez pas d'adresser votre vue racine avec un identifiant:

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

J'espère que ça aide quelqu'un.

Sdghasemi
la source
1
Je ne comprends pas pourquoi cette réponse n'est toujours pas en tête. Que d'autres glitch, flash, mais celui-ci est génial, surtout si vous avez 5+ api.
Anton Shkurenko le
1

utilisez uniquement android:windowSoftInputMode="adjustResize|stateHiddenlorsque vous utilisez AdjustPan, puis désactivez la propriété de redimensionnement

Mohammed Azharuddin Shaikh
la source
Je l'ai aussi utilisé ... veuillez vous assurer que vous le faites en mode plein écran et sur quel appareil testez-vous?
Vineet Shukla
HTC NEXUS one, ok je hvnt ajouter le plein écran
Mohammed Azharuddin Shaikh
pouvez-vous utiliser getWindow (). requestFeature (Window.FEATURE_NO_TITLE); onCreate () à la place en utilisant le thème?
Mohammed Azharuddin Shaikh
10
le code ci-dessus fonctionne bien sans plein écran mais en ajoutant le plein écran soit à partir de xml soit à partir du code ... Cela ne fonctionne pas ... Veuillez lire attentivement la question.
Vineet Shukla
1

J'ai utilisé la classe AndroidBug5497Workaround créée par Joseph Johnson, mais j'ai obtenu un espace noir entre le clavier logiciel et la vue. J'ai référé ce lien à Greg Ennis . Après avoir apporté quelques modifications à ce qui précède, c'est mon code de travail 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);
  }
 }
}
Venkat
la source
1

basé sur https://stackoverflow.com/a/19494006/1815624 et le désir d'y arriver ...

idée mise à jour


combinant les réponses de

Code pertinent:

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

            }

Source complète sur https://github.com/CrandellWS/AndroidBug5497Workaround/blob/master/AndroidBug5497Workaround.java

vieille idée

Créer une valeur statique de la hauteur des conteneurs avant d'ouvrir le clavier Définir la hauteur du conteneur en fonction du usableHeightSansKeyboard - heightDifferencemoment où le clavier s'ouvre et la remettre à la valeur enregistrée lors de sa fermeture

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éthodes dans 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);
        }

    });

}

Exemple de conteneur XML

<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
        <android.support.constraint.ConstraintLayout
            android:id="@+id/my_container"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            app:layout_constraintHeight_percent=".8">

de même des marges peuvent être ajoutées si nécessaire ...

Une autre considération est d'utiliser le rembourrage.Un exemple de ceci peut être trouvé à:

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

CrandellWS
la source
1

1) Créez 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) Laissez votre activité en plein écran:

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

3) Écoutez les changements de hauteur du clavier et ajoutez un rembourrage inférieur pour votre vue:

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

Ainsi , à chaque fois que le clavier apparaîtra à l'écran, le remplissage inférieur de votre vue changera et le contenu sera réorganisé.

répéter
la source
0

Vous voulez que la barre du bas colle au bas de la vue, mais lorsque le clavier est affiché, ils doivent se déplacer vers le haut pour être placés au-dessus du clavier, non?

Vous pouvez essayer cet extrait de code:

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

Le BottomBar restera au bas de la vue et le LinearLayout contenant le ScrollView prendra ce qui reste de la vue après l'affichage de la barre supérieure / inférieure et du clavier. Faites-moi savoir si cela fonctionne également pour vous.

banzai86
la source
1
Très étrange car cela a fonctionné dans mes applications plusieurs fois. À propos, RelativeLayout n'a pas d'orientation, vous pouvez donc supprimer ces attributs dans votre code. Je viens de reconnaître que j'aurais pu réduire l'extrait de code à la ligne: android: layout_below = "@ + id / scoringContainerView" que vous devez ajouter à votre ScrollView
banzai86
Plein écran? Voulez-vous dire sans mise en page en haut?
banzai86
non ..... Je veux dire pas de barre d'état qui montre la durée de vie de la batterie, la connectivité de l'appareil, etc.
Vineet Shukla
non, la barre d'état est visible dans mon application. pouvez-vous essayer de changer l'ordre de vos mises en page, ce qui signifie que vous mettez le code de votre mise en page avec les boutons au-dessus de l'autre code, puis réessayez? peut-être que vous devez d'abord les définir pour utiliser le layout_below
banzai86
1
s'il vous plaît lire attentivement la question ...... J'ai mentionné que j'ai des problèmes avec le mode plein écran ......
Vineet Shukla
0

Merci Joseph pour ta réponse. Cependant, dans la méthode possiblementResizeChildOfContent (), la partie

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

ne fonctionnait pas pour moi, car la partie inférieure de la vue est devenue cachée. J'ai donc dû prendre une variable globale restoreHeight, et dans le constructeur, j'ai inséré la dernière ligne

restoreHeight = frameLayoutParams.height;

puis j'ai remplacé l'ancienne partie mentionnée par

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

Mais je ne sais pas pourquoi votre code n'a pas fonctionné pour moi. Ce serait d'une grande aide si quelqu'un pouvait faire la lumière à ce sujet.

Debanjan
la source
0

J'utilisais uniquement le mode plein écran pour masquer la barre d'état. Cependant, je souhaite que l'application se redimensionne lorsque le clavier est affiché. Toutes les autres solutions (probablement en raison de l'âge du poste) étaient compliquées ou impossibles pour mon utilisation (je veux éviter de changer le code Java pour le sac de PhoneGap Build).

Au lieu d'utiliser le plein écran, j'ai modifié ma configuration pour Android pour qu'elle ne soit pas en plein écran:

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

Et ajouté le cordova-plugin-statusbar, via la ligne de commande:

cordova plugin add cordova-plugin-statusbar

Une fois l'application chargée, j'appelle simplement une méthode sur le plugin pour se cacher, comme:

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

Cela fonctionne comme un charme. Le seul inconvénient est que la barre d'état est rapidement visible pendant le chargement de l'application. Pour mes besoins, ce n'était pas un problème.

raider33
la source
0

J'ai essayé toutes les réponses possibles de stackOverflow, finalement j'ai résolu après une semaine de recherche longue. J'ai utilisé la disposition des coordonnées et j'ai changé cela avec linearLayout et mon problème est résolu. Je ne sais pas si la disposition des coordonnées a des bogues ou quoi que ce soit de mon erreur.

yubaraj poudel
la source
0

J'ai essayé de nombreuses solutions, notamment celles de Joseph Johnson et Johan Stuyts. Mais en conséquence, j'ai un espace blanc entre le contenu et le clavier sur certains appareils (comme Lenovo s820) dans tous les cas. J'ai donc apporté quelques modifications à leurs codes et j'ai finalement obtenu une solution fonctionnelle.

Mon idée est basée sur l'ajout d'une marge en haut du contenu lorsque le clavier est affiché.

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

Comme vous pouvez le voir, j'ajoute 30 px à la différence car il y a un petit espace blanc entre le haut de l'écran et la zone de contenu avec marge. Et je ne sais pas d'où il apparaît, alors j'ai décidé de réduire simplement les marges et maintenant cela fonctionne exactement comme j'avais besoin.

IDmikael
la source
0

Aujourd'hui, le problème d'ajustement de la taille en mode plein écran ne fonctionne pas pour Android SDK.

À partir des réponses que j'ai trouvées:
la solution - mais la solution montre ce problème sur l'image:

Ensuite, j'ai trouvé la solution et supprimez la seule action inutile:

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

Alors, consultez mon code de solution fixe sur 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
        }
    }
}

Mon code d'implémentation de correction de bogue:

 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()
    }
}
Serg Burlaka
la source
0

N'utilisez pas:

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

parce que ça marche mal. Au lieu de cela, utilisez:

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)
    }
Alberto
la source
-1

Dans mon cas, ce problème a commencé à se produire une fois que j'ai ajouté Crosswalk à mon application Cordova. Mon application n'est pas utilisée en plein écran et sous Android: windowSoftInputMode = "AdjustPan".

J'avais déjà le plugin de clavier ionique dans l'application, donc détecter si le clavier était haut ou bas était facile grâce à lui:

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

J'ai essayé tous les correctifs ci-dessus, mais la ligne simple qui a fini par le faire pour moi était ce morceau de css:

&.keyboardUp {
        overflow-y: scroll;
}

J'espère que cela vous fera gagner les quelques jours que j'ai passés là-dessus. :)

JR
la source
J'utilise également Crosswalk avec Cordova avec Android: windowSoftInputMode = "AdjustPan". Cependant, cela ne fonctionne pas. Je vois que la classe est ajoutée à l'élément html, mais le css n'a aucun effet sur l'écran. Existe-t-il un autre paramètre qui permet à l'écran de se déplacer?
darewreck
Je dois définir la transformation add: translateY (0px) pour que cela fonctionne. Cependant, le défilement ne fonctionne pas du tout. Des idées?
darewreck