Last active
September 16, 2024 13:47
-
-
Save elfefe/d15b86d7aaef81e4165677383de16676 to your computer and use it in GitHub Desktop.
Utilitaires Kotlin/Compose
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package fr.exem.citymapper2.controllers | |
| import androidx.compose.runtime.* | |
| import androidx.compose.ui.graphics.Color | |
| import androidx.compose.ui.graphics.toArgb | |
| import androidx.lifecycle.ViewModel | |
| import kotlinx.coroutines.CoroutineScope | |
| import kotlinx.coroutines.Dispatchers | |
| import kotlinx.coroutines.Job | |
| import kotlinx.coroutines.launch | |
| import org.json.JSONObject | |
| import java.io.File | |
| class Config { | |
| private var configFile: File = File(FileManager.appDirectory, "config.json").apply { | |
| if (!exists()) createNewFile() | |
| } | |
| private val config = configFile.run { JSONObject(readText()) } | |
| private val scope = CoroutineScope(Dispatchers.IO) | |
| private var job: Job? = null | |
| private val map: JSONObject | |
| get() { | |
| return try { | |
| config.getJSONObject("map") | |
| } catch (e: Exception) { | |
| JSONObject() | |
| } | |
| } | |
| private val trail: JSONObject | |
| get() { | |
| return try { | |
| config.getJSONObject("trail") | |
| } catch (e: Exception) { | |
| JSONObject() | |
| } | |
| } | |
| private var _macAdress by mutableStateOf(try { | |
| config.getString("mac") | |
| } catch (e: Exception) { | |
| "" | |
| }) | |
| var macAdress: String | |
| get() = _macAdress | |
| set(value) { | |
| _macAdress = value | |
| config.put("mac", value) | |
| updateConfig() | |
| } | |
| val defaultMapWidth = .3f | |
| private var _mapWidth by mutableFloatStateOf(try { | |
| map.getDouble("width").toFloat() | |
| } catch (e: Exception) { | |
| defaultMapWidth | |
| }) | |
| var mapWidth: Float | |
| get() = _mapWidth | |
| set(value) { | |
| _mapWidth = value | |
| map.put("width", value) | |
| config.put("map", map) | |
| updateConfig() | |
| } | |
| val defaultTrailWidth = 5f | |
| private var _trailWidth by mutableFloatStateOf(try { | |
| trail.getDouble("width").toFloat() | |
| } catch (e: Exception) { | |
| defaultTrailWidth | |
| }) | |
| var trailWidth: Float | |
| get() = _trailWidth | |
| set(value) { | |
| _trailWidth = value | |
| trail.put("width", value) | |
| config.put("trail", trail) | |
| updateConfig() | |
| } | |
| val defaultTrailColor = Color.Red | |
| private var _trailColor by mutableStateOf(try { | |
| Color(trail.getInt("color")) | |
| } catch (e: Exception) { | |
| defaultTrailColor | |
| }) | |
| var trailColor: Color | |
| get() = _trailColor | |
| set(value) { | |
| _trailColor = value | |
| trail.put("color", value.toArgb()) | |
| config.put("trail", trail) | |
| updateConfig() | |
| } | |
| private fun updateConfig() { | |
| if (job?.isActive == true) return | |
| job = scope.launch { | |
| while (config.toString() != configFile.readText()) { | |
| configFile.writeText(config.toString()) | |
| } | |
| } | |
| } | |
| companion object { | |
| val instance = Config() | |
| } | |
| } | |
| class ConfigViewModel: ViewModel() { | |
| var config = Config.instance | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import androidx.compose.foundation.ExperimentalFoundationApi | |
| import androidx.compose.foundation.gestures.snapping.rememberSnapFlingBehavior | |
| import androidx.compose.foundation.layout.Arrangement | |
| import androidx.compose.foundation.layout.Box | |
| import androidx.compose.foundation.layout.PaddingValues | |
| import androidx.compose.foundation.layout.Row | |
| import androidx.compose.foundation.layout.Spacer | |
| import androidx.compose.foundation.layout.height | |
| import androidx.compose.foundation.layout.size | |
| import androidx.compose.foundation.layout.width | |
| import androidx.compose.foundation.lazy.LazyColumn | |
| import androidx.compose.foundation.lazy.items | |
| import androidx.compose.foundation.lazy.rememberLazyListState | |
| import androidx.compose.material3.Text | |
| import androidx.compose.runtime.Composable | |
| import androidx.compose.runtime.getValue | |
| import androidx.compose.runtime.mutableStateOf | |
| import androidx.compose.runtime.remember | |
| import androidx.compose.runtime.setValue | |
| import androidx.compose.ui.Alignment | |
| import androidx.compose.ui.Modifier | |
| import androidx.compose.ui.geometry.Size | |
| import androidx.compose.ui.layout.boundsInParent | |
| import androidx.compose.ui.layout.onGloballyPositioned | |
| import androidx.compose.ui.layout.onSizeChanged | |
| import androidx.compose.ui.text.style.TextAlign | |
| import androidx.compose.ui.unit.dp | |
| import androidx.compose.ui.unit.sp | |
| import androidx.compose.ui.unit.toSize | |
| import kotlin.math.abs | |
| @Composable | |
| fun TimePicker(modifier: Modifier = Modifier, onPickTime: (Int, Int, Int) -> Unit) { | |
| var hours by remember { mutableStateOf(0) } | |
| var minuts by remember { mutableStateOf(0) } | |
| var seconds by remember { mutableStateOf(0) } | |
| Row( | |
| modifier = modifier, | |
| verticalAlignment = Alignment.CenterVertically | |
| ) { | |
| NumberPicker(numbers = (0..24).toList()) { | |
| hours = it | |
| onPickTime(hours, minuts, seconds) | |
| } | |
| Text(text = "h", fontSize = 16.sp) | |
| NumberPicker(numbers = (0..59).toList()) { | |
| minuts = it | |
| onPickTime(hours, minuts, seconds) | |
| } | |
| Text(text = "m", fontSize = 16.sp) | |
| NumberPicker(numbers = (0..59).toList()) { | |
| seconds = it | |
| onPickTime(hours, minuts, seconds) | |
| } | |
| Text(text = "s", fontSize = 16.sp) | |
| } | |
| } | |
| @OptIn(ExperimentalFoundationApi::class) | |
| @Composable | |
| fun <T: Number> NumberPicker(numbers: List<T>, onPickNumber: (T) -> Unit) { | |
| val hoursListState = rememberLazyListState() | |
| val hoursSnapFling = rememberSnapFlingBehavior(lazyListState = hoursListState) | |
| var hoursLayoutSize by remember { mutableStateOf(Size.Zero) } | |
| LazyColumn( | |
| flingBehavior = hoursSnapFling, | |
| modifier = Modifier | |
| .width(48.dp) | |
| .height(64.dp) | |
| .onSizeChanged { hoursLayoutSize = it.toSize() }, | |
| state = hoursListState, | |
| contentPadding = PaddingValues(0.dp, 24.dp), | |
| verticalArrangement = Arrangement.Center, | |
| horizontalAlignment = Alignment.CenterHorizontally | |
| ) { | |
| items(numbers.toList()) { hour -> | |
| var positionRatio by remember { mutableStateOf(0f) } | |
| Box( | |
| modifier = Modifier | |
| .size(24.dp) | |
| .onGloballyPositioned { coordinates -> | |
| coordinates | |
| .boundsInParent() | |
| .run { | |
| val x = | |
| (((top + (height / 2)) / (hoursLayoutSize.height)) - .5f) * 2 | |
| positionRatio = x * x | |
| if (top > 0 && bottom < hoursLayoutSize.height) onPickNumber(hour) | |
| } | |
| }, | |
| contentAlignment = Alignment.Center | |
| ) { | |
| Text( | |
| text = "$hour", | |
| textAlign = TextAlign.Center, | |
| fontSize = (16 - 14 * positionRatio).sp, | |
| ) | |
| } | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment