Android 沉浸式状态栏实现, 在Activity和Fragment中

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/decetwen1989/article/details/79798838

先上代码和效果图

一、 在Activity中

1、activity_immerse.xml 布局中的代码:

    *  隐藏系统自带的标题栏, 在需要实现沉浸式的布局中加入 android:fitsSystemWindows="true", 且该布局在页面需要在顶部显示

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <!--隐藏系统自带的标题栏, 在需要实现沉浸式的布局中加入 android:fitsSystemWindows="true"-->
    <LinearLayout
        android:id="@+id/ll_immerse_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/holo_blue_dark"
        android:fitsSystemWindows="true"
        android:orientation="vertical">
        
        <!--标题栏, 测试时换成自己的标题栏和颜色-->
        <!--自定义标题栏需要较高的自由度, 建议将其放在LinearLayout中, 并通过LinearLayout实现沉浸式-->
        <include layout="@layout/activity_title"/>

    </LinearLayout>

    <TextView
        android:id="@+id/tv_immerse_fragment"
        android:layout_width="match_parent"
        android:layout_height="52dp"
        android:gravity="center"
        android:text="沉浸式Fragment"
        android:textColor="@color/black"/>

</LinearLayout>

2、ImmerseActivity 中的代码

    *  设置布局后, 添加沉浸式属性

/**
 * 沉浸式状态栏
 */

public class ImmerseActivity extends BaseActivity {
    @Override
    public void setupViewLayout() {
        setContentView(R.layout.activity_immerse);
        //要实现沉浸式的布局, 一般是自定义的标题栏
        LinearLayout ll_immerse_title = getViewNoClickable(R.id.ll_immerse_title);
        //设置沉浸式状态栏效果
        BasisImmerseUtils.setImmerseLayout(mActivity, ll_immerse_title);
    }
}

3、BasisImmerUtils 工具类中 setImmerseLayout 方法

    *  设置沉浸式属性方法

/**
     * 设置沉浸式属性
     *
     * @param view 为实现沉浸式的布局, 需添加属性: android:fitsSystemWindows="true"
     */
    public static void setImmerseLayout(Activity activity, View view) {
        //沉浸式状态栏为Android4.4后特性
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            Window window = activity.getWindow();
            window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);//设置透明状态栏属性
            setPaddingTop(activity, view);
        }
    }

    /**
     * 将布局的PaddingTop增加系统栏的高度
     */
    public static void setPaddingTop(Activity activity, View view) {
        int statusBarHeight = getStatusBarHeight(activity);//获取系统状态栏高度
        view.setPadding(view.getPaddingLeft(), view.getPaddingTop() + statusBarHeight, view.getPaddingRight(), view.getPaddingBottom());//设置view的paddingTop高度, 防止显示错乱
    }

/**
     * 获取系统状态栏高度
     *
     * @return pixel
     */
    public static int getStatusBarHeight(Context context) {
        int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            return context.getResources().getDimensionPixelSize(resourceId);
        }
        return 0;
    }

4、效果图

    *  状态栏显示的就是我们设置的标题颜色, 其它是自定义标题栏测试


二、Activity 中 ViewPager + Fragment, Fragment布局实现沉浸式

1、activity_immersefragment.xml 布局中的代码

    *  viewpager需要是activity的第一个布局, 且需要设置activity的主题(theme)隐藏标题栏

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:background="@color/white"
              android:orientation="vertical">

    <!--viewpager需要是activity的第一个布局, 且需要设置activity的theme隐藏标题栏-->
    <android.support.v4.view.ViewPager
        android:id="@+id/vp_immersefragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </android.support.v4.view.ViewPager>

</LinearLayout>

2、ImmerseFragmentActivity 中代码

    *  设置布局后, 添加沉浸式属性

/**
 * 实现沉浸式状态栏Fragment
 */

public class ImmerseFragmentActivity extends BaseActivity {
    private ViewPager vp_immersefragment;
    private FragmentManager mFragmentManager = getSupportFragmentManager();
    private ArrayList<Fragment> mFragments = new ArrayList<>();
    public FragmentPagerAdapter mFragmentPagerAdapter;
    public FragmentStatePagerAdapter mFragmentStatePagerAdapter;

    @Override
    public void setupViewLayout() {
        setContentView(R.layout.activity_immersefragment);
        BasisImmerseUtils.setImmerseLayout(mActivity);//设置沉浸式状态

//        BasisImmerseUtils.hideStatusBar(mActivity);//隐藏顶部状态栏
//        BasisImmerseUtils.hideNavigationBar(mActivity);//隐藏底部导航栏
//        BasisImmerseUtils.setTransparentWindowBar(mActivity);//设置顶部状态栏和底部导航栏透明, 并使主题布局占据顶部和底部位置
    }

    @Override
    public void initView() {
        vp_immersefragment = getViewNoClickable(R.id.vp_immersefragment);
    }

    @Override
    public void listener() {
    }

    @Override
    public void logicDispose() {
        initFragmentData();
        setVPAdapter();
    }

    /**
     * 初始化Fragment
     */
    private void initFragmentData() {
        mFragments.add(new Test1Fragment());
        mFragments.add(new Test2Fragment());
        mFragments.add(new Test3Fragment());
        mFragments.add(new Test4Fragment());
        mFragments.add(new Test5Fragment());
    }

    /**
     * 设置适配器
     */
    private void setVPAdapter() {
        mFragmentPagerAdapter = new FragmentPagerAdapter(mFragmentManager) {
            @Override
            public Fragment getItem(int position) {
                return mFragments.get(position);
            }

            @Override
            public int getCount() {
                return mFragments == null ? 0 : mFragments.size();
            }
        };

        /**
         * 创建生命周期: onattach  oncreate  oncreateview  onactivitycreated  onstart  onresume
         * 销毁生命周期: onpause  onstop  ondestoryview  ondestory  ondetach
         * 创建时会多执行 onattach oncreate
         * 销毁时会多执行 ondestory ondetach
         */
        mFragmentStatePagerAdapter = new FragmentStatePagerAdapter(mFragmentManager) {
            @Override
            public Fragment getItem(int position) {
                return mFragments.get(position);
            }

            @Override
            public int getCount() {
                return mFragments == null ? 0 : mFragments.size();
            }
        };

        vp_immersefragment.setAdapter(mFragmentStatePagerAdapter);
    }

    @Override
    public void onClick(View v) {

    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
//        BasisImmerseUtils.setOnWindowFocusChanged(mActivity, hasFocus);
    }


}

3、Fragment 的布局 fragment_test1.xml 的代码

    *  在需要实现沉浸式的布局中加入 android:fitsSystemWindows="true"

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical">

    <!--在需要实现沉浸式的布局中加入 android:fitsSystemWindows="true"-->
    <LinearLayout
        android:id="@+id/ll_fragment_test1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/holo_blue_light"
        android:fitsSystemWindows="true"
        android:orientation="vertical">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="52dp"
            android:gravity="center"
            android:text="Test1Fragment"
            android:textColor="@color/black"/>
    </LinearLayout>


</LinearLayout>

4、Fragment 中需添加下面的方法

    *  设置沉浸式布局ll_fragment_test1的paddingtop, 防止显示异常

//设置沉浸式布局ll_fragment_test1的paddingtop, 防止显示异常
        BasisImmerseUtils.setPaddingTop(mActivity, ll_fragment_test1);

5、BasisImmerUtils 工具类中 setPaddingTop 方法

/**
     * 将布局的PaddingTop增加系统栏的高度
     */
    public static void setPaddingTop(Activity activity, View view) {
        int statusBarHeight = getStatusBarHeight(activity);//获取系统状态栏高度
        view.setPadding(view.getPaddingLeft(), view.getPaddingTop() + statusBarHeight, view.getPaddingRight(), view.getPaddingBottom());//设置view的paddingTop高度, 防止显示错乱
    }

/**
     * 获取系统状态栏高度
     *
     * @return pixel
     */
    public static int getStatusBarHeight(Context context) {
        int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            return context.getResources().getDimensionPixelSize(resourceId);
        }
        return 0;
    }

6、效果图

    *  其它Fragment类似, 在需要实现沉浸式的布局中加入 android:fitsSystemWindows="true"

三、说明

1、沉浸式原理,说明, 解说等已经有好多人进行了说明, 这里不再详细解说,只是简单给出实现沉浸式代码,在关联文章中也给出了两篇, 有兴趣可以看看

2、全屏大图的沉浸式类似,大家可自行尝试

3、Fragment 的沉浸式是为了不同 Fragment 需要不同自定义标题准备的, 若共用一个自定义标题, 使用Activity实现沉浸式更为简单

4、工具类 BasisImmerseUtils 中还包含一些隐藏导航栏, 全屏等方法,完整代码如下

package com.gingold.basislibrary.utils;

import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.os.Build;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;

/**
 * 沉浸式状态栏工具类
 *
 * @note viewPager中的Fragment自己使用沉浸式效果时, 占据状态栏的布局和标题布局需分开, 否则会引起标题显示错乱
 */

public class BasisImmerseUtils {

    /**
     * 设置沉浸式属性
     *
     * @param view 为实现沉浸式的布局, 需添加属性: android:fitsSystemWindows="true"
     */
    public static void setImmerseLayout(Activity activity, View view) {
        //沉浸式状态栏为Android4.4后特性
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            Window window = activity.getWindow();
            window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);//设置透明状态栏属性
            setPaddingTop(activity, view);
        }
    }

    /**
     * 将布局的PaddingTop增加系统栏的高度
     */
    public static void setPaddingTop(Activity activity, View view) {
        int statusBarHeight = getStatusBarHeight(activity);//获取系统状态栏高度
        view.setPadding(view.getPaddingLeft(), view.getPaddingTop() + statusBarHeight, view.getPaddingRight(), view.getPaddingBottom());//设置view的paddingTop高度, 防止显示错乱
    }

    /**
     * 设置沉浸式属性
     */
    public static void setImmerseLayout(Activity activity) {
        //沉浸式状态栏为Android4.4后特性
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            Window window = activity.getWindow();
            window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);//设置透明状态栏属性
        }
    }

    /**
     * 取消沉浸式属性
     *
     * @param view 为实现沉浸式的布局, 需添加属性: android:fitsSystemWindows="true"
     */
    public static void clearImmerseLayout(Activity activity, View view) {
        //沉浸式状态栏为Android4.4后特性
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            Window window = activity.getWindow();
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            int statusBarHeight = getStatusBarHeight(activity);//获取系统状态栏高度
            view.setPadding(view.getPaddingLeft(), view.getPaddingTop() - statusBarHeight, view.getPaddingRight(), view.getPaddingBottom());//设置view的paddingTop高度, 防止显示错乱
        }
    }

    /**
     * 取消沉浸式属性
     */
    public static void clearImmerseLayout(Activity activity) {
        //沉浸式状态栏为Android4.4后特性
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            Window window = activity.getWindow();
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        }
    }

    /**
     * 获取系统状态栏高度
     *
     * @return pixel
     */
    public static int getStatusBarHeight(Context context) {
        int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            return context.getResources().getDimensionPixelSize(resourceId);
        }
        return 0;
    }

    /**
     * 设置顶部状态栏和底部导航栏透明, 并使主题布局占据顶部和底部位置
     * <p>
     * 效果: 顶部状态栏和底部导航栏悬空在界面上
     */
    public static void setTransparentWindowBar(Activity activity) {
        //支持Android5.0以上版本
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            View decorView = activity.getWindow().getDecorView();
            int option = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
            decorView.setSystemUiVisibility(option);
            activity.getWindow().setNavigationBarColor(Color.TRANSPARENT);
            activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
        }
    }

    /**
     * 隐藏顶部状态栏
     */
    public static void hideStatusBar(Activity activity) {
        activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN);
    }

    /**
     * 隐藏底部导航栏
     */
    public static void hideNavigationBar(Activity activity) {
        activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
    }

    /**
     * 隐藏底部导航栏和顶部状态栏(点击任意位置效果消失)
     */
    public static void hideStatusBarAndNavigationBar(Activity activity) {
        activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
    }

    /**
     * 设置完全沉浸式效果(游戏和视频播放需求)
     * <p>
     * 需要在onWindowFocusChanged方法中调用
     */
    public static void setOnWindowFocusChanged(Activity activity, boolean hasFocus) {
        if (hasFocus && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            activity.getWindow().getDecorView().setSystemUiVisibility(
                    View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_FULLSCREEN
                            | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
        }
    }
}

四、相关文章

1、Android状态栏微技巧,带你真正理解沉浸式模式

2、Android沉浸式状态栏(透明状态栏)最佳实现

五、GitHup项目地址

https://github.com/GinGod/BasisDependency

阅读更多 登录后自动展开
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页