Anonymous
Sortierlistenelemente in LazyColumn - Android Jetpack komponieren
Post
by Anonymous » 02 Jun 2025, 19:59
Versuchen Sie, eine Funktion zu implementieren, bei der der Benutzer einen Weg auswählen kann, um die Liste der Brauereien zu sortieren, wenn ein bestimmtes Element in einem Dropdown -Menü ausgewählt ist (Name, Stadt, Adresse). Ich habe Probleme, herauszufinden, was ich falsch mache. Wenn ich im Dropdown -Menü ein Beispiel "Name" auswähle, sortiert die Liste der Brauereien nicht. Ich bin neu dabei, daher wird jeder Rat wirklich helfen. Vielen Dank!
Code: Select all
@SuppressLint("UnusedMaterialScaffoldPaddingParameter")
@RequiresApi(Build.VERSION_CODES.O)
@Composable
fun MainScreen(
navController: NavController,
mainViewModel: MainViewModel,
search: String?
) {
val apiData = brewData(mainViewModel = mainViewModel, search = search)
Scaffold(
content = {
if (apiData.loading == true){
Column(
modifier = Modifier
.fillMaxSize()
.background(colorResource(id = R.color.grey_blue)),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
CircularProgressIndicator()
}
} else if (apiData.data != null){
MainContent(bData = apiData.data!!, viewModel = mainViewModel)
}
},
topBar = { BrewTopBar(navController, search) }
)
}
@Composable
fun BrewTopBar(navController: NavController, search: String?) {
TopAppBar(
modifier = Modifier
.height(55.dp)
.fillMaxWidth(),
title = {
Text(
stringResource(id = R.string.main_title),
style = MaterialTheme.typography.h5,
maxLines = 1
)
},
actions = {
Row(
verticalAlignment = Alignment.CenterVertically
) {
Text(text = "$search")
IconButton(onClick = { navController.navigate(Screens.SearchScreen.name) }) {
Icon(
modifier = Modifier.padding(10.dp),
imageVector = Icons.Filled.Search,
contentDescription = stringResource(id = R.string.search)
)
}
}
},
backgroundColor = colorResource(id = R.color.light_purple)
)
}
@RequiresApi(Build.VERSION_CODES.O)
@Composable
fun MainContent(bData: List
, viewModel: MainViewModel){
val allBreweries = bData.size
var sortByName by remember { mutableStateOf(false) }
var sortByCity by remember { mutableStateOf(false) }
var sortByAddress by remember { mutableStateOf(false) }
var dataSorted1 = remember { mutableStateOf(bData.sortedBy { it.name }) }
var dataSorted: MutableState
Column(
modifier = Modifier
.fillMaxSize()
.background(colorResource(id = R.color.grey_blue))
){
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceAround,
verticalAlignment = Alignment.CenterVertically
){
// Amount text label
Text(
text = "Result(s): ${bData.size}",
modifier = Modifier.padding(top = 15.dp, start = 15.dp, bottom = 5.dp)
)
SortingMenu(sortByName, sortByCity, sortByAddress) // needs mutable booleans for sorting
}
// List of Brewery cards
LazyColumn(
Modifier
.fillMaxSize()
.padding(5.dp)
){
items(allBreweries){ index ->
Breweries(
bData = when {
sortByName == true -> remember { mutableStateOf(bData.sortedBy { it.name }) }
sortByCity == true -> remember { mutableStateOf(bData.sortedBy { it.city }) }
sortByAddress == true -> remember { mutableStateOf(bData.sortedBy { it.address_2 }) }
else -> remember { mutableStateOf(bData) }
} as MutableState, // Todo: create a way to select different sorting conditions
position = index,
viewModel = viewModel
)
}
}
}
}
@RequiresApi(Build.VERSION_CODES.O)
@Composable
fun Breweries(
bData: MutableState,
position: Int,
viewModel: MainViewModel
){
val cardNumber = position+1
val cityApiData = bData.value[position].city
val phoneNumberApiData = bData.value[position].phone
val countryApiData = bData.value[position].country
val breweryTypeApiData = bData.value[position].brewery_type
val countyApiData = bData.value[position].county_province
val postalCodeApiData = bData.value[position].postal_code
val stateApiData = bData.value[position].state
val streetApiData = bData.value[position].street
val apiLastUpdated = bData.value[position].updated_at
val context = LocalContext.current
val lastUpdated = apiLastUpdated?.let { viewModel.dateTextConverter(it) }
val websiteUrlApiData = bData.value[position].website_url
var expanded by remember { mutableStateOf(false) }
val clickableWebsiteText = buildAnnotatedString {
if (websiteUrlApiData != null) {
append(websiteUrlApiData)
}
}
val clickablePhoneNumberText = buildAnnotatedString {
if (phoneNumberApiData != null){
append(phoneNumberApiData)
}
}
Column(
Modifier.padding(10.dp)
) {
//Brewery Card
Card(
modifier = Modifier
.padding(start = 15.dp, end = 15.dp)
// .fillMaxSize()
.clickable(
enabled = true,
onClickLabel = "Expand to view details",
onClick = { expanded = !expanded }
)
.semantics { contentDescription = "Brewery Card" },
backgroundColor = colorResource(id = R.color.light_blue),
contentColor = Color.Black,
border = BorderStroke(0.5.dp, colorResource(id = R.color.pink)),
elevation = 15.dp
) {
Column(verticalArrangement = Arrangement.Center) {
//Number text for position of card
Text(
text = cardNumber.toString(),
modifier = Modifier.padding(15.dp),
fontSize = 10.sp,
)
// Second Row
BreweryTitle(bData = bData, position = position)
// Third Row
// Brewery Details
CardDetails(
cityApiData = cityApiData,
stateApiData = stateApiData,
streetApiData = streetApiData,
countryApiData = countryApiData,
countyApiData = countyApiData,
postalCodeApiData = postalCodeApiData,
breweryTypeApiData = breweryTypeApiData,
lastUpdated = lastUpdated,
expanded = expanded
)
//Fourth Row
Row(horizontalArrangement = Arrangement.Center,
modifier = Modifier.fillMaxWidth()
){
Column(
modifier = Modifier.padding(
start = 10.dp, end = 10.dp,
top = 15.dp, bottom = 15.dp
),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
//Phone Number Link
LinkBuilder(
clickablePhoneNumberText,
phoneNumberApiData,
modifier = Modifier.padding(bottom = 10.dp)
) {
if (phoneNumberApiData != null) {
viewModel.callNumber(phoneNumberApiData, context)
}
}
//Website Link
LinkBuilder(
clickableWebsiteText,
websiteUrlApiData,
modifier = Modifier.padding(bottom = 15.dp),
intentCall = {
if (websiteUrlApiData != null) {
viewModel.openWebsite(websiteUrlApiData, context)
}
}
)
}
}
}
}
}
}
@Composable
fun CardDetails(
cityApiData: String?,
stateApiData: String?,
streetApiData: String?,
countryApiData: String?,
countyApiData: String?,
postalCodeApiData: String?,
breweryTypeApiData: String?,
lastUpdated: String?,
expanded: Boolean
){
// Third Row
//Brewery Details
Column(
modifier = Modifier.padding(
start = 30.dp, end = 10.dp, top = 25.dp, bottom = 15.dp
),
verticalArrangement = Arrangement.Center
) {
if (expanded) {
Text(text = "City: $cityApiData")
Text(text = "State: $stateApiData")
Text(text = "Street: $streetApiData")
Text(text = "Country: $countryApiData")
Text(text = "County: $countyApiData")
Text(text = "Postal Code: $postalCodeApiData")
Text(text = "Type: $breweryTypeApiData")
Text(text = "Last updated: $lastUpdated")
}
}
}
@Composable
fun BreweryTitle(bData: MutableState, position: Int){
// Second Row
Column(
modifier = Modifier.fillMaxWidth(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center,
) {
// Name of Brewery
Text(
text = bData.value[position].name!!,
modifier = Modifier.padding(start = 15.dp, end = 15.dp),
fontWeight = FontWeight.Bold,
maxLines = 3,
textAlign = TextAlign.Center,
softWrap = true,
style = TextStyle(
color = colorResource(id = R.color.purple_500),
fontStyle = FontStyle.Normal,
fontSize = 17.sp,
fontFamily = FontFamily.SansSerif,
letterSpacing = 2.sp,
)
)
}
}
}
@Composable
fun LinkBuilder(
clickableText: AnnotatedString,
dataText: String?,
modifier: Modifier,
intentCall: (String?) -> Unit
){
if (dataText != null){
ClickableText(
text = clickableText,
modifier = modifier,
style = TextStyle(
textDecoration = TextDecoration.Underline,
letterSpacing = 2.sp
),
onClick = {
intentCall(dataText)
}
)
}
else {
Text(
text = "Sorry, Not Available",
color = Color.Gray,
fontSize = 10.sp
)
}
}
//Gets data from view model
@Composable
fun brewData(
mainViewModel: MainViewModel, search: String?
): DataOrException {
return produceState(
initialValue = DataOrException(loading = true)
) {
value = mainViewModel.getData(search)
}.value
}
@Composable
fun SortingMenu(sortByName: Boolean, sortByCity: Boolean, sortByAddress: Boolean,) {
var expanded by remember { mutableStateOf(false) }
val items = listOf("Name", "City", "Address")
val disabledValue = "B"
var selectedIndex by remember { mutableStateOf(0) }
Box(
modifier = Modifier
.wrapContentSize(Alignment.TopStart)
) {
Text(
text = "Sort by: ${items[selectedIndex]}",
modifier = Modifier
.clickable(onClick = { expanded = true })
.width(120.dp)
)
DropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false // todo: sort list data when clicked
when(selectedIndex){
0 -> sortByName == true
1 -> sortByCity == true
2 -> sortByAddress == true
} }
) {
items.forEachIndexed { index, text ->
DropdownMenuItem(onClick = {
selectedIndex = index
expanded = false
}) {
val disabledText = if (text == disabledValue) {
" (Disabled)"
} else {
""
}
Text(text = text + disabledText)
}
}
}
}
}
//not used
fun sorting(menuList: List, dataList: List
, index: Int){
when{
menuList[index] == "Name" -> dataList.sortedBy { it.name }
menuList[index] == "City" -> dataList.sortedBy { it.city }
menuList[index] == "Address" -> dataList.sortedBy { it.address_2 }
}
}
1748887165
Anonymous
Versuchen Sie, eine Funktion zu implementieren, bei der der Benutzer einen Weg auswählen kann, um die Liste der Brauereien zu sortieren, wenn ein bestimmtes Element in einem Dropdown -Menü ausgewählt ist (Name, Stadt, Adresse). Ich habe Probleme, herauszufinden, was ich falsch mache. Wenn ich im Dropdown -Menü ein Beispiel "Name" auswähle, sortiert die Liste der Brauereien nicht. Ich bin neu dabei, daher wird jeder Rat wirklich helfen. Vielen Dank![code]@SuppressLint("UnusedMaterialScaffoldPaddingParameter") @RequiresApi(Build.VERSION_CODES.O) @Composable fun MainScreen( navController: NavController, mainViewModel: MainViewModel, search: String? ) { val apiData = brewData(mainViewModel = mainViewModel, search = search) Scaffold( content = { if (apiData.loading == true){ Column( modifier = Modifier .fillMaxSize() .background(colorResource(id = R.color.grey_blue)), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { CircularProgressIndicator() } } else if (apiData.data != null){ MainContent(bData = apiData.data!!, viewModel = mainViewModel) } }, topBar = { BrewTopBar(navController, search) } ) } @Composable fun BrewTopBar(navController: NavController, search: String?) { TopAppBar( modifier = Modifier .height(55.dp) .fillMaxWidth(), title = { Text( stringResource(id = R.string.main_title), style = MaterialTheme.typography.h5, maxLines = 1 ) }, actions = { Row( verticalAlignment = Alignment.CenterVertically ) { Text(text = "$search") IconButton(onClick = { navController.navigate(Screens.SearchScreen.name) }) { Icon( modifier = Modifier.padding(10.dp), imageVector = Icons.Filled.Search, contentDescription = stringResource(id = R.string.search) ) } } }, backgroundColor = colorResource(id = R.color.light_purple) ) } @RequiresApi(Build.VERSION_CODES.O) @Composable fun MainContent(bData: List , viewModel: MainViewModel){ val allBreweries = bData.size var sortByName by remember { mutableStateOf(false) } var sortByCity by remember { mutableStateOf(false) } var sortByAddress by remember { mutableStateOf(false) } var dataSorted1 = remember { mutableStateOf(bData.sortedBy { it.name }) } var dataSorted: MutableState Column( modifier = Modifier .fillMaxSize() .background(colorResource(id = R.color.grey_blue)) ){ Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceAround, verticalAlignment = Alignment.CenterVertically ){ // Amount text label Text( text = "Result(s): ${bData.size}", modifier = Modifier.padding(top = 15.dp, start = 15.dp, bottom = 5.dp) ) SortingMenu(sortByName, sortByCity, sortByAddress) // needs mutable booleans for sorting } // List of Brewery cards LazyColumn( Modifier .fillMaxSize() .padding(5.dp) ){ items(allBreweries){ index -> Breweries( bData = when { sortByName == true -> remember { mutableStateOf(bData.sortedBy { it.name }) } sortByCity == true -> remember { mutableStateOf(bData.sortedBy { it.city }) } sortByAddress == true -> remember { mutableStateOf(bData.sortedBy { it.address_2 }) } else -> remember { mutableStateOf(bData) } } as MutableState, // Todo: create a way to select different sorting conditions position = index, viewModel = viewModel ) } } } } @RequiresApi(Build.VERSION_CODES.O) @Composable fun Breweries( bData: MutableState, position: Int, viewModel: MainViewModel ){ val cardNumber = position+1 val cityApiData = bData.value[position].city val phoneNumberApiData = bData.value[position].phone val countryApiData = bData.value[position].country val breweryTypeApiData = bData.value[position].brewery_type val countyApiData = bData.value[position].county_province val postalCodeApiData = bData.value[position].postal_code val stateApiData = bData.value[position].state val streetApiData = bData.value[position].street val apiLastUpdated = bData.value[position].updated_at val context = LocalContext.current val lastUpdated = apiLastUpdated?.let { viewModel.dateTextConverter(it) } val websiteUrlApiData = bData.value[position].website_url var expanded by remember { mutableStateOf(false) } val clickableWebsiteText = buildAnnotatedString { if (websiteUrlApiData != null) { append(websiteUrlApiData) } } val clickablePhoneNumberText = buildAnnotatedString { if (phoneNumberApiData != null){ append(phoneNumberApiData) } } Column( Modifier.padding(10.dp) ) { //Brewery Card Card( modifier = Modifier .padding(start = 15.dp, end = 15.dp) // .fillMaxSize() .clickable( enabled = true, onClickLabel = "Expand to view details", onClick = { expanded = !expanded } ) .semantics { contentDescription = "Brewery Card" }, backgroundColor = colorResource(id = R.color.light_blue), contentColor = Color.Black, border = BorderStroke(0.5.dp, colorResource(id = R.color.pink)), elevation = 15.dp ) { Column(verticalArrangement = Arrangement.Center) { //Number text for position of card Text( text = cardNumber.toString(), modifier = Modifier.padding(15.dp), fontSize = 10.sp, ) // Second Row BreweryTitle(bData = bData, position = position) // Third Row // Brewery Details CardDetails( cityApiData = cityApiData, stateApiData = stateApiData, streetApiData = streetApiData, countryApiData = countryApiData, countyApiData = countyApiData, postalCodeApiData = postalCodeApiData, breweryTypeApiData = breweryTypeApiData, lastUpdated = lastUpdated, expanded = expanded ) //Fourth Row Row(horizontalArrangement = Arrangement.Center, modifier = Modifier.fillMaxWidth() ){ Column( modifier = Modifier.padding( start = 10.dp, end = 10.dp, top = 15.dp, bottom = 15.dp ), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { //Phone Number Link LinkBuilder( clickablePhoneNumberText, phoneNumberApiData, modifier = Modifier.padding(bottom = 10.dp) ) { if (phoneNumberApiData != null) { viewModel.callNumber(phoneNumberApiData, context) } } //Website Link LinkBuilder( clickableWebsiteText, websiteUrlApiData, modifier = Modifier.padding(bottom = 15.dp), intentCall = { if (websiteUrlApiData != null) { viewModel.openWebsite(websiteUrlApiData, context) } } ) } } } } } } @Composable fun CardDetails( cityApiData: String?, stateApiData: String?, streetApiData: String?, countryApiData: String?, countyApiData: String?, postalCodeApiData: String?, breweryTypeApiData: String?, lastUpdated: String?, expanded: Boolean ){ // Third Row //Brewery Details Column( modifier = Modifier.padding( start = 30.dp, end = 10.dp, top = 25.dp, bottom = 15.dp ), verticalArrangement = Arrangement.Center ) { if (expanded) { Text(text = "City: $cityApiData") Text(text = "State: $stateApiData") Text(text = "Street: $streetApiData") Text(text = "Country: $countryApiData") Text(text = "County: $countyApiData") Text(text = "Postal Code: $postalCodeApiData") Text(text = "Type: $breweryTypeApiData") Text(text = "Last updated: $lastUpdated") } } } @Composable fun BreweryTitle(bData: MutableState, position: Int){ // Second Row Column( modifier = Modifier.fillMaxWidth(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center, ) { // Name of Brewery Text( text = bData.value[position].name!!, modifier = Modifier.padding(start = 15.dp, end = 15.dp), fontWeight = FontWeight.Bold, maxLines = 3, textAlign = TextAlign.Center, softWrap = true, style = TextStyle( color = colorResource(id = R.color.purple_500), fontStyle = FontStyle.Normal, fontSize = 17.sp, fontFamily = FontFamily.SansSerif, letterSpacing = 2.sp, ) ) } } } @Composable fun LinkBuilder( clickableText: AnnotatedString, dataText: String?, modifier: Modifier, intentCall: (String?) -> Unit ){ if (dataText != null){ ClickableText( text = clickableText, modifier = modifier, style = TextStyle( textDecoration = TextDecoration.Underline, letterSpacing = 2.sp ), onClick = { intentCall(dataText) } ) } else { Text( text = "Sorry, Not Available", color = Color.Gray, fontSize = 10.sp ) } } //Gets data from view model @Composable fun brewData( mainViewModel: MainViewModel, search: String? ): DataOrException { return produceState( initialValue = DataOrException(loading = true) ) { value = mainViewModel.getData(search) }.value } @Composable fun SortingMenu(sortByName: Boolean, sortByCity: Boolean, sortByAddress: Boolean,) { var expanded by remember { mutableStateOf(false) } val items = listOf("Name", "City", "Address") val disabledValue = "B" var selectedIndex by remember { mutableStateOf(0) } Box( modifier = Modifier .wrapContentSize(Alignment.TopStart) ) { Text( text = "Sort by: ${items[selectedIndex]}", modifier = Modifier .clickable(onClick = { expanded = true }) .width(120.dp) ) DropdownMenu( expanded = expanded, onDismissRequest = { expanded = false // todo: sort list data when clicked when(selectedIndex){ 0 -> sortByName == true 1 -> sortByCity == true 2 -> sortByAddress == true } } ) { items.forEachIndexed { index, text -> DropdownMenuItem(onClick = { selectedIndex = index expanded = false }) { val disabledText = if (text == disabledValue) { " (Disabled)" } else { "" } Text(text = text + disabledText) } } } } } //not used fun sorting(menuList: List, dataList: List , index: Int){ when{ menuList[index] == "Name" -> dataList.sortedBy { it.name } menuList[index] == "City" -> dataList.sortedBy { it.city } menuList[index] == "Address" -> dataList.sortedBy { it.address_2 } } } [/code]