diff --git a/demo/build.gradle.kts b/demo/build.gradle.kts index 351d300..2c88c7c 100644 --- a/demo/build.gradle.kts +++ b/demo/build.gradle.kts @@ -29,7 +29,7 @@ android { compose = true } composeOptions { - kotlinCompilerExtensionVersion = "1.5.1" + kotlinCompilerExtensionVersion = libs.versions.composeCompiler.get() } packaging { resources { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7349213..2e00368 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,11 +7,13 @@ junitVersion = "1.1.5" espresso = "3.5.1" lifecyle = "2.7.0" activityCompose = "1.8.2" +composeCompiler = "1.5.1" composeBom = "2024.02.00" spotless="6.25.0" detekt="1.23.5" [libraries] +kotlin_gradle_plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin"} android_gradle_plugin = { module = "com.android.tools.build:gradle", version.ref = "agp" } androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "coreKtx" } junit = { module = "junit:junit", version.ref = "junit" } @@ -23,6 +25,7 @@ androidx-activity-compose = { module = "androidx.activity:activity-compose", ver compose-bom = { module = "androidx.compose:compose-bom", version.ref = "composeBom" } compose-ui = { module = "androidx.compose.ui:ui" } compose-ui-graphics = { module = "androidx.compose.ui:ui-graphics" } +compose-foundation = { module = "androidx.compose.foundation:foundation" } compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling" } compose-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview" } compose-ui-test-manifest = { module = "androidx.compose.ui:ui-test-manifest" } diff --git a/lib/build.gradle.kts b/lib/build.gradle.kts index 3304c36..b2b038c 100644 --- a/lib/build.gradle.kts +++ b/lib/build.gradle.kts @@ -20,8 +20,10 @@ android { } } } + kotlin { jvmToolchain(17) + explicitApi() } dependencies { diff --git a/slider/build.gradle.kts b/slider/build.gradle.kts index 0fba583..690bf48 100644 --- a/slider/build.gradle.kts +++ b/slider/build.gradle.kts @@ -19,18 +19,29 @@ android { ) } } + + buildFeatures { + compose = true + } + + composeOptions { + kotlinCompilerExtensionVersion = libs.versions.composeCompiler.get() + } } kotlin { jvmToolchain(17) + explicitApi() } dependencies { - implementation(libs.androidx.core.ktx) implementation(platform(libs.compose.bom)) implementation(libs.compose.ui) + implementation(libs.compose.ui.graphics) implementation(libs.compose.ui.tooling.preview) + implementation(libs.compose.ui.tooling) + implementation(libs.compose.foundation) testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) diff --git a/slider/src/main/java/io/monstarlab/mosaic/slider/SliderColors.kt b/slider/src/main/java/io/monstarlab/mosaic/slider/SliderColors.kt new file mode 100644 index 0000000..324c939 --- /dev/null +++ b/slider/src/main/java/io/monstarlab/mosaic/slider/SliderColors.kt @@ -0,0 +1,9 @@ +package io.monstarlab.mosaic.slider + +import androidx.compose.ui.graphics.Color + +public data class SliderColors( + val active: Color, + val disabled: Color = active.copy(alpha = 0.2f), + val inactive: Color = active.copy(alpha = 0.5f), +) \ No newline at end of file diff --git a/slider/src/main/java/io/monstarlab/mosaic/slider/SliderDefaults.kt b/slider/src/main/java/io/monstarlab/mosaic/slider/SliderDefaults.kt new file mode 100644 index 0000000..03e6591 --- /dev/null +++ b/slider/src/main/java/io/monstarlab/mosaic/slider/SliderDefaults.kt @@ -0,0 +1,7 @@ +package io.monstarlab.mosaic.slider + +import androidx.compose.ui.unit.dp + +internal object SliderDefaults { + val TrackHeight = 4.dp +} \ No newline at end of file diff --git a/slider/src/main/java/io/monstarlab/mosaic/slider/SliderTrack.kt b/slider/src/main/java/io/monstarlab/mosaic/slider/SliderTrack.kt new file mode 100644 index 0000000..c6cf7f6 --- /dev/null +++ b/slider/src/main/java/io/monstarlab/mosaic/slider/SliderTrack.kt @@ -0,0 +1,61 @@ +package io.monstarlab.mosaic.slider + +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.geometry.Size +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.tooling.preview.Preview + +@Composable +internal fun SliderTrack( + progress: Float, + colors: SliderColors, + modifier: Modifier = Modifier, + disabledRange: ClosedFloatingPointRange = 0f..0f, +) { + + check(progress in 0f..1f) { "Invalid progress value should be between 0 and 1" } + Canvas( + modifier = modifier + .fillMaxWidth() + .height(SliderDefaults.TrackHeight) + ) { + val activeRectWidth = size.width * progress + drawRect( + color = colors.active, + topLeft = Offset.Zero, + size = Size(activeRectWidth, size.height) + ) + + drawRect( + color = colors.inactive, + topLeft = Offset(activeRectWidth, 0f), + size = Size(size.width - activeRectWidth, size.height) + ) + + if (!disabledRange.isEmpty()) { + val disabledStart = size.width * disabledRange.start + val disabledEnd = size.width * disabledRange.endInclusive + drawRect( + color = colors.disabled, + topLeft = Offset(size.width * disabledRange.start, 0f), + size = Size(disabledEnd - disabledStart, size.height) + ) + } + } +} + + +@Preview +@Composable +private fun PreviewSliderTrack() { + SliderTrack( + progress = 0.5f, + colors = SliderColors(Color.Red), + disabledRange = 0.8f..1f + ) +} \ No newline at end of file