前语

如何从Compose的点击事情中跳转到Fragment?初次听到这个问题我也是比较懵的。

细心想想,其实这个场景并不古怪,甚至在重构中经常会遇到。所以这儿将处理计划和遇到的问题记录下来。

运用场景

咱们原有的项目中基本选用的是单Activity架构,页面之间的跳转都是通过Navigation进行的,举个简略的比如。

奇思妙想:在Compose中跳转Fragment

在这种单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的教程。能够参阅:

/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.current
    val fragmentManager = (context as FragmentActivity).supportFragmentManager
    AndroidView(factory = { context ->
        val fragment = BlankFragment.newInstance()
        val view = FrameLayout(context)
        val fragmentContainer = FrameLayout(context)
        fragmentContainer.id = R.id.my_frame_layout
        view.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")
    }
}

运行程序,如下图所示。

奇思妙想:在Compose中跳转Fragment

写在最后

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

所以,静下心来,好好积累吧~