与 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 会中断组合吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何在使用Android Jetpack导航时禁用导航图标

Jetpack 导航动画完整监听器

Jetpack导航到一个共同的目的地

使用jetpack导航组件从一个底页导航到另一个底页时如何弹出底页对话框

jetpack compose 接收返回参数

底部导航栏与 Jetpack Compose 中的屏幕内容重叠