首先请让我们看看没有使用沉浸式的效果:
上面这张图是没有使用沉浸式的美团外卖,我们可以看到最上面的黑色的那一条就是状态栏,大部分android默认是黑色底,白色字。
好了,下面让我祭出使用了沉浸式以后的效果图:
说回来吧,状态栏(系统)跟我们的app的标题栏的颜色融为一体,非常美观大方得体。而这样就是我今天要介绍的效果。
为了能够和ISO尽量统一风格,为了更加美观大方,我们还是有必要学习一下沉浸式的实现方法。
这种方法主要是通过GitHub上面的一个开源库实现,下面让我原汁原味贴出项目的源码:
//需要引入的类库
compile 'com.readystatesoftware.systembartint:systembartint:1.0.4'
import android.annotation.TargetApi;
import android.app.Activity;
import android.os.Build;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import com.readystatesoftware.systembartint.SystemBarTintManager;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* 设置状态栏颜色的工具类
*/
public class TintBarUtils {
/**
* 设置activity的状态栏颜色,注意需要在activity的布局当中添加属性:android:fitsSystemWindows="true"
*
* @param activity
* @param statusBarTintColor
*/
public static void setStatusBarTintColor(Activity activity, int statusBarTintColor) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
setTranslucentStatus(true, activity);
SystemBarTintManager mTintManager = new SystemBarTintManager(activity);
mTintManager.setStatusBarTintEnabled(true);
mTintManager.setNavigationBarTintEnabled(true);
mTintManager.setTintColor(statusBarTintColor);
setStatusBarTextStyle(activity, true);
}
}
public static void setStatusBarTextStyle(Activity activity, boolean lightMode) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (lightMode) {
activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
} else {
MIUISetStatusBarLightMode(activity.getWindow(), lightMode);
FlymeSetStatusBarLightMode(activity.getWindow(), lightMode);
}
}
@TargetApi(19)
private static void setTranslucentStatus(boolean on, Activity activity) {
Window win = activity.getWindow();
WindowManager.LayoutParams winParams = win.getAttributes();
final int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
if (on) {
winParams.flags |= bits;
} else {
winParams.flags &= ~bits;
}
win.setAttributes(winParams);
}
@TargetApi(19)
public static void hideStatusBar(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
setTranslucentStatus(false, activity);
SystemBarTintManager mTintManager = new SystemBarTintManager(activity);
mTintManager.setStatusBarTintEnabled(false);
mTintManager.setNavigationBarTintEnabled(false);
Window win = activity.getWindow();
WindowManager.LayoutParams winParams = win.getAttributes();
final int bits = WindowManager.LayoutParams.FLAG_FULLSCREEN;
winParams.flags &= ~bits;
win.setAttributes(winParams);
}
}
/**
* 设置状态栏图标为深色和魅族特定的文字风格 * 可以用来判断是否为Flyme用户 * @param window 需要设置的窗口 * @param dark 是否把状态栏字体及图标颜色设置为深色 * @return boolean 成功执行返回true *
*/
public static boolean FlymeSetStatusBarLightMode(Window window, boolean dark) {
boolean result = false;
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);
if (dark) {
value |= bit;
} else {
value &= ~bit;
}
meizuFlags.setInt(lp, value);
window.setAttributes(lp);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
}
return result;
}
/**
* 设置状态栏字体图标为深色,需要MIUIV6以上
*
* @param window 需要设置的窗口
* @param dark 是否把状态栏字体及图标颜色设置为深色
* @return boolean 成功执行返回true
*/
public static boolean MIUISetStatusBarLightMode(Window window, boolean dark) {
boolean result = false;
if (window != null) {
Class clazz = window.getClass();
try {
int darkModeFlag = 0;
Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
darkModeFlag = field.getInt(layoutParams);
Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
if (dark) {
extraFlagField.invoke(window, darkModeFlag, darkModeFlag);//状态栏透明且黑色字体 }else{ extraFlagField.invoke(window, 0, darkModeFlag);//清除黑色字体 } result=true; }catch (Exception e){ } } return result; }
}
} catch (Exception e) {
e.printStackTrace();
}
}
return result;
}
}
这里需要特别强调一点就是activity布局文件中的跟布局必须有下面这个属性,否则我们的设置是没有效果的:
android:fitsSystemWindows="true"
我们要关注的核心方法是setStatusBarTintColor,这个方法需要传入一个Activity对象,以及颜色值,即可设置状态栏的颜色。需要注意的是这个方法需要判断当前的API版本是不是大于19才能使用。至于具体的实现,大家可以仔细看源码。这里只强调如何快速使用到你的项目当中。
但是这里有一个尴尬的问题就是:当我们的APP标题栏是白色的时候,例如上面的第二张图,如果我们设置了白色的状态栏,那么状态辣女白色的文字将会看不到。解决的办法比较棘手,我当时也是懵逼了好久,在项目经理的重压之下还是找到了解决方案。在android M也就是API23以上,google官方提供了设置状态栏文字风格的方法:
activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
为了向下兼容,小米和魅族两个品牌由于深度定制过android的ROM,都提供了通过反射的方式是改变状态栏的文字颜色。他们分别是:
MIUISetStatusBarLightMode和FlymeSetStatusBarLightMode,通过传入的参数dark为true就可改变状态栏文字颜色,至于怎么改变,大家可以亲自尝试一下,这里不再啰嗦。
如上面第三张图所示,我们的contentView进入了状态栏,这又是怎么实现的呢?其实很简单,只要把我们的布局延伸到状态栏,并且添加一个高度为状态栏高度的View(status_bar_top)或者上Padding即可。
protected int statusBarHeight;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
immerseLayout();
}
protected void immerseLayout() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
statusBarHeight = getStatusBarHeight(this.getBaseContext());
viewStatusBarTop = findViewById(R.id.status_bar_top);
RelativeLayout.LayoutParams params2 = (RelativeLayout.LayoutParams) viewStatusBarTop.getLayoutParams();
params2.height = statusBarHeight;
viewStatusBarTop.setLayoutParams(params2);
viewStatusBarTop.setVisibility(View.VISIBLE);
}
}
public int getStatusBarHeight(Context context) {
if (statusBarHeight != 0)
return statusBarHeight;
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
statusBarHeight = context.getResources().getDimensionPixelSize(resourceId);
}
return statusBarHeight;
}
下面给出这个activity的布局文件
。。。这里是我们的布局
今天的项目笔记就到这里了,有什么问题欢迎通过以下方式联系我:
QQ(微信):1435378192,楠总or小楠
android学习交流群:459355901