我一直在尝试使用 Compose 1.0.0-beta09、Kotlin 1.5.10 和 Jetpack Navigation 2.3.4 将一个简单的应用程序组合在一起。 该应用有一个活动和两个片段。
第一个(主要)片段/屏幕(点击按钮将我带到第二个片段/屏幕):Screen One screenshot
第二个片段:/屏幕:Screen Two screenshot
问题:在与第一个屏幕上的 TextField 交互(将光标置于其中)并随后单击按钮后,第二个屏幕加载但为空(调用了 SecondFragment 的 onCreateView 但 setContent 不起作用/屏幕没有重新组合?)。 如果我不与 TextField 交互,问题就不会发生。 我已经在 API 级别 28 和 30、compose 1.0.0-beta0709、Kotlin 1.4.32 和 1.5.10 的模拟器上进行了测试,结果相似。
主要课程:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
AndroidViewBinding(ContentMainBinding::inflate)
}
}
}
class FirstFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View = ComposeView(inflater.context).apply {
setContent {
FirstScreen( onButtonClick = {
findNavController().navigate(R.id.nav_second_fragment)
})
}
}
}
@Composable
fun FirstScreen(onButtonClick: () -> Unit) {
Column {
Text("Screen One", color = Color.Blue, fontSize = 30.sp)
Button(
onClick = {
onButtonClick() },
content = {
Text(text = "go to Screen Two", color = Color.White)
})
TextField(
value = "",
onValueChange = {},
label = { Text(stringResource(R.string.label_enter_value)) },
)
}
}
class SecondFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View = ComposeView(inflater.context).apply {
setContent {
Column {
Text("Screen Two", color = Color.Blue, fontSize = 30.sp)
}
}
}
}
plugins {
id 'com.android.application'
id 'kotlin-android'
}
android {
compileSdk 30
defaultConfig {
applicationId "com.example.composewithnavigation"
minSdk 28
targetSdk 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary true
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
useIR = true
}
buildFeatures {
compose true
viewBinding true
}
composeOptions {
kotlinCompilerExtensionVersion compose_version
kotlinCompilerVersion '1.5.10'
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.5.0'
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.3.0'
implementation "androidx.compose.ui:ui:$compose_version"
implementation "androidx.compose.material:material:$compose_version"
implementation "androidx.compose.ui:ui-tooling:$compose_version"
implementation "androidx.compose.ui:ui-viewbinding:$compose_version"
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
implementation 'androidx.activity:activity-compose:1.3.0-beta01'
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.4'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.4'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"
}
答案 0 :(得分:0)
据我所知,Compose 中不鼓励使用 Fragment 进行导航。您应该创建多个屏幕,例如此处的 FirstScreen Composable。无论如何,我认为没有调用 setContent 的原因是它是从第一个片段的另一个 setContent 中调用的。在 setContent 中,您进行导航调用,将其重定向到第二个片段,该片段再次调用 setContent。因为第二个片段已经显示在 FirstScreen Composable 的 setContent 中,您实际上是在嵌套它, compose 可能不支持它,(我的意思是,有道理)。
这就是为什么我们建议放弃 Fragment 并使用 Composables 代替,这不需要显式调用 setContent