操作Activity系统提供界面

前言

手机的屏幕越来越大,为了能够展示更多的界面元素现在兴起了沉浸式的界面,也就是整个屏幕都可以展示用户素材。通常的手机界面都有StatusBar状态栏在顶部,状态栏下面的ActionBar负责展示标题回退按钮以及操作菜单,中间部分是用户内容区,最下面则展示了NavigationBar,也就是用户导航栏,通常有Back、Home和Menu这几个键位。现在来学习一下如何操作这些系统提供的界面。

透明状态栏

状态栏现在常见的用法就是透明状态栏,当然也可以自己设置其他颜色的状态栏背景,但是这些都是有版本要求的。只有在版本号大于19才可以设置透明状态栏19以下版本无法修改状态栏颜色。在19以上需要使用translucentStatus属性,但是到了21版本,translucent变成半透明也就是有一点灰色的背景,为了达到透明效果需要设置statusBarColor为transparent。设置Theme的XML文件如下:
首先是values.xml只是供19以下的Android使用,这个不会有什么效果。

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
</style>

<style name="AppTheme.TranslucentStatus">
</style>

values-v19.xml供19以上版本使用的样式:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="AppTheme.TranslucentStatus">
        <item name="android:windowTranslucentStatus">true</item>
        <item name="android:windowTranslucentNavigation">true</item>
    </style>
</resources>

values-v21.xml供21以上版本使用的样式:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="AppTheme.TranslucentStatus">
        // 21以上不再设置translucentStatus,直接设置statusBarColor就行了
        <item name="android:windowTranslucentStatus">false</item>
        <item name="android:statusBarColor">@android:color/transparent</item>
        <item name="android:windowTranslucentNavigation">true</item>
    </style>
</resources>

在N5上测试windowTranslucentStatus和windowTranslucentNavigation必须同时设置否则就不会展示透明的状态栏

设置完这些就可以看到状态栏在19以上变成透明的,但是如果你设置的背景是白色的,在StatusBar上的文字和图标也是白色的,这时后可以设置windowLightStatusBar属性将文字调成黑色展示,但是这个属性目前只在23以上支持,MiUI和FlyMe可以适配,其他的手机还要看具体的效果。
values-v23.xml提供23以上版本使用的样式:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="AppTheme.TranslucentStatus">
        <item name="android:windowTranslucentStatus">false</item>
        <item name="android:statusBarColor">@android:color/transparent</item>
        <item name="android:windowTranslucentNavigation">true</item>
        <item name="android:windowLightStatusBar">true</item>
    </style>
</resources>

小米和魅族的适配代码如下:

public static void setStatusBarLight(Activity activity) {
    String manufacturer = Build.MANUFACTURER.toLowerCase();
    // 首先获取当前设备制造商,而且版本高于23
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (manufacturer.contains("xiaomi")) {
            setXiaomiStatusBarLightMode(activity);
        } else if (manufacturer.contains("meizu")) {
            setMeizuStatusBarLightMode(activity);
        }
    }
}

/**
 * MIUI
 * <p>
 * {@inheritDoc https://dev.mi.com/doc/p=4769/index.html}
 *
 * @param activity 引用的Activity
 */
private static void setXiaomiStatusBarLightMode(Activity activity) {
    Class<? extends Window> clazz = activity.getWindow().getClass();
    try {
        @SuppressLint("PrivateApi")
        Class<?> layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
        Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
        int darkModeFlag = field.getInt(layoutParams);
        if (darkModeFlag == 0) darkModeFlag = 16;
        Method extraFlagField = clazz.getMethod("addExtraFlags", int.class);
        extraFlagField.invoke(activity.getWindow(), darkModeFlag);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

/**
 * flyme4+才可修改
 * {@inheritDoc http://open-wiki.flyme.cn/index.php?title=Flyme%E7%B3%BB%E7%BB%9FAPI}
 *
 * @param activity 引用的Activity
 */
private static void setMeizuStatusBarLightMode(Activity activity) {
    Window window = activity.getWindow();
    if (window != null) {
    try {
        WindowManager.LayoutParams lp = window.getAttributes();
        Field darkFlag = WindowManager.LayoutParams.class
                .getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
        Field meizuFlags = WindowManager.LayoutParams.class
                .getDeclaredField("meizuFlags");
        darkFlag.setAccessible(true);
        meizuFlags.setAccessible(true);
        int bit = darkFlag.getInt(null);
        int value = meizuFlags.getInt(lp);
        value |= bit;
        meizuFlags.setInt(lp, value);
        window.setAttributes(lp);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

ActionBar

前面已经设置好状态栏是透明色,但是ActionBar还没有设置,如何将ActionBar也设置为透明呢?其实也是有一个actionBarStyle的属性,可以在里面设置状态栏的背景为透明,同时也要设置 windowActionBarOverlay状态栏处于悬浮状态,否则ActionBar会在状态栏和内容之间形成一个空白。这样设置之后在低版本上还会看到ActionBar底部有一条黑色的线,设置windowContentOverlay黑色线就会消失。

<style name="OverlayActionBar" parent="AppTheme.TranslucentStatus">
    <item name="android:actionBarStyle">@style/ActionBarStyle</item>
    <item name="actionBarStyle">@style/ActionBarStyle</item>
    <item name="android:windowContentOverlay">@null</item>
</style>

<style name="ActionBarStyle" parent="@style/Widget.AppCompat.Light.ActionBar.Solid.Inverse">
    <item name="android:background">@android:color/transparent</item>
    <item name="background">@android:color/transparent</item>
    <item name="android:windowActionBarOverlay">true</item>
    <item name="windowActionBarOverlay">true</item>
</style>

现在已经不推荐再使用ActionBar了,而是使用Toolbar控件取代原有的对象,使用Toolbar的时候需要注意Activity的Theme必须设置为NoActionBar。

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

然后在setContentView的xml里定义ToolBar对象,运行会发现Toobar的顶部和StatusBar顶部在一起,设置contentView的fitSystemWindows就可以为Toolbar父控件添加StatusBar高度的padding。

public class IndexActivity extends AppCompatActivity {
    private Toolbar mToolbar;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_index);
        mToolbar = (Toolbar) findViewById(R.id.tool_bar);
        mToolbar.setTitle(R.string.app_name);
        setSupportActionBar(mToolbar);
    }
}

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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:background="@drawable/timg"
    android:fitsSystemWindows="true"
    tools:context="com.example.image.IndexActivity">

    <android.support.v7.widget.Toolbar
        android:id="@+id/tool_bar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize">
    </android.support.v7.widget.Toolbar>
</FrameLayout>

其他的设置不变,可以发现Toolbar也变成了透明背景。

导航栏除了前面设置windowTranslucentNavigation设置为半透明色,4.0以上版本可以使用setSystemUiVisibility在代码中动态设置展示还是隐藏导航栏。现在可以把Activity设置为没有透明顶部的普通Theme,通过代码设置状态栏和NavigationBar的展示和隐藏。

int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
        View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
        View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
        View.SYSTEM_UI_FLAG_FULLSCREEN |
        View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
        View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
getWindow().getDecorView().setSystemUiVisibility(uiOptions);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值