> 文章列表 > Android进阶宝典—在Compose中跳转Fragment

Android进阶宝典—在Compose中跳转Fragment

Android进阶宝典—在Compose中跳转Fragment

使用场景
我们原有的项目中基本采用的是单Activity架构,页面之间的跳转都是通过Navigation进行的,举个简单的例子。
在这里插入图片描述

在这种单Activity架构模式下,有一天我们想把MainActivity或者BFragment使用Compose重构,这个时候我们就需要去处理页面跳转事件,即从Compose中跳转到Fragment,处理这种问题的方式有很多,比如:

  1. 将要跳转的Fragment修改为Activity,然后在点击事件中startActivity
  2. 针对有页面跳转事件的UI采用原生方式编写与Compose混合使用
  3. 将要跳转的Fragment包装成Compose页面,构建统一路由

第1种方式违背了单Activity架构直接不考虑,第2种方式当点击事件多的时候代码会非常丑陋,并且不满足首页就是ListView的场景。

综合考虑我觉得第三种方法可能最适合一些。接下来,我们来看如何使用第3种方式处理这个问题。

场景复现

复现的场景比较简单,我们直接编写一个Compose页面,Compose页面中有一个Button事件。

@Composable
fun MainPage(){Button(onClick = {//点击事件}) {Text(text = "跳转Fragment")}
}

创建一个 BlankFragment,里面有一个TextView,给TextView一个点击事件,用来验证跳转后Fragment的功能是正常的。

val v = inflater.inflate(R.layout.fragment_blank, container, false)
val tvName:TextView = v.findViewById(R.id.tvName)
tvName.setOnClickListener {Toast.makeText(requireContext(),"我是正常的",Toast.LENGTH_SHORT). show ()
} 

接下来我们就要开始采用方案3解决这个问题了。

解决方案

构建路由

Compose页面之间的跳转也需要使用到Navigation,所以我们先构建好路由。之前我已经分享过在Compose中使用Navigation的教程。可以参考:

juejin.cn/post/710155…

所以这里我们只给出实现方案,Navigation的使用教程可以参考上文链接。

首先我们定义好路由地址,ROUTE_PAGEONE就是我们的第一个页面,ROUTE_FRAGMENT是我们要跳转到的Fragment页面,代码如下所示。

object RouteConfig {/* 页面1路由*/const val ROUTE_PAGEONE = "pageOne"/* Fragment的路由*/const val ROUTE_FRAGMENT = "Fragment"
}

在NavHost中构建好Compose路由,代码如下所示。

@Composable
fun NavHostDemo() {val navController = rememberNavController()NavHost(navController = navController, startDestination = ROUTE_PAGEONE) {composable(ROUTE_PAGEONE) {MainPage(navController)}composable(ROUTE_FRAGMENT) {ComposeFragment()}}
}

接着我们来看ComposeFragment的构建。

包装Fragment

包装Fragment就是典型的Compose和Android XML混合使用的方式,代码比较简单,如下所示。

@Composable
fun ComposeFragment() {val context = LocalContext.currentval fragmentManager = (context as FragmentActivity).supportFragmentManagerAndroidView(factory = { context ->val fragment = BlankFragment.newInstance()val view = FrameLayout(context)val fragmentContainer = FrameLayout(context)fragmentContainer.id = R.id.my_frame_layoutview.addView(fragmentContainer)fragmentManager.beginTransaction().replace(fragmentContainer.id,fragment).commit()view})
}

我们动态添加一个FrameLayout并且为FrameLayout设置id,然后通过FragmentManager将BlankFragment添加进来即可。

这里一定要注意两件事:

  • 确保Activity继承自FragmentActivity,因为新建的Compose项目默认是继承自ComponentActivity
  • 一定要为FrameLayout设置id,否则会遇到 Can’t add fragment BlankFragment{b122356} (d235c2b6-5461-4b18-8e4d-09e15c87b129) with tag null to container view with no id 的错误

包装好Fragment后,我们就可以直接使用Navigation跳转了,代码修改如下所示:

@Composable
fun MainPage(navController: NavController){Button(onClick = {navController.navigate(ROUTE_FRAGMENT)}) {Text(text = "跳转Fragment")}
}

写在最后

近期,飞速发展的人工智能,又让许多人(包括我自己)变得心浮气躁,这里温馨提醒:ChatGPT可以提升你的工作效率,但提升不了你的编码能力。