@@ -5,19 +5,26 @@ import android.text.method.LinkMovementMethod
55import android.util.TypedValue
66import android.view.View
77import androidx.annotation.DrawableRes
8+ import androidx.compose.animation.core.animateDpAsState
89import androidx.compose.foundation.Image
10+ import androidx.compose.foundation.background
11+ import androidx.compose.foundation.border
912import androidx.compose.foundation.clickable
1013import androidx.compose.foundation.layout.Arrangement
14+ import androidx.compose.foundation.layout.Box
1115import androidx.compose.foundation.layout.Column
1216import androidx.compose.foundation.layout.Row
1317import androidx.compose.foundation.layout.Spacer
1418import androidx.compose.foundation.layout.fillMaxWidth
1519import androidx.compose.foundation.layout.height
20+ import androidx.compose.foundation.layout.offset
1621import androidx.compose.foundation.layout.padding
1722import androidx.compose.foundation.layout.size
1823import androidx.compose.foundation.layout.width
1924import androidx.compose.foundation.layout.wrapContentHeight
2025import androidx.compose.foundation.layout.wrapContentSize
26+ import androidx.compose.foundation.shape.CircleShape
27+ import androidx.compose.foundation.shape.RoundedCornerShape
2128import androidx.compose.runtime.Composable
2229import androidx.compose.runtime.getValue
2330import androidx.compose.runtime.mutableIntStateOf
@@ -28,6 +35,8 @@ import androidx.compose.runtime.rememberCoroutineScope
2835import androidx.compose.runtime.setValue
2936import androidx.compose.ui.Alignment
3037import androidx.compose.ui.Modifier
38+ import androidx.compose.ui.draw.clip
39+ import androidx.compose.ui.graphics.Brush
3140import androidx.compose.ui.graphics.Color
3241import androidx.compose.ui.graphics.ColorFilter
3342import androidx.compose.ui.graphics.toArgb
@@ -41,8 +50,6 @@ import androidx.compose.ui.viewinterop.AndroidView
4150import com.github.creativecodecat.components.views.FontAppCompatTextView
4251import com.github.droidworksstudio.mlauncher.services.HapticFeedbackService
4352import com.github.droidworksstudio.mlauncher.style.SettingsTheme
44- import com.github.droidworksstudio.mlauncher.style.textDisabled
45- import com.github.droidworksstudio.mlauncher.style.textEnabled
4653import kotlinx.coroutines.Job
4754import kotlinx.coroutines.delay
4855import kotlinx.coroutines.launch
@@ -431,68 +438,111 @@ object SettingsComposable {
431438 @Composable
432439 fun SettingsSwitch (
433440 text : String ,
434- fontSize : TextUnit = TextUnit . Unspecified ,
441+ fontSize : TextUnit = 14.sp ,
435442 titleColor : Color = SettingsTheme .typography.title.color,
436443 defaultState : Boolean = false,
437444 onCheckedChange : (Boolean ) -> Unit
438445 ) {
439446 var isChecked by remember { mutableStateOf(defaultState) }
440-
441- val resolvedFontSizeSp = if (fontSize != TextUnit .Unspecified ) fontSize.value else 14f
447+ // Extract font size and color from theme safely in composable scope
448+ val resolvedFontSizeSp = if (fontSize != TextUnit .Unspecified ) fontSize.value else 16f
442449 val context = LocalContext .current
443450
444- Column (
451+ Row (
445452 modifier = Modifier
446453 .fillMaxWidth()
447- .padding(vertical = 4 .dp, horizontal = 16 .dp)
448454 .clickable {
449455 isChecked = ! isChecked
450456 onCheckedChange(isChecked)
451457
452- // Haptic feedback
453458 HapticFeedbackService .trigger(
454- context = context ,
455- effectType = if (isChecked)
459+ context,
460+ if (isChecked)
456461 HapticFeedbackService .EffectType .ON
457462 else
458463 HapticFeedbackService .EffectType .OFF
459464 )
460- },
461- verticalArrangement = Arrangement . Center ,
462- horizontalAlignment = Alignment .Start
465+ }
466+ .padding(horizontal = 16 .dp, vertical = 12 .dp) ,
467+ verticalAlignment = Alignment .CenterVertically
463468 ) {
464- // Title text
469+
470+ // Label
465471 AndroidView (
466- factory = { ctx ->
467- FontAppCompatTextView (ctx ).apply {
468- textAlignment = View . TEXT_ALIGNMENT_VIEW_START
472+ factory = { context ->
473+ FontAppCompatTextView (context ).apply {
474+ this .text = text
469475 setTextSize(TypedValue .COMPLEX_UNIT_SP , resolvedFontSizeSp)
476+ setTextColor(titleColor.toArgb())
477+ textAlignment = View .TEXT_ALIGNMENT_VIEW_START
470478 }
471479 },
472- modifier = Modifier .wrapContentHeight(),
473- update = { textView ->
474- textView.text = text
475- textView.setTextColor(titleColor.toArgb())
476- }
480+ modifier = Modifier
481+ .weight(1f )
482+ .wrapContentHeight()
477483 )
478484
479- // “Enabled/Disabled” text
480- AndroidView (
481- factory = { ctx ->
482- FontAppCompatTextView (ctx).apply {
483- setTextSize(TypedValue .COMPLEX_UNIT_SP , (resolvedFontSizeSp / 1.3 ).toFloat())
484- textAlignment = View .TEXT_ALIGNMENT_VIEW_START
485- }
486- },
487- modifier = Modifier .wrapContentHeight(),
488- update = { textView ->
489- textView.text = if (isChecked) " ✔" else " ✖"
490- textView.setTextColor(if (isChecked) textEnabled.toArgb() else textDisabled.toArgb())
491- }
485+ // Custom switch
486+ CustomSwitch (
487+ checked = isChecked
488+ )
489+ }
490+ }
491+
492+
493+ @Composable
494+ fun CustomSwitch (
495+ checked : Boolean ,
496+ modifier : Modifier = Modifier
497+ ) {
498+ val thumbSize = 14 .dp
499+ val trackWidth = 32 .dp
500+ val trackHeight = 16 .dp
501+
502+ val thumbOffset by animateDpAsState(
503+ targetValue = if (checked) trackWidth - thumbSize - 2 .dp else 2 .dp,
504+ label = " thumbOffset"
505+ )
506+
507+ Box (
508+ modifier = modifier
509+ .size(width = trackWidth, height = trackHeight)
510+ .clip(RoundedCornerShape (trackHeight / 2 ))
511+ .background(
512+ if (checked)
513+ Brush .verticalGradient(
514+ colors = listOf (
515+ Color (0xFF4CAF73 ),
516+ Color (0xFF2E8B57 )
517+ )
518+ )
519+ else
520+ Brush .verticalGradient(
521+ colors = listOf (
522+ Color (0xFFD6D6D6 ),
523+ Color (0xFFD6D6D6 )
524+ )
525+ )
526+
527+ )
528+ ) {
529+ Box (
530+ modifier = Modifier
531+ .offset(x = thumbOffset)
532+ .size(thumbSize)
533+ .align(Alignment .CenterStart )
534+ .clip(CircleShape )
535+ .background(Color .White )
536+ .border(
537+ width = 1 .dp,
538+ color = Color .Black .copy(alpha = 0.15f ),
539+ shape = CircleShape
540+ )
492541 )
493542 }
494543 }
495544
545+
496546 @Composable
497547 fun SettingsSelect (
498548 title : String ,
0 commit comments