安卓开发常见问题总结
前言
总结了我个人遇到的问题,不代表所有人,可能解决方案并不是最优的,欢迎联系我交流经验:)
1.沉浸式状态栏/导航栏
首先设置窗口管理
enableEdgeToEdge()
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, 0, systemBars.right, 0)
insets
}
然后给布局的顶栏AppBarLayout等等设置这个属性android:fitsSystemWindows="true"
,底栏需要的话也设置这个
2.动态颜色
如果Activity继承的是Application()
那么在onCreate后用DynamicColors.applyToActivitiesIfAvailable(this)
否则用DynamicColors.applyToActivityIfAvailable(this)
需要在每个Activity都加这个
3.在Fragment中获取Context
requireContext()
Activity同理requireActivity()
4.延迟绑定布局id
如果直接在onCreate里find会警告甚至爆红
kt里延迟赋值直接用
private val text: TextView by lazy { findViewById(R.id.text) }
5.获取夜间模式状态
fun isNightMode(context: Context): Boolean {
return (context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES
}
6.沉静导航栏+输入法影响布局
ViewCompat.setOnApplyWindowInsetsListener(rootLayout) {
view, insets ->
val imeInsets = insets.getInsets(WindowInsetsCompat.Type.ime())
val navigationBarInsets = insets.getInsets(WindowInsetsCompat.Type.navigationBars())
val statusBarInsets = insets.getInsets(WindowInsetsCompat.Type.statusBars())
// 调整底部需要被影响的位置,fab,其他布局,使其位于输入法上方
bottomSymbolBar.translationY = -imeInsets.bottom.toFloat()
fab.translationY = -imeInsets.bottom.toFloat()
// 设置根布局的底部内边距
if (imeInsets.bottom > 0) {
// 输入法可见时,不需要额外的底部内边距来避免被导航栏遮挡,
// 因为 bottomSymbolBar 已经移动到输入法上方
view.setPadding(
navigationBarInsets.left,
statusBarInsets.top,
navigationBarInsets.right,
0
)
} else {
// 输入法不可见时,设置底部内边距以避免内容被导航栏遮挡
view.setPadding(
navigationBarInsets.left,
statusBarInsets.top,
navigationBarInsets.right,
navigationBarInsets.bottom
)
}
insets
}
7.丝滑过渡两个View
用于一个view转变成另一个view,实质第一个view移动到第二个view,使第一个view不可见,第二个view可见
fun startContainerTransition(root: View, v1: View, v2: View) {
val transform = MaterialContainerTransform().apply {
fadeMode = MaterialContainerTransform.FADE_MODE_IN // 0,对应 FADE_MODE_IN
fitMode = MaterialContainerTransform.FIT_MODE_AUTO // 0,对应 FIT_MODE_AUTO
scrimColor = Color.TRANSPARENT
startView = v1
endView = v2
addTarget(v2)
}
// 开始动画过渡
TransitionManager.beginDelayedTransition(root as ViewGroup, transform)
v1.visibility = View.INVISIBLE
v2.visibility = View.VISIBLE
}
用法
startContainerTransition(根布局,第一个view,第二个view)
8.AppBar遮挡布局
适用于在CoordinatorLayout
根布局下的
给被遮挡的加属性
app:layout_behavior="@string/appbar_scrolling_view_behavior"
使起显示在appbar下面
9.BottomBar遮挡布局
和8有点像但是目前没非常好的解决办法
这里使用动态设置布局的PaddingBottom
//view被遮挡的布局
// 设置布局的bottom高度适配
activity?.findViewById<BottomNavigationView>(R.id.bottomBar)?.let { bottomNavigationView ->
val bottomBarHeight = bottomNavigationView.height
view.setPadding(
view.paddingLeft,
view.paddingTop,
view.paddingRight,
bottomBarHeight
)
}
10.Activity和Context的区别
Activity继承
自Context
Activity主要是管理一个界面
Activity拥有完善的生命周期
回调方法onCreate...
Context主要用于资源、服务、启动组件
通常用Context的地方用Activity不会报错,但是反过来不行,但是不建议都用activity,会占用更多内存等等
11.一个app项目里java和kt可以混着用吗
可以
同时存在java文件和kt文件,相互导入等等操作
12.不要在ScrollView
里嵌套RecyclerView
众所周知,RecyclerView
是动态加载数据的,高性能。
但是将其嵌套在ScrollView
就会导致其一次性加载完所有数据,及其影响性能。
13.ImageView
图片过于清晰导致界面卡顿
ImageView
加载清晰的过高的图片可能导致卡顿
解决方法,设置固定宽高,不要用wrap_content
android:layout_width="64dp"
android:layout_height="64dp"
14.分界线
不建议自己构造分界线
用Material自带的,还自动支持夜间模式哦
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
15.MaterialCardView
空心/填充/阴影
不建议手动改属性
用Style
空心
style="@style/Widget.Material3.CardView.Outlined"
填充
style="@style/Widget.Material3.CardView.Filled"
阴影
style="@style/Widget.Material3.CardView.Elevated"
16.文字样式
用material的文字style
总结如下
语义化名称 | Material 3 TextAppearance 样式名称 | 描述 |
---|---|---|
Display | @style/TextAppearance.Material3.DisplayLarge | 最大的标题 |
@style/TextAppearance.Material3.DisplayMedium | 较大的标题 | |
@style/TextAppearance.Material3.DisplaySmall | 较小的标题 | |
Headline | @style/TextAppearance.Material3.HeadlineLarge | 最大的高强调文本 |
@style/TextAppearance.Material3.HeadlineMedium | 较大的高强调文本 | |
@style/TextAppearance.Material3.HeadlineSmall | 较小的高强调文本 | |
Title | @style/TextAppearance.Material3.TitleLarge | 较大的标题 |
@style/TextAppearance.Material3.TitleMedium | 中等的标题 | |
@style/TextAppearance.Material3.TitleSmall | 较小的标题 | |
Body | @style/TextAppearance.Material3.BodyLarge | 较大的正文 |
@style/TextAppearance.Material3.BodyMedium | 标准正文 | |
@style/TextAppearance.Material3.BodySmall | 较小的正文 | |
Label | @style/TextAppearance.Material3.LabelLarge | 较大的标签 |
@style/TextAppearance.Material3.LabelMedium | 标准标签 | |
@style/TextAppearance.Material3.LabelSmall | 较小的标签 |
未完待续...