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 ListView
jest 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ć?
Odpowiedzi:
Brakuje następującej właściwości:
android:fitsSystemWindows="true"
w katalogu głównym
RelativeLayout
ukł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
źródło
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żywamFrameLayout
, 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ć wgetInsets()
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ż
fitSystemWindow
s był przestarzały, zapoznaj się z odpowiedzią poniżej, aby dokończyć obejście.źródło
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; } }
źródło
To zadziałało, aby mieć półprzezroczysty pasek stanu i dostosować rozmiar we fragmencie:
Utwórz niestandardowy RelativeLayout, jak powiedział @ Victor91 i @kcoppock.
Użyj CustomRelativeLayout jako układu nadrzędnego dla swojego fragmentu.
Zadeklaruj motyw za pomocą androida: windowTranslucentStatus = true
Aktywność kontenera musi być zadeklarowana w Manifest z android: windowSoftInputMode = "adjustResize" i użyć zadeklarowanego motywu
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>
źródło
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
fitsSystemWindows
dopeł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
fitsSystemWindows
flagę, 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
źródło
BaseFragment
, wraz zview.fitsSystemWindows = true
i po prostu działa bez żadnych zmian w rzeczywistych układach XML lub podklasach widoku.container
(w moim przypadku tak byłoConstraintLayout
). Rozwiązaniem było owinięcie mojego układuFrameLayout
tym, co stało się nowymcontainer
. Doceń rozwiązanie!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" />
źródło
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óźniejsetContentView()
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ć
fitsSystemWindows
atrybut aktywności nafalse
.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; } }
źródło
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
źródło
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); } }); } }
źródło
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!
źródło
<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>
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView("Your Activity"); setAdjustScreen(); }
protected void setAdjustScreen(){ getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); /*android:windowSoftInputMode="adjustPan|adjustResize"*/ }
<activity android:name="Your Activity" android:windowSoftInputMode="adjustPan|adjustResize" android:screenOrientation="portrait"></activity>
źródło
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);
źródło
<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>
źródło
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
źródło
Mała aktualizacja pomocny @Victor Rendina „s odpowiedź spowodowane
replaceSystemWindowInsets
isystemWindowInsetBottom
zaniechania metod.Wymagania wstępne:
implementation 'androidx.core:core-ktx:1.5.0-alpha02'
przynajmniejRozszerzenie 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
rootView
jest 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
ConstraintLayout
jakorootView
) zawiń cały układFrameLayout
tak, abyFrameLayout
stał się nowym widokiem głównym .źródło
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 pliku
ScrollView
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ź
źródło