Отображение фрагмента в Jetpack Compose с использованием AndroidFragment

Вопрос или проблема

У меня есть зависимость от стороннего пакета, который не реализован в Jetpack Compose, поэтому я пытаюсь отобразить Fragment, используя рекомендуемый подход Android с использованием AndroidFragment<>, но не могу этого сделать, так как постоянно получаю следующее исключение, не уверен, что я делаю не так:

java.lang.IllegalStateException: View androidx.compose.ui.platform.AndroidComposeView{896ffd7 VFED..... ......ID 0,0-1440,3120} не находится в подклассе FragmentActivity.

Так как перед импортом библиотеки мы хотели протестировать подход, мы пытаемся добавить Fragment в тестовое приложение, ниже приведены файл и включенные зависимости.

fragment_test.xml

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:background="@color/purple_500"
    >

    <TextView
        android:id="@+id/tvOne"
        android:text="One Fragment"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/white"
        android:textSize="25sp"
        />

</androidx.constraintlayout.widget.ConstraintLayout>

TestFragment.kt

class TestFragment : Fragment() {
    private lateinit var binding: FragmentTestBinding
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = FragmentTestBinding.inflate(inflater)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        binding.tvOne.setOnClickListener {
            Toast.makeText(context, "Кнопка была нажата! Ура!!!!", Toast.LENGTH_LONG)
        }
    }
}

MainActivity.kt

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        enableEdgeToEdge()
        setContent {
            DriveTestAceTheme {
                Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
                    Greeting(
                        name = "Android",
                        modifier = Modifier.padding(innerPadding)
                    )
                }
            }
        }
    }
    @Composable
    fun Greeting(name: String, modifier: Modifier = Modifier) {
        AndroidFragment<TestFragment>(
            modifier = Modifier.fillMaxSize()
        )
    }
}

build.gradle.kts

    // Зависимости для фрагмента Compose
    val fragment_version = "1.8.3"
    implementation("androidx.fragment:fragment:$fragment_version")
    implementation("androidx.fragment:fragment-ktx:$fragment_version")
    implementation("androidx.fragment:fragment-compose:$fragment_version")
    debugImplementation("androidx.fragment:fragment-testing:$fragment_version")

Я пытался использовать AndroidFragment<>, так как это кажется рекомендуемым подходом сообществом Android, но не добился успеха. Я пытался воспроизвести те вещи, которые сделали другие, но все равно безуспешно. Похоже, я чего-то не хватает.

Исключение здесь довольно понятно: вы используете AndroidFragment в композиционном представлении внутри MainActivity, который является подклассом ComponentActivity. ComponentActivity не может обрабатывать фрагменты, для этого существует FragmentActivity. Вам следует сделать так, чтобы MainActivity наследовался от FragmentActivity.

Ответ или решение

Проблема, с которой вы столкнулись, связана с тем, что вы используете AndroidFragment<> внутри MainActivity, которая наследуется от ComponentActivity. К сожалению, ComponentActivity не поддерживает работу с фрагментами, так как для этого предназначен FragmentActivity.

Вам необходимо изменить MainActivity, чтобы она наследовалась от FragmentActivity. Вот как вы можете это сделать:

Измененный код MainActivity.kt

import androidx.fragment.app.FragmentActivity
import androidx.compose.runtime.Composable
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Scaffold
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.setContent
import androidx.compose.ui.tooling.preview.Preview

class MainActivity : FragmentActivity() { // Измените на FragmentActivity
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        enableEdgeToEdge() // Выполняйте настройки встраивания
        setContent {
            DriveTestAceTheme {
                Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
                    Greeting(
                        name = "Android",
                        modifier = Modifier.padding(innerPadding)
                    )
                }
            }
        }
    }

    @Composable
    fun Greeting(name: String, modifier: Modifier = Modifier) {
        AndroidFragment<TestFragment>(
            modifier = Modifier.fillMaxSize()
        )
    }
}

Объяснение изменений

  1. Наследование от FragmentActivity: Путем изменения наследования на FragmentActivity, вы получаете необходимую поддержку для работы с фрагментами внутри вашего Jetpack Compose приложения. Это позволяет использовать AndroidFragment<> без ошибок, связанных с состоянием фрагмента.

  2. Используйте Fragment правильно: Таким образом, вы можете использовать ваш TestFragment внутри интерфейса Compose, и система будет правильно управлять его состоянием.

Пояснение об ошибке

Сообщение об ошибке, которое вы получали (java.lang.IllegalStateException: View androidx.compose.ui.platform.AndroidComposeView... is not within a subclass of FragmentActivity), указывает на то, что вы пытались отобразить фрагмент в активити, которая не поддерживает их использование. Изменив MainActivity на FragmentActivity, эта ошибка должна быть устранена.

Теперь вы можете продолжить разработку вашего приложения, и TestFragment будет правильно отображаться в пользовательском интерфейсе, используя Jetpack Compose.

Оцените материал
Добавить комментарий

Капча загружается...