Compose很好用,但是在真正应用到项目时,我们还需要解决一些问题。
我要开发一个这样的页面,外层用Bottom Navigation Activity,每个tab对应的一个fragment,页面内容我用Compose来填充,不使用xml来布局,因为Compose太好用了,如果不是页面缓存的原因,我可能会选择全部使用Compose来写。
我曾尝试使用material3的Navigation Bar来处理tab,但是每次点击tab后,页面总会重新加载,虽然功能实现了,但是这不是我想要的结果,我希望重新点回页面时,页面的位置、状态还是之前的样子。
这是最终的效果
创建 Bottom Navigation Activity
New Project时,选择Bottom Navigation Activity,系统就会帮你创建一个带有3个tab页面的应用,此时都是正常的,但是我的应用需要有4个tab,当我将第4个tab加上去之后,我发现tab item,只有选中的,才会展示文字标题,就像下面这个样子。
那为什么会这样呢,其实是因为Android有意而为之,关于Bottom Navigation Item的设计规范,可以参考这里Bottom Navigation,那要怎么样,才能让所有的tab item都能够展示文字标题呢,只需要在onCreate中设置下显示模式即可
val navView: BottomNavigationView = binding.navView
navView.labelVisibilityMode = NavigationBarView.LABEL_VISIBILITY_LABELED
添加 Compose 到 fragment 里
现在的代码,又臭又长,让我们先把Frament对应的xml布局文件删掉,不需要在xml中写布局了,另外把Fragment中onCreateView也清理一下,填充上简洁的代码片段,如下
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
return ComposeView(requireContext()).apply {
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent {
Text("HomeFragment")
}
}
}
瞬间整个世界都清净了,值得一提的是,ComposeView是普通视图和Compose视图的桥梁,起着至关重要的作用。
添加这段代码后,会报错,因为没有添加对应Compose库,等待Android Studio自动补全需要的库文件,补全之后,错误会消失,并且会在build.gradle添加好依赖。
这个时候运行项目,我们发现一个奇怪的问题,页面顶部会出现一部分空白,有一块白色区域
我们需要找到activity_main.xml文件,删除其中的这行代码,这个高度为56dp的空白就可以消失了。
android:paddingTop="?attr/actionBarSize"
填充列表页面
不得不说Compose实在比xml布局好用多了,写起来更像是写SwiftUI和Flutter。列表页面填充完之后,我发现列表最后一项,并不能完全展示,被Bottom Nav View给挡住了
怎么解决呢,我们还是需要找到activity_main.xml文件,将fragment的高度,由match_parent改为默认0dp,不要过早的撑满容器,这样页面就能够显示正常了
android:layout_height="0dp"
替换布局文件中的fragment
解决掉上面的那么些问题之后,这里还有一个黄色的小提示,Android Studio建议我们把fragment替换成FragmentContainerView,当我们根据建议点击替换后,再运行项目,我们发现应用崩溃了
Caused by: java.lang.IllegalStateException: Activity xx.xx.xx.MainActivity@7b7a278 does not have a NavController set on 2131231026
此时我们需要找到MainActivity,将其中的一行代码
val navController = findNavController(R.id.nav_host_fragment_activity_main)
替换为
val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment_activity_main) as NavHostFragment
val navController = navHostFragment.navController
此时就一切都正常了,可以进行下一步了。
参考链接
stackoverflow.com/questions/5…
developer.android.com/jetpack/com…
stackoverflow.com/questions/5…
blog.csdn.net/Misdirectio…
作者:今天又学到了
链接:https://juejin.cn/post/7179590175515738168
网友评论