Android Compose对Window Insets的处理_rememberinsetspaddingvalues

文末

好了,今天的分享就到这里,如果你对在面试中遇到的问题,或者刚毕业及工作几年迷茫不知道该如何准备面试并突破现状提升自己,对于自己的未来还不够了解不知道给如何规划,可以来看看同行们都是如何突破现状,怎么学习的,来吸收他们的面试以及工作经验完善自己的之后的面试计划及职业规划。

这里放上一部分我工作以来以及参与过的大大小小的面试收集总结出来的一套进阶学习的视频及面试专题资料包,主要还是希望大家在如今大环境不好的情况下面试能够顺利一点,希望可以帮助到大家

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

ProvideWindowInsets {
Sample1(modifier = Modifier.systemBarsPadding())
}


等等, 这么一处理, 如果忽略system bars颜色的设置. 和最开始默认的情形看起来是一模一样.


那么我们是不是可以直接删掉`WindowCompat.setDecorFitsSystemWindows(window, false)`这行, 用默认设置就好了?


* 是. 如果你的需求真的是这样.
* 不是. 如果你需要把app背景绘制出去; 如果你还有输入框的处理.


如果需求想要的是背景延伸出去, 文字内嵌. 分别给上下两个元素加了不同的padding:



Column(
modifier = modifier.fillMaxSize()
.background(color = Color.Blue.copy(alpha = 0.3f)),
verticalArrangement = Arrangement.SpaceBetween
) {
Text(
modifier = Modifier.fillMaxWidth()
.background(color = Color.Yellow.copy(alpha = 0.5f))
.statusBarsPadding(),
text = “Top Text”,
style = MaterialTheme.typography.h2
)
Text(text = “Content”, style = MaterialTheme.typography.h2)
Text(
modifier = Modifier.fillMaxWidth()
.navigationBarsPadding()
.background(color = Color.Yellow.copy(alpha = 0.5f)),
text = “Bottom Text”,
style = MaterialTheme.typography.h2
)
}


运行以后如下图中右边所示:


![add insets pading](https://img-blog.csdnimg.cn/img_convert/6c51af961cb94851b02cad04d20c8af0.png)


注意这里modifier的顺序, 上下延伸出去的颜色是不同的, 下面延伸出去的其实是Column的颜色.


左边是把insets padding加在整体布局的情况, 如果用的是system bars的话, 和默认UI效果是一样的.


具体根据需求定制即可.


#### LazyColumn的padding和content padding


有一个非常长的LazyColumn, 在edge-to-edge的设计下应该怎么显示呢? 这里有三种选择:


1. List完全全屏: `LazyColumn {}`
2. List留出上下padding: `LazyColumn(modifier = Modifier.systemBarsPadding()) {}`
3. List留出Content padding:



LazyColumn(
contentPadding = rememberInsetsPaddingValues(
insets = LocalWindowInsets.current.systemBars,
applyTop = true,
applyBottom = true,
)
) {}


其实1和2的行为非常类似, 只是显示区域大小的区别. content padding只是在第一个item的上面和最后一个item的下面加上padding, 在滚动的中间过程中内容是可以全屏的, 只有到头或者到底了才会显示出padding.


![lazycolumn-padding.png](https://img-blog.csdnimg.cn/img_convert/ea5470f87dbc7f9e215123cce2efe23a.png)


content padding用动图更能说明情况:


![content pading](https://img-blog.csdnimg.cn/img_convert/a9fc51087401ea1a524ed80192b8fc3b.gif)


#### 内容区域处理总结


Insets这个库提供了这么几个Modifier:


* `Modifier.statusBarsPadding()`
* `Modifier.navigationBarsPadding()`
* `Modifier.systemBarsPadding()`
* `Modifier.imePadding()`
* `Modifier.navigationBarsWithImePadding()`
* `Modifier.cutoutPadding()` 可以直接在布局中用上, 就获取了应该有的padding, 比如statusBarPadding是top, navigationBarsPadding是bottom. 这都不用开发者自己想.


如果这些都不满足你的需求, 也可以直接用尺寸:


* `Modifier.statusBarsHeight()`
* `Modifier.navigationBarsHeight()`
* `Modifier.navigationBarsWidth()`


或者更直接地用`LocalWindowInsets.current`自己获取想要inset类型的相关尺寸.


### 输入框元素和键盘


on-screen keyboard, 又叫IME (Input Method Editor), 一般点击输入框会弹出, IME也是一种Inset.


#### 输入框被键盘遮挡问题


当输入框处于屏幕上半屏的时候, 基本不用考虑键盘遮挡的问题. 但是当输入框在屏幕下半屏, 我们需要在键盘弹出来的时候让输入框完全显示出来而不被盖住.


解决这个问题需要这么几个东西:


* Activity的`android:windowSoftInputMode="adjustResize"`, 表示在键盘弹出时, Activity会改变布局大小, 这种改变是挤压型的.
* `Modifier.imePadding`的使用, 给布局加上一个恰好等于键盘高度的bottom padding. 通常是给输入框的父布局, 加在哪一层视情况而定.
* 如果上面两个都设置了仍然不能把输入框完全显示出来, 可能需要再加入点强力的唤醒行为.


根据这个issue下的[这条comment], 可以用这个Modifier, 在这个ui获取到焦点的时候, 自己把自己bring into view.



@ExperimentalComposeUiApi
fun Modifier.bringIntoViewAfterImeAnimation(): Modifier = composed {
val imeInsets = LocalWindowInsets.current.ime
var focusState by remember { mutableStateOf<FocusState?>(null) }
val relocationRequester = remember { RelocationRequester() }

LaunchedEffect(
    imeInsets.isVisible,
    imeInsets.animationInProgress,
    focusState,
    relocationRequester
) {
    if (imeInsets.isVisible &&
        !imeInsets.animationInProgress &&
        focusState?.isFocused == true) {
        relocationRequester.bringIntoView()
    }
}

relocationRequester(relocationRequester)
    .onFocusChanged { focusState = it }

}


这个`ReloactionRequest`已经deprecated了, Compose新版的叫`BringIntoViewRequester`.


#### IME padding计算和布置


`.imePadding()`的值是变化的, 在没有键盘的情况下是0, 等有键盘的时候变为键盘高度.


计算键盘弹出的高度要注意:


* 最简单的情况直接用`.imePadding()`完事, 布局的bottom padding自动和IME贴合.
* 如果整体已经有了navigation bar的高度, 可以考虑用`.navigationBarsWithImePadding()`, 它是取IME和navigation bar高度的最大值.
* 如果键盘上方出现了白条, 说明padding算多了, 要么是布局中已经有inner padding, 要么就是已经加过`navigationBarsPadding`. 这时候可以自己做一个减法处理.


比如这个:



LazyColumn(
contentPadding = PaddingValues(
bottom = with(LocalDensity.current) {
LocalWindowInsets.current.ime.bottom.toDp() - innerPadding.bottom
}.coerceAtLeast(0.dp)
)
) { /* … */ }


`.imePadding`放在哪里, 关系到什么样的区域会被显示出来, 被包裹的区域会显示在键盘上方.


来举个例子, 有个带输入框的界面.


我们给它整体设置一个`.navigationBarsWithImePadding()`, 表示没键盘的时候, 底部留navigation bar的高度, 有键盘的时候留键盘的高度:



Column(
modifier = Modifier.fillMaxSize().statusBarsPadding().navigationBarsWithImePadding()
.background(color = Color.Cyan.copy(alpha = 0.2f)),
verticalArrangement = Arrangement.SpaceBetween
) {
Text(
modifier = Modifier.fillMaxWidth()
.background(color = Color.Yellow.copy(alpha = 0.5f)),
text = “Top Text”,
style = MaterialTheme.typography.h2
)
Text(text = “Content”, style = MaterialTheme.typography.h2)
MyTextField(“Text Field 1”)
MyTextField(“Text Field 2”)
Text(
modifier = Modifier.fillMaxWidth()
.background(color = Color.Yellow.copy(alpha = 0.5f)),
text = “Bottom Text”,
style = MaterialTheme.typography.h2
)
}


键盘弹出时, Bottom Text也会被顶上去, 这是因为imePadding作用于整块的布局.


如果我们这样改, 只包裹输入框的部分, 那么键盘就不会把底部的UI顶上去:



Column(
modifier = Modifier.fillMaxSize().statusBarsPadding()
.background(color = Color.Cyan.copy(alpha = 0.2f)),
verticalArrangement = Arrangement.SpaceBetween
) {
Text(
modifier = Modifier.fillMaxWidth()
.background(color = Color.Yellow.copy(alpha = 0.5f)),
text = “Top Text”,
style = MaterialTheme.typography.h2
)
Text(text = “Content”, style = MaterialTheme.typography.h2)

Text(
    modifier = Modifier.fillMaxWidth()
        .background(color = Color.Yellow.copy(alpha = 0.5f)),
    text = "Bottom Text",
    style = MaterialTheme.typography.h2
)

}


两种效果见图:


![ime-handling.png](https://img-blog.csdnimg.cn/img_convert/c13f69a7047f17c86253f844744c4ecb.png)


#### 键盘部分总结延伸


总结: 输入框键盘的处理包括了:


* adjustResize.
* 设置合理的bottom padding: 在哪里设置, 需要设置多少.
* 让View主动bring自己到可见位置.


Insets库里还提供了键盘随着滚动消失和出现的例子. 感兴趣可以看下.



### 最后我想说

**为什么很多程序员做不了架构师?**
1、良好健康的职业规划很重要,但大多数人都忽略了
2、学习的习惯很重要,持之以恒才是正解。
3、编程思维没能提升一个台阶,局限在了编码,业务,没考虑过选型、扩展
4、身边没有好的架构师引导、培养。所处的圈子对程序员的成长影响巨大。

金九银十面试季,跳槽季,整理面试题已经成了我多年的习惯!**在这里我和身边一些朋友特意整理了一份快速进阶为Android高级工程师的系统且全面的学习资料。涵盖了Android初级——Android高级架构师进阶必备的一些学习技能。**

附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)

![](https://img-blog.csdnimg.cn/img_convert/5f7a08d28294cde6bd870eb64fec5691.webp?x-oss-process=image/format,png)

**里面包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…**




**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化学习资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618156601)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

转存中...(img-u900ktOz-1715158876581)]

**里面包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中…**




**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化学习资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618156601)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

  • 30
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值