(2017)Android技能状态栏(StatusBar)解析
博客专区 > HzhiBo 的博客 > 博客详情
(2017)Android技能状态栏(StatusBar)解析
HzhiBo 发表于5个月前
(2017)Android技能状态栏(StatusBar)解析
  • 发表于 5个月前
  • 阅读 154
  • 收藏 2
  • 点赞 0
  • 评论 0

腾讯云 十分钟定制你的第一个小程序>>>   

摘要: 这里只是先介绍下如何在开发中玩转StatusBar的自定义颜色让您的APP更美腻,其次在深度分析StatusBar的机制

这里先说明下

  • android 4.4版本以上才支持开发者对StatusBar全透明
  • android 5.0版本以上支持 可以修改 StatusBar 的颜色

都知道大家都是<图片党加项目党>,所以我就用文字和工程项目给大家讲解我的理解,有误还请不吝赐教啊。

工程中的Stytes.xml文件:

  <!-- Base application theme.(APP的基本主题设置 白色底无导航栏主题) -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item> 
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

item的中三个参数都是啥呢? 看下面(图片党的看来)

colorPrimary:顶部导航栏颜色(一般自定义布局,忽略)

colorPrimaryDark:状态栏背景颜色

colorAccent是光标,编辑框底下横线的颜色

对于属性还有很多妙用,这里在贴出一张图,大家可以去查阅下(深究的去看源码这里推荐一个网站http://androidxref.com/)或者(在你所装的SDK的这个目录android-sdk-windows\platforms\android-3\data\res\values 有个themes.xml的文件!)

 <style name="Theme.Light">
        <item name="windowBackground">@android:drawable/screen_background_selector_light</item>
        <item name="colorBackground">@android:color/background_light</item>
        <item name="colorForeground">@color/bright_foreground_light</item>
        <item name="colorForegroundInverse">@android:color/bright_foreground_light_inverse</item>
        
        <item name="textColorPrimary">@android:color/primary_text_light</item>
        <item name="textColorSecondary">@android:color/secondary_text_light</item>
        <item name="textColorTertiary">@android:color/tertiary_text_light</item>
        <item name="textColorPrimaryInverse">@android:color/primary_text_dark</item>
        <item name="textColorSecondaryInverse">@android:color/secondary_text_dark</item>
        <item name="textColorTertiaryInverse">@android:color/tertiary_text_dark</item>
        <item name="textColorPrimaryDisableOnly">@android:color/primary_text_light_disable_only</item>
        <item name="textColorPrimaryInverseDisableOnly">@android:color/primary_text_dark_disable_only</item>
        <item name="textColorPrimaryNoDisable">@android:color/primary_text_light_nodisable</item>
        <item name="textColorSecondaryNoDisable">@android:color/secondary_text_light_nodisable</item>
        <item name="textColorPrimaryInverseNoDisable">@android:color/primary_text_dark_nodisable</item>
        <item name="textColorSecondaryInverseNoDisable">@android:color/secondary_text_dark_nodisable</item>
        <item name="textColorHint">@android:color/hint_foreground_light</item>
        <item name="textColorHintInverse">@android:color/hint_foreground_dark</item>        
        <item name="textColorHighlight">@android:color/highlighted_text_light</item>
        <item name="textColorHighlightInverse">@android:color/highlighted_text_dark</item>
        <item name="textColorLink">@android:color/link_text_light</item>
        <item name="textColorLinkInverse">@android:color/link_text_dark</item>
        
        <item name="editTextColor">@android:color/primary_text_light</item>
        <item name="listChoiceBackgroundIndicator">@android:drawable/list_selector_background</item>

        <item name="activatedBackgroundIndicator">@android:drawable/activated_background_light</item>
        <item name="quickContactBadgeOverlay">@android:drawable/quickcontact_badge_overlay_light</item>

        <item name="popupWindowStyle">@android:style/Widget.PopupWindow</item>
        
        <item name="textCheckMark">@android:drawable/indicator_check_mark_light</item>
        <item name="textCheckMarkInverse">@android:drawable/indicator_check_mark_dark</item>

        <item name="gestureOverlayViewStyle">@android:style/Widget.GestureOverlayView.White</item>
        <item name="expandableListViewStyle">@android:style/Widget.ExpandableListView.White</item>
        <item name="listViewStyle">@android:style/Widget.ListView.White</item>
        <item name="listDivider">@drawable/divider_horizontal_bright</item>
        <item name="listSeparatorTextViewStyle">@android:style/Widget.TextView.ListSeparator.White</item>

        <item name="progressBarStyle">@android:style/Widget.ProgressBar.Inverse</item>
        <item name="progressBarStyleSmall">@android:style/Widget.ProgressBar.Small.Inverse</item>
        <item name="progressBarStyleLarge">@android:style/Widget.ProgressBar.Large.Inverse</item>
        <item name="progressBarStyleInverse">@android:style/Widget.ProgressBar</item>
        <item name="progressBarStyleSmallInverse">@android:style/Widget.ProgressBar.Small</item>
        <item name="progressBarStyleLargeInverse">@android:style/Widget.ProgressBar.Large</item>
        <item name="actionModeCutDrawable">@android:drawable/ic_menu_cut_holo_light</item>
        <item name="actionModeCopyDrawable">@android:drawable/ic_menu_copy_holo_light</item>
        <item name="actionModePasteDrawable">@android:drawable/ic_menu_paste_holo_light</item>
        <item name="actionModeSelectAllDrawable">@android:drawable/ic_menu_selectall_holo_light</item>
        <item name="actionModeShareDrawable">@android:drawable/ic_menu_share_holo_light</item>
        <item name="actionModeFindDrawable">@android:drawable/ic_menu_find_holo_light</item>
        <item name="actionModeWebSearchDrawable">@android:drawable/ic_menu_search_holo_light</item>
        <item name="actionModeBackground">@android:drawable/cab_background_top_holo_light</item>
        <item name="actionModeSplitBackground">@android:drawable/cab_background_bottom_holo_light</item>

        <!-- SearchView attributes -->
        <item name="searchDropdownBackground">@android:drawable/search_dropdown_light</item>
        <item name="searchViewTextField">@drawable/textfield_searchview_holo_light</item>
        <item name="searchViewTextFieldRight">@drawable/textfield_searchview_right_holo_light</item>
        <item name="searchViewCloseIcon">@android:drawable/ic_clear_holo_light</item>
        <item name="searchViewSearchIcon">@android:drawable/ic_search_api_holo_light</item>
        <item name="searchViewGoIcon">@android:drawable/ic_go_search_api_holo_light</item>
        <item name="searchViewVoiceIcon">@android:drawable/ic_voice_search_api_holo_light</item>
        <item name="searchViewEditQuery">@android:drawable/ic_commit_search_api_holo_light</item>

        <item name="detailsElementBackground">@android:drawable/panel_bg_holo_light</item>

        <item name="mediaRouteButtonStyle">@android:style/Widget.DeviceDefault.Light.MediaRouteButton</item>
        <item name="findOnPageNextDrawable">@android:drawable/ic_find_next_holo_light</item>
        <item name="findOnPagePreviousDrawable">@android:drawable/ic_find_previous_holo_light</item>
    </style>

项目实践:->https://git.oschina.net/huagnzhibo123/mystatusbar.git

  • 状态栏为白色:
    在styles.xml的指定app的主题下修改colorPrimaryDark的颜色

  •   <style name="AppTheme" parent="Theme.AppCompat.Light">
            <!-- Customize your theme here. -->
            <item name="colorPrimary">@color/colorPrimary</item>
            <item name="colorPrimaryDark">@android:color/white</item><!--单单设置状态栏bg颜色-->
            <item name="colorAccent">@color/colorAccent</item>
        </style>

     

        效果图

        

这里底色是白色了,但是状态栏字体却不见了(字体颜色默认白色),这怎么能容忍呢?查了下文档,android系统中只有6.0以上支持状态栏高亮,也就是字体为黑色.

 <style name="AppTheme" parent="Theme.AppCompat.Light">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@android:color/white</item><!--单单设置状态栏bg颜色 发现字体颜色也为白色(难看)-->
       <item name="android:windowLightStatusBar">true</item><!--6.0以上(黑色字体)-->
        <item name="colorAccent">@color/colorAccent</item>
    </style>

对于低于6.0的系统只能用系统的默认字体颜色为白色了,想小米,魅族有各自提供的接口实现(http://www.jianshu.com/p/7f5a9969be53)

  • 状态栏为透明(布局占用状态栏)
    在很多场景中,都会使用到布局占用状态栏的高度,整个页面统一化,好看啊,比如这张:
    实现步骤:
    1.使得布局占用状态栏高度
    2.状态透明化

         重新建立一个TranActivity 这里重新指定主题为:

 <style name="TranActivityTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
    </style>


在manifest清单中为这个TranActiivty指定无导航栏主题

          布局文件(使得布局占用状态栏高度):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="false"
    tools:context="lixiaoqian.com.mystatusbar.TranActivity">
    <!--注意  fitsSystemWindows 属性:false是不考虑系统的布局,直接占用状态栏高度-->
    <ImageView
        android:id="@+id/imageView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/colorAccent"
         />
</RelativeLayout>

        状态栏透明化:
        这里想通过xml中的状态栏颜色改变为透明,实践是失败的,目前的方案是通过代码设置状态栏为全透明:


public class TranActivity extends AppCompatActivity {

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

    /**
     * 状态栏透明化
     */
    private void tranStatusBar() {
        getWindow().requestFeature(Window.FEATURE_NO_TITLE);
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Window window = getWindow();
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
                    | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
            window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            /*window.setStatusBarColor(Color.TRANSPARENT);
            window.setNavigationBarColor(Color.TRANSPARENT);*/ //可以不用了
        }
    }
}

    代码中主要的是tranStatusBar的实现逻辑,其中有几个需要解释下:

    clearFlags,setFlags,addFlags 都是对window窗体进行修改:

    FLAG_TRANSLUCENT_STATUS: 透明状态栏

    FLAG_TRANSLUCENT_NAVIGATION:透明底部导航栏

    SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN:全屏模式

    SYSTEM_UI_FLAG_LAYOUT_STABLE:显示顶部状态栏

补充 :

对于华为机型中底部有虚拟导航栏,在设置全屏时,会导致导航栏遮住布局,我么的目的是 占据顶部,不占底部

所以这里提供另一种思路(5.0以上)

if (Build.VERSION.SDK_INT >= 21) {
View decorView = getWindow().getDecorView();
int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
decorView.setSystemUiVisibility(option);
getWindow().setStatusBarColor(Color.TRANSPARENT);
}
ActionBar actionBar = getSupportActionBar();
actionBar.hide();

View.setSystemUiVisibility(int visibility)中,visibility是Mode与Layout任意取值的组合,可传入的实参为:

Mode

  1. View.SYSTEM_UI_FLAG_LOW_PROFILE:状态栏显示处于低能显示状态(low profile模式),状态栏上一些图标显示会被隐藏。
  2. View.SYSTEM_UI_FLAG_FULLSCREEN:Activity全屏显示,且状态栏被隐藏覆盖掉。等同于(WindowManager.LayoutParams.FLAG_FULLSCREEN)
  3. View.SYSTEM_UI_FLAG_HIDE_NAVIGATION:隐藏虚拟按键(导航栏)。有些手机会用虚拟按键来代替物理按键。
  4. View.SYSTEM_UI_FLAG_IMMERSIVE:这个flag只有当设置了SYSTEM_UI_FLAG_HIDE_NAVIGATION才起作用。如果没有设置这个flag,任意的View相互动作都退出SYSTEM_UI_FLAG_HIDE_NAVIGATION模式。如果设置就不会退出。
  5. View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY:这个flag只有当设置了SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_HIDE_NAVIGATION 时才起作用。如果没有设置这个flag,任意的View相互动作都坏退出SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_HIDE_NAVIGATION模式。如果设置就不受影响。

Layout

  1. View.SYSTEM_UI_FLAG_LAYOUT_STABLE: 保持View Layout不变,隐藏状态栏或者导航栏后,View不会拉伸。
  2. View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN:让View全屏显示,Layout会被拉伸到StatusBar下面,不包含NavigationBar。
  3. View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION:让View全屏显示,Layout会被拉伸到StatusBar和NavigationBar下面。

总结:

在第一种方案状态栏透明这个功能上,要注意布局系统对底层的窗体都要设置全屏模式(缺一不可),然后在设置状态栏的背景颜色,上面所说的用xml使得状态栏透明失败是因为系统对底层的窗体没有设置全屏,大家可以自己去试试

共有 人打赏支持
粉丝 7
博文 22
码字总数 14202
×
HzhiBo
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: