Skip to content

安卓开发常见问题总结

🕒 Published at:

安卓开发常见问题总结

前言

总结了我个人遇到的问题,不代表所有人,可能解决方案并不是最优的,欢迎联系我交流经验:)

1.沉浸式状态栏/导航栏

首先设置窗口管理

kotlin
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里延迟赋值直接用

kotlin
private val text: TextView by lazy { findViewById(R.id.text) }

5.获取夜间模式状态

kotlin
 fun isNightMode(context: Context): Boolean {
        return (context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES
    }

6.沉静导航栏+输入法影响布局

kotlin

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可见

kotlin
  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
    }

用法

kotlin
startContainerTransition(根布局,第一个view,第二个view)

8.AppBar遮挡布局

适用于在CoordinatorLayout根布局下的

给被遮挡的加属性

kotlin
 app:layout_behavior="@string/appbar_scrolling_view_behavior"

使起显示在appbar下面

9.BottomBar遮挡布局

和8有点像但是目前没非常好的解决办法

这里使用动态设置布局的PaddingBottom

kotlin
 //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

kotlin
android:layout_width="64dp"
android:layout_height="64dp"

14.分界线

不建议自己构造分界线

用Material自带的,还自动支持夜间模式哦

kotlin
   <com.google.android.material.divider.MaterialDivider
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
    />

15.MaterialCardView空心/填充/阴影

不建议手动改属性

用Style

空心

kotlin
 style="@style/Widget.Material3.CardView.Outlined"

填充

kotlin
 style="@style/Widget.Material3.CardView.Filled"

阴影

kotlin
 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较小的标签

未完待续...