fitsSystemWindows意义与作用

System windows 指的就是屏幕上status bar、 navigation bar等系统控件所占据的部分。

绝大多数情况下,你都不需要理会status bar或者navigation bar 下面的空间,不过你需要注意不能让你的交互控件(比如Button)藏在status bar 或者 navigation bar下面。而android:fitsSystemWindows="true"的默认行为正好解决了这种情况,这个属性的作用就是通过设置View的padding,使得应用的content部分——Activity中setContentView()中传入的就是content——不会与system window重叠。

还有一些事情需要注意:

  • fitsSystemWindows 需要被设置给根View——这个属性可以被设置给任意View,但是只有根View(content部分的根)外面才是SystemWindow,所以只有设置给根View才有用。
  • Insets始终相对于全屏幕——Insets即边框,它决定着整个Window的边界。对Insets设置padding的时候,这个padding始终是相对于全屏幕的。因为Insets的生成在View layout之前就已经完成了,所以系统对于View长什么样一无所知。
  • 其它padding将通通被覆盖。需要注意,如果你对一个View设置了android:fitsSystemWindows="true",那么你对该View设置的其他padding将通通无效。

在绝大多数情况下,默认情况就已经够用了。比如一个全屏的视屏播放器。如果你不想被ActionBar 或者其他System View遮住的话,那么在MatchParent的ViewGroup上设置fitsSystemWindows="true"即可。

或者,也许你希望你的RecyclerView能够在透明的navigation bar 下面滚动。那么只需将android:fitsSystemWindows="true"android:clipToPadding="false"同时使用即可, 滚动的内容会绘制在navigation bar下面,同时当滚动到最下面的时候,最后一个item下面依旧会有padding,使其可以滚到navigation bar上方(而不是在navigation bar下面滚不上来!)。

译者注:clipToPaddingViewGroup的属性。这个属性定义了是否允许ViewGroup在padding中绘制,该值默认为true,即不允许。

https://github.com/hehonghui/android-tech-frontier/blob/master/issue-35/%E4%B8%BA%E4%BB%80%E4%B9%88%E6%88%91%E4%BB%AC%E8%A6%81%E7%94%A8fitsSystemWindows.md

`WindowInsetsController` 主要用于控制窗口插入(WindowInsets)相关的行为,而 `fitsSystemWindows` 是 `View` 的一个属性,`WindowInsetsController` 本身不能直接设置 `fitsSystemWindows`,但可以通过它来控制系统窗口的显示和隐藏,结合设置 `fitsSystemWindows` 实现不同的界面效果。 在 Android 11(API 级别 30)及以上版本,可以使用 `WindowInsetsController` 来控制系统栏的显示和隐藏。以下是一个示例代码,展示如何结合使用 `WindowInsetsController` 和设置 `fitsSystemWindows`: ```java import android.os.Build; import android.view.View; import android.view.Window; import android.view.WindowInsets; import android.view.WindowInsetsController; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 获取当前窗口 Window window = getWindow(); View decorView = window.getDecorView(); // 设置 fitsSystemWindows 为 false decorView.setFitsSystemWindows(false); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { // 获取 WindowInsetsController WindowInsetsController controller = window.getInsetsController(); if (controller != null) { // 隐藏状态栏和导航栏 controller.hide(WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars()); // 设置系统栏行为 controller.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE); } } } } ``` 在 Kotlin 中: ```kotlin import android.os.Build import android.os.Bundle import android.view.View import android.view.WindowInsets import android.view.WindowInsetsController import androidx.appcompat.app.AppCompatActivity class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 获取当前窗口 val window = window val decorView = window.decorView // 设置 fitsSystemWindows 为 false decorView.fitsSystemWindows = false if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { // 获取 WindowInsetsController val controller = window.insetsController controller?.let { // 隐藏状态栏和导航栏 it.hide(WindowInsets.Type.statusBars() or WindowInsets.Type.navigationBars()) // 设置系统栏行为 it.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE } } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值