Skip to content

Commit 6ca89fe

Browse files
add ring-rect hsl color picker
1 parent 5f33535 commit 6ca89fe

File tree

5 files changed

+283
-9
lines changed

5 files changed

+283
-9
lines changed

app/src/main/java/com/smarttoolfactory/composecolorpicker/demo/ColorPickerDemo.kt

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,19 @@ fun ColorPickerDemo() {
4747
.padding(4.dp)
4848

4949
// Ring Hue, Diamond Saturation-Lightness selector HSL Picker
50-
DialogRingHSL(
50+
DialogRingDiamondHSL(
51+
modifier = buttonModifier,
52+
color = color,
53+
onPreviousColorChange = {
54+
previousColor = it
55+
},
56+
onCurrentColorChange = {
57+
color = it
58+
}
59+
)
60+
61+
// Ring Hue, Rect Saturation-Lightness selector HSL Picker
62+
DialogRingRectHSL(
5163
modifier = buttonModifier,
5264
color = color,
5365
onPreviousColorChange = {
@@ -59,7 +71,7 @@ fun ColorPickerDemo() {
5971
)
6072

6173
// Ring Hue, Rect Saturation-Value selector HSV Picker
62-
DialogRingHSV(
74+
DialogRingRectHSV(
6375
modifier = buttonModifier,
6476
color = color,
6577
onPreviousColorChange = {
@@ -152,7 +164,7 @@ fun ColorPickerDemo() {
152164
}
153165

154166
@Composable
155-
private fun DialogRingHSL(
167+
private fun DialogRingDiamondHSL(
156168
modifier: Modifier,
157169
color: Color,
158170
onPreviousColorChange: (Color) -> Unit,
@@ -183,7 +195,38 @@ private fun DialogRingHSL(
183195
}
184196

185197
@Composable
186-
private fun DialogRingHSV(
198+
private fun DialogRingRectHSL(
199+
modifier: Modifier,
200+
color: Color,
201+
onPreviousColorChange: (Color) -> Unit,
202+
onCurrentColorChange: (Color) -> Unit,
203+
204+
) {
205+
var showDialog by remember { mutableStateOf(false) }
206+
207+
OutlinedButton(
208+
modifier = modifier,
209+
onClick = { showDialog = !showDialog },
210+
colors = ButtonDefaults.outlinedButtonColors(
211+
backgroundColor = Color.Transparent
212+
)
213+
214+
) {
215+
Text(text = "Hue Ring-Rect HSL Dialog")
216+
}
217+
218+
if (showDialog) {
219+
onPreviousColorChange(color.copy())
220+
221+
ColorPickerRingRectHSLDialog(color) {
222+
showDialog = !showDialog
223+
onCurrentColorChange(it)
224+
}
225+
}
226+
}
227+
228+
@Composable
229+
private fun DialogRingRectHSV(
187230
modifier: Modifier,
188231
color: Color,
189232
onPreviousColorChange: (Color) -> Unit,

colorpicker/src/main/java/com/smarttoolfactory/colorpicker/dialog/ColorPickerDialog.kt

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,58 @@ fun ColorPickerRingDiamondHSLDialog(
7272
}
7373
}
7474

75+
@Composable
76+
fun ColorPickerRingRectHSLDialog(
77+
initialColor: Color,
78+
ringOuterRadiusFraction: Float = .9f,
79+
ringInnerRadiusFraction: Float = .6f,
80+
ringBackgroundColor: Color = Color.Transparent,
81+
ringBorderStrokeColor: Color = Color.Black,
82+
ringBorderStrokeWidth: Dp = 4.dp,
83+
selectionRadius: Dp = 8.dp,
84+
onDismiss: (Color) -> Unit
85+
) {
86+
87+
var color by remember { mutableStateOf(initialColor.copy()) }
88+
Dialog(
89+
onDismissRequest = {
90+
onDismiss(color)
91+
}
92+
) {
93+
Column(horizontalAlignment = Alignment.CenterHorizontally) {
94+
95+
ColorPickerRingRectHSL(
96+
modifier = Modifier
97+
.fillMaxWidth()
98+
.weight(1f)
99+
.background(Color(0xcc212121), shape = RoundedCornerShape(5.dp))
100+
.padding(horizontal = 10.dp, vertical = 2.dp),
101+
initialColor = initialColor,
102+
ringOuterRadiusFraction = ringOuterRadiusFraction,
103+
ringInnerRadiusFraction = ringInnerRadiusFraction,
104+
ringBackgroundColor = ringBackgroundColor,
105+
ringBorderStrokeColor = ringBorderStrokeColor,
106+
ringBorderStrokeWidth = ringBorderStrokeWidth,
107+
selectionRadius = selectionRadius
108+
) {
109+
color = it
110+
}
111+
112+
FloatingActionButton(
113+
onClick = { onDismiss(color) },
114+
backgroundColor = Color.Black
115+
) {
116+
Icon(
117+
imageVector = Icons.Filled.Close,
118+
contentDescription = null,
119+
tint = Blue400
120+
)
121+
}
122+
}
123+
}
124+
}
125+
126+
75127
@Composable
76128
fun ColorPickerRingRectHSVDialog(
77129
initialColor: Color,
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
package com.smarttoolfactory.colorpicker.picker
2+
3+
import androidx.compose.foundation.layout.*
4+
import androidx.compose.runtime.*
5+
import androidx.compose.ui.Alignment
6+
import androidx.compose.ui.Modifier
7+
import androidx.compose.ui.graphics.Color
8+
import androidx.compose.ui.unit.Dp
9+
import androidx.compose.ui.unit.dp
10+
import com.smarttoolfactory.colorpicker.model.ColorHSL
11+
import com.smarttoolfactory.colorpicker.model.ColorModel
12+
import com.smarttoolfactory.colorpicker.selector.SelectorDiamondSaturationLightnessHSL
13+
import com.smarttoolfactory.colorpicker.selector.SelectorRectSaturationLightnessHSL
14+
import com.smarttoolfactory.colorpicker.selector.SelectorRingHue
15+
import com.smarttoolfactory.colorpicker.slider.CompositeSliderPanel
16+
import com.smarttoolfactory.colorpicker.util.colorToHSL
17+
import com.smarttoolfactory.colorpicker.widget.ColorDisplayRoundedRect
18+
import com.smarttoolfactory.colorpicker.widget.ColorModelChangeTabRow
19+
20+
/**
21+
* ColorPicker with [SelectorRingHue] hue selector and [SelectorRectSaturationLightnessHSL]
22+
* saturation lightness Selector that uses [HSL](https://en.wikipedia.org/wiki/HSL_and_HSV)
23+
* color model as base.
24+
* This color picker has tabs section that can be changed between
25+
* HSL, HSV and RGB color models and color can be set using [CompositeSliderPanel] which contains
26+
* sliders for each color models.
27+
*
28+
* @param initialColor color that is passed to this picker initially.
29+
* @param ringOuterRadiusFraction outer radius of [SelectorRingHue].
30+
* @param ringInnerRadiusFraction inner radius of [SelectorRingHue].
31+
* @param ringBackgroundColor background from center to inner radius of [SelectorRingHue].
32+
* @param ringBorderStrokeColor stroke color for drawing borders around inner or outer radius.
33+
* @param ringBorderStrokeWidth stroke width of borders.
34+
* @param selectionRadius radius of white and black circle selector.
35+
* @param onColorChange callback that is triggered when [Color] is changed using [SelectorRingHue],
36+
* [SelectorDiamondSaturationLightnessHSL] or [CompositeSliderPanel]
37+
*/
38+
@Composable
39+
fun ColorPickerRingRectHSL(
40+
modifier: Modifier = Modifier,
41+
initialColor: Color,
42+
ringOuterRadiusFraction: Float = .9f,
43+
ringInnerRadiusFraction: Float = .6f,
44+
ringBackgroundColor: Color = Color.Transparent,
45+
ringBorderStrokeColor: Color = Color.Black,
46+
ringBorderStrokeWidth: Dp = 4.dp,
47+
selectionRadius: Dp = 8.dp,
48+
onColorChange: (Color) -> Unit
49+
) {
50+
51+
var inputColorModel by remember { mutableStateOf(ColorModel.HSL) }
52+
53+
val hslArray = colorToHSL(initialColor)
54+
55+
var hue by remember { mutableStateOf(hslArray[0]) }
56+
var saturation by remember { mutableStateOf(hslArray[1]) }
57+
var lightness by remember { mutableStateOf(hslArray[2]) }
58+
var alpha by remember { mutableStateOf(initialColor.alpha) }
59+
60+
val currentColor =
61+
Color.hsl(hue = hue, saturation = saturation, lightness = lightness, alpha = alpha)
62+
onColorChange(currentColor)
63+
64+
Column(
65+
modifier = modifier,
66+
horizontalAlignment = Alignment.CenterHorizontally,
67+
verticalArrangement = Arrangement.Center
68+
) {
69+
70+
Spacer(modifier = Modifier.height(10.dp))
71+
72+
// Initial and Current Colors
73+
ColorDisplayRoundedRect(
74+
modifier = Modifier
75+
.fillMaxWidth()
76+
.padding(horizontal = 50.dp, vertical = 10.dp),
77+
initialColor = initialColor,
78+
currentColor = currentColor
79+
)
80+
81+
Box(contentAlignment = Alignment.Center) {
82+
83+
// Ring Shaped Hue Selector
84+
SelectorRingHue(
85+
modifier = Modifier.fillMaxWidth(1f),
86+
hue = hue,
87+
outerRadiusFraction = ringOuterRadiusFraction,
88+
innerRadiusFraction = ringInnerRadiusFraction,
89+
backgroundColor = ringBackgroundColor,
90+
borderStrokeColor = ringBorderStrokeColor,
91+
borderStrokeWidth = ringBorderStrokeWidth,
92+
selectionRadius = selectionRadius,
93+
) { hueChange ->
94+
hue = hueChange
95+
}
96+
97+
// Rect Shaped Saturation and Lightness Selector
98+
SelectorRectSaturationLightnessHSL(
99+
modifier = Modifier
100+
.fillMaxWidth(ringInnerRadiusFraction * .65f)
101+
.aspectRatio(1f),
102+
hue = hue,
103+
saturation = saturation,
104+
lightness = lightness,
105+
selectionRadius = selectionRadius
106+
) { s, l ->
107+
saturation = s
108+
lightness = l
109+
}
110+
}
111+
112+
// HSL-HSV-RGB Color Model Change Tabs
113+
ColorModelChangeTabRow(
114+
modifier = Modifier.width(350.dp),
115+
colorModel = inputColorModel,
116+
onColorModelChange = {
117+
inputColorModel = it
118+
}
119+
)
120+
121+
// HSL-HSV-RGB Sliders
122+
CompositeSliderPanel(
123+
modifier = Modifier.padding(start = 10.dp, end = 7.dp),
124+
compositeColor = ColorHSL(
125+
hue = hue,
126+
saturation = saturation,
127+
lightness = lightness,
128+
alpha = alpha
129+
),
130+
onColorChange = {
131+
(it as? ColorHSL)?.let { color ->
132+
hue = color.hue
133+
saturation = color.saturation
134+
lightness = color.lightness
135+
alpha = color.alpha
136+
}
137+
},
138+
showAlphaSlider = true,
139+
inputColorModel = inputColorModel,
140+
outputColorModel = ColorModel.HSL
141+
)
142+
}
143+
}

colorpicker/src/main/java/com/smarttoolfactory/colorpicker/picker/ColorPickerRingRectHSV.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ fun ColorPickerRingRectHSV(
9494
hue = hueChange
9595
}
9696

97-
// Diamond Shaped Saturation and Lightness Selector
97+
// Rect Shaped Saturation and Lightness Selector
9898
SelectorRectSaturationValueHSV(
9999
modifier = Modifier
100100
.fillMaxWidth(ringInnerRadiusFraction * .65f)

colorpicker/src/main/java/com/smarttoolfactory/colorpicker/widget/ColorDisplayRoundedRect.kt

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
package com.smarttoolfactory.colorpicker.widget
22

33
import androidx.compose.foundation.background
4-
import androidx.compose.foundation.layout.Box
5-
import androidx.compose.foundation.layout.Row
6-
import androidx.compose.foundation.layout.fillMaxHeight
7-
import androidx.compose.foundation.layout.height
4+
import androidx.compose.foundation.layout.*
85
import androidx.compose.foundation.shape.RoundedCornerShape
96
import androidx.compose.runtime.Composable
107
import androidx.compose.ui.Modifier
8+
import androidx.compose.ui.graphics.Brush
119
import androidx.compose.ui.graphics.Color
10+
import androidx.compose.ui.unit.DpSize
1211
import androidx.compose.ui.unit.dp
1312

1413
/**
@@ -28,6 +27,7 @@ fun ColorDisplayRoundedRect(
2827
modifier = Modifier
2928
.weight(1f)
3029
.fillMaxHeight()
30+
.drawChecker(RoundedCornerShape(topStart = 8.dp, bottomStart = 8.dp))
3131
.background(
3232
initialColor,
3333
shape = RoundedCornerShape(topStart = 8.dp, bottomStart = 8.dp)
@@ -44,4 +44,40 @@ fun ColorDisplayRoundedRect(
4444
)
4545
)
4646
}
47+
}
48+
49+
/**
50+
* Color display that displays both colors horizontally aligned with half [RoundedCornerShape]
51+
* with [Modifier.drawChecker] to display checker pattern when any color's alpha is less than 1.0f
52+
* @param boxSize size of left [Box] with [initialBrush] and size of right [Box] with [currentBrush]
53+
* @param initialBrush [Brush] that should be static
54+
* @param currentBrush [Brush] that is changed based on user actions
55+
*/
56+
@Composable
57+
fun ColorDisplayRoundedRect(
58+
modifier: Modifier,
59+
boxSize: DpSize,
60+
initialBrush: Brush,
61+
currentBrush: Brush
62+
) {
63+
Row() {
64+
Box(
65+
modifier = Modifier
66+
.size(boxSize)
67+
.drawChecker(RoundedCornerShape(topStart = 8.dp, bottomStart = 8.dp))
68+
.background(
69+
initialBrush,
70+
shape = RoundedCornerShape(topStart = 8.dp, bottomStart = 8.dp)
71+
)
72+
)
73+
Box(
74+
modifier = Modifier
75+
.size(boxSize)
76+
.drawChecker(RoundedCornerShape(topEnd = 8.dp, bottomEnd = 8.dp))
77+
.background(
78+
currentBrush,
79+
shape = RoundedCornerShape(topEnd = 8.dp, bottomEnd = 8.dp)
80+
)
81+
)
82+
}
4783
}

0 commit comments

Comments
 (0)