fitSystemWindows ทำอะไรกันแน่?


126

ฉันกำลังดิ้นรนเพื่อทำความเข้าใจแนวคิดที่fitsSystemWindowsว่าขึ้นอยู่กับมุมมองที่ทำในสิ่งที่แตกต่างกัน ตามเอกสารอย่างเป็นทางการมันคือไฟล์

แอตทริบิวต์ภายในบูลีนเพื่อปรับเค้าโครงมุมมองตามหน้าต่างระบบเช่นแถบสถานะ ถ้าเป็นจริงปรับขยายในมุมมองนี้ไปยังพื้นที่ลาสำหรับ Windows

ตอนนี้ตรวจสอบView.javaคลาสที่ฉันเห็นว่าเมื่อตั้งค่าtrueเป็นหน้าต่างที่แทรก (แถบสถานะแถบนำทาง ... นี่คือส่วนที่เกี่ยวข้องของรหัส:

private boolean fitSystemWindowsInt(Rect insets) {
    if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
        mUserPaddingStart = UNDEFINED_PADDING;
        mUserPaddingEnd = UNDEFINED_PADDING;
        Rect localInsets = sThreadLocal.get();
        if (localInsets == null) {
            localInsets = new Rect();
            sThreadLocal.set(localInsets);
        }
        boolean res = computeFitSystemWindows(insets, localInsets);
        mUserPaddingLeftInitial = localInsets.left;
        mUserPaddingRightInitial = localInsets.right;
        internalSetPadding(localInsets.left, localInsets.top,
                localInsets.right, localInsets.bottom);
        return res;
    }
    return false;
}

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

เอกสารประกอบViewCompat.javaสำหรับsetFitsSystemWindowsกล่าวว่า:

ตั้งค่าว่ามุมมองนี้ควรคำนึงถึงการตกแต่งหน้าจอระบบเช่นแถบสถานะและแทรกเนื้อหาหรือไม่ นั่นคือการควบคุมว่าจะดำเนินการใช้งาน {@link View # fitSystemWindows (Rect)} เริ่มต้นหรือไม่ ดูวิธีการที่สำหรับรายละเอียดเพิ่มเติม

ตามนี้fitsSystemWindowsหมายความว่าฟังก์ชันfitsSystemWindows()จะถูกเรียกใช้? คลาสวัสดุใหม่ดูเหมือนจะใช้สิ่งนี้สำหรับการวาดภาพใต้แถบสถานะ หากเราดูDrawerLayout.javaรหัสของเราจะเห็นสิ่งนี้:

if (ViewCompat.getFitsSystemWindows(this)) {
        IMPL.configureApplyInsets(this);
        mStatusBarBackground = IMPL.getDefaultStatusBarBackground(context);
    }

...

public static void configureApplyInsets(View drawerLayout) {
    if (drawerLayout instanceof DrawerLayoutImpl) {
        drawerLayout.setOnApplyWindowInsetsListener(new InsetsListener());
        drawerLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
    }
}

และเราเห็นรูปแบบเดียวกันในใหม่CoordinatorLayoutหรือAppBarLayout.

ไม่ได้ผลในทางตรงกันข้ามกับเอกสารสำหรับfitsSystemWindows? ในกรณีที่ผ่านมามันหมายถึงการวาดหลังบาร์ระบบ

อย่างไรก็ตามหากคุณต้องการFrameLayoutให้วาดตัวเองหลังแถบสถานะการตั้งค่าfitsSystemWindowsเป็นจริงจะไม่ทำเคล็ดลับเนื่องจากการใช้งานเริ่มต้นจะทำตามที่บันทึกไว้ในตอนแรก คุณต้องลบล้างและเพิ่มแฟล็กเดียวกันกับคลาสอื่น ๆ ที่กล่าวถึง ฉันพลาดอะไรไปรึเปล่า?


1
นี่ดูเหมือนจะเป็นข้อบกพร่องฉันได้โพสต์รายงานข้อบกพร่องบนตัวติดตามปัญหาของ Android
Tim Rae

1
ตรวจสอบที่นี่: medium.com/google-developers/…
Fatih S.

ขอบคุณสำหรับลิงค์มีประโยชน์มาก ยังคงยืนยันว่ามีความไม่สอดคล้องกันที่นั่น ในหน้าที่เชื่อมโยงระบุว่าบางส่วนของวิดเจ็ตใหม่เช่นCoordinatorLayoutใช้แฟล็กนั้นเพื่อสรุปว่าควรทาสีหลังแถบสถานะหรือไม่ นั่นไม่ใช่กรณีFrameLayoutตัวอย่างเช่น
ปักหมุด

2
นี่เป็นคำถามที่ยอดเยี่ยมและเป็นงานที่ดีมากในการค้นหาซอร์สโค้ด Android ฉันชื่นชมเป็นพิเศษที่คุณระบุว่าคลาส MD ใหม่จัดการกับ SystemWindows แตกต่างกันอย่างไร .... ฉันแทบจะบ้าที่พยายามคิดออก!
coolDude

คำตอบ:


19

หน้าต่างระบบเป็นส่วนของหน้าจอที่ระบบกำลังวาดเนื้อหาแบบไม่โต้ตอบ (ในกรณีของแถบสถานะ) หรือแบบโต้ตอบ (ในกรณีของแถบนำทาง)

โดยส่วนใหญ่แอปของคุณไม่จำเป็นต้องวาดใต้แถบสถานะหรือแถบนำทาง แต่ถ้าคุณทำคุณต้องแน่ใจว่าองค์ประกอบแบบโต้ตอบ (เช่นปุ่ม) ไม่ได้ซ่อนอยู่ข้างใต้ นั่นคือลักษณะการทำงานเริ่มต้นของแอตทริบิวต์ android: fitSystemWindows = "true": มันตั้งค่าช่องว่างภายในของมุมมองเพื่อให้แน่ใจว่าเนื้อหาจะไม่ซ้อนทับหน้าต่างระบบ

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


1
โอเคฉันเข้าใจ
MJ Studio

6

มันไม่ได้วาดอยู่หลังแถบระบบซึ่งจะยืดออกไปด้านหลังแถบเพื่อย้อมสีด้วยสีเดียวกันกับที่มี แต่มุมมองที่มีอยู่จะถูกบุไว้ภายในแถบสถานะหากเหมาะสม

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