与 Jetpack 导航一起使用时,TextField 会中断组合吗?
Posted
技术标签:
【中文标题】与 Jetpack 导航一起使用时,TextField 会中断组合吗?【英文标题】:TextField breaks composing when used with Jetpack navigation? 【发布时间】:2021-09-08 09:37:50 【问题描述】:我一直在尝试使用 Compose 1.0.0-beta09、Kotlin 1.5.10 和 Jetpack Navigation 2.3.4 组合一个简单的应用程序。 该应用有一个活动和两个片段。
第一个(主)片段/屏幕(单击按钮将我带到第二个片段/屏幕):Screen One screenshot
第二个片段:/screen:Screen Two screenshot
问题:与第一个屏幕上的 TextField 交互(将光标放入)并随后单击按钮后,第二个屏幕加载但为空(调用 SecondFragment 的 onCreateView 但 setContent 不起作用/屏幕没有重新组合?)。 如果我不与 TextField 交互,问题就不会发生。 我已经在 API 级别 28 和 30、compose 1.0.0-beta0709、Kotlin 1.4.32 和 1.5.10 的模拟器上进行了测试,结果相似。
Empty Screen Two
主要课程:
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"
【问题讨论】:
您好,我尝试了您在 JetChat 示例应用程序中描述的内容,它可以在这里工作。可以分享您的导航图吗? 感谢蒂姆的尝试。我提出了一个撰写错误的问题,并且它已得到修复。 【参考方案1】:据我所知,不鼓励在 Compose 中使用片段进行导航。您应该创建多个屏幕,例如此处的 FirstScreen Composable。无论如何,我认为 setContent 没有被调用的原因是它是从你的第一个片段的另一个 setContent 中调用的。在 setContent 中,您进行导航调用,将其重定向到第二个片段,该片段再次调用 setContent。因为第二个片段已经显示在 FirstScreen Composable 的 setContent 中,所以您实际上是在嵌套它,这可能不受 compose 支持,(我的意思是,有道理)。
这就是为什么我们建议放弃 Fragment 并改用 Composables,这不需要显式调用 setContent
【讨论】:
嗯,不鼓励和不支持是不一样的。我的导航解决方案基于 google 的 compose 示例应用程序之一:github.com/android/compose-samples/tree/main/Jetchat以上是关于与 Jetpack 导航一起使用时,TextField 会中断组合吗?的主要内容,如果未能解决你的问题,请参考以下文章