You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Jetpack Compose:让LazyColumn搜索结果项点击跳转至HymnScreen

解决赞美诗应用搜索结果跳转问题

问题分析

你当前的代码存在两个核心问题:

  1. 点击事件里的Intent语法完全错误,根本无法正确创建跳转意图
  2. 如果HymnScreen是Composable页面,直接用startActivity启动Activity的方式不符合Compose的页面管理逻辑,应该用Compose Navigation组件处理跳转;如果是传统Activity,也需要修正Intent写法,同时确保歌曲数据类实现Parcelable接口才能正确传递对象。

解决方案一:用Compose Navigation跳转至Composable页面(推荐)

这是Compose项目的标准页面跳转方式,步骤如下:

  1. 集成Navigation依赖
    在Module级别的build.gradle中添加依赖:
dependencies {
    implementation "androidx.navigation:navigation-compose:2.7.7"
}
  1. 歌曲数据类实现Parcelable
    数据类需要实现Parcelable才能在导航中传递对象:
import android.os.Parcelable
import kotlinx.parcelize.Parcelize

@Parcelize
data class Song(
    val title: String,
    val lyrics: String
) : Parcelable
  1. 配置导航路由并实现跳转
    在搜索页面Composable中获取navController,点击时触发跳转:
import androidx.compose.foundation.clickable
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.Card
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController

@Composable
fun SearchScreen(navController: NavController) {
    val viewModel: SearchViewModel = viewModel()
    val songList = viewModel.list.collectAsState().value

    LazyColumn {
        songList?.let { songs ->
            items(songs) { song ->
                Card(
                    modifier = Modifier
                        .fillMaxWidth()
                        .clickable {
                            // 跳转到HymnScreen,传递歌曲标题作为参数
                            navController.navigate("hymn/${song.title}") {
                                launchSingleTop = true
                            }
                        },
                    shape = androidx.compose.foundation.shape.RoundedCornerShape(10.dp)
                ) {
                    Text(
                        text = song.title,
                        style = MaterialTheme.typography.headlineSmall,
                        color = MaterialTheme.colorScheme.onBackground,
                        modifier = Modifier
                            .fillMaxWidth()
                            .padding(horizontal = 20.dp, vertical = 12.dp)
                    )
                }
            }
        }
    }
}

// 全局导航配置
@Composable
fun AppNavHost(navController: NavController) {
    NavHost(navController = navController, startDestination = "search") {
        composable("search") {
            SearchScreen(navController = navController)
        }
        composable("hymn/{songTitle}") { backStackEntry ->
            val title = backStackEntry.arguments?.getString("songTitle")
            HymnScreen(songTitle = title ?: "")
        }
    }
}

@Composable
fun HymnScreen(songTitle: String) {
    val viewModel: HymnViewModel = viewModel()
    val song = viewModel.getSongByTitle(songTitle).collectAsState().value

    song?.let {
        Text(text = it.title, style = MaterialTheme.typography.headlineLarge)
        Text(text = it.lyrics, style = MaterialTheme.typography.bodyLarge)
    }
}

解决方案二:跳转至传统Activity

如果HymnScreen是继承自AppCompatActivity的传统页面,按以下步骤修正:

  1. 歌曲数据类实现Parcelable
    和上述方案一致,确保数据类可序列化:
@Parcelize
data class Song(
    val title: String,
    val lyrics: String
) : Parcelable
  1. 修正点击事件的Intent代码
    在Composable中获取Context,正确创建并启动Intent:
import androidx.compose.foundation.clickable
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.Card
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import android.content.Intent

@Composable
fun SearchScreen() {
    val viewModel: SearchViewModel = viewModel()
    val songList = viewModel.list.collectAsState().value
    val context = LocalContext.current

    LazyColumn {
        songList?.let { songs ->
            items(songs) { song ->
                Card(
                    modifier = Modifier
                        .fillMaxWidth()
                        .clickable {
                            // 正确创建Intent并传递歌曲对象
                            val intent = Intent(context, HymnActivity::class.java).apply {
                                putExtra("SONG_KEY", song)
                            }
                            context.startActivity(intent)
                        },
                    shape = androidx.compose.foundation.shape.RoundedCornerShape(10.dp)
                ) {
                    Text(
                        text = song.title,
                        style = MaterialTheme.typography.headlineSmall,
                        color = MaterialTheme.colorScheme.onBackground,
                        modifier = Modifier
                            .fillMaxWidth()
                            .padding(horizontal = 20.dp, vertical = 12.dp)
                    )
                }
            }
        }
    }
}
  1. 在HymnActivity中接收参数
class HymnActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_hymn)

        val song = intent.getParcelableExtra<Song>("SONG_KEY")
        song?.let {
            findViewById<TextView>(R.id.tv_title).text = it.title
            findViewById<TextView>(R.id.tv_lyrics).text = it.lyrics
        }
    }
}

关键注意点

  • 无论哪种跳转方式,歌曲数据类必须实现Parcelable,否则无法传递对象
  • Compose项目优先使用Navigation组件管理页面,这是官方推荐的最佳实践,适配Compose生命周期更友好

内容的提问来源于stack exchange,提问作者Opeoluwa-Muritala

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 02:46:18