内容
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
が使えなくなってしまってちょっときつそうです。