ความสูงของแถบสถานะใน Android


332

ความสูงของแถบสถานะใน Android คืออะไร มันเหมือนเดิมหรือไม่

จากการวัดของฉันดูเหมือนว่ามันจะ 25dp แต่ฉันไม่แน่ใจว่ามันมีความสูงเท่ากันในทุกแพลตฟอร์มหรือไม่

(ฉันต้องการทราบสิ่งนี้ในการดำเนินการเปลี่ยนสีจางจากกิจกรรมที่ไม่มีแถบสถานะไปเป็นสถานะที่เหมาะสม)


หากคุณทำเครื่องหมายกากบาทจางคุณจะไม่จำเป็นต้องทราบความสูงของแถบสถานะ
stealthcopter

2
ฉันต้องการมันเพราะองค์ประกอบบางอย่างอยู่กึ่งกลางในเลย์เอาต์และฉันต้องการให้มันจางหายไปซึ่งกันและกัน
hpique

เป็นไปได้ที่ซ้ำกันของHeight of statusbar?
molnarm

คำตอบ:


363

คำถามนี้ตอบก่อน ... ความสูงของแถบสถานะ?

อัพเดท ::

วิธีการปัจจุบัน:

ตกลงความสูงของแถบสถานะขึ้นอยู่กับขนาดหน้าจอตัวอย่างเช่นในอุปกรณ์ที่มีขนาดหน้าจอ 240 X 320 ความสูงของแถบสถานะคือ 20px สำหรับอุปกรณ์ที่มีขนาดหน้าจอ 320 X 480 ความสูงของแถบสถานะคือ 25px สำหรับ อุปกรณ์ที่มี 480 x 800 ความสูงของแถบสถานะจะต้องเป็น 38px

ดังนั้นฉันแนะนำให้ใช้สคริปต์นี้เพื่อรับความสูงของแถบสถานะ

Rect rectangle = new Rect();
Window window = getWindow();
window.getDecorView().getWindowVisibleDisplayFrame(rectangle);
int statusBarHeight = rectangle.top;
int contentViewTop = 
    window.findViewById(Window.ID_ANDROID_CONTENT).getTop();
int titleBarHeight= contentViewTop - statusBarHeight;

   Log.i("*** Elenasys :: ", "StatusBar Height= " + statusBarHeight + " , TitleBar Height = " + titleBarHeight); 

(วิธีเก่า) เพื่อรับส่วนสูงของแถบสถานะบนonCreate()วิธีการกิจกรรมของคุณใช้วิธีนี้:

public int getStatusBarHeight() { 
      int result = 0;
      int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
      if (resourceId > 0) {
          result = getResources().getDimensionPixelSize(resourceId);
      } 
      return result;
} 

ไม่แน่นอน ฉันยังถามด้วยว่าฉันสามารถสันนิษฐานได้หรือไม่ว่าแถบสถานะนั้นมีความสูงเท่ากันในทุกอุปกรณ์
hpique

16
หรือใช้จุ่ม? หากมี 25dip อยู่เสมอก็ไม่จำเป็นต้องใช้รหัส
hpique

8
คุณไม่สามารถคาดเดาได้ว่ามันจะอยู่ที่ 25dp เสมอ (ดูความสูงของไฟที่จุดไฟ)
DallinDyer

1
ไม่ทำงานใน runnable ส่งผ่านไปยัง view.post () ใน onCreate () - ส่งคืน 0
Ixx

4
window.getDecorView().getWindowVisibleDisplayFrame(rectangle)ไม่ใช่วิธีที่ถูกต้องในการรับความสูงของแถบสถานะหากคุณอยู่ในโหมดหลายหน้าต่าง + หมุนตามแนวตั้ง + หน้าต่างที่สอง คุณจะได้รับค่ามาก (รวมความสูงที่ 1)
Tuan Chau

211

จากตัวอย่างโค้ดที่ฉันเคยใช้เพื่อให้ได้ความสูงของแถบสถานะมีเพียงอันเดียวที่ดูเหมือนจะใช้งานได้จริงในonCreateวิธีการของอันActivityนี้คือ:

public int getStatusBarHeight() {
    int result = 0;
    int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
    if (resourceId > 0) {
        result = getResources().getDimensionPixelSize(resourceId);
    }
    return result;
}

เห็นได้ชัดว่าความสูงที่แท้จริงของแถบสถานะจะถูกเก็บไว้เป็นทรัพยากร Android รหัสข้างต้นสามารถเพิ่มเข้าไปในContextWrapperชั้นเรียน (เช่น an Activity)

พบได้ที่http://mrtn.me/blog/2012/03/17/get-the-height-of-the-status-bar-in-android/


แทนที่จะเป็นการเข้ารหัสที่ยากควรคำนวณแบบไดนามิกดีกว่า วิธีการดังกล่าวได้ผลสำหรับฉัน!
นักเล่นแร่แปรธาตุ

คุณไม่ควรใช้ getDimension (... ) แทนใช่ไหม
นักพัฒนา android

6
คำเตือน - สิ่งนี้ไม่สามารถใช้ได้กับอุปกรณ์ทั้งหมด เช่นบน Transformer TF201 (เช่นเดียวกับ TF101, TF300 และอุปกรณ์อื่น ๆ ) ความสูงจะรายงานเป็น 25 โดยที่ไม่มีแถบสถานะ
Błażej Czapp

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

ใน XML ทรัพยากร dimen "@android: dimen / status_bar_height" สามารถใช้ได้ <! - ความสูงของแถบสถานะที่กำหนดในไฟล์ต้นฉบับระบบ Android -> <dimen name = "status_bar_height"> 24dp </dimen> แต่คุณไม่สามารถอ้างอิงโดยตรงในโครงการแอปของคุณ ดังนั้นคุณต้องใช้รหัส
Tshunglee

48

บนอุปกรณ์ MDPI แถบสถานะคือ 25px เราสามารถใช้สิ่งนี้เป็นฐานและคูณด้วยความหนาแน่น (ปัดขึ้น) เพื่อรับความสูงของแถบสถานะบนอุปกรณ์ใด ๆ :

int statusBarHeight = Math.ceil(25 * context.getResources().getDisplayMetrics().density);

สำหรับการอ้างอิง: ldpi = .75, mdpi = 1, hdpi = 1.5, xhdpi = 2


6
สิ่งนี้ถูกต้องสำหรับอุปกรณ์ที่มีแถบสถานะ โปรดทราบว่าตั้งแต่ที่เขียนข้างต้นมันกลายเป็นความจริงที่ว่าอุปกรณ์บางอย่างอาจไม่มี โดยเฉพาะอุปกรณ์ที่ใช้งาน ICS อาจมีสถานะ / แถบนำทางที่ด้านล่างและไม่มีอะไรอยู่ด้านบน ดังนั้นสำหรับกรณีดังกล่าวเพื่อจุดประสงค์ในการเขียนโปรแกรมส่วนใหญ่คุณต้องการกำหนดความสูงเป็นศูนย์ให้กับแถบสถานะ แต่การกำหนดสูตรด้านบนจะให้ขนาดที่ไม่เป็นศูนย์
Carl

1
นอกจากนี้ค่า 25px ไม่ถูกต้องสำหรับอุปกรณ์ mdpi ทั้งหมด มันอาจแตกต่างกันไปตามระดับ API ตัวอย่างเช่นอุปกรณ์จำลองแท็บเล็ต 10.1 WXGA รายงาน 25px ที่ API 16 & 19 แต่ 24px ที่ API 24
jk7

48

การเข้ารหัสขนาดหรือการใช้การสะท้อนกลับเพื่อให้ได้ค่าstatus_bar_heightถือว่าเป็นการปฏิบัติที่ไม่ดี คริส Banes พูดคุยเกี่ยวกับเรื่องนี้ในที่ Droidcon นิวยอร์ก วิธีที่แนะนำในการรับขนาดแถบสถานะคือผ่านOnApplyWindowInsetsListener :

myView.setOnApplyWindowInsetsListener { view, insets -> {
  val statusBarSize = insets.systemWindowInsetTop
  return insets
}

นี้ถูกบันทึกอยู่ใน API 20 และยังเป็นที่ backported ผ่านViewAppCompat


นี่เป็นคำตอบที่ถูกต้องที่สุดในวันนี้
คี ธ

สำหรับฉันนี่ไฟเพียงครั้งเดียวถ้าฉันมีชิ้นส่วนผ่าน nav ด้านล่าง ถ้าฉันเปลี่ยนแฟรกเมนต์อีกครั้งผู้ฟังรายนี้ไม่ได้รับการโทรเรียก
urSus

74
และยัง API นี้น่ากลัวเพราะจำนวน WTF / Gotchas เบื้องหลังคือใหญ่ คุณคิดว่าคุณสามารถทำได้ทุกมุมมอง แต่ไม่คุณต้องแทนที่สิ่งต่าง ๆ และให้แน่ใจว่าคุณส่งสิ่งที่ใส่เข้าไปให้ลูก ๆ ของคุณ (??) เพราะบางกลุ่มดูจะ (การออกแบบวัสดุ) และอื่น ๆ ทั้งหมดจะไม่ ( รูปแบบเชิงเส้น? ข้อ จำกัด เค้าโครง? สวัสดี?) แทนที่จะเป็นระบบที่มี Window.getStatusBarSize () ... เราต้องสมัครเป็นสมาชิกผู้ฟัง LISTENER …กลับบ้านไป Android คุณเมาแล้ว เพียงแค่ทำการ hardcode ขนาดจนกระทั่ง Google ตื่นขึ้นมาเราจะอยู่ในปี 2018 ฉันหวังว่า Chris Banes จะเห็นสิ่งนี้ในวันหนึ่ง ...
Martin Marconcini

ในกรณีของฉันมันไม่ได้ถูกไล่ออก ฉันใส่มันไว้ใน Activity # onCreated ฉันทำอะไรผิดหรือเปล่า? นอกจากนี้ทำไมเราไม่ใช้ mView.getRootWindowInsets ()
Adil Aliyev

34

ฉันได้รวมโซลูชันบางอย่างเข้าด้วยกัน:

public static int getStatusBarHeight(final Context context) {
    final Resources resources = context.getResources();
    final int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
    if (resourceId > 0)
        return resources.getDimensionPixelSize(resourceId);
    else
        return (int) Math.ceil((VERSION.SDK_INT >= VERSION_CODES.M ? 24 : 25) * resources.getDisplayMetrics().density);
    }

ทางเลือกอื่น:

    final View view = findViewById(android.R.id.content);
    runJustBeforeBeingDrawn(view, new Runnable() {
        @Override
        public void run() {
            int statusBarHeight = getResources().getDisplayMetrics().heightPixels - view.getMeasuredHeight();
        }
    });

แก้ไข: ทางเลือกในการเรียกใช้ JustBeforeBeingDrawn: https://stackoverflow.com/a/28136027/878126


getResources (). getDisplayMetrics (). heightPixels -getActivity (). findViewById (android.R.id.content) .getMeasuredHeight () ไม่ทำงานใน Android lolipop
abbasalim

@ ArMo372 คำตอบล่าสุด เป็นเพียงว่ามุมมองต้องผ่านการวัดก่อน คุณไม่จำเป็นต้องใช้ runJustBeforeBeingDrawn ถ้าคุณผ่านมันไปแล้ว คุณจะใช้มันเฉพาะในกรณีที่เร็วเกินไป
นักพัฒนา android

28

ตามแนวทางการออกแบบของ Google ; ความสูงของแถบสถานะคือ 24 dp

หากคุณต้องการความสูงของแถบสถานะเป็นพิกเซลคุณสามารถใช้วิธีการด้านล่าง:

private static int statusBarHeight(android.content.res.Resources res) {
    return (int) (24 * res.getDisplayMetrics().density);
}

ซึ่งสามารถเรียกใช้จากกิจกรรมด้วย:

statusBarHeight(getResources());

18
จนกระทั่ง Marshmallow มีค่า 25 dp ตั้งแต่ Marshmallow มันเป็น 24dp
Eugen Pechanec

1
นี่คือการเข้ารหัสฮาร์ดโค้ดซึ่งไม่อนุญาตให้มีการเปลี่ยนแปลงการออกแบบ
siliconeagle

1
และไม่ได้คำนึงถึงข้อเท็จจริงที่ว่าแถบสถานะจะไม่ปรากฏในกรณีเดียวกัน
jk7

19

ความสูงเริ่มต้นที่ใช้เป็น 25dp ด้วย Android Marshmallow (API 23) ความสูงจะลดลงเป็น 24dp

อัปเดต: โปรดทราบว่าตั้งแต่อายุของรอยหยักและการชกทั้งกล้องเริ่มต้นขึ้นการใช้ความสูงคงที่สำหรับแถบสถานะจะไม่ทำงานอีกต่อไป โปรดใช้ส่วนแทรกหน้าต่างแทน!


1
หวาน! ฉันเพิ่งสร้าง dimens.xml สำหรับระดับ API ขึ้นไปโดยเฉพาะที่ระดับความสูง 24dp
คนอยู่ที่ไหนสักแห่ง

18

สิ่งนี้ยังใช้งานได้กับลิงก์ refrence

public int getStatusBarHeight() {
  int result = 0;
  int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
  if (resourceId > 0) {
      result = getResources().getDimensionPixelSize(resourceId);
  }
  return result;
}

13

ฉันมีปัญหาแบบเดียวกันกับการได้รับความสูงของแถบสถานะใน onCreate มันใช้งานได้สำหรับฉัน

private static final int LOW_DPI_STATUS_BAR_HEIGHT = 19;

private static final int MEDIUM_DPI_STATUS_BAR_HEIGHT = 25;

private static final int HIGH_DPI_STATUS_BAR_HEIGHT = 38;

ภายในบนสร้าง:

DisplayMetrics displayMetrics = new DisplayMetrics();
((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(displayMetrics);

int statusBarHeight;

switch (displayMetrics.densityDpi) {
    case DisplayMetrics.DENSITY_HIGH:
        statusBarHeight = HIGH_DPI_STATUS_BAR_HEIGHT;
        break;
    case DisplayMetrics.DENSITY_MEDIUM:
        statusBarHeight = MEDIUM_DPI_STATUS_BAR_HEIGHT;
        break;
    case DisplayMetrics.DENSITY_LOW:
        statusBarHeight = LOW_DPI_STATUS_BAR_HEIGHT;
        break;
    default:
        statusBarHeight = MEDIUM_DPI_STATUS_BAR_HEIGHT;
}

ดู:

http://developer.android.com/reference/android/util/DisplayMetrics.html http://developer.android.com/guide/practices/ui_guidelines/icon_design.html


3
ฉันชอบความคิดของคุณในการใช้ค่าความหนาแน่น หากคุณจะใช้รหัสในหลาย ๆ ที่ (หรือใช้ค่าที่เกี่ยวข้องกับความหนาแน่นอื่น ๆ ) ฉันชอบที่จะลดปริมาณงานลงในระบบและเก็บค่าไว้ในทรัพยากรที่มีมิติซึ่งทำให้สวิตช์ไม่จำเป็น คุณจำเป็นต้องสร้างโฟลเดอร์และไฟล์เฉพาะมิติสำหรับแต่ละความหนาแน่น ทรัพยากรสุดท้าย res = context.getResources (); int statusbarHeight = 0; ลอง {statusbarHeight = res.getDimensionPixelSize (R.dimen.android_statusbar_height); } catch (NotFoundException e) {}
ProjectJourneyman

5
การ Hardcoding ค่าเหล่านี้เป็นอันตรายจะเกิดอะไรขึ้นถ้าพวกเขาเปลี่ยนแปลงในเวอร์ชันแพลตฟอร์มในภายหลัง
David Snabel-Caunt

ฉันคิดว่าแทนที่จะใช้ขนาดพิกเซล hardcoded (หนึ่งอันสำหรับแต่ละความหนาแน่น) ควรใช้ "25dp"
นักพัฒนา android


12

ใช่เมื่อฉันลองดูด้วยจะให้ผลลัพธ์ 25px นี่คือรหัสทั้งหมด:

public class SpinActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LinearLayout lySpin = new LinearLayout(this);
        lySpin.setOrientation(LinearLayout.VERTICAL);       
        lySpin.post(new Runnable()
        {
            public void run()
            {
                Rect rect = new Rect();
                Window window = getWindow();
                window.getDecorView().getWindowVisibleDisplayFrame(rect);
                int statusBarHeight = rect.top;
                int contentViewTop = 
                    window.findViewById(Window.ID_ANDROID_CONTENT).getTop();
                int titleBarHeight = contentViewTop - statusBarHeight;
                System.out.println("TitleBarHeight: " + titleBarHeight 
                    + ", StatusBarHeight: " + statusBarHeight);
            }
        }
    }
}

โค้ดด้านบนใช้งานได้สำหรับฉันเมื่อฉันสร้างเลย์เอาต์แบบเชิงเส้นใหม่ตามที่คุณได้ทำไปแล้ว แต่เมื่อฉันหา findviewbyid สำหรับ lySpin จาก xml จากนั้นจะส่งคืน null ไม่เข้าใจมันทำเช่นนั้น
Shaista Naaz

เนื่องจากเลย์เอาต์ไม่ทราบขนาดของมันอยู่ใน onCreate เพราะยังไม่ได้วาดเสร็จ สิ่งที่ฉันมักจะทำคือโพสต์ Runnable บนเธรด UI จาก onCreate ซึ่งให้เวลา UI ในการวาดเอง
Jason Robinson


7

ลองสิ่งนี้:

    Rect rect = new Rect();
    Window win = this.getWindow();
    win.getDecorView().getWindowVisibleDisplayFrame(rect);
    int statusBarHeight = rect.top;
    int contentViewTop = win.findViewById(Window.ID_ANDROID_CONTENT).getTop();
    int titleBarHeight = contentViewTop - statusBarHeight;
    Log.d("ID-ANDROID-CONTENT", "titleBarHeight = " + titleBarHeight );

มันไม่ได้ผลสำหรับฉันในวิธี onCreate สำหรับกิจกรรม แต่ทำเมื่อฉันใส่ไว้ใน onClickListener และให้ค่าการวัด 25


ฉันสงสัยว่า ณ จุดที่เขาทดสอบใน onCreate () แถบสถานะยังไม่ได้ถูกสร้างขึ้น ในทางตรงกันข้ามเมื่อเขาคลิกเพื่อเปิดใช้งานรหัส onClickListener () ของเขาด้วยตนเองแถบนั้นก็มีเวลาคิดจำนวนมากที่จะแสดงและเขาก็สามารถดึงขนาดของมันได้
คาร์ล

6

ความสูงของแถบสถานะคือ 24dp ใน android 6.0

 <!-- Height of the status bar -->
 <dimen name="status_bar_height">24dp</dimen>
 <!-- Height of the bottom navigation / system bar. -->
 <dimen name="navigation_bar_height">48dp</dimen>

คุณสามารถหาคำตอบได้ในซอร์สโค้ด: frameworks \ base \ core \ res \ res \ values ​​\ dimens.xml


มีวิธีการรับทรัพยากรนี้ใน XML ของเราหรือไม่ @android:dimen/status_bar_heightไม่ได้ผลสำหรับฉัน
Patrick

4

เพื่อแก้ปัญหานี้ฉันใช้วิธีการรวมกัน สิ่งนี้จำเป็นสำหรับแท็บเล็ตที่แถบระบบจะลบพิกเซลเมื่อ display.getHeight () ถูกเรียกใช้ ดังนั้นก่อนอื่นให้ตรวจสอบว่ามีแถบของระบบอยู่หรือไม่จากนั้น Ben Claytons เข้าใกล้ซึ่งทำงานได้ดีบนโทรศัพท์

public int getStatusBarHeight() {
    int statusBarHeight = 0;

    if (!hasOnScreenSystemBar()) {
        int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            statusBarHeight = getResources().getDimensionPixelSize(resourceId);
        }
    }

    return statusBarHeight;
}

private boolean hasOnScreenSystemBar() {
    Display display = getWindowManager().getDefaultDisplay();
    int rawDisplayHeight = 0;
    try {
        Method getRawHeight = Display.class.getMethod("getRawHeight");
        rawDisplayHeight = (Integer) getRawHeight.invoke(display);
    } catch (Exception ex) {
    }

    int UIRequestedHeight = display.getHeight();

    return rawDisplayHeight - UIRequestedHeight > 0;
}

3

ขอบคุณ@Niklas +1 นี่เป็นวิธีที่ถูกต้องที่จะทำ

public class MyActivity extends Activity implements android.support.v4.View.OnApplyWindowInsetsListener {

    Rect windowInsets;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.my_activity);

        View rootview = findViewById(android.R.id.content);

        android.support.v4.View.ViewCompat.setOnApplyWindowInsetsListener(rootview, this);
    }

    android.support.v4.View.WindowInsetsCompat android.support.v4.View.OnApplyWindowInsetsListener.OnApplyWindowInsets(View v, android.support.v4.View.WindowInsetsCompat insets)
    {
        windowInsets = new Rect();
        windowInsets.set(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(), insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom());
        //StatusBarHeight = insets.getSystemWindowInsetTop();

        //Refresh/Adjust view accordingly

        return insets;
    }
}

โปรดแก้ตัวฉันหากรหัสไม่ถูกต้อง 100% แปลงจาก Xamarin C # แต่นี่เป็นเพียงของมัน ใช้งานได้กับ Notches ฯลฯ


2

โซลูชันเต็มหน้าจอที่ถูกจับคู่:

วิธีการแก้ปัญหานี้อาจดูเหมือนวิธีแก้ปัญหา แต่จริง ๆ แล้วบัญชีว่าแอปของคุณเป็นแบบเต็มหน้าจอ (หรือที่ซ่อนแถบสถานะ) หรือไม่:

Display display = getWindowManager().getDefaultDisplay();
Point size = new Point(); display.getSize(size);
int barheight = size.y - findViewById(R.id.rootView).getHeight();

วิธีนี้หากแอปของคุณเต็มหน้าจอในปัจจุบันbarheightจะเท่ากับ 0

โดยส่วนตัวฉันต้องใช้สิ่งนี้เพื่อแก้ไขพิกัด TouchEvent สัมบูรณ์ให้กับบัญชีสำหรับแถบสถานะดังนี้:

@Override
public boolean onTouch(View view,MotionEvent event) {
    Display display = getWindowManager().getDefaultDisplay();
    Point size = new Point(); display.getSize(size);
    int YCoord = (int)event.getRawY() - size.y + rootView.getHeight());
}

และนั่นจะได้รับพิกัด y ที่แน่นอนไม่ว่าจะเป็นแอปแบบเต็มหน้าจอหรือไม่

สนุก


ขอบคุณนี่เป็นทางออกเดียวที่ทำงานสำหรับฉันเมื่อแป้นพิมพ์ Android กำลังแสดงเกินไป
Thiago Moura

2

บน Android 4.1 และสูงกว่าคุณสามารถตั้งค่าเนื้อหาแอปพลิเคชันของคุณให้ปรากฏด้านหลังแถบสถานะเพื่อให้เนื้อหาไม่ปรับขนาดเนื่องจากแถบสถานะจะซ่อนและแสดง หากต้องการทำสิ่งนี้ให้ใช้ SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN คุณอาจต้องใช้ SYSTEM_UI_FLAG_LAYOUT_STABLE เพื่อช่วยให้แอปของคุณรักษาเลย์เอาต์ที่เสถียร

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

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

แบบฟอร์ม: https://developer.android.com/training/system-ui/status.html#behind


1

ถ้าคุณรู้ว่าขนาด VS สูง

ชอบ

ตัวอย่างเช่นในอุปกรณ์ที่มีขนาดหน้าจอ 320 X 480 ความสูงของแถบสถานะคือ 25px สำหรับอุปกรณ์ที่มี 480 x 800 ความสูงของแถบสถานะต้องเป็น 38px

จากนั้นคุณสามารถรับความกว้างของมุมมอง / ขนาดหน้าจอคุณสามารถใช้คำสั่ง if else เพื่อรับความสูงของแถบสถานะ


จากประสบการณ์ของฉันความสูงนั้นขึ้นอยู่กับความหนาแน่นมากกว่าขนาดหน้าจอ แน่นอนว่าความหนาแน่นมักเกี่ยวข้องกับขนาดหน้าจอดังนั้นจึงมีความสัมพันธ์ทางอ้อม ตัวอย่างเช่น Moto Droid เก่าของฉันมีจอแสดงผล 480x854 (แทนที่จะเป็น 480x800) และแถบสถานะก็สูง 38 พิกเซลเช่นกัน
คาร์ล

พวกเขาคิดค้น DP สำหรับสิ่งนี้ (พิกเซลอิสระหนาแน่น)
Roel

1

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

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    final ViewGroup decorView = (ViewGroup) this.getWindow().getDecorView();
    decorView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            if (Build.VERSION.SDK_INT >= 16) {
                decorView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            } else {
                // Nice one, Google
                decorView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            }
            Rect rect = new Rect();
            decorView.getWindowVisibleDisplayFrame(rect);
            rect.top; // This is the height of the status bar
        }
    }
}

นี่เป็นวิธีที่น่าเชื่อถือที่สุด


1
@androiddeveloper OnGlobal! = GlobalOn
marijnz0r

@ marijnz0r มันช่างแปลกจริงๆ การจัดการกับสิ่งนั้นคืออะไร?
นักพัฒนา android

@androiddeveloper ฉันไม่รู้ แต่ฉันก็คิดแบบเดียวกับที่คุณทำเมื่อสองสามวันก่อนเช่นกัน ดู: stackoverflow.com/a/19216041/4587214
marijnz0r

@ marijnz0r ดังนั้นทั้งคู่ก็ทำเช่นเดียวกัน เตือนฉันถึงกรณีอื่น ๆ ที่พวกเขาตั้งชื่อใหม่ให้กับสิ่งที่มีอยู่แล้วและเลิกใช้ก่อนหน้านี้ ตัวอย่าง "fill_parent" vs "match_parent": developer.android.com/reference/android/view/
นักพัฒนาซอฟต์แวร์ Android

1

เนื่องจากโหมดหลายหน้าต่างพร้อมใช้งานในขณะนี้แอปของคุณอาจไม่มีแถบสถานะอยู่ด้านบน

โซลูชันต่อไปนี้จัดการทุกกรณีโดยอัตโนมัติเพื่อคุณ

android:fitsSystemWindows="true"

หรือเป็นโปรแกรม

findViewById(R.id.your_root_view).setFitsSystemWindows(true);

คุณยังสามารถดูรูทได้ด้วย

findViewById(android.R.id.content).getRootView();
or
getWindow().getDecorView().findViewById(android.R.id.content)

สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับการรับรูทดู - https://stackoverflow.com/a/4488149/9640177


0

เมื่อเร็ว ๆ นี้ปัญหานี้มีความเกี่ยวข้องกับฉันเพราะรอยขีดข่วนใน Pixel 3XL ของฉัน ฉันชอบวิธีแก้ปัญหาของนักพัฒนาระบบ Androidแต่ฉันต้องการที่จะรับความสูงของแถบสถานะได้ตามต้องการเพราะมันเป็นสิ่งจำเป็นสำหรับภาพเคลื่อนไหวแบบเต็มหน้าจอที่ฉันต้องการเล่นโดยเฉพาะ ฟังก์ชั่นด้านล่างเปิดใช้งานแบบสอบถามที่เชื่อถือได้:

private val DEFAULT_INSET = 96
fun getInsets(view: View?): Int {
     var inset = DEFAULT_INSET
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {//Safe because only P supports notches
          inset = view?.rootWindowInsets?.stableInsetTop ?: DEFAULT_INSET
     }
     return inset
}

fun blurView(rootView: View?, a: SpacesActivity?) {
    val screenBitmap = getBitmapFromView(rootView!!)
    val heightDifference = getInsets(rootView)
    val croppedMap = Bitmap.createBitmap(
                    screenBitmap, 0, heightDifference,
                    screenBitmap.width,
                    screenBitmap.height - heightDifference)
    val blurredScreen = blurBitmap(croppedMap)
    if (blurredScreen != null) {
         val myDrawable = BitmapDrawable(a!!.resources, blurredScreen)
         a.errorHudFrameLayout?.background = myDrawable
         a.appBarLayout?.visibility = View.INVISIBLE
   }
}

แล้วในชั้นเรียนกิจกรรม:

fun blurView() {
    this.runOnUiThread {
        Helper.blurView(this)
    }
}

แน่นอนว่าคุณจะต้องการส่งผ่านการอ้างอิงที่อ่อนแอของกิจกรรมไปยังพารามิเตอร์เมธอดคลาส Helper แบบสแตติก แต่เพื่อความกะทัดรัดที่ฉันงดเว้นในตัวอย่างนี้ blurBitmapและerrorHudFrameLayoutจะถูกตัดออกด้วยเหตุผลเดียวกันเนื่องจากพวกเขาไม่ได้เกี่ยวข้องโดยตรงกับการได้รับความสูงของแถบสถานะ


หากเป็น Android P ขึ้นไปตรวจสอบกับ Android M ทำไม นอกจากนี้คุณจะทำอย่างไรถ้าคุณไม่มีอินสแตนซ์ดู ตัวอย่างเช่นถ้าคุณไม่มีกิจกรรมในปัจจุบัน ...
นักพัฒนา android

M เป็นสิ่งที่เร็วที่สุดที่คุณสามารถตรวจสอบ stableInsetTop ได้และถึงแม้ว่ามีเพียงรอย P ที่สนับสนุนเท่านั้นที่ฉันควรจะได้รับสิ่งที่ใส่เข้าไปจริงเป็นไปได้แทนการย้อนกลับไปสู่ค่าเริ่มต้นที่ฉันสามารถทำได้ วิธีนี้ไม่ได้ผลหากคุณไม่มีกิจกรรม
James Jordan Taylor

ฉันเห็น. ขอบคุณ. คุณช่วยกรุณาแสดงตัวอย่าง "เต็ม" เพิ่มเติมได้หรือไม่
นักพัฒนา android

ฉันเปลี่ยนคำตอบของฉันด้านบนเพื่อใช้วิธีในตัวอย่าง
James Jordan Taylor

0

รุ่น Kotlin ที่รวมสองโซลูชั่นที่ดีที่สุด

fun getStatusBarHeight(): Int {
    val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android")
    return if (resourceId > 0) resources.getDimensionPixelSize(resourceId)
    else Rect().apply { window.decorView.getWindowVisibleDisplayFrame(this) }.top
}
  1. รับstatus_bar_heightค่าถ้ามี
  2. หากstatus_bar_heightไม่มีอยู่ให้คำนวณความสูงของแถบสถานะจากการตกแต่งหน้าต่าง
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.