Android :狀態欄的高度獲取、getWindowVisibleDisplayFrame

獲取狀態欄高度


    /**
     * 方式一: 通過反射獲取狀態欄高度
     */
    @SuppressLint("PrivateApi")
    private fun getStatusBarHeight(context: Context): Int {
        var statusbarheight = 0
        try {
            val c = Class.forName("com.android.internal.R\$dimen")
            val o = c.newInstance()
            val field: Field = c.getField("status_bar_height")
            val x = field.get(o) as Int
            statusbarheight = context.getResources().getDimensionPixelSize(x)
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return statusbarheight
    }

    /**
     * 方式二:通過getWindowVisibleDisplayFrame方法獲取狀態欄高度
     */
    private fun getStatusBarHeight(view: View): Int {
        val outRect = Rect()
        view.getWindowVisibleDisplayFrame(outRect)
        return outRect.top
    }

測試:

et_receive_comment.viewTreeObserver.addOnGlobalLayoutListener {
    //獲取狀態欄高度
    val statusBarHeight1 = getStatusBarHeight(et_receive_comment)
    println("statusBarHeight1=================================$statusBarHeight1")
    val statusBarHeight2 = getStatusBarHeight(et_receive_comment.context)
    println("statusBarHeight2=================================$statusBarHeight2")
}

view.parent 與 view.rootView

et_receive_comment.viewTreeObserver.addOnGlobalLayoutListener {
    //父view
    val parent = et_receive_comment.parent
    
    //根view : DecorView 
    val rootView = et_receive_comment.rootView
    println("parent======================$parent")
    println("rootView======================$rootView")
    //DecorView 高度不會變
    val rootViewHeight = et_receive_comment.rootView.height
    println("DecorView 高度======================$rootViewHeight")//1520
}

一、使用工具類獲取狀態欄,導航欄,標題欄高度:

https://github.com/Blankj/AndroidUtilCode

implementation 'com.blankj:utilcodex:1.28.3'
Log.e(TAG, "getScreenHeight========" + ScreenUtils.getScreenHeight())//1520
Log.e(TAG, "getActionBarHeight========" + BarUtils.getActionBarHeight())//112
Log.e(TAG, "getNavBarHeight===========" + BarUtils.getNavBarHeight())//80
Log.e(TAG, "getStatusBarHeight========" + BarUtils.getStatusBarHeight())//55

二、decorView.getWindowVisibleDisplayFrame獲取狀態欄高度


override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
  
    gallery.viewTreeObserver
        .addOnGlobalLayoutListener {
            Log.e(TAG, "=============================================================")

            val decorView = window.decorView
            Log.e(TAG, "decorView ===================== $decorView")
            Log.e(TAG, "decorView.height ===================== ${decorView.height}")//1520

            //decorView.getWindowVisibleDisplayFrame
            //注意:
            //1、rect.top/bottom/height的值不會隨着主題NoActionBar變化
            //2、rect.bottom/height 的值會隨着軟鍵盤的打開而變小
            val rect = Rect()
            decorView.getWindowVisibleDisplayFrame(rect)
            Log.e(TAG, "rect.top ===================== ${rect.top}")//55
            Log.e(TAG, "rect.bottom ================== ${rect.bottom}")//1440
            Log.e(TAG, "rect height ================== ${rect.bottom - rect.top}")//1385

            //decorView.findViewById<View>(Window.ID_ANDROID_CONTENT)
            //view.top/bottom : 相對父容器
            val contentTop = decorView.findViewById<View>(Window.ID_ANDROID_CONTENT).top
            val contentBottom = decorView.findViewById<View>(Window.ID_ANDROID_CONTENT).bottom
            val contentHeight = contentBottom - contentTop
            //注意:
            //1、如果設置NoActionBar的主題contentTop爲0, contentBottom = contentHeight = 1385
            //2、contentBottom/height 的值會隨着軟鍵盤的打開而變小
            Log.e(TAG, "content top ================== $contentTop")//112 / 0
            Log.e(TAG, "content bottom ================== $contentBottom")//1385
            Log.e(TAG, "content height ================== $contentHeight")//1273 / 1385

            Log.e(TAG, "狀態欄高度 ================== ${rect.top}")//55
            Log.e(TAG, "標題欄高度 ================== $contentTop")//112 / 0
            Log.e(TAG, "內容高度 ================== $contentHeight")//1273

            //獲取content的方式有以下兩種方式
            // 打印結果一致:
            iteratorContentView1()
            iteratorContentView2()
        }
}

private fun iteratorContentView1() {
    val contentView1 = window.decorView.findViewById<View>(Window.ID_ANDROID_CONTENT)
    Log.e(TAG, "contentView1=================$contentView1")
    //androidx.appcompat.widget.ContentFrameLayout
    // {8b0458c V.E...... .......D 0,112-720,1385 #1020002 android:id/content}
    if (contentView1 is FrameLayout) {
        val childCount = contentView1.childCount
        for (i in 0 until childCount) {
            val childView = contentView1.getChildAt(i)
            Log.e(TAG, "$i=================$childView")
            //我們自己的佈局
            //0 === androidx.constraintlayout.widget.ConstraintLayout
            // {e8674d5 V.E...... .......D 0,0-720,1273 #7f080058 app:id/container}
        }
    }
}

private fun iteratorContentView2() {
    val contentView2 = this.findViewById<View>(android.R.id.content)
    Log.e(TAG, "contentView2=================$contentView2")
    if (contentView2 is FrameLayout) {
        val childCount = contentView2.childCount
        for (i in 0 until childCount) {
            val childView = contentView2.getChildAt(i)
            Log.e(TAG, "$i=================$childView")
        }
    }
}

在這裏插入圖片描述

view樹結構

帶標題的界面佈局

<androidx.constraintlayout.widget.ConstraintLayout
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">



</androidx.constraintlayout.widget.ConstraintLayout>

查看view樹結構 :

  • class com.android.internal.policy.DecorView
    • android.widget.LinearLayout{}
      • android.view.ViewStub{android:id/action_mode_bar_stub}
      • android.widget.FrameLayout{}
        • androidx.appcompat.widget.ActionBarOverlayLayout{app:id/decor_content_parent}
          • androidx.appcompat.widget.ContentFrameLayout{android:id/content}
            • androidx.constraintlayout.widget.ConstraintLayout{app:id/container}
              • 自己的佈局…
          • androidx.appcompat.widget.ActionBarContainer{app:id/action_bar_container}
            • androidx.appcompat.widget.Toolbar{app:id/action_bar}
              • androidx.appcompat.widget.AppCompatTextView{}
            • androidx.appcompat.widget.ActionBarContextView{app:id/action_context_bar}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章