在学习Android4.4沉浸模式的时候,
点击打开链接的博主将下面的问题写的比较全面,大家可以参考一下。
- 沉浸模式进入退出时系统栏和状态栏会遮盖画面问题
- 怎么样进入Activity和切换Activity时切换沉浸模式
不过补充一点:在退出沉浸模式时将系统栏和状态栏恢复的时候,调用了setSystemUiVisibility后直接去取画面的偏移高度Top的时候
<pre name="code" class="java">Rect frame = new Rect();
topView.getWindowVisibleDisplayFrame(frame) ;
int height = frame.top;
heightの值为0,因此画面还是因为没有计算系统栏的高度被遮盖了一半。
该height=0应该是此时还没被UI线程更新和赋值。
解决方法是将获取系统栏和状态栏的高度放在一个UI线程的handler里面去排队执行。
public class MainActivity extends Activity implements OnClickListener{
LinearLayout rl;
View topView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeButtonEnabled(true);
// activity_main ID
rl = (LinearLayout)findViewById(R.id.rl);
topView = getWindow().getDecorView();
rl.setPadding(0, 0, 0, 0);
Button btOn = (Button) findViewById(R.id.on);
btOn.setOnClickListener(this);
Button btOff = (Button) findViewById(R.id.off);
btOff.setOnClickListener(this);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
switch(item.getItemId()){
case android.R.id.home:
finish();
break;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.on:
hideSystemUI(topView);
rl.setPadding(0, 0, 0, 0);
break;
case R.id.off:
showSystemUI(topView);
topView.postInvalidate();
// 放到UI线程的handler里面执行
Message msg = new Message();
msg.what = 1;
this.validateHandler.sendMessage(msg);
break;
default:
break;
}
}
private Handler validateHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what)
{
case 1:
Rect frame = new Rect();
topView.getWindowVisibleDisplayFrame(frame);
int paddingTop = getActionBar().getHeight()+ frame.top;
rl.setPadding(0, paddingTop, 0, 0);
break;
}
super.handleMessage(msg);
}
};
public static void hideSystemUI(View view) {
view.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);
}
@SuppressLint("NewApi")
public static void showSystemUI(View view) {
view.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
由该博主后来回答,其实还可以通过反射方法直接从系统中取出actionbar和Statusbar的高度,也是一个很好的方法,这里引用一下。
// 获取手机状态栏高度
public static int getStatusBarHeight(Context context) {
Class<?> c = null;
Object obj = null;
Field field = null;
int x = 0, statusBarHeight = 0;
try {
c = Class.forName("com.android.internal.R$dimen");
obj = c.newInstance();
field = c.getField("status_bar_height");
x = Integer.parseInt(field.get(obj).toString());
statusBarHeight = context.getResources().getDimensionPixelSize(x);
} catch (Exception e) {
e.printStackTrace();
}
return statusBarHeight;
}
// 获取ActionBar的高度
public static int getActionBarHeight(Context context) {
TypedValue tv = new TypedValue();
int actionBarHeight = 0;
if (context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true))
{
actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data, context.getResources().getDisplayMetrics());
}
return actionBarHeight;
}