DecorView的setSystemUiVisibility方法和getSystemUiVisibility方法

探讨了Android中实现全屏显示与沉浸式用户体验的方法,包括使用PhoneWindow和DecorView,以及通过设置不同UI标志实现状态栏和导航栏的隐藏。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

开发中,通常都是在onCreate()中调用setContentView(R.layout.custom_layout)来实现想要的页面布局。页面都是依附在窗口之上的,而DecorView即是窗口最顶层的视图。Android frameworks中,与窗口视图处理相关的类,主要是Window及其实现类PhoneWindow

public class PhoneWindow extends Window implements MenuBuilder.Callback {
  
  //...

  //窗口顶层View
   private DecorView mDecor;
   
  //所有自定义View的根View, id="@android:id/content"
   private ViewGroup mContentParent;

  //...

}

DecorView其实是PhoneWindow中的一个内部类,本质上也是一个View,其只是扩展了FrameLayout的实现

private final class DecorView extends FrameLayout implements RootViewSurfaceTaker

 

setSystemUiVisibility(int visibility)方法可传入的实参为:

    1. View.SYSTEM_UI_FLAG_VISIBLE:显示状态栏,Activity不全屏显示(恢复到有状态栏的正常情况)。

    2. View.INVISIBLE:隐藏状态栏,同时Activity会伸展全屏显示。

    3. View.SYSTEM_UI_FLAG_FULLSCREEN:Activity全屏显示,且状态栏被隐藏覆盖掉。

    4. View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN:Activity全屏显示,但状态栏不会被隐藏覆盖,状态栏依然可见,Activity顶端布局部分会被状态遮住。

    5. View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION:效果同View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

    6. View.SYSTEM_UI_LAYOUT_FLAGS:效果同View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

    7. View.SYSTEM_UI_FLAG_HIDE_NAVIGATION:隐藏虚拟按键(导航栏)。有些手机会用虚拟按键来代替物理按键。

    8. View.SYSTEM_UI_FLAG_LOW_PROFILE:状态栏显示处于低能显示状态(low profile模式),状态栏上一些图标显示会被隐藏。

  

Android4.4新特性又增加下面俩个:

View.SYSTEM_UI_FLAG_IMMERSIVE
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY

Android 4.4新特性之开启全屏沉浸模式

 

另外

View.SYSTEM_UI_FLAG_LAYOUT_STABLE

这个标志来帮助你的应用维持一个稳定的布局。

package com.st.base.ui; import android.content.Intent; import android.graphics.Color; import android.os.Bundle; import android.view.View; import android.view.Window; import android.view.WindowManager; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import androidx.databinding.DataBindingUtil; import androidx.databinding.ViewDataBinding; import androidx.fragment.app.FragmentActivity; import androidx.lifecycle.ViewModel; import androidx.lifecycle.ViewModelProvider; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; public abstract class BaseActivity<V extends ViewDataBinding> extends AppCompatActivity implements IBaseView { protected V binding; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); //页面接受的参数方法 initParam(); //隐藏顶部底部栏 transparentNavBar(getWindow()); //私有的初始化DatabindingViewModel方法 initViewDataBinding(savedInstanceState); //初始化ui initView(); //私有的ViewModel与View的契约事件回调逻辑 registorUIChangeLiveDataCallBack(); //页面数据初始化方法 initData(); //页面事件监听的方法,一般用于ViewModel层转到View层的事件注册 initViewObservable(); //页面监听回调 initCallback(); } protected abstract void initView(); protected abstract void initCallback(); protected abstract void releaseCallback(); private void initViewDataBinding(Bundle savedInstanceState) { //DataBindingUtil类需要在project的build中配置 dataBinding {enabled true }, 同步后会自动关联android.databinding包 binding = DataBindingUtil.setContentView(this, initContentView(savedInstanceState)); //支持LiveData绑定xml,数据改变,UI自动会更新 binding.setLifecycleOwner(this); initViewDataModel(); } protected void initViewDataModel() { } /** * 初始化根布局 * * @return 布局layout的id */ public abstract int initContentView(Bundle savedInstanceState); protected int initVariableId() { return 0; } protected void registorUIChangeLiveDataCallBack() { } @Override public void initParam() { } @Override public ViewModel initViewModel() { return null; } @Override public void initData() { } @Override public void initViewObservable() { } /** * 跳转页面 * * @param clz 所跳转的目的Activity类 * @param bundle 跳转所携带的信息 */ public void startActivity(Class<?> clz, Bundle bundle) { Intent intent = new Intent(this, clz); if (bundle != null) { intent.putExtras(bundle); } startActivity(intent); } /** * 创建ViewModel * * @param cls * @param <T> * @return */ public <T extends ViewModel> T createViewModel(FragmentActivity activity, Class<T> cls) { return new ViewModelProvider(activity).get(cls); } @Override protected void onDestroy() { super.onDestroy(); if (binding != null) { binding.unbind(); } releaseCallback(); } protected void transparentNavBar(@NonNull final Window window) { 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_STABLE); window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); //状态栏、导航栏透明 window.setStatusBarColor(Color.TRANSPARENT); window.setNavigationBarContrastEnforced(false); window.setNavigationBarColor(Color.TRANSPARENT); View decorView = window.getDecorView(); int vis = decorView.getSystemUiVisibility(); int option = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE; decorView.setSystemUiVisibility(vis | option); } } --------- 这个代码的单元测试可以通过PowerMockmockito实现吗
07-25
package com.st.engineeringmode.base; import android.os.Bundle; import android.view.View; import android.view.WindowManager; import androidx.activity.ComponentActivity; import androidx.annotation.Nullable; import androidx.databinding.DataBindingUtil; import androidx.databinding.ViewDataBinding; import androidx.lifecycle.ViewModelProvider; import com.st.engineeringmode.util.LogUtils; /** * Description: * Author: shaofengf * Create: 2024/9/6 16:29 */ public abstract class BaseActivity<V extends ViewDataBinding, VM extends BaseViewModel> extends ComponentActivity { public final String TAG = this.getClass().getSimpleName(); protected V binding; protected VM viewModel; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); hideStatusBar(); initViewDataBinding(savedInstanceState); initView(); } private void hideStatusBar(){ LogUtils.i("TAG", "hideStatusBar: " ); WindowManager.LayoutParams attributes = getWindow().getAttributes(); attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; getWindow().setAttributes(attributes); View decorView = getWindow().getDecorView(); int systemUiVisibility; systemUiVisibility = decorView.getSystemUiVisibility(); int flags = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; systemUiVisibility |= flags; getWindow().getDecorView().setSystemUiVisibility(systemUiVisibility); } protected abstract int getLayoutView(); protected abstract void initView(); protected abstract Class<VM> initViewMode(); /** * 初始化ViewModel的id * * @return BR的id */ public abstract int initVariableId(); private void initViewDataBinding(Bundle savedInstanceState) { binding = DataBindingUtil.setContentView(this, getLayoutView()); viewModel = new ViewModelProvider(this).get(initViewMode()); binding.setVariable(initVariableId(), viewModel); binding.setLifecycleOwner(this); } @Override protected void onDestroy() { super.onDestroy(); if (null != binding) { binding.unbind(); } } }
最新发布
08-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值