windowSoftInputMode =“ adjustResize” ไม่ทำงานกับการกระทำโปร่งแสง / navbar


129

ฉันมีปัญหากับโปร่งแสง actionbar / navbar ใน Android ใหม่ KitKat (4.4) windowSoftInputMode="adjustResize"และ

Normaly เปลี่ยน InputMode เป็น AdjustResize แอปควรปรับขนาดตัวเองเมื่อแป้นพิมพ์แสดง ... แต่ที่นี่จะไม่! ถ้าฉันลบบรรทัดสำหรับเอฟเฟ็กต์แบบโปร่งใสการปรับขนาดกำลังทำงาน

ดังนั้นหากมองเห็นแป้นพิมพ์ ListView ของฉันจะอยู่ข้างใต้และฉันไม่สามารถเข้าถึงรายการสองสามรายการสุดท้ายได้ (โดยการซ่อนแป้นพิมพ์ด้วยตนเองเท่านั้น)

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>

ค่า-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>

ใครมีแนวคิดในการแก้ไขปัญหานี้


คำตอบ:


184

คุณไม่มีคุณสมบัติต่อไปนี้:

android:fitsSystemWindows="true"

ในรากRelativeLayoutของส่วนรูปแบบ .xml

ปรับปรุง:

ปีที่แล้วมีการพูดคุยที่น่าสนใจโดย Chris Bane ซึ่งอธิบายในรายละเอียดดีว่ามันทำงานอย่างไร:

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


5
ฉันเดาว่ามันเป็นสิ่งที่มีนโยบายแบบเต็มหน้าจอ
Felix.D

1
คุณเป็นผู้ชาย! ฉันปัญหานี้เกิดขึ้นกับฉันเฉพาะรุ่น Lollipop และแก้ไขได้
เดวิด

6
@David ยังไม่ได้แก้ไข แต่ยังคงอยู่ในอุปกรณ์มาร์ชเมลโลว์ถ้าคุณเปิดกล่องโต้ตอบและพยายามเลื่อนจากนั้น softkeboard จะบล็อกการเลื่อน
Bytecode

5
มันใช้งานได้ แต่ขัดแย้งกับแถบเครื่องมือและการปรับแต่งแถบสถานะของฉัน
Ninja

2
ใช้งานได้ แต่จากนั้นแถบสถานะจะไม่โปร่งแสงอีกต่อไป ฉันต้องการเค้าโครงเพื่อให้ครอบคลุมทั้งหน้าจอ
htafoya

34

มีรายงานข้อผิดพลาดที่เกี่ยวข้องเป็นที่นี่ ฉันพบวิธีแก้ปัญหาที่ดูเหมือนจะใช้กลอุบายโดยไม่มีการสะท้อนกลับจากการทดสอบที่ จำกัด เพิ่มการใช้งานรูทแบบกำหนดเองของคุณViewGroup(ฉันเกือบจะใช้อยู่ตลอดเวลาFrameLayoutดังนั้นนี่คือสิ่งที่ฉันทดสอบด้วย) ด้วยตรรกะด้านล่าง จากนั้นใช้เค้าโครงแบบกำหนดเองนี้แทนเค้าโครงแบบรากของคุณและตรวจสอบให้แน่ใจว่าคุณได้ตั้งค่าandroid:fitsSystemWindows="true"แล้ว จากนั้นคุณสามารถโทรได้getInsets()ตลอดเวลาหลังจากการจัดวาง (เช่นเพิ่ม an OnPreDrawListener) เพื่อปรับการจัดวางส่วนที่เหลือของคุณเพื่อรองรับการแทรกระบบหากต้องการ

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

เนื่องจากfitSystemWindows เลิกใช้แล้วโปรดอ้างอิงคำตอบด้านล่างเพื่อแก้ปัญหาให้เสร็จสิ้น


1
ที่จริงแล้ว SOFT_INPUT_ADJUST_PAN ดูเหมือนจะไม่ถูกเพิกเฉยตามประสบการณ์ของฉัน - มันจะย้ายทั้งหน้าจอขึ้นรวมถึงแถบระบบและแป้นพิมพ์กะภายใต้มุมมองที่เน้น
sealskej

ขอบคุณ - คุณถูกต้องเกี่ยวกับ SOFT_INPUT_ADJUST_PAN ฉันใช้สิ่งนี้ในส่วนของฉัน: getActivity (). getWindow (). setSoftInputMode (WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
Simon

นั่นเป็นวิธีเดียวที่ฉันสามารถประสบความสำเร็จในการปรับขนาดสำหรับกิจกรรม (จำเป็นสำหรับการเลื่อนมุมมองเมื่อแสดงแป้นพิมพ์), fitSystemWindows ตั้งค่าเป็นจริงเพื่อให้การเลื่อนเกิดขึ้นจริงบน> = Lollipop และมีสถานะแถบโปร่งแสง ขอบคุณมาก.
ลูคัส

นี่คือทางออกที่แท้จริง
martyglaubitz

ใช้เวลาในการแสดงและซ่อนแป้นพิมพ์แม้ว่าจะต้องใช้เวลาในการพุชเลย์เอาต์ขึ้น ทางออกใด ๆ ?
Vanjara Sweta

28

@kcoppock คำตอบมีประโยชน์จริง ๆ แต่ fitSystemWindows ถูกคัดค้านใน API ระดับ 20

ดังนั้นตั้งแต่ API 20 (KITKAT_WATCH) คุณควรแทนที่ onApplyWindowInsets

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

เราควรแทนที่สิ่งนี้ในระดับใด
เบ็นเจ

@ Ben-J ในคลาสที่ขยายคลาสดั้งเดิม
Victor91

ฉันไม่รู้ว่าทำไมคุณตั้งค่าองค์ประกอบ mInsets ในขณะที่ไม่ได้ใช้ แต่ใช้งานได้
Buckstabue

1
แทนที่จะตรวจสอบเวอร์ชั่นของคุณคุณสามารถใช้ViewCompat.setOnApplyWindowInsetsListener
ซ้ำ

ฉันไม่สามารถรับทำงานนี้ แต่เอาชนะdispatchApplyWindowInsetsแทน (รหัสเดียวกัน) ทำงานให้ฉัน
Petter

11

สิ่งนี้ทำงานได้สำหรับฉันที่จะมีแถบสถานะโปร่งแสงและปรับขนาดในส่วน:

  1. สร้าง RelativeLayout แบบกำหนดเองตามที่ @ Victor91 และ @kcoppock กล่าว

  2. ใช้ CustomRelativeLayout เป็นเลย์เอาต์หลักสำหรับแฟรกเมนต์ของคุณ

  3. ประกาศธีมด้วย android: windowTranslucentStatus = true

  4. กิจกรรมภาชนะจะต้องประกาศใน Manifest กับ Android: windowSoftInputMode = "adjustResize" และใช้ธีมที่ประกาศ

  5. กรุณาใช้ FitsSystemWindows บนเค้าโครงของส่วนย่อย!

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

จากนั้นใน 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>

1
นี่คือคำตอบที่ดีที่สุดและฉันกำลังมองหาวิธีการแก้ปัญหาในขณะนี้ มันทำงานได้อย่างสมบูรณ์แบบ แต่คุณต้องเพิ่มช่องว่างภายในแถบเครื่องมือของคุณโดยที่แถบเครื่องมือของคุณจะซ้อนทับแถบสถานะ
Paulina

หน้าต่างทรานสลูมิงเนชั่นเกี่ยวกับอะไร คุณช่วยได้ไหม
V-rund Puro-hit

10

หากคุณต้องการกำหนดค่าส่วนเสริมและคุณกำหนดเป้าหมายระดับ API> = 21 คุณสามารถทำสิ่งนี้ได้โดยไม่ต้องสร้างกลุ่มมุมมองที่กำหนดเอง เพียงแค่การตั้งค่าการfitsSystemWindowsเติมจะถูกนำไปใช้กับมุมมองคอนเทนเนอร์ของคุณตามค่าเริ่มต้นซึ่งคุณอาจไม่ต้องการ

การตรวจสอบเวอร์ชั่นถูกสร้างขึ้นในวิธีนี้และมีเพียงอุปกรณ์> = 21 เท่านั้นที่จะเรียกใช้โค้ดภายในแลมบ์ดา ตัวอย่าง Kotlin:

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

ตรวจสอบให้แน่ใจว่าเลย์เอาต์ของคุณยังคงตั้งfitsSystemWindowsค่าสถานะไว้ไม่เช่นนั้นฟังจะไม่ถูกเรียกฟัง

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

แหล่งข้อมูลเหล่านี้มีประโยชน์:

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


1
วิธีนี้ยังคงเป็นวิธีที่ดีที่สุดเนื่องจากคุณสามารถใช้สิ่งนี้เป็นของคุณBaseFragmentควบคู่ไปกับการview.fitsSystemWindows = trueทำงานและไม่มีการเปลี่ยนแปลงใด ๆ กับเค้าโครง XML จริงหรือคลาสย่อยมุมมอง
Bogdan Zurac

5

ฉันมีปัญหาเดียวกันกิจกรรมของฉันมี ScrollView เป็นมุมมองรูทและเมื่อเปิดใช้งานแถบสถานะแบบโปร่งแสงก็ไม่ได้ปรับขนาดอย่างถูกต้องเมื่อแป้นพิมพ์แสดง ... และหน้าจอไม่เลื่อนซ่อนมุมมองอินพุต

การแก้ไข: ย้ายทุกอย่าง (เค้าโครงและตรรกะกิจกรรม) ภายใน Fragment ใหม่ จากนั้นเปลี่ยนกิจกรรมให้รวมเฉพาะส่วนนี้เท่านั้น ตอนนี้ทุกอย่างทำงานได้ตามที่คาดไว้!

นี่คือเค้าโครงของกิจกรรม:

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

ใช้งานได้เหมือนเสน่ห์สำหรับฉัน
imike

2

ขึ้นอยู่กับการแก้ปัญหาของโจเซฟจอห์นสันในAndroid วิธีปรับเลย์เอาต์ในโหมดเต็มหน้าจอเมื่อซอฟต์คีย์บอร์ดมองเห็นได้

onCreate()หลังจากนี้ในsetContentView()กิจกรรมของคุณ

AndroidBug5497Workaround.assistActivity(this);

litte ต่างจากต้นฉบับแทนที่return (r.bottom - r.top);ด้วยreturn r.bottom;ในcomputeUsableHeight()

ด้วยเหตุผลบางอย่างที่ฉันต้องกำหนดกิจกรรมของฉันแอตทริบิวต์fitsSystemWindowsfalse

วิธีแก้ปัญหานี้ช่วยฉัน มันทำงานได้ดีสำหรับฉัน หวังว่าจะช่วยคุณได้

ระดับการใช้งานคือ:

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

}

2

ไม่ควรทำงานกับแถบสถานะโปร่งแสง การตั้งค่านั้นบังคับให้หน้าต่างเข้าสู่โหมดเต็มหน้าจอซึ่งไม่สามารถใช้งานได้กับ adjustResize

คุณสามารถใช้ adjustPan หรือใช้คุณสมบัติ FitsSystemWindows ฉันขอแนะนำให้อ่านเกี่ยวกับคุณลักษณะนี้ แต่ก็มีผลข้างเคียงที่สำคัญ:

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


0

AndroidBug5497Workaround.java ดูแลหน่วยความจำรั่ว ต้องการรหัสด้านล่าง

getViewTreeObserver().removeOnGlobalLayoutListener(listener);

ตัวอย่างของฉันใช้ RxJava ที่เรียกว่า removeOnGlobalLayoutListener () โดยอัตโนมัติเมื่อ onPause () ในวงจรชีวิตของกิจกรรม

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

0

ฉันมีปัญหา

ฉันตั้ง windowDrawsSystemBarBackgrounds เป็น 'จริง' และแอพของฉันควรแสดงภายใต้แถบสถานะ

มันเป็นธีมกิจกรรมของฉัน

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

และผมได้รับความช่วยเหลือจากบล็อกของ jianshu คุณสามารถอ่านรหัส แต่ข้อความเช่นฉัน ฉันเพิ่มรหัสอีกไม่กี่

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

นี่คือเค้าโครงส่วนของฉัน

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

ฉันต้องการที่จะเป็นประโยชน์กับคุณ โชคดี!


ใช้เวลาในการซ่อนและแสดงแป้นพิมพ์และต้องใช้เวลาในการพุชเลย์เอาต์ขึ้น ทางออกใด ๆ วิธีจัดการ
Vanjara Sweta

0
  • หลังจากที่ฉันได้วิจัยในฟอรั่มทั้งหมด วิธี thoese ไม่สามารถช่วยหาจุด โชคดีเมื่อฉันพยายามทำเช่นนี้ มันช่วยให้ฉันแก้ปัญหาได้

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>

กิจกรรม

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

}

สร้าง Func

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

ในที่สุดก็เพิ่มบางบรรทัดเพื่อ mainifest ของคุณ

 <activity
     android:name="Your Activity"
     android:windowSoftInputMode="adjustPan|adjustResize"
     android:screenOrientation="portrait"></activity>

0

ผมมีปัญหาเหมือนกัน. ฉันแก้ไขด้วยการใช้ผู้ประสานงานออก

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

ตอนนี้เพิ่มบรรทัดนี้ linearLayoutManager.setStackFromEnd (จริง);

 LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        linearLayoutManager.setStackFromEnd(true);
        recyclerView.setLayoutManager(linearLayoutManager);
        Adapter adapter1=new Adapter(arrayList);
        recyclerView.setAdapter(adapter1);

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>

0

เพิ่มนี้ก่อนที่รูปแบบรูทของคุณ

android:fitsSystemWindows="true"

เมื่อคุณใช้วิธีการนี้จะเป็นความรับผิดชอบของคุณเพื่อให้แน่ใจว่าส่วนที่สำคัญของ UI ของแอปของคุณ (ตัวอย่างเช่นการควบคุมในตัวในแอปพลิเคชั่น Maps) จะไม่ได้รับการคุ้มครองจากแถบระบบ นี่อาจทำให้แอปของคุณใช้งานไม่ได้ ในกรณีส่วนใหญ่คุณสามารถจัดการสิ่งนี้ได้โดยการเพิ่มคุณสมบัติ android: fitsSystemWindows ไปยังไฟล์เลย์เอาต์ XML ของคุณตั้งค่าเป็นจริง สิ่งนี้จะปรับการขยายของ ViewGroup หลักเพื่อเว้นที่ว่างสำหรับหน้าต่างระบบ นี่เพียงพอสำหรับการใช้งานส่วนใหญ่

อย่างไรก็ตามในบางกรณีคุณอาจจำเป็นต้องปรับเปลี่ยนการแพ็ดเริ่มต้นเพื่อให้ได้เลย์เอาต์ที่ต้องการสำหรับแอพของคุณ ในการจัดการโดยตรงกับเนื้อหาของคุณที่สัมพันธ์กับแถบระบบ (ซึ่งใช้พื้นที่ที่เรียกว่า "content insets" ของหน้าต่าง) ให้แทนที่ fitSystemWindows (rectets insets) เมธอด fitSystemWindows () ถูกเรียกโดยลำดับชั้นมุมมองเมื่อเนื้อหาที่แทรกสำหรับหน้าต่างเปลี่ยนไปเพื่อให้หน้าต่างปรับเนื้อหาตามความเหมาะสม ด้วยการเอาชนะวิธีนี้คุณสามารถจัดการกับสิ่งที่แทรก (และรูปแบบของแอพของคุณ) ตามที่คุณต้องการ

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

หากคุณต้องการที่จะเป็นหน้าต่างหลักกรุณาดูวิดีโอจากนักพัฒนา Android https://www.youtube.com/watch?v=_mGDMVRO3iE


-1

แนวปฏิบัติที่ดีที่สุดช่วยให้ผู้ใช้เลื่อนเนื้อหาเมื่อมีการแสดงแป้นพิมพ์ ดังนั้นในการเพิ่มฟังก์ชั่นนี้คุณต้องวางเค้าโครงรูทไว้ข้างในScrollViewและใช้windowSoftInputMode="adjustResize"วิธีการกิจกรรม

แต่ถ้าคุณต้องการใช้ฟังก์ชั่นนี้ด้วย <item name="android:windowTranslucentStatus">true</item> ตั้งค่าสถานะบนเนื้อหา Android 5 จะไม่สามารถเลื่อนได้และจะทับซ้อนกับแป้นพิมพ์

เพื่อแก้ปัญหานี้ตรวจสอบคำตอบนี้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.