Rewrite color picker
This commit is contained in:
parent
64e7528cb0
commit
7bb16753e0
@ -81,8 +81,6 @@ dependencies {
|
||||
|
||||
implementation(libs.androidx.navigation.compose)
|
||||
|
||||
implementation(libs.composecolorpicker)
|
||||
|
||||
implementation(libs.jsoup)
|
||||
|
||||
// Legacy dependencies
|
||||
|
||||
@ -0,0 +1,230 @@
|
||||
package de.mm20.launcher2.ui.component.colorpicker
|
||||
|
||||
import androidx.compose.foundation.Canvas
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.gestures.detectDragGestures
|
||||
import androidx.compose.foundation.gestures.detectTapGestures
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.BoxWithConstraints
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.aspectRatio
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Slider
|
||||
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.AbsoluteAlignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.draw.rotate
|
||||
import androidx.compose.ui.draw.shadow
|
||||
import androidx.compose.ui.geometry.CornerRadius
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.drawscope.Fill
|
||||
import androidx.compose.ui.graphics.drawscope.Stroke
|
||||
import androidx.compose.ui.input.pointer.pointerInput
|
||||
import androidx.compose.ui.unit.dp
|
||||
import de.mm20.launcher2.ui.ktx.toHexString
|
||||
import kotlin.math.atan2
|
||||
import android.graphics.Color as AndroidColor
|
||||
|
||||
|
||||
@Composable
|
||||
fun ColorPicker(
|
||||
value: Color,
|
||||
onValueChanged: (Color) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val (hue, sat, vl) = remember(value) {
|
||||
val hsv = FloatArray(3)
|
||||
val r = value.red * 255f
|
||||
val g = value.green * 255f
|
||||
val b = value.blue * 255f
|
||||
AndroidColor.RGBToHSV(r.toInt(), g.toInt(), b.toInt(), hsv)
|
||||
hsv
|
||||
}
|
||||
Column(modifier = modifier) {
|
||||
BoxWithConstraints(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 32.dp)
|
||||
.aspectRatio(1f)
|
||||
) {
|
||||
val width = this.maxWidth
|
||||
val height = this.maxHeight
|
||||
Canvas(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.pointerInput(Unit) {
|
||||
detectDragGestures(
|
||||
onDrag = { change, it ->
|
||||
val (x, y) = change.position
|
||||
val angle = atan2(
|
||||
y.toDouble() - height.toPx() / 2,
|
||||
x.toDouble() - width.toPx() / 2,
|
||||
)
|
||||
val h = (Math.toDegrees(angle) + 360f) % 360f
|
||||
onValueChanged(Color.hsv(h.toFloat(), sat, vl))
|
||||
}
|
||||
)
|
||||
}
|
||||
.pointerInput(Unit) {
|
||||
detectTapGestures {
|
||||
val (x, y) = it
|
||||
val angle = atan2(
|
||||
y.toDouble() - height.toPx() / 2,
|
||||
x.toDouble() - width.toPx() / 2,
|
||||
)
|
||||
val h = (Math.toDegrees(angle) + 360f) % 360f
|
||||
onValueChanged(Color.hsv(h.toFloat(), sat, vl))
|
||||
|
||||
}
|
||||
}
|
||||
.padding(8.dp)
|
||||
) {
|
||||
drawCircle(
|
||||
brush = Brush.sweepGradient(
|
||||
colors = listOf(
|
||||
Color.Red,
|
||||
Color.Yellow,
|
||||
Color.Green,
|
||||
Color.Cyan,
|
||||
Color.Blue,
|
||||
Color.Magenta,
|
||||
Color.Red
|
||||
)
|
||||
),
|
||||
style = Stroke(20.dp.toPx())
|
||||
)
|
||||
drawCircle(
|
||||
color = value,
|
||||
style = Fill,
|
||||
center = center,
|
||||
radius = size.minDimension / 2 - 18.dp.toPx()
|
||||
)
|
||||
}
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.rotate(hue),
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(16.dp)
|
||||
.shadow(1.dp, CircleShape)
|
||||
.clip(CircleShape)
|
||||
.background(MaterialTheme.colorScheme.surface)
|
||||
.align(AbsoluteAlignment.CenterRight)
|
||||
)
|
||||
}
|
||||
}
|
||||
Slider(
|
||||
modifier = Modifier.padding(top = 16.dp),
|
||||
value = sat,
|
||||
onValueChange = {
|
||||
onValueChanged(Color.hsv(hue, it, vl))
|
||||
},
|
||||
track = {
|
||||
Canvas(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(20.dp)
|
||||
) {
|
||||
drawRoundRect(
|
||||
brush = Brush.horizontalGradient(
|
||||
colors = listOf(
|
||||
Color.hsv(hue, 0f, 1f),
|
||||
Color.hsv(hue, 1f, 1f)
|
||||
)
|
||||
),
|
||||
style = Fill,
|
||||
cornerRadius = CornerRadius(10.dp.toPx(), 10.dp.toPx())
|
||||
)
|
||||
}
|
||||
},
|
||||
thumb = {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(vertical = 2.dp, horizontal = 8.dp)
|
||||
.size(16.dp)
|
||||
.shadow(1.dp, CircleShape)
|
||||
.clip(CircleShape)
|
||||
.background(MaterialTheme.colorScheme.surface)
|
||||
)
|
||||
}
|
||||
)
|
||||
Slider(
|
||||
modifier = Modifier,
|
||||
value = vl,
|
||||
onValueChange = {
|
||||
onValueChanged(Color.hsv(hue, sat, it))
|
||||
},
|
||||
track = {
|
||||
Canvas(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(20.dp)
|
||||
) {
|
||||
drawRoundRect(
|
||||
brush = Brush.horizontalGradient(
|
||||
colors = listOf(
|
||||
Color.hsv(hue, sat, 0f),
|
||||
Color.hsv(hue, sat, 1f)
|
||||
)
|
||||
),
|
||||
style = Fill,
|
||||
cornerRadius = CornerRadius(10.dp.toPx(), 10.dp.toPx())
|
||||
)
|
||||
}
|
||||
},
|
||||
thumb = {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(vertical = 2.dp, horizontal = 8.dp)
|
||||
.size(16.dp)
|
||||
.shadow(1.dp, CircleShape)
|
||||
.clip(CircleShape)
|
||||
.background(MaterialTheme.colorScheme.surface)
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
var hexValue by remember(value) {
|
||||
mutableStateOf(
|
||||
value.toHexString().substring(1)
|
||||
)
|
||||
}
|
||||
|
||||
OutlinedTextField(
|
||||
modifier = Modifier.padding(top = 16.dp).padding(horizontal = 16.dp),
|
||||
value = hexValue,
|
||||
onValueChange = {
|
||||
if (Regex("[0-9a-fA-F]{0,6}").matches(it)) {
|
||||
hexValue = it
|
||||
if (it.length == 6) {
|
||||
val hex = it.toIntOrNull(16) ?: return@OutlinedTextField
|
||||
val color = Color(hex).copy(alpha = 1f)
|
||||
onValueChanged(color)
|
||||
}
|
||||
}
|
||||
},
|
||||
prefix = {
|
||||
Text(
|
||||
text = "#",
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
@ -8,7 +8,7 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.godaddy.android.colorpicker.ClassicColorPicker
|
||||
import de.mm20.launcher2.ui.component.colorpicker.ColorPicker
|
||||
import de.mm20.launcher2.ui.ktx.toHexString
|
||||
|
||||
@Composable
|
||||
@ -51,35 +51,9 @@ fun ColorPreference(
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
|
||||
ClassicColorPicker(
|
||||
color = value ?: Color.Black,
|
||||
onColorChanged = {
|
||||
color = it.toColor()
|
||||
},
|
||||
showAlphaBar = false,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(200.dp)
|
||||
)
|
||||
|
||||
var hexValue by remember(color) {
|
||||
mutableStateOf(
|
||||
color?.toHexString() ?: "#000000"
|
||||
)
|
||||
}
|
||||
|
||||
TextField(
|
||||
modifier = Modifier.padding(top = 16.dp),
|
||||
value = hexValue,
|
||||
onValueChange = {
|
||||
hexValue = it
|
||||
if (Regex("#[0-9a-fA-F]{6}").matches(it)) {
|
||||
val hex = it.substring(1).toIntOrNull(16) ?: return@TextField
|
||||
color = Color(hex).copy(alpha = 1f)
|
||||
}
|
||||
}
|
||||
)
|
||||
ColorPicker(value = color ?: Color.Black, onValueChanged = {
|
||||
color = it
|
||||
})
|
||||
}
|
||||
},
|
||||
confirmButton = {
|
||||
|
||||
@ -169,14 +169,6 @@ val OpenSourceLicenses = arrayOf(
|
||||
licenseText = R.raw.license_apache_2,
|
||||
url = "https://coil-kt.github.io/coil/"
|
||||
),
|
||||
OpenSourceLibrary(
|
||||
name = "compose-color-picker",
|
||||
description = "A component that provides an HSV color picker, written in Jetpack compose.",
|
||||
copyrightNote = "Copyright (c) 2021GoDaddy Operating Company, LLC.",
|
||||
licenseName = R.string.mit_license_name,
|
||||
licenseText = R.raw.license_mit,
|
||||
url = "https://github.com/godaddy/compose-color-picker"
|
||||
),
|
||||
OpenSourceLibrary(
|
||||
name = "Apache Commons Text",
|
||||
description = "Apache Commons Text is a library focused on algorithms working on strings. ",
|
||||
|
||||
@ -186,9 +186,6 @@ dependencyResolutionManagement {
|
||||
library("coil.compose", "io.coil-kt", "coil-compose")
|
||||
.versionRef("coil")
|
||||
|
||||
library("composecolorpicker", "com.godaddy.android.colorpicker", "compose-color-picker")
|
||||
.version("0.7.0")
|
||||
|
||||
library("leakcanary", "com.squareup.leakcanary", "leakcanary-android")
|
||||
.version("2.10")
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user