Skip to content

Commit 5808509

Browse files
authored
Merge pull request #2648 from switchifyapp/fix/compact-reorderable-lists-2647
Improve reorderable rows on small screens
2 parents 6e110e6 + 4566745 commit 5808509

4 files changed

Lines changed: 319 additions & 127 deletions

File tree

app/src/main/java/com/enaboapps/switchify/screens/settings/favouriteapps/FavouriteAppsScreen.kt

Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import androidx.compose.foundation.background
44
import androidx.compose.foundation.clickable
55
import androidx.compose.foundation.interaction.MutableInteractionSource
66
import androidx.compose.foundation.layout.Arrangement
7+
import androidx.compose.foundation.layout.BoxWithConstraints
78
import androidx.compose.foundation.layout.Column
89
import androidx.compose.foundation.layout.Row
910
import androidx.compose.foundation.layout.Spacer
@@ -127,31 +128,63 @@ private fun FavouriteAppItem(
127128
.padding(horizontal = 16.dp, vertical = 4.dp),
128129
shape = MaterialTheme.shapes.medium
129130
) {
130-
Row(
131-
modifier = Modifier
132-
.fillMaxWidth()
133-
.padding(horizontal = 12.dp, vertical = 8.dp),
134-
verticalAlignment = Alignment.CenterVertically
135-
) {
136-
reorderControls()
137-
Text(
138-
text = app.appName,
139-
style = MaterialTheme.typography.bodyLarge,
140-
modifier = Modifier
141-
.weight(1f)
142-
.padding(horizontal = 8.dp)
143-
)
144-
IconButton(onClick = onRemove) {
145-
Icon(
146-
imageVector = Icons.Default.Delete,
147-
contentDescription = "Remove",
148-
tint = MaterialTheme.colorScheme.error
149-
)
131+
BoxWithConstraints {
132+
val compact = maxWidth < 360.dp
133+
if (compact) {
134+
Column(
135+
modifier = Modifier
136+
.fillMaxWidth()
137+
.padding(horizontal = 12.dp, vertical = 8.dp)
138+
) {
139+
Row(
140+
modifier = Modifier.fillMaxWidth(),
141+
horizontalArrangement = Arrangement.SpaceBetween,
142+
verticalAlignment = Alignment.CenterVertically
143+
) {
144+
reorderControls()
145+
RemoveFavouriteAppButton(onRemove)
146+
}
147+
Text(
148+
text = app.appName,
149+
style = MaterialTheme.typography.bodyLarge,
150+
modifier = Modifier
151+
.fillMaxWidth()
152+
.padding(horizontal = 8.dp, vertical = 4.dp)
153+
)
154+
}
155+
} else {
156+
Row(
157+
modifier = Modifier
158+
.fillMaxWidth()
159+
.padding(horizontal = 12.dp, vertical = 8.dp),
160+
verticalAlignment = Alignment.CenterVertically
161+
) {
162+
reorderControls()
163+
Text(
164+
text = app.appName,
165+
style = MaterialTheme.typography.bodyLarge,
166+
modifier = Modifier
167+
.weight(1f)
168+
.padding(horizontal = 8.dp)
169+
)
170+
RemoveFavouriteAppButton(onRemove)
171+
}
150172
}
151173
}
152174
}
153175
}
154176

177+
@Composable
178+
private fun RemoveFavouriteAppButton(onRemove: () -> Unit) {
179+
IconButton(onClick = onRemove) {
180+
Icon(
181+
imageVector = Icons.Default.Delete,
182+
contentDescription = "Remove",
183+
tint = MaterialTheme.colorScheme.error
184+
)
185+
}
186+
}
187+
155188
@Composable
156189
private fun AppPickerDialog(
157190
viewModel: FavouriteAppsScreenModel,

app/src/main/java/com/enaboapps/switchify/screens/settings/menu/MenuCustomizationScreen.kt

Lines changed: 100 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -486,45 +486,54 @@ fun MenuItemRow(
486486
shape = RoundedCornerShape(12.dp),
487487
tonalElevation = if (isDragging) 8.dp else 0.dp
488488
) {
489-
Row(
490-
modifier = Modifier
491-
.fillMaxWidth()
492-
.padding(16.dp),
493-
verticalAlignment = Alignment.CenterVertically,
494-
horizontalArrangement = Arrangement.SpaceBetween
495-
) {
496-
// Reorder controls (drag handle, arrow buttons, or select control)
497-
reorderControls()
498-
499-
// Item label
500-
Text(
501-
text = itemLabel,
502-
style = MaterialTheme.typography.bodyLarge,
503-
fontWeight = if (isVisible) FontWeight.Normal else FontWeight.Light,
504-
color = if (isVisible) MaterialTheme.colorScheme.onSurface else MaterialTheme.colorScheme.onSurfaceVariant,
505-
modifier = Modifier.weight(1f)
506-
)
507-
508-
if (showTrailingActions) {
509-
// Delete button for user-added items, visibility toggle for default items
510-
if (onDelete != null) {
511-
IconButton(onClick = onDelete) {
512-
Icon(
513-
imageVector = Icons.Default.Close,
514-
contentDescription = stringResource(R.string.button_delete),
515-
tint = MaterialTheme.colorScheme.error
516-
)
489+
BoxWithConstraints {
490+
val compact = maxWidth < 360.dp
491+
if (compact) {
492+
Column(
493+
modifier = Modifier
494+
.fillMaxWidth()
495+
.padding(16.dp)
496+
) {
497+
Row(
498+
modifier = Modifier.fillMaxWidth(),
499+
verticalAlignment = Alignment.CenterVertically,
500+
horizontalArrangement = Arrangement.SpaceBetween
501+
) {
502+
reorderControls()
503+
if (showTrailingActions) {
504+
MenuItemTrailingAction(
505+
isVisible = isVisible,
506+
onVisibilityToggle = onVisibilityToggle,
507+
onDelete = onDelete
508+
)
509+
}
517510
}
518-
} else {
519-
IconButton(onClick = onVisibilityToggle) {
520-
Icon(
521-
imageVector = if (isVisible) Icons.Default.Visibility else Icons.Default.VisibilityOff,
522-
contentDescription = if (isVisible) {
523-
stringResource(R.string.content_desc_hide_item)
524-
} else {
525-
stringResource(R.string.content_desc_show_item)
526-
},
527-
tint = if (isVisible) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurfaceVariant
511+
Spacer(modifier = Modifier.height(8.dp))
512+
MenuItemLabel(
513+
itemLabel = itemLabel,
514+
isVisible = isVisible,
515+
modifier = Modifier.fillMaxWidth()
516+
)
517+
}
518+
} else {
519+
Row(
520+
modifier = Modifier
521+
.fillMaxWidth()
522+
.padding(16.dp),
523+
verticalAlignment = Alignment.CenterVertically,
524+
horizontalArrangement = Arrangement.SpaceBetween
525+
) {
526+
reorderControls()
527+
MenuItemLabel(
528+
itemLabel = itemLabel,
529+
isVisible = isVisible,
530+
modifier = Modifier.weight(1f)
531+
)
532+
if (showTrailingActions) {
533+
MenuItemTrailingAction(
534+
isVisible = isVisible,
535+
onVisibilityToggle = onVisibilityToggle,
536+
onDelete = onDelete
528537
)
529538
}
530539
}
@@ -533,6 +542,58 @@ fun MenuItemRow(
533542
}
534543
}
535544

545+
@Composable
546+
private fun MenuItemLabel(
547+
itemLabel: String,
548+
isVisible: Boolean,
549+
modifier: Modifier = Modifier
550+
) {
551+
Text(
552+
text = itemLabel,
553+
style = MaterialTheme.typography.bodyLarge,
554+
fontWeight = if (isVisible) FontWeight.Normal else FontWeight.Light,
555+
color = if (isVisible) {
556+
MaterialTheme.colorScheme.onSurface
557+
} else {
558+
MaterialTheme.colorScheme.onSurfaceVariant
559+
},
560+
modifier = modifier
561+
)
562+
}
563+
564+
@Composable
565+
private fun MenuItemTrailingAction(
566+
isVisible: Boolean,
567+
onVisibilityToggle: () -> Unit,
568+
onDelete: (() -> Unit)?
569+
) {
570+
if (onDelete != null) {
571+
IconButton(onClick = onDelete) {
572+
Icon(
573+
imageVector = Icons.Default.Close,
574+
contentDescription = stringResource(R.string.button_delete),
575+
tint = MaterialTheme.colorScheme.error
576+
)
577+
}
578+
} else {
579+
IconButton(onClick = onVisibilityToggle) {
580+
Icon(
581+
imageVector = if (isVisible) Icons.Default.Visibility else Icons.Default.VisibilityOff,
582+
contentDescription = if (isVisible) {
583+
stringResource(R.string.content_desc_hide_item)
584+
} else {
585+
stringResource(R.string.content_desc_show_item)
586+
},
587+
tint = if (isVisible) {
588+
MaterialTheme.colorScheme.primary
589+
} else {
590+
MaterialTheme.colorScheme.onSurfaceVariant
591+
}
592+
)
593+
}
594+
}
595+
}
596+
536597
@Composable
537598
private fun SelectModeBanner(
538599
selectedLabel: String,
@@ -565,4 +626,4 @@ private fun SelectModeBanner(
565626
}
566627
}
567628
}
568-
}
629+
}

app/src/main/java/com/enaboapps/switchify/screens/settings/patterns/GesturePatternsScreen.kt

Lines changed: 64 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ package com.enaboapps.switchify.screens.settings.patterns
33
import android.widget.Toast
44
import androidx.compose.foundation.layout.Arrangement
55
import androidx.compose.foundation.layout.Box
6+
import androidx.compose.foundation.layout.BoxWithConstraints
67
import androidx.compose.foundation.layout.Column
78
import androidx.compose.foundation.layout.Row
89
import androidx.compose.foundation.layout.Spacer
910
import androidx.compose.foundation.layout.fillMaxSize
1011
import androidx.compose.foundation.layout.fillMaxWidth
12+
import androidx.compose.foundation.layout.height
1113
import androidx.compose.foundation.layout.padding
1214
import androidx.compose.foundation.layout.width
1315
import androidx.compose.material.icons.Icons
@@ -240,45 +242,77 @@ private fun PatternItem(
240242
MaterialTheme.colorScheme.surfaceColorAtElevation(1.dp)
241243
}
242244
) {
243-
Row(
244-
modifier = Modifier
245-
.fillMaxWidth()
246-
.padding(16.dp),
247-
horizontalArrangement = Arrangement.SpaceBetween,
248-
verticalAlignment = Alignment.CenterVertically
249-
) {
250-
// Reorder controls (drag handle or arrow buttons)
251-
reorderControls()
252-
253-
Text(
254-
text = pattern.name,
255-
style = MaterialTheme.typography.titleMedium,
256-
modifier = Modifier.weight(1f),
257-
maxLines = 1
258-
)
259-
260-
Row(
261-
horizontalArrangement = Arrangement.SpaceBetween,
262-
verticalAlignment = Alignment.CenterVertically
263-
) {
264-
IconButton(onClick = onEdit) {
265-
Icon(
266-
imageVector = Icons.Default.Edit,
267-
contentDescription = stringResource(R.string.edit_pattern)
245+
BoxWithConstraints {
246+
val compact = maxWidth < 360.dp
247+
if (compact) {
248+
Column(
249+
modifier = Modifier
250+
.fillMaxWidth()
251+
.padding(16.dp)
252+
) {
253+
Row(
254+
modifier = Modifier.fillMaxWidth(),
255+
horizontalArrangement = Arrangement.SpaceBetween,
256+
verticalAlignment = Alignment.CenterVertically
257+
) {
258+
reorderControls()
259+
PatternActions(onEdit = onEdit, onDelete = onDelete)
260+
}
261+
Spacer(modifier = Modifier.height(8.dp))
262+
Text(
263+
text = pattern.name,
264+
style = MaterialTheme.typography.titleMedium,
265+
modifier = Modifier.fillMaxWidth(),
266+
maxLines = 1
268267
)
269268
}
270-
271-
IconButton(onClick = onDelete) {
272-
Icon(
273-
imageVector = Icons.Default.Delete,
274-
contentDescription = stringResource(R.string.delete_pattern)
269+
} else {
270+
Row(
271+
modifier = Modifier
272+
.fillMaxWidth()
273+
.padding(16.dp),
274+
horizontalArrangement = Arrangement.SpaceBetween,
275+
verticalAlignment = Alignment.CenterVertically
276+
) {
277+
reorderControls()
278+
Text(
279+
text = pattern.name,
280+
style = MaterialTheme.typography.titleMedium,
281+
modifier = Modifier.weight(1f),
282+
maxLines = 1
275283
)
284+
PatternActions(onEdit = onEdit, onDelete = onDelete)
276285
}
277286
}
278287
}
279288
}
280289
}
281290

291+
@Composable
292+
private fun PatternActions(
293+
onEdit: () -> Unit,
294+
onDelete: () -> Unit
295+
) {
296+
Row(
297+
horizontalArrangement = Arrangement.SpaceBetween,
298+
verticalAlignment = Alignment.CenterVertically
299+
) {
300+
IconButton(onClick = onEdit) {
301+
Icon(
302+
imageVector = Icons.Default.Edit,
303+
contentDescription = stringResource(R.string.edit_pattern)
304+
)
305+
}
306+
307+
IconButton(onClick = onDelete) {
308+
Icon(
309+
imageVector = Icons.Default.Delete,
310+
contentDescription = stringResource(R.string.delete_pattern)
311+
)
312+
}
313+
}
314+
}
315+
282316
@Composable
283317
private fun EditPatternNameDialog(
284318
currentName: String,

0 commit comments

Comments
 (0)