美文网首页Android技术知识Android开发Android开发
Android - 让视图文件显示到状态栏下,且不受底部虚拟按键

Android - 让视图文件显示到状态栏下,且不受底部虚拟按键

作者: Cosecant | 来源:发表于2018-12-17 18:04 被阅读0次

    Android - 让视图文件显示到状态栏下,且不受底部导航虚拟按键影响

    最新需要实现这个功能,琢磨了半天,网上也查找了一些资料,不过都是零零散散的,而且大部分是xml实现的,现在我用代码大致来实现一下这个功能。

    第一步,获取状态栏高度,底部虚拟导航按键高度

    /**
         * 获取状态栏高度
         *
         * @param context 上下文对象
         */
        @SuppressLint("PrivateApi")
        @JvmStatic
        fun getStatusBarHeight(context: Context): Int = try {
            val c: Class<*>? = Class.forName("com.android.internal.R\$dimen")
            val obj: Any? = c?.newInstance()
            val field: Field? = c?.getField("status_bar_height")
            if (obj != null && field != null) {
                field.isAccessible = true
                val x = Integer.parseInt(field.get(obj).toString())
                context.resources.getDimensionPixelSize(x)
            } else {
                75
            }
        } catch (e1: Exception) {
            Log.d("ApkUtil", "get status bar height fail")
            e1.printStackTrace()
            75
        }
    
        /**
         * 获取底部导航栏高度
         *
         * @param context
         * @return
         */
        @JvmStatic
        fun getNavigationBarHeight(context: Context): Int {
            if (!isHasNavBar(context)) return 0
            val resourceId: Int
            val rid = context.resources.getIdentifier("config_showNavigationBar", "bool", "android")
            return if (rid != 0) {
                resourceId = context.resources.getIdentifier("navigation_bar_height", "dimen", "android")
                context.resources.getDimensionPixelSize(resourceId)
            } else {
                0
            }
        }
    
        /**
         * 判断虚拟按键栏是否重写
         *
         * @return
         */
        private val navBarOverride: String?
            @SuppressLint("PrivateApi")
            get() {
                var sNavBarOverride: String? = null
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                    try {
                        val c = Class.forName("android.os.SystemProperties")
                        val m = c.getDeclaredMethod("get", String::class.java)
                        m.isAccessible = true
                        sNavBarOverride = m.invoke(null, "qemu.hw.mainkeys") as String
                    } catch (e: Throwable) {
                    }
    
                }
                return sNavBarOverride
            }
    
        /**
         * 检查是否存在虚拟按键栏
         *
         * @param context
         * @return
         */
        @JvmStatic
        @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
        fun isHasNavBar(context: Context): Boolean {
            val res = context.resources
            val resourceId = res.getIdentifier("config_showNavigationBar", "bool", "android")
            return when {
                resourceId != 0 -> {
                    var hasNav = res.getBoolean(resourceId)
                    // check override flag
                    val sNavBarOverride = navBarOverride
                    if ("1" == sNavBarOverride) {
                        hasNav = false
                    } else if ("0" == sNavBarOverride) {
                        hasNav = true
                    }
                    hasNav
                }
                else -> // fallback
                    !ViewConfiguration.get(context).hasPermanentMenuKey()
            }
        }
    

    第二步,处理Activity的Window的Flag属性

    override fun onCreate(...){
        window.requestFeature(Window.FEATURE_NO_TITLE)
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                       
      window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
                    window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
                    window.statusBarColor = Color.TRANSPARENT
                    window.navigationBarColor = Color.BLACK
                }
    }
    

    第三步,添加视图到Activity的RootView(DecorView)中

      setContentView(
                            contentView,
                            WindowManager.LayoutParams(
                                WindowManager.LayoutParams.MATCH_PARENT,
                                WindowManager.LayoutParams.MATCH_PARENT
                            )
                        )
    

    第四步,动态监听布局变化,动态设置导航栏高度

    /** 根据导航栏高度判断页面布局 **/
        private fun setContentViewLayoutParamsByNavigationBarHeight() {
            val navigationBarHeight by lazy { ApkUtil.getNavigationBarHeight(this@PActivity) }
            val lp: FrameLayout.LayoutParams?
            if (navigationBarHolderView == null) {
                navigationBarHolderView = View(this)
                navigationBarHolderView?.setBackgroundColor(Color.BLACK)
                lp = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, navigationBarHeight)
                lp.gravity = Gravity.BOTTOM
                this@PActivity.rootView.addView(navigationBarHolderView, lp)
            } else {
                lp = navigationBarHolderView?.layoutParams as? FrameLayout.LayoutParams
                lp?.height = navigationBarHeight
                navigationBarHolderView?.layoutParams = lp
            }
            binder.root.setPadding(0, 0, 0, navigationBarHeight)
        }
    
        override fun onGlobalLayout() {
            if (isContentViewAttachScreenTop)
                setContentViewLayoutParamsByNavigationBarHeight()
        }
    
        override fun onResume() {
            if (isContentViewAttachScreenTop)
                rootView.viewTreeObserver.addOnGlobalLayoutListener(this)
            super.onResume()
        }
    
        override fun onStop() {
            super.onStop()
            if (isContentViewAttachScreenTop) {
                @Suppress("DEPRECATION")
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
                    rootView.viewTreeObserver.removeOnGlobalLayoutListener(this)
                else
                    rootView.viewTreeObserver.removeGlobalOnLayoutListener(this)
            }
        }
    

    先写成这个样子,后面我有时间会再来修改的!

    相关文章

      网友评论

        本文标题:Android - 让视图文件显示到状态栏下,且不受底部虚拟按键

        本文链接:https://www.haomeiwen.com/subject/lxbckqtx.html