Android定制透明悬浮StatusBar 多分辨率适配

Posted 苦逼程序员_

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android定制透明悬浮StatusBar 多分辨率适配相关的知识,希望对你有一定的参考价值。

定制透明悬浮StatusBar 多分辨率适配

  1. 修改statusBar需要修改framework下的systemUI,systemUI的目录位于frameworks/base/packages/SystemUI
  2. 设计自定义View(TBarView),放到目录SystemUI的src/com/android/systemui/statusbar下.
  3. 对于TBarView做不同分辨率适配,需要在SystemUI的res/values-480x240,res/values-864x480等不同分辨率下创建对应的dimens.xml
  4. 需要在framework-res下增加status_bar_width并做不同分辨率适配,在framworks/base/core/res/res下创建文件夹values-480x240和values-864x480,并各自创建一个dimens.xml
  5. 在不同文件夹dimens.xml中增加<dimen name="status_bar_width">130dp</dimen>
  6. 在frameworks/base/core/res/res/values/symbols.xml中增加<java-symbol type="dimen" name="status_bar_width" />,只有增加后才能在system其他位置通过com.android.internal.R.dimen.status_bar_width引用到该资源
  7. 进入src/com/android/systemui/statusbar/phone,复制一份PhoneStatusBar到src/com/android/systemui/statusbar/改名为MyStatusBar,修改R.layout.status_bar布局,加入自定义view,在addStatusBarWindow()中通过getDimension(com.android.internal.R.dimen.status_bar_width)获取statusBar的宽度,初始化LayoutParams时传入宽度和高度。
  8. 修改src/com/android/systemui/statusbar/SystemBars,createStatusBarFromConfig(), Class<?> cls = MyStatusBar.class;(后来才发现,SystemBars初始化StatusBar是可以动态配置的,不需要修改SystemBars的任何代码,因为SystemBars是读取res/values/config.xml里面config_statusBarComponent获取到StatusBar的全路径类名,所以只要修改config.xml文件把com.android.systemui.statusbar.phone.PhoneStatusBar,修改为com.android.systemui.statusbar.MyStatusBar即可)
  9. 修改frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager(这是实际控制statusBar占据屏幕范围的类)
  10. 在原生系统中,statusBar是从上往下占据一定位置的,所以系统中会读取com.android.internal.R.dimen.status_bar_height到mStatusBarHeight变量中,而这里定制的系统statusBar是从右到左占据屏幕一定位置的,所以仿照mStatusBarHeight的逻辑,创建变量mStatusBarWidth:mStatusBarWidth = (int)mContext.getResources().getDimension(com.android.internal.R.dimen.status_bar_width);
  11. 修改PhoneWindowManager,getConfigDisplayWidth(),返回屏幕宽度减去mStatusBarWidth宽度。getConfigDisplayHeight(),返回整个屏幕的高度。
  12. 修改PhoneWindowManager,selectAnimationLw()if (win == mStatusBar)部分,进入显示动画改成R.anim.dock_right_enter,退出隐藏动画改成R.anim.dock_right_exit
  13. 修改PhoneWidowManager,beginLayoutLw(),分别修改 mStableLeft = mUnrestrictedScreenLeft;, mStableRight = mUnrestrictedScreenWidth - mStatusBarWidth;, mDockLeft = mUnrestrictedScreenLeft;, mDockRight = mUnrestrictedScreenWidth - mStatusBarWidth;, mSystemLeft = mUnrestrictedScreenLeft;, mSystemRight = mUnrestrictedScreenWidth - mStatusBarWidth;
  14. 修改PhoneWindowManager,getSystemDecorLayerLw(), if (mStatusBar != null) return 0;,配合SystemUI/res/layout/status_bar.xml, android:background="#00000000",实现透明背景导航栏,参考Android 设置系统SystemUI 顶部StatusBar状态栏透明一体化

在app中使透明状态栏悬浮在上方

对于静态的情况,只需要activity增加android:windowTranslucentStatus到style中即可实现

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:windowTranslucentStatus">true</item>
</style>

对于动态切换悬浮和非悬浮状态的情况,有两种方案可用:

  1. 使用静态方案,在切换到非悬浮的状态时,对Activity设置padding值,使padding值与statusBar的宽度或高度相等;而切换到悬浮状态时,取消Activity设置的padding值恢复到之前的状态。
  2. Activity动态设置android:windowTranslucentStatus状态,参考资料:fitSystemWindows programmatically for status bar transparency
if(test)
    Log.d(TAG, "fit true ");
    relativeLayout.setFitsSystemWindows(true);
    relativeLayout.requestFitSystemWindows();
    getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
else 
    Log.d(TAG, "fit false");
    relativeLayout.setFitsSystemWindows(false);
    relativeLayout.requestFitSystemWindows();
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

以上是关于Android定制透明悬浮StatusBar 多分辨率适配的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Flutter 中使 StatusBar 对 Android 透明

Android棒棒糖中的透明actionBar和statusBar

Lollipop:在 statusBar 后面绘制,其颜色设置为透明

android 透明状态栏方法及其适配键盘上推

android v7包里的Toolbar,怎么定制图标,字体居中的效果

android 状态栏梳理