Android技术知识Android开发Android开发

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

2018-12-17  本文已影响0人  Cosecant

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

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

上一篇下一篇

猜你喜欢

热点阅读