上篇介绍api21以上的沉浸式状态栏,这篇介绍状态栏以及导航栏
使用DecorView的setSystemUiVisibility方法
package com.whuthm.immersive;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
/**
* Created by DELL on 2015/7/20.
*/
public class FullScreenActivity extends BaseActivity implements View.OnClickListener {
private static final String TAG = "FullScreenActivity";
private TextView mShowTips;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fullscreen);
initToolbar();
mShowTips = (TextView) findViewById(R.id.tv_show_tips);
findViewById(R.id.btn_clear).setOnClickListener(this);
findViewById(R.id.btn_show_status_bar).setOnClickListener(this);
findViewById(R.id.btn_hide_status_bar).setOnClickListener(this);
findViewById(R.id.btn_show_nav_bar).setOnClickListener(this);
findViewById(R.id.btn_hide_nav_bar).setOnClickListener(this);
findViewById(R.id.btn_full_screen).setOnClickListener(this);
findViewById(R.id.btn_full_screen_imm).setOnClickListener(this);
findViewById(R.id.btn_full_screen_imm_sticky).setOnClickListener(this);
findViewById(R.id.btn_layout_stable).setOnClickListener(this);
setOnSystemUiVisibilityChangeListener();
}
public void setOnSystemUiVisibilityChangeListener() {
if (Build.VERSION.SDK_INT >= 14) {
final View decorView = getDecorView();
decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
@Override
public void onSystemUiVisibilityChange(int visibility) {
FullScreenActivity.this.onSystemUiVisibilityChange(visibility);
}
});
}
}
private void clear() {
final View decorView = getDecorView();
if (decorView != null) {
if (Build.VERSION.SDK_INT >= 14) {
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
}
} else {
Toast.makeText(this, "Need API 14 at least", Toast.LENGTH_SHORT).show();
}
}
private void showStatusBar() {
final View decorView = getDecorView();
if (decorView != null) {
if (Build.VERSION.SDK_INT >= 14) {
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
}
} else {
Toast.makeText(this, "Need API 14 at least", Toast.LENGTH_SHORT).show();
}
}
private void hideStatusBar() {
}
private void showNavigationBar() {
}
/**
* Api 14 及以上才有用
* SYSTEM_UI_FLAG_HIDE_NAVIGATION使用此Flag后,导航栏隐藏,点击屏幕的任何区域,取消导航栏的隐藏
* 在全屏后不能有任何操作(4.4之前)
*/
private void hideNavigationBar() {
final View decorView = getDecorView();
if (decorView != null) {
if (Build.VERSION.SDK_INT >= 14) {
int flag = decorView.getSystemUiVisibility();
Log.i(TAG, "hideStatusBar flag = " + flag);
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
Log.i(TAG, "hideStatusBar flag = " + decorView.getSystemUiVisibility());
} else {
Toast.makeText(this, "Need API 14 at least", Toast.LENGTH_SHORT).show();
}
}
}
/**
* SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN : 让view显示在状态栏之下 API16
* SYSTEM_UI_FLAG_FULLSCREEN:隐藏状态栏 API 16
* SYSTEM_UI_FLAG_HIDE_NAVIGATION:隐藏导航栏 API 14
* SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION:让view显示在导航栏之下
* 当在根布局使用属性android:fitsSystemWindows="true"时,在5.0之前,布局始终跟着状态栏或者导航栏(隐藏或者显示),但是5.0中contentView没有在状态栏处全屏显示
* 打出的log显示当系统UI变化(onSystemUiVisibilityChange)时,根布局的paddingTop有变化,状态栏的高度,但是5.0中没有变化
* 在api16 之前android:fitsSystemWindows属性不要和SYSTEM_UI_FLAG_HIDE_NAVIGATION状态栏一起显示
*/
private void fullScreen() {
final View decorView = getDecorView();
if (decorView != null) {
if (Build.VERSION.SDK_INT >= 16) {
int flag = decorView.getSystemUiVisibility();
Log.i(TAG, "hideStatusBar flag = " + flag);
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
Log.i(TAG, "hideStatusBar flag = " + decorView.getSystemUiVisibility());
} else {
Toast.makeText(this, "Need API 16 at least", Toast.LENGTH_SHORT).show();
}
}
}
/**
* 沉浸模式android 4.4(API 19)及以上
* SYSTEM_UI_FLAG_IMMERSIVE和SYSTEM_UI_FLAG_HIDE_NAVIGATION和SYSTEM_UI_FLAG_FULLSCREEN一起使用,用户可以全屏状态下拦截所有的触摸时间
* 注意,immersive类的标签只有在与SYSTEM_UI_FLAG_HIDE_NAVIGATION,SYSTEM_UI_FLAG_FULLSCREEN中一个或两个一起使用的时候才会生效。你可以只使用其中的一个,但是一般情况下你需要同时隐藏状态栏和导航栏以达到沉浸的效果。
*/
private void fullScreenImmersive() {
final View decorView = getDecorView();
if (decorView != null) {
if (Build.VERSION.SDK_INT >= 19) {
int flag = decorView.getSystemUiVisibility();
Log.i(TAG, "hideStatusBar flag = " + flag);
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE);
Log.i(TAG, "hideStatusBar flag = " + decorView.getSystemUiVisibility());
} else {
Toast.makeText(this, "Need API 14 at least", Toast.LENGTH_SHORT).show();
}
}
}
/**
* 使用粘性的沉浸模式
* SYSTEM_UI_FLAG_IMMERSIVE_STICKY:使用后,向下滑动显示状态栏和导航栏,五秒后隐藏,但是锁屏后在解锁,不会消失
* 和theme android:windowFullscreen 使用时,不管是否使用粘性的模式,状态栏都会自动消失,导航栏不会,导航栏只在粘性模式下自动消失
*/
private void fullScreenImmersiveSticky() {
final View decorView = getDecorView();
if (decorView != null) {
if (Build.VERSION.SDK_INT >= 19) {
int flag = decorView.getSystemUiVisibility();
Log.i(TAG, "hideStatusBar flag = " + flag);
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
Log.i(TAG, "hideStatusBar flag = " + decorView.getSystemUiVisibility());
} else {
Toast.makeText(this, "Need API 14 at least", Toast.LENGTH_SHORT).show();
}
}
}
private void layoutStable() {
final View decorView = getDecorView();
if (decorView != null) {
if (Build.VERSION.SDK_INT >= 16) {
int flag = decorView.getSystemUiVisibility();
Log.i(TAG, "hideStatusBar flag = " + flag);
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
Log.i(TAG, "hideStatusBar flag = " + decorView.getSystemUiVisibility());
} else {
Toast.makeText(this, "Need API 16 at least", Toast.LENGTH_SHORT).show();
}
}
}
private View getDecorView() {
final Window window = getWindow();
View decorView = window != null ? window.getDecorView() : null;
return decorView;
}
@Override
public void onClick(View v) {
int id = v.getId();
switch (id) {
case R.id.btn_clear:
clear();
break;
case R.id.btn_show_status_bar:
showStatusBar();
break;
case R.id.btn_hide_status_bar:
hideStatusBar();
break;
case R.id.btn_show_nav_bar:
showNavigationBar();
break;
case R.id.btn_hide_nav_bar:
hideNavigationBar();
break;
case R.id.btn_full_screen:
fullScreen();
break;
case R.id.btn_full_screen_imm:
fullScreenImmersive();
break;
case R.id.btn_full_screen_imm_sticky:
fullScreenImmersiveSticky();
break;
case R.id.btn_layout_stable:
layoutStable();
break;
default:
break;
}
if (v instanceof Button) {
mShowTips.setText(((Button) v).getText());
}
}
public void onSystemUiVisibilityChange(int visibility) {
Log.e(TAG, "onSystemUiVisibilityChange visibility = " + visibility);
View rootView = findViewById(R.id.fullscreen_layout);
Log.e(TAG, rootView.getPaddingTop() + " " + rootView.getPaddingBottom());
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
Log.e(TAG, "onWindowFocusChanged hasFocus = " + hasFocus);
}
}
package com.whuthm.immersive;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ListView;
import android.widget.TextView;
import com.whuthm.base.view.BaseAdapter;
import java.util.ArrayList;
import java.util.List;
/**
* Created by DELL on 2015/7/22.
*/
public class TranslucentSystemUIActivity extends BaseActivity {
private static final String TAG = "TranslucentSystemUI";
private ListView mListView;
private List<Integer> mDatas;
private MyAdapter mAdapter;
/**
* 透明状态下是真正的全屏显示,除非在根布局下使用android:fitsSystemWindows="true",则布局现在状态栏和导航栏中间
*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//translucentSystemUI();
//colorSystemUI();
setContentView(R.layout.activity_translucent_system_ui);
initToolbar();
mListView = (ListView) findViewById(R.id.list_view);
mDatas = new ArrayList<Integer>();
for (int i = 0; i < 80; i++) {
mDatas.add(i);
}
mAdapter = new MyAdapter(this, mDatas);
mListView.setAdapter(mAdapter);
Log.e(TAG, getNavigationBarHeight(this) + " " + checkDeviceHasNavigationBar(this));
}
/**
* 使用style来控制
* <item name="android:windowTranslucentStatus">true</item>
* <item name="android:windowTranslucentNavigation">true</item>
* 使用代码来控制状态栏和导航栏的透明
* API 19
*/
private void translucentSystemUI() {
if (Build.VERSION.SDK_INT >= 19) {
Window window = getWindow();
window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
}
}
private void colorSystemUI() {
if (Build.VERSION.SDK_INT >= 21) {
Window window = getWindow();
//window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
//window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
//window.setFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS, WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.BLUE);
window.setNavigationBarColor(Color.BLUE);
}
}
public static int getNavigationBarHeight(Context context) {
Resources resources = context.getResources();
int resourceId = resources.getIdentifier("navigation_bar_height",
"dimen", "android");
//获取NavigationBar的高度
int height = resources.getDimensionPixelSize(resourceId);
return height;
}
public static boolean checkDeviceHasNavigationBar(Context context) {
if (Build.VERSION.SDK_INT >= 14) {
//通过判断设备是否有返回键、菜单键(不是虚拟键,是手机屏幕外的按键)来确定是否有navigation bar
boolean hasMenuKey = ViewConfiguration.get(context)
.hasPermanentMenuKey();
boolean hasBackKey = KeyCharacterMap
.deviceHasKey(KeyEvent.KEYCODE_BACK);
if (!hasMenuKey && !hasBackKey) {
// 做任何你需要做的,这个设备有一个导航栏
return true;
}
}
return false;
}
class MyAdapter extends BaseAdapter<Integer> {
public MyAdapter(Context context, List<Integer> list) {
super(context, list);
}
public View createView(Context context, ViewGroup parent) {
return new TextView(context);
}
public BaseAdapter.ViewHolder<Integer> createViewHolder() {
return new MyHolder();
}
}
class MyHolder extends BaseAdapter.ViewHolder<Integer> {
TextView tv;
@Override
public void init(Context context, View convertView) {
tv = (TextView) convertView;
}
@Override
public void update(Context context, Integer data) {
tv.setText("Item " + data);
}
}
}
使用主题实现 api19
<resources>
<style name="TranslucentSystemUITheme" parent="AppBaseTheme">
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:windowContentOverlay">@null</item>
</style>
</resources>