在android4.4及以上版本中为setSystemUiVisibility()方法引入了一个新的flag:SYSTEM_UI_FLAG_IMMERSIVE,它可以使你的app实现真正意义上的全屏体验。当SYSTEM_UI_FLAG_IMMERSIVE、SYSTEM_UI_FLAG_HIDE_NAVIGATION 和SYSTEM_UI_FLAG_FULLSCREEN三个flag一起使用的时候,可以隐藏状态栏与导航栏,同时让你的app可以捕捉到用户的所有触摸屏事件。
当你使用SYSTEM_UI_FLAG_IMMERSIVE标签的时候,它是基于其他设置过的标签(SYSTEM_UI_FLAG_HIDE_NAVIGATION和SYSTEM_UI_FLAG_FULLSCREEN)来隐藏系统栏的。当用户向内滑动,系统栏重新显示并保持可见。
当使用了SYSTEM_UI_FLAG_IMMERSIVE_STICKY标签的时候,向内滑动的操作会让系统栏临时显示,并处于半透明的状态。此时没有标签会被清除,系统UI可见性监听器也不会被触发。如果用户没有进行操作,系统栏会在一段时间内自动隐藏。
虚拟导航栏:采用软件方式实现的屏幕底部的back、home、menu导航键,显示在屏幕的下方。
public class GameActivity extends Activity {
public static class Content extends TouchPaint.PaintView implements
View.OnSystemUiVisibilityChangeListener, View.OnClickListener {
Activity mActivity;
Button mPlayButton;
boolean mPaused;
int mLastSystemUiVis;
boolean mUpdateSystemUi;
Runnable mFader = new Runnable() {
@Override public void run() {
fade();
if (mUpdateSystemUi) {
updateNavVisibility();
}
if (!mPaused) {
getHandler().postDelayed(mFader, 1000/30);
}
}
};
public Content(Context context, AttributeSet attrs) {
super(context, attrs);
setOnSystemUiVisibilityChangeListener(this);
}
public void init(Activity activity, Button playButton) {
// This called by the containing activity to supply the surrounding
// state of the game that it will interact with.
mActivity = activity;
mPlayButton = playButton;
mPlayButton.setOnClickListener(this);
setGamePaused(true);
}
@Override public void onSystemUiVisibilityChange(int visibility) {
// 监测导航栏是否被隐藏,来决定我们是否需要更新系统栏。如果用户在游戏的时候需
// 要调用导航栏,则可能通过在状态栏与导航栏原来区域的边缘向内滑动让系统栏重新
// 显示。此时需要更新系统栏。
int diff = mLastSystemUiVis ^ visibility;
mLastSystemUiVis = visibility;
if (!mPaused && (diff&SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
&& (visibility&SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) {
// We are running and the system UI navigation has become
// shown... we want it to remain hidden, so update our system
// UI state at the next game loop.
mUpdateSystemUi = true;
}
}
@Override protected void onWindowVisibilityChanged(int visibility) {
super.onWindowVisibilityChanged(visibility);
// When we become visible or invisible, play is paused.
setGamePaused(true);
}
@Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
super.onWindowFocusChanged(hasWindowFocus);
// When we become visible or invisible, play is paused.
// Optional: pause game when window loses focus. This will cause it to
// pause, for example, when the notification shade is pulled down.
if (!hasWindowFocus) {
//setGamePaused(true);
}
}
@Override public void onClick(View v) {
if (v == mPlayButton) {
// Clicking on the play/pause button toggles its state.
setGamePaused(!mPaused);
}
}
void setGamePaused(boolean paused) {
mPaused = paused;
mPlayButton.setText(paused ? R.string.play : R.string.pause);
//在视图可见的情况下是否保持屏幕的唤醒状态
setKeepScreenOn(!paused);
updateNavVisibility();
Handler h = getHandler();
if (h != null) {
getHandler().removeCallbacks(mFader);
if (!paused) {
mFader.run();
text("Draw!");
}
}
}
void updateNavVisibility() {
int newVis = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| SYSTEM_UI_FLAG_LAYOUT_STABLE;
if (!mPaused) {
newVis |= SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_FULLSCREEN
| SYSTEM_UI_FLAG_HIDE_NAVIGATION | SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
}
// Set the new desired visibility.
setSystemUiVisibility(newVis);
//重新设置后则不需要再更新了
mUpdateSystemUi = false;
}
}
Content mContent;
public GameActivity() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.game);
mContent = (Content)findViewById(R.id.content);
mContent.init(this, (Button)findViewById(R.id.play));
}
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
}
@Override
protected void onPause() {
super.onPause();
// Pause game when its activity is paused.
mContent.setGamePaused(true);
}
}
game.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent"
>
<!-- This is the outer area of the entire game screen, extending out under
system UI elements. -->
<view class="com.example.android.apis.view.GameActivity$Content"
android:id="@+id/content"
android:src="@drawable/frantic"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="center"
/>
<!-- This is the inner area of the game, not covered by system UI elements.
Any UI elements that need to be accessible when the game is paused or other
states where the system UI is shown (such as in menus) should go here. -->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:animateLayoutChanges="true"
>
<Button
android:id="@+id/play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="top|right"
android:textSize="28dp"
/>
</FrameLayout>
</FrameLayout>