内容
Activityに FragmentContainerViewをおいて、 fragmentManager使って Fragmentを設置したとします。
Fragmentはというと
class MainFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return ComposeView(requireContext()).apply {
setContent {
ComposenavigationsampleTheme {
Surface(color = Color.Green) {
Text(text = "This is Compose on MainFragment")
}
}
}
}
}
}
一見うまくいきそうですが、実行するとこんなエラーが
java.lang.IllegalStateException: ViewTreeLifecycleOwner not found from DecorView@ef08ca9[MainActivity]
調べてみると、Compose UIコンテンツを Fragmentや既存のViewレイアウトに組み込む場合は、 ComposeView を使用して、その setContent()メソッドを呼び出すのですが、 ComposeView
を ViewTreeLifecycleOwnerにアタッチする必要があるようです。
なので具体的には Activityの onCreate()で ViewTreeLifecycleOwner.set(window.decorView, this)を追加してあげる必要があります。
結果的に Activityはというと
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
ViewTreeLifecycleOwner.set(window.decorView, this)
if (savedInstanceState == null) {
val fragmentManager = supportFragmentManager
val fragmentTransaction = fragmentManager.beginTransaction()
fragmentTransaction.replace(R.id.container, MainFragment())
fragmentTransaction.commit()
}
}
}
これで、 MainActivity→ MainFragment→ ComposeViewというような感じでComposeでのUI構築ができるようになりました。
これを使えば既存のプロジェクトに画面ごとにCompose移行ができそうな感じがします。
追記2021/05/29
MainActivityで ComponentActivityを継承すれば ViewTreeLifecycleOwner.setする必要はないみたいです。
では、既存のプロジェクトでComposeをFragment1つずつに徐々に入れていきたいとき、そうすればいいんじゃ?と思ったのですが、いきなり大元のActivityを ComponentActivityを継承するものにしてしまうと supportFragmentManagerが使えなくなってしまってちょっときつそうです。