注册

Compose + Fragment是一个不错的选择

Compose很好用,但是在真正应用到项目时,我们还需要解决一些问题。


我要开发一个这样的页面,外层用Bottom Navigation Activity,每个tab对应的一个fragment,页面内容我用Compose来填充,不使用xml来布局,因为Compose太好用了,如果不是页面缓存的原因,我可能会选择全部使用Compose来写。


我曾尝试使用material3的Navigation Bar来处理tab,但是每次点击tab后,页面总会重新加载,虽然功能实现了,但是这不是我想要的结果,我希望重新点回页面时,页面的位置、状态还是之前的样子。


这是最终的效果


Screenshot_20221221_192042.png


创建 Bottom Navigation Activity


New Project时,选择Bottom Navigation Activity,系统就会帮你创建一个带有3个tab页面的应用,此时都是正常的,但是我的应用需要有4个tab,当我将第4个tab加上去之后,我发现tab item,只有选中的,才会展示文字标题,就像下面这个样子。


Screenshot_20221221_1941322.png


那为什么会这样呢,其实是因为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添加好依赖。


这个时候运行项目,我们发现一个奇怪的问题,页面顶部会出现一部分空白,有一块白色区域


Screenshot_20221221_2012272.png


我们需要找到activity_main.xml文件,删除其中的这行代码,这个高度为56dp的空白就可以消失了。

android:paddingTop="?attr/actionBarSize"

填充列表页面


不得不说Compose实在比xml布局好用多了,写起来更像是写SwiftUI和Flutter。列表页面填充完之后,我发现列表最后一项,并不能完全展示,被Bottom Nav View给挡住了


Screenshot_20221221_2025262.png


怎么解决呢,我们还是需要找到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

此时就一切都正常了,可以进行下一步了。


作者:今天又学到了
链接:https://juejin.cn/post/7179590175515738168
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

0 个评论

要回复文章请先登录注册