Вопрос или проблема
У меня есть зависимость от стороннего пакета, который не реализован в 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()
)
}
}
Объяснение изменений
-
Наследование от
FragmentActivity
: Путем изменения наследования наFragmentActivity
, вы получаете необходимую поддержку для работы с фрагментами внутри вашего Jetpack Compose приложения. Это позволяет использоватьAndroidFragment<>
без ошибок, связанных с состоянием фрагмента. -
Используйте
Fragment
правильно: Таким образом, вы можете использовать вашTestFragment
внутри интерфейса Compose, и система будет правильно управлять его состоянием.
Пояснение об ошибке
Сообщение об ошибке, которое вы получали (java.lang.IllegalStateException: View androidx.compose.ui.platform.AndroidComposeView... is not within a subclass of FragmentActivity
), указывает на то, что вы пытались отобразить фрагмент в активити, которая не поддерживает их использование. Изменив MainActivity
на FragmentActivity
, эта ошибка должна быть устранена.
Теперь вы можете продолжить разработку вашего приложения, и TestFragment
будет правильно отображаться в пользовательском интерфейсе, используя Jetpack Compose.