转载:https://blog.csdn.net/fan7983377/article/details/51604657
最近公司产品提出透明状态栏的要求,将一张背景填充满屏幕,自己记录一下:
Android 透明状态栏:有两种,背景是图片还是纯色,下面分开讲:
1.当背景为图片时,布局可以这么写:
方法1,在代码onCreate()方法里书写下面代码:
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); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { Window window = getWindow(); window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); }
然后在xml跟布局,设置属性:android:fitsSystemWindows="true",代码如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg_scenery"
android:fitsSystemWindows="true">
</LinearLayout>
效果图:
方法二:主要的操作都在style.xml 和 AndroidManifest.xml 中,Activity里面没有任何涉及到需要设置的代码,所以可以忽略不看。
ps:
首先需要到AndroidManifest中为指定的Activity设置Theme。但是需要注意的是,我们不能直接在values/style.xml直接去自定义 Translucet System Bar 的Theme,因为改特性仅兼容 Android 4.4 开始的平台,所以直接在values/style.xml声明引入,工程会报错。有些开发者朋友会在代码中去判断SDK的版本,然后再用代码设置Theme。虽然同样可以实现效果,但个人并不推崇这种做法。我所采取的方法则是建立多个SDK版本的values文件夹,系统会根据SDK的版本选择合适的Theme进行设置。大家可以看到上面我的工程里面有values、values-v19、values-v21。
该方法需要做下面三步设置:
step1:在values、values-v19、values-v21的style.xml都设置一个 Translucent System Bar 风格的Theme
values/style.xml
<style name="ImageTranslucentTheme" parent="AppTheme"> <!--在Android 4.4之前的版本上运行,直接跟随系统主题--> </style>
values-v19/style.xml
<style name="ImageTranslucentTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:windowTranslucentStatus">true</item> <item name="android:windowTranslucentNavigation">true</item> </style>
values-v21/style.xml
<style name="ImageTranslucentTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:windowTranslucentStatus">false</item> <item name="android:windowTranslucentNavigation">true</item> <!--Android 5.x开始需要把颜色设置透明,否则导航栏会呈现系统默认的浅灰色--> <item name="android:statusBarColor">@android:color/transparent</item> </style>
上面需要注意的地方是,无论你在哪个SDK版本的values目录下,设置了主题,都应该在最基本的values下设置一个同名的主题。这样才能确保你的app能够正常运行在 Android 4.4 以下的设备。否则,肯定会报找不到Theme的错误。
step2:在AndroidManifest.xml中对指定Activity的theme进行设置
<activity android:name=".activity.ImageActivity" android:theme="@style/ImageTranslucentTheme"/>
step3:在Activity的布局文件中设置背景图片,同时,需要把android:fitsSystemWindows设置为true
xml布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/bg_building"
android:fitsSystemWindows="true">
</LinearLayout>
效果图:
上面2中方法,如果仅仅需要ImageView控件覆盖状态栏,那么将android:fitsSystemWindows设置为false即可。
xml布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/bg_building" android:fitsSystemWindows="false"> <ImageView android:layout_width="match_parent" android:layout_height="200dp" android:scaleType="fitXY" android:src="@drawable/hehua"/> </LinearLayout>
效果图:
1.当背景为纯色时,
由于它的Tab栏是纯色的,所以只要把系统通知栏的颜色设置和Tab栏的颜色一致即可,实现上相比方法一要简单很多。同样要到不同SDK版本的values下,创建一个同名的theme,在values-v21下,需要设置系统导航栏的颜色:
values/style.xml
<style name="ColorTranslucentTheme" parent="AppTheme"> </style>
values-v19/style.xml
<style name="ColorTranslucentTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:windowTranslucentStatus">true</item> <item name="android:windowTranslucentNavigation">true</item> </style>
values-v21/style.xml
<style name="ColorTranslucentTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:windowTranslucentStatus">false</item> <item name="android:windowTranslucentNavigation">true</item> <item name="android:statusBarColor">@android:color/transparent</item> </style>
在AndroidManifest.xml中对指定Activity的theme进行设置
<!--图片--> <activity android:name=".activity.ColorActivity" android:theme="@style/ColorTranslucentTheme"/>
xml布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/bar_color" android:fitsSystemWindows="true"> <!--标题布局--> <RelativeLayout android:layout_width="match_parent" android:layout_height="55dp" android:background="@color/bar_color"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="这是title栏" android:textColor="@android:color/white" android:textSize="20sp" /> </RelativeLayout> <!--内容布局--> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:background="@android:color/white"> <!--自己根据实际需求填写--> </LinearLayout> </LinearLayout>
效果图:
好了,以上就是沉浸式状态栏实现的全过程,但是还有一点值得注意的就是,如果我们activity比较多,每一个页面都添加android:fitsSystemWindows="true"
比较麻烦,我们需要改动一下:
写一个基类BaseColorActivity.class,代码如下:
public abstract class BaseColorActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);//这一行注意!看本文最后的说明!!!!
setContentView(getLayoutId());
ViewGroup contentFrameLayout = (ViewGroup) findViewById(Window.ID_ANDROID_CONTENT);
View parentView = contentFrameLayout.getChildAt(0);
if(parentView != null && Build.VERSION.SDK_INT >= 14){
parentView.setFitsSystemWindows(true);
}
}
protected abstract int getLayoutId();
}
然后需要沉浸状态栏的activity继承该基类:
public class ColorActivity extends BaseColorActivity {
public static void startActivity(Context context){
Intent intent = new Intent(context, ColorActivity.class);
context.startActivity(intent);
}
@Override
protected int getLayoutId() {
return R.layout.activity_color;
}
}
然后需要沉浸状态栏的activity的布局文件中就可以把android:fitsSystemWindows="true"
这行代码给省略了!,其他设置还是按照一开始操作。
写个工具类StatusBarCompat.class
:
public class StatusBarCompat {
private static final int INVALID_VAL = -1;
private static final int COLOR_DEFAULT = Color.parseColor("#20000000");
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public static void compat(Activity activity, int statusColor)
{
//当前手机版本为5.0及以上
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
{
if (statusColor != INVALID_VAL)
{
activity.getWindow().setStatusBarColor(statusColor);
}
return;
}
//当前手机版本为4.4
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
{
int color = COLOR_DEFAULT;
ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content);
if (statusColor != INVALID_VAL)
{
color = statusColor;
}
View statusBarView = new View(activity);
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
getStatusBarHeight(activity));
statusBarView.setBackgroundColor(color);
contentView.addView(statusBarView, lp);
}
}
public static void compat(Activity activity)
{
compat(activity, INVALID_VAL);
}
public static int getStatusBarHeight(Context context)
{
int result = 0;
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0)
{
result = context.getResources().getDimensionPixelSize(resourceId);
}
return result;
}
}
使用方法:
在当前activity的onCreate中,调用方法StatusBarCompat.compat
就可以了:
//第二个参数是想要设置的颜色
StatusBarCompat.compat(this, Color.RED);
如果嫌每个activity都要写有点麻烦,那就写个基类来完成这一步:
public class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
StatusBarCompat.compat(this, Color.RED);
}
}
关于上面代码中提示注意的那个地方的说明:
隐藏系统title注意的两点:
-
继承AppCompatActivity时使用:
supportRequestWindowFeature(Window.FEATURENOTITLE) -
继承activity时使用:
requestWindowFeature(Window.FEATURENOTITLE)