Reputation: 2589
I am creating a profile page for the app and need to perform different actions based upon items clicked inside LazyColumn
.
What I want is when I click on Rate us, play store to open, click on feedback browser should open, clicking on settings user should navigate to the settings screen. How to perform such different actions in LazyColumn
click listener.
Here is code,
ProfileListModel.kt
data class ProfileListModel(
val imageVector: ImageVector,
@StringRes val contentDescription: Int,
@StringRes val text: Int
)
ProfileListRepository.kt
class ProfileListRepository {
fun getAllData(): List<ProfileListModel> {
return listOf(
ProfileListModel(
imageVector = Icons.Default.InvertColors,
contentDescription = R.string.app_theme,
text = R.string.app_theme
),
ProfileListModel(
imageVector = Icons.Default.NoAccounts,
contentDescription = R.string.turn_on_incognito,
text = R.string.turn_on_incognito
),
ProfileListModel(
imageVector = Icons.Default.Language,
contentDescription = R.string.app_language,
text = R.string.app_language
),
ProfileListModel(
imageVector = Icons.Default.Settings,
contentDescription = R.string.settings,
text = R.string.settings
),
ProfileListModel(
imageVector = Icons.Default.ModeOfTravel,
contentDescription = R.string.drive_mode,
text = R.string.drive_mode
),
ProfileListModel(
imageVector = Icons.Default.ChildCare,
contentDescription = R.string.child_mode,
text = R.string.child_mode
),
ProfileListModel(
imageVector = Icons.Default.BarChart,
contentDescription = R.string.time_watched,
text = R.string.time_watched
),
ProfileListModel(
imageVector = Icons.Default.Storage,
contentDescription = R.string.account_data,
text = R.string.account_data
),
ProfileListModel(
imageVector = Icons.Default.StarRate,
contentDescription = R.string.rate_us_on_play_store,
text = R.string.rate_us_on_play_store
),
ProfileListModel(
imageVector = Icons.Default.Feedback,
contentDescription = R.string.feedback,
text = R.string.feedback
),
ProfileListModel(
imageVector = Icons.Default.Forum,
contentDescription = R.string.forum,
text = R.string.forum
),
ProfileListModel(
imageVector = Icons.Default.HelpCenter,
contentDescription = R.string.help_center,
text = R.string.help_center
),
ProfileListModel(
imageVector = Icons.Default.PrivacyTip,
contentDescription = R.string.privacy_policy,
text = R.string.privacy_policy
),
ProfileListModel(
imageVector = Icons.Default.ControlPointDuplicate,
contentDescription = R.string.terms_of_service,
text = R.string.terms_of_service
)
)
}
}
ProfileListItem.kt
@Composable
fun ProfileListItem(profileListModel: ProfileListModel) {
Row(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
.clickable(
onClick = {
/*todo("perform different actions based upon item clicked")*/
}
)
/*.clickable { selectedItem(profileListModel) }*/
.padding(all = 16.dp),
verticalAlignment = Alignment.CenterVertically
) {
Icon(
imageVector = profileListModel.imageVector,
contentDescription = stringResource(id = profileListModel.contentDescription),
tint = MaterialTheme.colorScheme.onBackground,
modifier = Modifier.padding(end = 16.dp)
)
Text(
modifier = Modifier.wrapContentSize(),
text = stringResource(id = profileListModel.text)
)
}
}
ProfileScreen.kt
@ExperimentalMaterial3Api
@Composable
fun ProfileScreen() {
Box(modifier = Modifier.fillMaxSize()) {
Surface(color = MaterialTheme.colorScheme.background) {
ProfileList()
}
}
}
@ExperimentalMaterial3Api
@Composable
fun ProfileList() {
val profileListRepository = ProfileListRepository()
val getAllData = profileListRepository.getAllData()
LazyColumn(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
) {
item {
ProfileCard()
}
item {
NightLight()
}
itemsIndexed(items = getAllData) { index, profileListModel ->
ProfileListItem(profileListModel = profileListModel)
}
}
}
@Composable
fun NightLight() {
val checkedState = remember { mutableStateOf(false) }
Row(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
.clickable(onClick = { checkedState.value = !checkedState.value })
.padding(horizontal = 16.dp, vertical = 10.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
Row(modifier = Modifier.wrapContentSize(), verticalAlignment = Alignment.CenterVertically) {
Icon(
imageVector = Icons.Default.ModeNight,
contentDescription = stringResource(id = R.string.night_light),
tint = MaterialTheme.colorScheme.onBackground,
modifier = Modifier.padding(end = 16.dp)
)
Text(
modifier = Modifier.wrapContentSize(),
text = stringResource(id = R.string.night_light)
)
}
Switch(checked = checkedState.value, onCheckedChange = { checkedState.value = it })
}
}
@ExperimentalMaterial3Api
@Composable
fun ProfileCard(
modifier: Modifier = Modifier
) {
Card(
modifier = modifier
.fillMaxWidth()
.wrapContentHeight()
.padding(all = 16.dp),
shape = RoundedCornerShape(size = 16.dp),
elevation = CardDefaults.cardElevation(defaultElevation = 1.dp)
) {
Column(
modifier = Modifier.padding(all = 16.dp)
) {
Row(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(text = "Click to login")
Image(
painter = painterResource(id = R.drawable.avatar),
contentDescription = "avatar",
contentScale = ContentScale.Crop,
modifier = Modifier
.size(size = 72.dp)
.clip(shape = CircleShape)
)
}
Row(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
.padding(vertical = 8.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Text(text = "Level 0")
Card(
modifier = Modifier.wrapContentSize(),
shape = RoundedCornerShape(size = 16.dp),
elevation = CardDefaults.cardElevation(defaultElevation = 3.dp)
) {
Text(
text = "Check in",
modifier = Modifier.padding(vertical = 4.dp, horizontal = 8.dp)
)
}
}
Row(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
.padding(top = 16.dp)
) {
Column(
modifier = Modifier
.wrapContentHeight()
.weight(1f)
) {
Text(text = "0")
Text(text = "Social reputation")
}
Column(
modifier = Modifier
.wrapContentHeight()
.weight(1f)
) {
Text(text = "0", modifier = Modifier.fillMaxWidth())
Text(text = "Credit score", modifier = Modifier.fillMaxWidth())
}
}
}
}
}
@ExperimentalMaterial3Api
@Preview(
showBackground = true, name = "Light mode",
uiMode = Configuration.UI_MODE_NIGHT_NO or Configuration.UI_MODE_TYPE_NORMAL
)
/*@Preview(
showBackground = true, name = "Night mode",
uiMode = Configuration.UI_MODE_NIGHT_YES or Configuration.UI_MODE_TYPE_NORMAL
)*/
@Composable
fun ProfileScreenPreview() {
ProfileScreen()
}
Upvotes: 3
Views: 1217
Reputation: 29877
You can pass in an id to identify the item being clicked and then when the item is clicked, pass that id back to your viewmodel. This is what uni-directional flow is about in Compose. Example:
@ExperimentalMaterialApi
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
startActivity(intent)
setContent {
ProfileList(
onItemClick = {itemId ->
viewmodel.handleItem(itemId)
}
)
}
}
}
@Composable
fun ProfileList(
onItemClick: (itemId: MenuItemIDs) -> Unit
) {
val profileListRepository = ProfileListRepository()
val getAllData = profileListRepository.getAllData()
LazyColumn(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
) {
item {
ProfileCard(
itemId = MenuItemIDs.ProfilCard,
onItemClick = onItemClick
)
}
item {
NightLight()
}
itemsIndexed(items = getAllData) { index, profileListModel ->
ProfileListItem(profileListModel = profileListModel)
}
}
}
@Composable
fun ProfileCard(
modifier: Modifier = Modifier,
itemId: MenuItemIDs,
onItemClick: (itemId: MenuItemIDs) -> Unit
) {
Card(
modifier = modifier
.fillMaxWidth()
.wrapContentHeight()
.padding(all = 16.dp)
.clickable {
onItemClick(itemId)
}
) {
}
}
enum class MenuItemIDs {
ProfilCard,
NightLight,
AppTheme,
blah, blah, blah...
}
Upvotes: 3