windowSoftInputMode = „adjustResize” nie działa z półprzezroczystym działaniem / paskiem nawigacyjnym

133

Mam problemy z półprzezroczystym paskiem akcji / paskiem nawigacyjnym w nowym Androidzie KitKat (4.4) i windowSoftInputMode="adjustResize".

Normalnie, zmieniając InputMode na adjustResize, aplikacja powinna zmienić swój rozmiar po wyświetleniu klawiatury, ale tutaj nie będzie! Jeśli usunę linie dla efektu przezroczystości, zmiana rozmiaru działa.

Więc jeśli klawiatura jest widoczna, moja ListViewjest pod nią i nie mam dostępu do kilku ostatnich elementów (tylko ręcznie chowając klawiaturę).

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="XYZ"
android:versionCode="23"
android:versionName="0.1" >

<uses-sdk
    android:minSdkVersion="9"
    android:targetSdkVersion="19" />

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/Theme.XYZStyle" >
    <activity
        android:name="XYZ"
        android:label="@string/app_name"
        android:windowSoftInputMode="adjustResize" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

</manifest>

wartości-v19 / styles.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

<style name="Theme.XYZStyle" parent="@style/Theme.AppCompat.Light">
    <item name="android:windowTranslucentStatus">true</item>
    <item name="android:windowTranslucentNavigation">true</item>
</style>

</resources>

fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

<ListView
    android:id="@+id/listView_contacts"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipToPadding="false"
    android:divider="@null"
    android:dividerHeight="0dp"
    android:drawSelectorOnTop="true"
    android:fastScrollAlwaysVisible="true"
    android:fastScrollEnabled="true"
    android:paddingBottom="@dimen/navigationbar__height" >
</ListView>

</RelativeLayout>

Jakieś pomysły, jak to naprawić?

fabianbru
źródło

Odpowiedzi:

189

Brakuje następującej właściwości:

android:fitsSystemWindows="true"

w katalogu głównym RelativeLayoutukładu fragmentu .xml.

Aktualizacja:

W zeszłym roku Chris Bane wygłosił interesującą rozmowę, która szczegółowo wyjaśnia, jak to działa:

https://www.youtube.com/watch?v=_mGDMVRO3iE

pablisco
źródło
36

Jest tutaj powiązany raport o błędzie . Znalazłem obejście, które na podstawie ograniczonych testów wydaje się działać bez żadnych konsekwencji. Dodaj niestandardową implementację swojego roota ViewGroup(prawie zawsze używam FrameLayout, więc to jest to, co testowałem) z logiką poniżej. Następnie użyj tego niestandardowego układu zamiast układu głównego i upewnij się, że ustawiłeś android:fitsSystemWindows="true". Możesz wtedy po prostu zadzwonić w getInsets()dowolnym momencie po układzie (np. Dodać OnPreDrawListener), aby dostosować resztę układu, aby uwzględnić wstawki systemowe, jeśli chcesz.

import android.content.Context;
import android.graphics.Rect;
import android.os.Build;
import android.util.AttributeSet;
import android.widget.FrameLayout;
import org.jetbrains.annotations.NotNull;

/**
 * @author Kevin
 *         Date Created: 3/7/14
 *
 * https://code.google.com/p/android/issues/detail?id=63777
 * 
 * When using a translucent status bar on API 19+, the window will not
 * resize to make room for input methods (i.e.
 * {@link android.view.WindowManager.LayoutParams#SOFT_INPUT_ADJUST_RESIZE} and
 * {@link android.view.WindowManager.LayoutParams#SOFT_INPUT_ADJUST_PAN} are
 * ignored).
 * 
 * To work around this; override {@link #fitSystemWindows(android.graphics.Rect)},
 * capture and override the system insets, and then call through to FrameLayout's
 * implementation.
 * 
 * For reasons yet unknown, modifying the bottom inset causes this workaround to
 * fail. Modifying the top, left, and right insets works as expected.
 */
public final class CustomInsetsFrameLayout extends FrameLayout {
    private int[] mInsets = new int[4];

    public CustomInsetsFrameLayout(Context context) {
        super(context);
    }

    public CustomInsetsFrameLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomInsetsFrameLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public final int[] getInsets() {
        return mInsets;
    }

    @Override
    protected final boolean fitSystemWindows(@NotNull Rect insets) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            // Intentionally do not modify the bottom inset. For some reason, 
            // if the bottom inset is modified, window resizing stops working.
            // TODO: Figure out why.

            mInsets[0] = insets.left;
            mInsets[1] = insets.top;
            mInsets[2] = insets.right;

            insets.left = 0;
            insets.top = 0;
            insets.right = 0;
        }

        return super.fitSystemWindows(insets);
    }
}

Ponieważ fitSystemWindows był przestarzały, zapoznaj się z odpowiedzią poniżej, aby dokończyć obejście.

Kevin Coppock
źródło
1
Właściwie SOFT_INPUT_ADJUST_PAN nie wydaje się być ignorowany zgodnie z moim doświadczeniem - przesunie cały ekran w górę, w tym pasek systemowy i przesuń klawiaturę pod ostrym widokiem.
sealskej
Dzięki - masz rację co do SOFT_INPUT_ADJUST_PAN. Użyłem tego w moim fragmencie: getActivity (). GetWindow (). SetSoftInputMode (WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
Simon
To był jedyny sposób, w jaki mogłem osiągnąć, mając AdjustResize dla aktywności (potrzebne do przewijania widoku po wyświetleniu klawiatury), fitSystemWindows ustawione na true, aby przewijanie faktycznie miało miejsce na> = Lollipop i ma półprzezroczysty statusBar. Wielkie dzięki.
Lucas
30

Odpowiedź @kcoppock jest bardzo pomocna, ale fitSystemWindows została wycofana na poziomie API 20

Więc od API 20 (KITKAT_WATCH) powinieneś nadpisać naApplyWindowInsets

@Override
public final WindowInsets onApplyWindowInsets(WindowInsets insets) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
        return super.onApplyWindowInsets(insets.replaceSystemWindowInsets(0, 0, 0,
                insets.getSystemWindowInsetBottom()));
    } else {
        return insets;
    }
}
Victor91
źródło
13

To zadziałało, aby mieć półprzezroczysty pasek stanu i dostosować rozmiar we fragmencie:

  1. Utwórz niestandardowy RelativeLayout, jak powiedział @ Victor91 i @kcoppock.

  2. Użyj CustomRelativeLayout jako układu nadrzędnego dla swojego fragmentu.

  3. Zadeklaruj motyw za pomocą androida: windowTranslucentStatus = true

  4. Aktywność kontenera musi być zadeklarowana w Manifest z android: windowSoftInputMode = "adjustResize" i użyć zadeklarowanego motywu

  5. Użyj fitSystemWindows na fragmentowym układzie głównym!

    public class CustomRelativeLayout extends RelativeLayout {
    
        private int[] mInsets = new int[4];
    
        public CustomRelativeLayout(Context context) {
            super(context);
        }
    
        public CustomRelativeLayout(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public CustomRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        public CustomRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
            super(context, attrs, defStyleAttr, defStyleRes);
        }
    
        @Override
        public final WindowInsets onApplyWindowInsets(WindowInsets insets) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
                mInsets[0] = insets.getSystemWindowInsetLeft();
                mInsets[1] = insets.getSystemWindowInsetTop();
                mInsets[2] = insets.getSystemWindowInsetRight();
                return super.onApplyWindowInsets(insets.replaceSystemWindowInsets(0, 0, 0,
                        insets.getSystemWindowInsetBottom()));
            } else {
                return insets;
            }
        }
    }
    

Następnie w xml,

<com.blah.blah.CustomRelativeLayout 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:fitsSystemWindows="true">
</com.blah.blah.CustomRelativeLayout>
Hermana
źródło
1
Jak dotąd jest to najlepsza odpowiedź i od jakiegoś czasu szukam rozwiązania. Działa idealnie, ale musisz dodać dodatkowe wypełnienie do paska narzędzi, bez tego pasek narzędzi będzie nakładał się na pasek stanu
Paulina.
11

Jeśli chcesz dostosować wstawki i kierujesz się na poziom interfejsu API> = 21, możesz to zrobić bez konieczności tworzenia niestandardowej grupy widoków. Po prostu ustawienie fitsSystemWindowsdopełnienia zostanie domyślnie zastosowane do widoku kontenera, czego możesz nie chcieć.

Sprawdzanie wersji jest wbudowane w tę metodę i tylko urządzenia> = 21 wykonają kod wewnątrz lambdy. Przykład Kotlina:

ViewCompat.setOnApplyWindowInsetsListener(container) { view, insets ->
  insets.replaceSystemWindowInsets(0, 0, 0, insets.systemWindowInsetBottom).apply {
    ViewCompat.onApplyWindowInsets(view, this)
  }
}

Upewnij się, że układ nadal ustawia fitsSystemWindowsflagę, w przeciwnym razie nasłuchiwanie wstawek okiennych nie zostanie wywołane.

<FrameLayout
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    />

Te źródła są pomocne:

https://medium.com/google-developers/why-would-i-want-to-fitssystemwindows-4e26d9ce1eec https://medium.com/@azizbekian/windowinsets-24e241d4afb9

Victor Rendina
źródło
1
To wciąż pozostaje najlepszym podejściem, ponieważ możesz zastosować to, co jest twoje BaseFragment, wraz z view.fitsSystemWindows = truei po prostu działa bez żadnych zmian w rzeczywistych układach XML lub podklasach widoku.
Bogdan Zurac
Chciałem zauważyć, że rozwiązanie może nie działać dla niektórych widoków działających jako container(w moim przypadku tak było ConstraintLayout). Rozwiązaniem było owinięcie mojego układu FrameLayouttym, co stało się nowym container. Doceń rozwiązanie!
Onik
5

Miałem ten sam problem, Moja aktywność miała ScrollView jako widok główny, a przy aktywnym półprzezroczystym pasku stanu nie zmieniał rozmiaru poprawnie, gdy pojawiła się klawiatura ... i konsekwentnie ekran nie przewijał się, ukrywając widoki wejściowe.

Rozwiązanie: Przeniesiono wszystko (układ i logikę działania) do nowego fragmentu. Następnie zmieniono działanie, aby zawierało tylko ten fragment. Teraz wszystko działa zgodnie z oczekiwaniami!

Oto plan zajęć:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"

    android:id="@+id/contentView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true" />
araks
źródło
2

Na podstawie obejścia Josepha Johnsona w systemie Android. Jak dostosować układ w trybie pełnego ekranu, gdy widoczna jest klawiatura programowa

wezwij to onCreate()później setContentView()w swojej aktywności.

AndroidBug5497Workaround.assistActivity(this);

inny Litte z oryginalnego zastępuje return (r.bottom - r.top);się return r.bottom;wcomputeUsableHeight()

z jakiegoś powodu muszę ustawić fitsSystemWindowsatrybut aktywności na false.

to obejście uratowało mnie. to działa dobrze dla mnie. nadzieja może ci pomóc.

klasa implementacji to:

public class AndroidBug5497Workaround {

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

}
Loyea
źródło
2

Nie powinno działać z półprzezroczystym paskiem stanu; to ustawienie wymusza przejście okna do trybu pełnoekranowego, który nie działa z funkcją AdjustResize.

Możesz użyć funkcji adjustPan lub właściwości fitSystemWindows. Proponuję jednak przeczytać o tej funkcji, ma ona znaczące skutki uboczne:

https://medium.com/google-developers/why-would-i-want-to-fitssystemwindows-4e26d9ce1eec

RESTfulGeoffrey
źródło
0

AndroidBug5497Workaround.java uważaj na wyciek pamięci. Potrzebujesz poniższego kodu

getViewTreeObserver().removeOnGlobalLayoutListener(listener);

Moja próbka używająca RxJava, która automatycznie wywołuje metodę removeOnGlobalLayoutListener () podczas onPause () w cyklu życia działania

public class MyActivity extends RxAppCompatActivity {
    // ...

protected void onStart(){
    super.onStart();

        TRSoftKeyboardVisibility
            .changes(this) // activity
            .compose(this.<TRSoftKeyboardVisibility.ChangeEvent>bindUntilEvent(ActivityEvent.PAUSE))
            .subscribe(keyboardEvent -> {
                FrameLayout content = (FrameLayout) findViewById(android.R.id.content);
                View firstChildView = content.getChildAt(0);
                firstChildView.getLayoutParams().height = keyboardEvent.viewHeight();
                firstChildView.requestLayout();

                // keyboardEvent.isVisible      = keyboard visible or not
                // keyboardEvent.keyboardHeight = keyboard height
                // keyboardEvent.viewHeight     = fullWindowHeight - keyboardHeight
            });
   //...
}





package commonlib.rxjava.keyboard;

import android.app.Activity;
import android.view.View;
import android.widget.FrameLayout;
import kr.ohlab.android.util.Assert;
import rx.Observable;

public class TRSoftKeyboardVisibility {

    public static Observable<ChangeEvent> changes(Activity activity) {
        Assert.notNull(activity, "activity == null");
        FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);
        View childOfContent = content.getChildAt(0);
        return Observable.create(
            new TRSoftKeyboardVisibilityEventOnSubscribe(childOfContent));
    }

    public static final class ChangeEvent {
        private final int keyboardHeight;
        private final boolean visible;
        private final int viewHeight;

        public static ChangeEvent create(boolean visible, int keyboardHeight,
            int windowDisplayHeight) {
            return new ChangeEvent(visible, keyboardHeight, windowDisplayHeight);
        }

        private ChangeEvent(boolean visible, int keyboardHeight, int viewHeight) {
            this.keyboardHeight = keyboardHeight;
            this.visible = visible;
            this.viewHeight = viewHeight;
        }

        public int keyboardHeight() {
            return keyboardHeight;
        }

        public boolean isVisible() {
            return this.visible;
        }

        public int viewHeight() {
            return viewHeight;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (!(o instanceof ChangeEvent)) return false;

            ChangeEvent that = (ChangeEvent) o;

            if (keyboardHeight != that.keyboardHeight) return false;
            if (visible != that.visible) return false;
            return viewHeight == that.viewHeight;
        }

        @Override
        public int hashCode() {
            int result = keyboardHeight;
            result = 31 * result + (visible ? 1 : 0);
            result = 31 * result + viewHeight;
            return result;
        }

        @Override
        public String toString() {
            return "ChangeEvent{" +
                "keyboardHeight=" + keyboardHeight +
                ", visible=" + visible +
                ", viewHeight=" + viewHeight +
                '}';
        }
    }
}


package commonlib.rxjava.keyboard;

import android.graphics.Rect;
import android.view.View;
import android.view.ViewTreeObserver;
import kr.ohlab.android.util.Assert;
import rx.Observable;
import rx.Subscriber;
import rx.android.MainThreadSubscription;
import timber.log.Timber;

public class TRSoftKeyboardVisibilityEventOnSubscribe
    implements Observable.OnSubscribe<TRSoftKeyboardVisibility.ChangeEvent> {
    private final View mTopView;
    private int mLastVisibleDecorViewHeight;
    private final Rect mWindowVisibleDisplayFrame = new Rect();

    public TRSoftKeyboardVisibilityEventOnSubscribe(View topView) {
        mTopView = topView;
    }

    private int computeWindowFrameHeight() {
        mTopView.getWindowVisibleDisplayFrame(mWindowVisibleDisplayFrame);
        return (mWindowVisibleDisplayFrame.bottom - mWindowVisibleDisplayFrame.top);
    }

    private TRSoftKeyboardVisibility.ChangeEvent checkKeyboardVisibility() {
        int windowFrameHeightNow = computeWindowFrameHeight();
        TRSoftKeyboardVisibility.ChangeEvent event = null;
        if (windowFrameHeightNow != mLastVisibleDecorViewHeight) {
            int mTopViewHeight = mTopView.getHeight();
            int heightDiff = mTopViewHeight - windowFrameHeightNow;
            Timber.e("XXX heightDiff=" + heightDiff);
            if (heightDiff > (mTopViewHeight / 4)) {
                event = TRSoftKeyboardVisibility.ChangeEvent.create(true, heightDiff, windowFrameHeightNow);
            } else {
                event = TRSoftKeyboardVisibility.ChangeEvent.create(false, 0, windowFrameHeightNow);
            }
            mLastVisibleDecorViewHeight = windowFrameHeightNow;
            return event;
        }

        return null;
    }

    public void call(final Subscriber<? super TRSoftKeyboardVisibility.ChangeEvent> subscriber) {
        Assert.checkUiThread();

        final ViewTreeObserver.OnGlobalLayoutListener listener =
            new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    TRSoftKeyboardVisibility.ChangeEvent event = checkKeyboardVisibility();
                    if( event == null)
                        return;
                    if (!subscriber.isUnsubscribed()) {
                        subscriber.onNext(event);
                    }
                }
            };

        mTopView.getViewTreeObserver().addOnGlobalLayoutListener(listener);

        subscriber.add(new MainThreadSubscription() {
            @Override
            protected void onUnsubscribe() {
                mTopView.getViewTreeObserver().removeOnGlobalLayoutListener(listener);
            }
        });
    }
}
ohlab
źródło
0

Miałem problem.

Ustawiłem windowDrawsSystemBarBackgrounds na „true” i moja aplikacja powinna być wyświetlana pod paskiem stanu.

To temat mojej aktywności.

<item name="android:windowTranslucentStatus" tools:targetApi="KITKAT">false</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>

i otrzymałem pomoc z bloga jianshu . możesz czytać kod, ale tekst jak ja. Dodaję jeszcze kilka kodów.

public final class ZeroInsetsFrameLayout extends FrameLayout {
    private int[] mInsets = new int[4];

    public ZeroInsetsFrameLayout(Context context) {
        super(context);
    }

    public ZeroInsetsFrameLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ZeroInsetsFrameLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public final int[] getInsets() {
        return mInsets;
    }

    @Override
    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
        outLocalInsets.left = 0;
        outLocalInsets.top = 0;
        outLocalInsets.right = 0;

        return super.computeSystemWindowInsets(in, outLocalInsets);
    }

    @Override
    protected final boolean fitSystemWindows(@NonNull Rect insets) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            // Intentionally do not modify the bottom inset. For some reason,
            // if the bottom inset is modified, window resizing stops working.
            // TODO: Figure out why.

            mInsets[0] = insets.left;
            mInsets[1] = insets.top;
            mInsets[2] = insets.right;

            insets.left = 0;
            insets.top = 0;
            insets.right = 0;
        }

        return super.fitSystemWindows(insets);
    }
}

To jest mój układ fragmentów.

<com.dhna.widget.ZeroInsetsFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    android:background="@color/white">

    <!-- your xml code -->

</ZeroInsetsFrameLayout>

Chcę, żeby ci to pomogło. powodzenia!

Hogun
źródło
0
  • Po zbadaniu wszystkich forum. te sposoby nie mogą pomóc w zwróceniu uwagi. Na szczęście, kiedy próbowałem to zrobić. Pomaga mi rozwiązać problem

XML

<RelativeLayout 
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:fitsSystemWindows="true">
       <!-- Your xml -->
    </RelativeLayout>

Czynność

@Override
protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView("Your Activity");
   setAdjustScreen();

}

Utworzono Func

protected void setAdjustScreen(){
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
        /*android:windowSoftInputMode="adjustPan|adjustResize"*/
}

Na koniec dodając kilka wierszy do swojego mainifestu

 <activity
     android:name="Your Activity"
     android:windowSoftInputMode="adjustPan|adjustResize"
     android:screenOrientation="portrait"></activity>
Trần Thanh Phong
źródło
0

Miałem ten sam problem. Rozwiązałem za pomocą układu koordynatora

activity.main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    android:layout_height="match_parent" android:layout_width="match_parent"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android">


    <android.support.design.widget.AppBarLayout
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:theme="@style/AppTheme.AppBarOverlay">

    <android.support.v7.widget.Toolbar
        android:layout_height="?attr/actionBarSize"
        android:layout_width="match_parent"
        app:popupTheme="@style/AppTheme.PopupOverlay"
        android:background="?attr/colorPrimary"
        android:id="@+id/toolbar"/>

</android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_main2"/>

</android.support.design.widget.CoordinatorLayout>

content_main2.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">


    <android.support.v7.widget.RecyclerView
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:layout_marginTop="30dp"
        android:layout_marginBottom="30dp"
        app:layout_scrollFlags="scroll|exitUntilCollapsed"
        android:id="@+id/post_msg_recyclerview">
    </android.support.v7.widget.RecyclerView>

    <EditText
        android:layout_width="match_parent"
        android:layout_height="50dp"
        app:layout_constraintBottom_toBottomOf="parent"
        android:background="@color/colorPrimary"


        />

</android.support.constraint.ConstraintLayout>

MainActivity.java

teraz dodaj tę linię linearLayoutManager.setStackFromEnd (true);

 LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        linearLayoutManager.setStackFromEnd(true);
        recyclerView.setLayoutManager(linearLayoutManager);
        Adapter adapter1=new Adapter(arrayList);
        recyclerView.setAdapter(adapter1);
gaurav gupta
źródło
0
<androidx.constraintlayout.widget.ConstraintLayout
  android:fitsSystemWindows="true">

  <androidx.coordinatorlayout.widget.CoordinatorLayout>
    <com.google.android.material.appbar.AppBarLayout>

      <com.google.android.material.appbar.CollapsingToolbarLayout/>

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.core.widget.NestedScrollView>
    <Editext/>
    <androidx.core.widget.NestedScrollView/>

  </androidx.coordinatorlayout.widget.CoordinatorLayout>

</androidx.constraintlayout.widget.ConstraintLayout>
shehan gamage
źródło
0

Dodaj to najpierw w układzie głównym.

android:fitsSystemWindows="true"

Korzystając z tego podejścia, Twoim obowiązkiem jest upewnienie się, że krytyczne części interfejsu użytkownika aplikacji (na przykład wbudowane elementy sterujące w aplikacji Mapy) nie zostaną zakryte przez paski systemowe. Może to uniemożliwić korzystanie z aplikacji. W większości przypadków możesz sobie z tym poradzić, dodając atrybut android: fitSystemWindows do pliku układu XML o wartości true. Spowoduje to dostosowanie dopełnienia nadrzędnej grupy ViewGroup, aby zostawić miejsce na okna systemowe. Jest to wystarczające dla większości zastosowań.

Jednak w niektórych przypadkach może być konieczne zmodyfikowanie domyślnego wypełnienia, aby uzyskać żądany układ aplikacji. Aby bezpośrednio manipulować układem zawartości względem pasków systemowych (które zajmują przestrzeń zwaną „wstawkami zawartości” okna), nadpisuj fitSystemWindows (wstawki Rect). Metoda fitSystemWindows () jest wywoływana przez hierarchię widoków po zmianie wstawek zawartości okna, aby umożliwić odpowiednie dostosowanie zawartości okna. Zastępując tę ​​metodę, możesz obsłużyć wstawki (a tym samym układ aplikacji) w dowolny sposób.

https://developer.android.com/training/system-ui/status#behind

Jeśli chcesz zostać głównym instalatorem okien, obejrzyj wideo od programisty Androida. https://www.youtube.com/watch?v=_mGDMVRO3iE

xiaoyuan hu
źródło
0

Mała aktualizacja pomocny @Victor Rendina „s odpowiedź spowodowane replaceSystemWindowInsetsi systemWindowInsetBottomzaniechania metod.

Wymagania wstępne:

  • API > = 21
  • implementation 'androidx.core:core-ktx:1.5.0-alpha02' przynajmniej

Rozszerzenie Kotlin:

fun View?.fitSystemWindowsAndAdjustResize() = this?.let { view ->
    ViewCompat.setOnApplyWindowInsetsListener(view) { v, insets ->
        view.fitsSystemWindows = true
        val bottom = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom

        WindowInsetsCompat
            .Builder()
            .setInsets(
                WindowInsetsCompat.Type.systemBars(),
                Insets.of(0, 0, 0, bottom)
            )
            .build()
            .apply {
                ViewCompat.onApplyWindowInsets(v, this)
            }
    }
}

Stosowanie:

rootView.fitSystemWindowsAndAdjustResize()

gdzie rootViewjest dosłownie główny widok układu :)

Uwaga: jeśli rozszerzenie nie działa dla twojego widoku głównego (natknąłem się na to, mając ConstraintLayoutjako rootView) zawiń cały układ FrameLayouttak, aby FrameLayoutstał się nowym widokiem głównym .

Onik
źródło
-1

Najlepsze rozwiązanie pozwala użytkownikowi przewijać zawartość, gdy wyświetlana jest klawiatura. Aby dodać tę funkcję, musisz umieścić układ główny w plikuScrollView i użyćwindowSoftInputMode="adjustResize" metody działania.

Ale jeśli chcesz korzystać z tej funkcji z <item name="android:windowTranslucentStatus">true</item> flagą na Androidzie 5, zawartość nie będzie przewijana i będzie się nakładać na klawiaturę.

Aby rozwiązać ten problem, sprawdź tę odpowiedź

Gdakanie
źródło