Android So passen Sie das Layout im Vollbildmodus an, wenn das Softkeyboard sichtbar ist


178

Ich habe viel recherchiert, um das Layout anzupassen, wenn das Softkeyboard aktiv ist, und ich habe es erfolgreich implementiert, aber das Problem tritt auf, wenn ich android:theme="@android:style/Theme.NoTitleBar.Fullscreen"dies in meinem Aktivitäts-Tag in der Manifest-Datei verwende.

Dafür habe ich android:windowSoftInputMode="adjustPan|adjustResize|stateHidden"mit verschiedenen Optionen aber kein Glück verwendet.

Danach habe ich FullScreenprogrammgesteuert implementiert und verschiedene Layouts ausprobiert, FullScreenaber alles umsonst.

Ich habe auf diese Links verwiesen und hier viele Beiträge zu diesem Thema gelesen:

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/

Hier ist XML-Code:

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

Geben Sie hier die Bildbeschreibung ein

Ich möchte, dass die unteren 2 Tasten nach oben gehen, wenn das Softkeyboard im Bild erscheint.

Geben Sie hier die Bildbeschreibung ein


1
Ich denke, Sie müssen Schaltflächen in ScrollView und unter EditText hinzufügen.
Balaji Khadake

Ich habe bereits viele Optionen ausprobiert, die nicht funktionieren ...
Vineet Shukla

1
Setzen Sie Ihre Knöpfe in ein Framelayout und setzen Sie das Gewicht des Framelayout auf 1 und verwenden Sie schließlich nur android:windowSoftInputMode="adjustPan"sagen Sie mir, ob dies funktioniert ..
Sherif elKhatib

@VineetShukla hast du irgendwelche Arbeiten mit Vollbild gefunden?
Muhammad Babar

2
Beachten Sie, dass Sie nicht verwenden sollten , adjustResizeund adjustPangleichzeitig an, von der javadoc von android.view.WindowManager.LayoutParams#SOFT_INPUT_ADJUST_RESIZE: „Das kann nicht mit {@link SOFT_INPUT_ADJUST_PAN} kombiniert werden“
Denis Kniazhev

Antworten:


256

Basierend auf der Problemumgehung von yghm habe ich eine Convenience-Klasse codiert, mit der ich das Problem mit einem Einzeiler lösen kann (natürlich nachdem ich die neue Klasse zu meinem Quellcode hinzugefügt habe). Der Einzeiler ist:

     AndroidBug5497Workaround.assistActivity(this);

Und die Implementierungsklasse ist:


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

Hoffe das hilft jemandem.


8
Vielen Dank! Ich habe keine Ahnung , warum, aber ich hatte zu ersetzen return (r.bottom - r.top); mit return r.bottomihm auf meinem HTC One Mini bekommen arbeiten, sonst wäre die Aktivitätsansicht zu hoch durch die Größe der Statusleiste geschoben werden. Ich habe es jedoch noch nicht auf einem anderen Gerät getestet. Hoffe das kann helfen.
Joan

4
Hallo Joseph Johnson, ich habe Ihren Code verwendet und er hat perfekt funktioniert. Aber heutzutage gibt es bei einigen kleinen Geräten ein Problem, bei dem die Lücke (leerer Bildschirm) zwischen Tastatur und Layout angezeigt wird. Haben Sie eine Idee zu diesem Thema? Ich habe auch versucht, r.bottom zurückzugeben.
Pankaj

2
Joseph Johnson: Ich habe Ihre Methode implementiert. Sie funktioniert einwandfrei, wenn wir auf den oberen Bearbeitungstext klicken, aber wenn wir auf den unteren Edittext klicken, geht das gesamte Design nach oben
Ranjith

3
Leider funktioniert es nicht auf Nexus 7 (2013). Es schwenkt auch mit adjustNothing noch.
Le-roy Staines

4
Tolle Antwort, vielen Dank. Es funktioniert auf einem Nexus 6, aber anstatt frameLayoutParams.height = usableHeightSansKeyboard;es zu verwenden, muss frameLayoutParams.height = usableHeightNow; ich es verwenden. Wenn ich dies nicht tue, fallen einige Elemente außerhalb des Bildschirms.
RobertoAllende

36

Da die Antwort bereits ausgewählt wurde und das Problem als Fehler bekannt ist, dachte ich, ich würde eine "mögliche Umgehung" hinzufügen.

Sie können den Vollbildmodus umschalten, wenn die Softtastatur angezeigt wird. Dadurch kann das "adjustPan" korrekt funktionieren.

Mit anderen Worten, ich verwende immer noch @android: style / Theme.Black.NoTitleBar.Fullscreen als Teil des Anwendungsthemas und stateVisible | adjustResize als Teil des Soft-Eingabemodus des Aktivitätsfensters, aber um sie zum Zusammenarbeiten zu bringen, muss ich den Vollbildmodus umschalten bevor die Tastatur hochkommt.

Verwenden Sie den folgenden Code:

Schalten Sie den Vollbildmodus aus

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

Aktivieren Sie den Vollbildmodus

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

Hinweis - Inspiration kam von: Titel im Vollbildmodus ausblenden


1
Ich schätze, dass Sie dem Problem Zeit gegeben haben, +1 dafür. Ich werde diesen Ansatz auf jeden Fall testen und Sie bald wissen lassen, ob er bei mir funktioniert hat, danke.
Vineet Shukla

1
Arbeitet wie vermutet! Wirklich gute Lösung! +1 von meiner Seite.
Mike


Die Tastatur rastet ein und der Tastaturhintergrund wird schwarz. Der Schnappeffekt sieht nicht gut aus :(
Nibz

wow danke ... es funktioniert wirklich gut für mich, wenn ich die von AndroidBug5497Workaround erwähnte Problemumgehung kombiniere ... Ich habe die kombinierte Quelle auf GitHub hochgeladen ... github.com/CrandellWS/AndroidBug5497Workaround/blob/master/…
CrandellWS

23

Ich habe die Lösung von Joseph Johnson ausprobiert , aber wie andere bin ich auf das Problem zwischen Inhalt und Tastatur gestoßen. Das Problem tritt auf, weil der weiche Eingabemodus immer pan , wenn Vollbild - Modus. Dieses Schwenken stört Josephs Lösung, wenn Sie ein Eingabefeld aktivieren, das von der weichen Eingabe ausgeblendet wird.

Wenn die weiche Eingabe angezeigt wird, wird der Inhalt zuerst anhand seiner ursprünglichen Höhe geschwenkt und dann anhand des von der Joseph-Lösung angeforderten Layouts in der Größe geändert. Die Größenänderung und das nachfolgende Layout machen das Schwenken nicht rückgängig, was zu einer Lücke führt. Die vollständige Reihenfolge der Ereignisse lautet:

  1. Globaler Layout-Listener
  2. Schwenken
  3. Layout des Inhalts (= tatsächliche Größenänderung des Inhalts)

Es ist nicht möglich, das Schwenken zu deaktivieren, aber es ist möglich, den Schwenkversatz durch Ändern der Höhe des Inhalts auf 0 zu setzen. Dies kann im Listener erfolgen, da es vor dem Schwenken ausgeführt wird. Das Einstellen der Inhaltshöhe auf die verfügbare Höhe führt zu einer reibungslosen Benutzererfahrung, dh ohne Flackern.

Ich habe diese Änderungen auch vorgenommen. Wenn eines dieser Probleme auftritt, lassen Sie es mich wissen:

  • Umgeschaltete Bestimmung der verfügbaren Höhe zu verwenden getWindowVisibleDisplayFrame. Das Rectwird zwischengespeichert, um ein wenig unnötigen Müll zu vermeiden.
  • Lassen Sie den Listener auch entfernen. Dies ist nützlich, wenn Sie eine Aktivität für verschiedene Fragmente mit unterschiedlichen Vollbildanforderungen wiederverwenden.
  • Unterscheiden Sie nicht zwischen angezeigter oder ausgeblendeter Tastatur, sondern stellen Sie die Höhe des Inhalts immer auf die sichtbare Höhe des Anzeigerahmens ein.

Es wurde auf einem Nexus 5 und Emulatoren mit API-Level 16-24 mit Bildschirmgrößen von klein bis groß getestet.

Der Code wurde nach Kotlin portiert, aber das Zurückportieren meiner Änderungen nach Java ist einfach. Lass es mich wissen falls du Hilfe benötigst:

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
Dies scheint die beste Antwort zu sein. Ich habe hier nach Java portiert . Gist.github.com/grennis/2e3cd5f7a9238c59861015ce0a7c5584 . Hinweis Ich habe Ausnahmen erhalten, dass der Beobachter nicht am Leben war, und musste dies auch überprüfen.
Greg Ennis

Oh mein Gott! Ich habe alle Hierarchien der Systemansichten durchlaufen und nach diesem Ghost-Bereich gesucht. Ich war kurz davor, Computer für einen Imbisswagen abzustellen, sah aber Ihre Antwort in letzter Minute. Es funktioniert :)
Rupps

1
@ Greg Ennis Danke für den Java Port. Spart viel Aufwand und Zeit.
Ikun

@ GregEnnis, danke, deine Lösung funktioniert mit onResume (), onPause (), onDestroy () (siehe Kommentare im GitHub-Code).
CoolMind

Dies funktioniert für mich, außer dass der Aufruf von removeListener nicht zu funktionieren scheint. Ich habe Haltepunkte sowohl in den possiblyResizeChildOfContentAnruf als auch in den removeListenerAnruf eingefügt, und selbst nachdem ich den removeListenerHaltepunkt erreicht habe, possiblyResizeChildOfContentwird immer noch aufgerufen. Hat noch jemand dieses Problem?
Quinn

13

Ich habe gerade eine einfache und zuverlässige Lösung gefunden, wenn Sie den System-UI-Ansatz verwenden ( https://developer.android.com/training/system-ui/immersive.html ).

Dies funktioniert in dem Fall, in dem Sie verwenden View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN, z. B. wenn Sie verwenden CoordinatorLayout.

Es funktioniert nicht für WindowManager.LayoutParams.FLAG_FULLSCREEN(das, mit dem Sie auch ein Thema festlegen können android:windowFullscreen), aber Sie können einen ähnlichen Effekt erzielen SYSTEM_UI_FLAG_LAYOUT_STABLE(der laut Dokumentation "den gleichen visuellen Effekt hat" ), und diese Lösung sollte wieder funktionieren.

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)

Ich habe es auf meinem Gerät mit Marshmallow getestet.

Der Schlüssel ist, dass Soft-Tastaturen auch eines der Systemfenster sind (wie Statusleiste und Navigationsleiste), sodass die WindowInsetsvom System versendeten Informationen genaue und zuverlässige Informationen darüber enthalten.

Für den Anwendungsfall, in DrawerLayoutdem wir versuchen, hinter die Statusleiste zu zeichnen, können wir ein Layout erstellen, das nur den oberen Einschub ignoriert und den unteren Einschub anwendet, der für die Softtastatur verantwortlich ist.

Hier ist mein Brauch 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);
        }
    }
}

Und um es zu benutzen:

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

Dies sollte theoretisch für jedes Gerät ohne verrückte Modifikation funktionieren, viel besser als jeder Hack, der versucht, eine zufällige 1/3oder 1/4Bildschirmgröße als Referenz zu verwenden.

(Es erfordert API 16+, aber ich verwende Vollbild nur auf Lollipop +, um hinter die Statusleiste zu zeichnen, daher ist dies in diesem Fall die beste Lösung.)


@Dilip Es funktioniert unter API 16+, sofern die oben genannten Bedingungen erfüllt sind.
Hai Zhang

10

Bitte beachten Sie, dass android:windowSoftInputMode="adjustResize"dies nicht funktioniert, wenn WindowManager.LayoutParams.FLAG_FULLSCREENes für eine Aktivität eingestellt ist. Sie haben zwei Möglichkeiten.

  1. Deaktivieren Sie entweder den Vollbildmodus für Ihre Aktivität. Die Aktivität wird im Vollbildmodus nicht in der Größe geändert. Sie können dies entweder in XML (durch Ändern des Themas der Aktivität) oder in Java-Code tun. Fügen Sie der onCreate () -Methode die folgenden Zeilen hinzu.

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

ODER

  1. Verwenden Sie eine alternative Methode, um den Vollbildmodus zu erreichen. Fügen Sie Ihrer onCreate () -Methode den folgenden Code hinzu.

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

Bitte beachten Sie, dass Methode 2 nur in Android 4.1 und höher funktioniert.


@AnshulTyagi Methode-2 funktioniert nur in Android 4.1 und höher.
Abhinav Chauhan

4
Getestet auf 5.0 und 4.4.2, Nexus 9 bzw. Samsung s4, funktioniert die 2. Methode nicht.
RobVoisey

1
Die 2. Methode funktioniert einfach nicht und ich habe viel Zeit damit verschwendet.
Greg Ennis

Danke, rette meinen Tag.
Deni Rohimat

9

Ich musste mich auch diesem Problem stellen und hatte eine Arbeit, um die ich HTC One, Galaxy S1, S2, S3, Note und HTC Sensation überprüfte.

Fügen Sie einen globalen Layout-Listener in die Stammansicht Ihres Layouts ein

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

und dort habe ich den Höhenunterschied überprüft und wenn der Höhenunterschied des Bildschirms größer ist als ein Drittel der Bildschirmhöhe, können wir davon ausgehen, dass die Tastatur geöffnet ist. nahm es aus dieser Antwort .

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

Dies ist wahrscheinlich nicht kugelsicher und auf einigen Geräten funktioniert es möglicherweise nicht, aber es hat bei mir funktioniert und ich hoffe, es wird Ihnen auch helfen.


1
Benötigte einige Anpassungen, aber es hat funktioniert. Im Nexus 7 2013 musste ich die Tastaturhöhe (screenHeight / 3) um einige Pixel verringern. Schöne Idee, danke!
Joao Sousa

7

Ich habe die Joseph Johnson-Lösung implementiert und sie hat gut funktioniert. Nach der Verwendung dieser Lösung wurde festgestellt, dass die Schublade in der Anwendung manchmal nicht richtig geschlossen wird. Ich habe eine Funktion hinzugefügt, um den Listener removeOnGlobalLayoutListener zu entfernen, wenn der Benutzer das Fragment schließt, in dem sich die Edittexte befinden.

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

verwendet die Klasse, in der sich meine Edittexte befinden

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

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

7

In android:fitsSystemWindows="true"dem Layout, und das Layout wird die Größe neu.


Das hat es für mich gelöst. Stellen Sie außerdem sicher, dass Sie die richtige Ansicht einstellen. Wenn Sie einen Hintergrund haben, der unterhalb der Statusleiste liegen soll, legen Sie ihn nicht dort fest, sondern in einem Layout im Inneren. Wahrscheinlich sollten sich EditText-Ansichten usw. in diesem zweiten Layout befinden. Sehen Sie sich auch diesen Vortrag an, da er die Dinge klarer macht: youtube.com/watch?v=_mGDMVRO3iE
Stan

Hat auch für mich gearbeitet. Dank des @ Stan-Kommentars konnte ich es auch mit dem FULLSCREEN-Design zum Laufen bringen, indem dieses Attribut anstelle des Aktivitäts- / Fragment-Layouts auf dem ViewPager platziert wurde.
Marcouberti

5

So funktioniert es mit FullScreen:

Verwenden Sie das ionische Tastatur-Plugin. Auf diese Weise können Sie abhören, wann die Tastatur angezeigt und ausgeblendet wird.

OnDeviceReady fügt diese Ereignis-Listener hinzu:

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

Die Logik:

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

Wenn der Unterschied minus ist, ist dies im Grunde die Anzahl der Pixel, die die Tastatur für Ihre Eingabe abdeckt. Wenn Sie also Ihr übergeordnetes Div dadurch anpassen, sollte dies dem entgegenwirken.

Durch Hinzufügen von Zeitüberschreitungen zur Logik, z. B. 300 ms, sollte auch die Leistung optimiert werden (da dadurch die Tastaturzeit angezeigt wird.


3

Ich habe Joseph Johnsons Unterricht ausprobiert und es hat funktioniert, aber meine Bedürfnisse wurden nicht ganz erfüllt. Anstatt android: windowSoftInputMode = "adjustResize" zu emulieren, musste ich android: windowSoftInputMode = "adjustPan" emulieren.

Ich verwende dies für eine Vollbild-Webansicht. Um die Inhaltsansicht auf die richtige Position zu verschieben, muss eine Javascript-Oberfläche verwendet werden, die Details zur Position des Seitenelements enthält, das den Fokus hat und somit die Tastatureingabe empfängt. Ich habe diese Details weggelassen, aber meine Umschreibung von Joseph Johnsons Klasse bereitgestellt. Es bietet Ihnen eine sehr solide Basis, um eine benutzerdefinierte Pfanne im Vergleich zu seiner Größenänderung zu implementieren.

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

}

scheint das zu sein, was ich brauche, könnten Sie bitte ein komplettes Muster hinzufügen? danke für deine arbeit!
Vilicvane

Ich wollte nicht ein ganzes Projekt veröffentlichen. Was ich bereitgestellt habe, wird Ihnen jedoch einen sehr langen Weg zu einer perfekt funktionierenden Lösung bringen. Was Sie selbst definieren müssen: Erstellen Sie eine "JavaScriptObject" -Klasse und fügen Sie sie als js-Schnittstelle in Ihre Webansicht ein (überprüfen Sie die Webview-Dokumentation dazu). Es besteht eine gute Chance, dass Sie dies bereits getan haben, wenn Sie etwas schreiben, das eine umfassende Webansicht verwendet. Fügen Sie der Webansicht JavaScript hinzu, um auf Fokusereignisse zu warten und Daten über die Positionierung des Fokuselements in Ihre JavaScriptObject-Klasse einzuspeisen.
BuvinJ

2

In der Tat scheint das Erscheinungsbild der Softtastatur das Activityin keiner Weise zu beeinflussen , egal was windowSoftInputModeich im FullScreenModus auswähle .

Obwohl ich zu dieser Eigenschaft nicht viel Dokumentation finden konnte, denke ich, dass der FullScreenModus für Spieleanwendungen entwickelt wurde, bei denen die Softtastatur nicht viel verwendet werden muss. Wenn es sich bei Ihrer Aktivität um eine Aktivität handelt, für die eine Benutzerinteraktion über eine Softtastatur erforderlich ist, überdenken Sie bitte die Verwendung eines Nicht-Vollbild-Themas. Sie können die Titelleiste mithilfe eines NoTitleBarThemas deaktivieren . Warum sollten Sie die Benachrichtigungsleiste ausblenden?


2

Einfach so bleiben android:windowSoftInputMode="adjustResize". Da nur eines von "adjustResize"und "adjustPan"ferngehalten werden soll (Der Fensteranpassungsmodus wird entweder mit adjustResize oder adjustPan angegeben. Es wird dringend empfohlen, immer das eine oder das andere anzugeben). Sie finden es hier: http://developer.android.com/resources/articles/on-screen-inputs.html

Es funktioniert perfekt für mich.


Ich bekomme kein Problem ... Ich habe auch Ihr XML ausprobiert. Dieser funktioniert auch..m mit Os Version 2.2
Balaji Khadake

Ich habe es nur im Vollbildmodus versucht ... ich teste es auf meinem Nexus One und Nexus S ... Es funktioniert.
Balaji Khadake

1
Ich habe es mit Galaxy S, HTC Wildfire, HTC Hero, Motorola Deify und Sony XPeria versucht. Funktioniert nicht auf einem einzelnen Gerät.
Vineet Shukla


1

Verwenden android:windowSoftInputMode="adjustResize|stateHiddenSie AdjustPan nur, wenn Sie es verwenden, und deaktivieren Sie dann die Größenänderungseigenschaft


Ich habe es auch benutzt ... bitte machen Sie es im Vollbildmodus und auf welchem ​​Gerät testen Sie?
Vineet Shukla

HTC NEXUS eins, ok, ich habe nicht Vollbild hinzugefügt
Mohammed Azharuddin Shaikh

können Sie getWindow (). requestFeature (Window.FEATURE_NO_TITLE) verwenden; onCreate () stattdessen Thema verwenden?
Mohammed Azharuddin Shaikh

10
Der obige Code funktioniert ohne Vollbild, aber das Hinzufügen von Vollbild entweder aus XML oder aus Code ... Es funktioniert nicht ... Bitte lesen Sie die Frage sorgfältig durch.
Vineet Shukla

1

Ich habe die von Joseph Johnson erstellte AndroidBug5497Workaround-Klasse verwendet, aber zwischen dem Softkeyboard und der Ansicht wurde ein schwarzer Raum angezeigt. Ich habe diesen Link Greg Ennis verwiesen . Nachdem ich einige Änderungen an den oben genannten vorgenommen habe, ist dies mein endgültiger Arbeitscode.

 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

Ich verwende derzeit diesen Ansatz und er funktioniert wie ein Zauber. Der Trick besteht darin, dass wir die Tastaturhöhe mit verschiedenen Methoden auf 21 oben und unten ermitteln und sie dann als untere Auffüllung unserer Stammansicht in unserer Aktivität verwenden. Ich habe angenommen, dass Ihr Layout keine obere Polsterung benötigt (geht unter die Statusleiste), aber falls Sie dies tun, informieren Sie mich, um meine Antwort zu aktualisieren.

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

Vergessen Sie nicht, Ihre Stammansicht mit einer ID zu versehen:

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

Hoffe es hilft jemandem.


1

basierend auf https://stackoverflow.com/a/19494006/1815624 und dem Wunsch, dies zu verwirklichen ...

aktualisierte Idee


Antworten aus kombinieren

Relevanter Code:

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

            }

Vollständige Quelle unter https://github.com/CrandellWS/AndroidBug5497Workaround/blob/master/AndroidBug5497Workaround.java

alte Idee

Erstellen Sie vor dem Öffnen der Tastatur einen statischen Wert für die Containerhöhe. Stellen Sie die Containerhöhe basierend auf dem usableHeightSansKeyboard - heightDifferenceZeitpunkt des Öffnens der Tastatur ein und setzen Sie sie beim Schließen auf den gespeicherten Wert zurück

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

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

    });

}

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

Ebenso können bei Bedarf Ränder hinzugefügt werden ...

Eine weitere Überlegung ist die Verwendung von Polstern. Ein Beispiel hierfür finden Sie unter:

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


1

1) Erstellen Sie 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) Lassen Sie Ihre Aktivität im Vollbildmodus sein:

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

3) Achten Sie auf Änderungen der Tastaturhöhe und fügen Sie Ihrer Ansicht eine untere Polsterung hinzu:

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

So wird jedes Mal , Tastatur , um den Bildschirm auf - Bodenpolster für Ihre Ansicht wird sich ändern, und Inhalte werden neu angeordnet werden.


0

Sie möchten, dass die untere Leiste am unteren Rand der Ansicht bleibt, aber wenn die Tastatur angezeigt wird, sollten sie nach oben verschoben werden, um über der Tastatur platziert zu werden, oder?

Sie können dieses Code-Snippet ausprobieren:

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

Die untere Leiste bleibt am unteren Rand der Ansicht hängen, und das LinearLayout mit der ScrollView nimmt die verbleibenden Teile der Ansicht auf, nachdem die obere / untere Leiste und die Tastatur angezeigt wurden. Lassen Sie mich wissen, ob es auch bei Ihnen funktioniert.


1
Sehr seltsam, da es in meinen Apps mehrmals funktioniert hat. RelativeLayout hat übrigens keine Ausrichtung, sodass Sie diese Attribute in Ihrem Code löschen können. Ich habe gerade erkannt, dass ich das Code-Snippet auf die folgende Zeile hätte reduzieren können: android: layout_below = "@ + id / ScoringContainerView", das Sie Ihrem ScrollView hinzufügen müssen
banzai86

Ganzer Bildschirm? Meinst du ohne Layout oben?
Banzai86

nein ..... ich meine keine Statusleiste, die Batterielebensdauer, Konnektivität für das Gerät usw.
anzeigt

Nein, die Statusleiste ist in meiner App sichtbar. Können Sie versuchen, die Reihenfolge Ihrer Layouts zu ändern, dh den Code für Ihr Layout mit den Schaltflächen über dem anderen Code einfügen und es dann erneut versuchen? Vielleicht müssen Sie sie zuerst definieren, um das layout_below
banzai86

1
Bitte lesen Sie die Frage sorgfältig durch ...... Ich habe erwähnt, dass ich Probleme mit dem Vollbildmodus habe ......
Vineet Shukla

0

Danke Joseph für deine Antwort. In der Methode evtl.ResizeChildOfContent () ist jedoch der Teil

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

funktionierte nicht für mich, da der untere Teil der Sicht verborgen wurde. Also musste ich eine globale Variable restoreHeight nehmen und im Konstruktor die letzte Zeile einfügen

restoreHeight = frameLayoutParams.height;

und dann habe ich den erstgenannten Teil durch ersetzt

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

Aber ich habe keine Ahnung, warum Ihr Code bei mir nicht funktioniert hat. Es wäre eine große Hilfe, wenn jemand Licht ins Dunkel bringen könnte.


0

Ich habe nur den Vollbildmodus verwendet, um die Statusleiste auszublenden. Ich möchte jedoch, dass die Größe der App geändert wird, wenn die Tastatur angezeigt wird. Alle anderen Lösungen (wahrscheinlich aufgrund des Alters der Veröffentlichung) waren für meine Verwendung kompliziert oder nicht möglich (ich möchte vermeiden, den Java-Code für den Sack von PhoneGap Build zu ändern).

Anstatt Vollbild zu verwenden, habe ich meine Konfiguration für Android so geändert, dass sie nicht im Vollbildmodus angezeigt wird:

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

Und fügte hinzu cordova-plugin-statusbar, über die Kommandozeile:

cordova plugin add cordova-plugin-statusbar

Wenn die App geladen wurde, rufe ich einfach eine Methode im Plugin auf, um sich zu verstecken, wie:

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

Das funktioniert wie ein Zauber. Der einzige wirkliche Nachteil ist, dass die Statusleiste beim Laden der App kurz sichtbar ist. Für meine Bedürfnisse war das kein Problem.


0

Ich habe alle möglichen Antworten von stackOverflow ausprobiert und nach einer Woche lange Suche endlich gelöst. Ich habe das Koordinatenlayout verwendet und dies mit linearLayout geändert und mein Problem ist behoben. Ich weiß nicht, ob das Koordinatenlayout Fehler oder irgendetwas von meinem Fehler enthält.


0

Ich habe viele Lösungen ausprobiert, darunter die von Joseph Johnson und Johan Stuyts. Infolgedessen habe ich auf einigen Geräten (wie dem Lenovo s820) in allen Fällen einen Leerraum zwischen Inhalt und Tastatur erhalten. Also habe ich einige Änderungen an ihren Codes vorgenommen und endlich eine funktionierende Lösung gefunden.

Meine Idee basiert auf dem Hinzufügen eines Randes zum oberen Rand des Inhalts, wenn die Tastatur angezeigt wird.

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

Wie Sie sehen können, addiere ich 30 Pixel zum Unterschied, da zwischen dem oberen Bildschirmrand und der Inhaltszone mit Rand ein kleiner weißer Bereich vorhanden ist. Und ich weiß nicht, woher es kommt, also habe ich beschlossen, die Ränder kleiner zu machen, und jetzt funktioniert es genau so, wie ich es brauchte.


0

Heute funktioniert nicht anpassen adjustResize auf Vollbild Problem ist aktuell für Android SDK.

Aus den Antworten fand ich:
die Lösung - aber die Lösung zeigt dies auf dem Bild:

Dann habe ich die Lösung gefunden und die eine unnötige Aktion entfernt:

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

Siehe also meinen festen Lösungscode auf 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
        }
    }
}

Mein Code zur Fehlerbehebung:

 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

Verwenden Sie nicht:

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

weil funktioniert schlecht. Verwenden Sie stattdessen:

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

In meinem Fall trat dieses Problem auf, als ich meiner Cordova-Anwendung Crosswalk hinzufügte. Meine App wird nicht in Vollbild und Android verwendet: windowSoftInputMode = "adjustPan".

Ich hatte bereits das Plugin für ionische Tastaturen in der Anwendung, sodass es dank dieser Funktion leicht zu erkennen war, ob die Tastatur hoch oder runter war:

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

Ich habe alle oben genannten Korrekturen ausprobiert, aber die einfache Zeile, die es für mich getan hat, war dieses bisschen CSS:

&.keyboardUp {
        overflow-y: scroll;
}

Ich hoffe, das erspart Ihnen die wenigen Tage, die ich damit verbracht habe. :) :)


Ich benutze Zebrastreifen mit Cordova auch mit Android: windowSoftInputMode = "adjustPan". Es funktioniert jedoch nicht. Ich sehe, dass die Klasse zum HTML-Element hinzugefügt wird, aber das CSS hat keine Auswirkung auf den Bildschirm. Gibt es eine andere Einstellung, mit der sich der Bildschirm bewegen kann?
Darewreck

Ich muss die Add-Transformation setzen: translateY (0px), damit es funktioniert. Das Scrollen funktioniert jedoch überhaupt nicht. Irgendwelche Ideen?
Darewreck
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.