Skip to content

Commit 2e44270

Browse files
Fix hex conversion
1 parent b4944f7 commit 2e44270

File tree

8 files changed

+97
-63
lines changed

8 files changed

+97
-63
lines changed

README.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,18 @@ by [mchome's flutter_colorpicker for Flutter](https://github.com/mchome/flutter
2222
There are various selection of default color pickers and with selectors sliders, and hex displays
2323
it's possible to create new ones either.
2424

25-
| Hue Ring-Diamond HSL | Hue- Ring-Rect HSL | Hue Ring-Rect HSV| Hue-Circle HSV|
25+
| Hue Ring-Diamond HSL | Hue- Ring-Rect HSL | Hue Ring-Rect HSV| Hue-Hex HSV|
2626
| ----------|-----------| -----------| -----------|
27-
| <img src="./screenshots/colorpicker/cp_ring_diamond_hsl.png"/> | <img src="./screenshots/colorpicker/cp_ring_rect_hsl.png"/> | <img src="./screenshots/colorpicker/cp_ring_rect_hsv.png"/> | <img src="./screenshots/colorpicker/cp_circle_hue_saturation_hsv.png"/> |
27+
| <img src="./screenshots/colorpicker/cp_ring_diamond_hsl.png"/> | <img src="./screenshots/colorpicker/cp_ring_rect_hsl.png"/> | <img src="./screenshots/colorpicker/cp_ring_rect_hsv.png"/> | <img src="./screenshots/colorpicker/cp_ring_rect_hex_hsv.png"/> |
2828

29-
| Saturation-Value HSV | Saturation-Lightness HSL | Hue-Saturation HSV | Hue-Value HSV |
29+
| Saturation-Value HSV | Saturation-Lightness HSL | Hue-Circle HSV
30+
| ----------|-----------| -----------|
31+
| <img src="./screenshots/colorpicker/cp_rect_saturation_value_hsv.png"/> | <img src="./screenshots/colorpicker/cp_rect_saturation_lightness_hsl.png"/> | <img src="./screenshots/colorpicker/cp_circle_hue_saturation_hsv.png"/>
32+
33+
| Hue-Saturation HSV | Hue-Value HSV | Hue-Saturation HSL | Hue-Lightness HSL |
3034
| ----------|-----------| -----------| -----------|
31-
| <img src="./screenshots/colorpicker/cp_rect_saturation_value_hsv.png"/> | <img src="./screenshots/colorpicker/cp_rect_saturation_lightness_hsl.png"/> | <img src="./screenshots/colorpicker/cp_rect_hue_saturation_hsv.png"/> | <img src="./screenshots/colorpicker/cp_rect_hue_value_hsv.png"/> |
35+
| <img src="./screenshots/colorpicker/cp_rect_hue_saturation_hsv.png"/> | <img src="./screenshots/colorpicker/cp_rect_hue_value_hsv.png"/> | <img src="./screenshots/colorpicker/cp_rect_hue_saturation_hsl.png"/> | <img src="./screenshots/colorpicker/cp_rect_hue_lightness_hsl.png"/> |
3236

33-
| Hue-Saturation HSL | Hue-Lightness HSL |
34-
| ----------|-----------|
35-
| <img src="./screenshots/colorpicker/cp_rect_hue_saturation_hsl.png"/> | <img src="./screenshots/colorpicker/cp_rect_hue_lightness_hsl.png"/> |
3637

3738
#### Implementation Hue Ring-Diamond HSL, Hue- Ring-Rect HSL,Hue Ring-Rect HSV
3839

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.smarttoolfactory.composecolorpicker.demo
22

33
import androidx.compose.foundation.background
4-
import androidx.compose.foundation.border
54
import androidx.compose.foundation.layout.*
65
import androidx.compose.foundation.rememberScrollState
76
import androidx.compose.foundation.verticalScroll
@@ -10,12 +9,11 @@ import androidx.compose.runtime.*
109
import androidx.compose.ui.Alignment
1110
import androidx.compose.ui.Modifier
1211
import androidx.compose.ui.graphics.Color
13-
import androidx.compose.ui.text.TextStyle
1412
import androidx.compose.ui.text.font.FontWeight
1513
import androidx.compose.ui.unit.dp
1614
import androidx.compose.ui.unit.sp
1715
import com.smarttoolfactory.colorpicker.util.colorToHexAlpha
18-
import com.smarttoolfactory.colorpicker.widget.HexAlphaTextField
16+
import com.smarttoolfactory.colorpicker.widget.HexTextField
1917
import com.smarttoolfactory.composecolorpicker.ui.theme.backgroundColor
2018

2119
@Composable
@@ -45,7 +43,7 @@ fun HexConversionDemo() {
4543
)
4644
Spacer(modifier = Modifier.height(16.dp))
4745

48-
HexAlphaTextField(
46+
HexTextField(
4947
hexString = hexString,
5048

5149
onTextChange = {

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

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import com.smarttoolfactory.colorpicker.selector.SelectorRingHue
1212
import com.smarttoolfactory.colorpicker.slider.CompositeSliderPanel
1313
import com.smarttoolfactory.colorpicker.util.colorToHSV
1414
import com.smarttoolfactory.colorpicker.util.colorToHex
15-
import com.smarttoolfactory.colorpicker.widget.HexTextWithCircleDisplay
15+
import com.smarttoolfactory.colorpicker.widget.HexTextFieldWithCircleDisplay
1616

1717

1818
/**
@@ -41,18 +41,11 @@ fun ColorPickerRingRectHex(
4141
var saturation by remember { mutableStateOf(hsvArray[1]) }
4242
var value by remember { mutableStateOf(hsvArray[2]) }
4343

44-
var currentColor by remember(hue, saturation, value) {
45-
mutableStateOf(
46-
Color.hsv(
47-
hue = hue,
48-
saturation = saturation,
49-
value = value
50-
)
51-
)
52-
}
53-
54-
var hexString by remember(currentColor) { mutableStateOf(colorToHex(currentColor)) }
55-
44+
val currentColor = Color.hsv(
45+
hue = hue,
46+
saturation = saturation,
47+
value = value
48+
)
5649

5750
onColorChange(currentColor, colorToHex(currentColor))
5851

@@ -92,18 +85,14 @@ fun ColorPickerRingRectHex(
9285
}
9386
}
9487

95-
HexTextWithCircleDisplay(
96-
modifier =Modifier.padding(8.dp),
88+
HexTextFieldWithCircleDisplay(
89+
modifier = Modifier.padding(8.dp),
9790
color = currentColor,
98-
hexString = hexString,
99-
onTextChange = {
100-
hexString = it
101-
}, onColorChange = {
91+
onColorChange = {
10292
val hsvArrayNew = colorToHSV(it)
10393
hue = hsvArrayNew[0]
10494
saturation = hsvArrayNew[1]
10595
value = hsvArrayNew[2]
106-
currentColor = it
10796
}
10897
)
10998
}

colorpicker/src/main/java/com/smarttoolfactory/colorpicker/util/HexConversionUtil.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import androidx.compose.ui.graphics.Color
77
*/
88
fun hexToColorInt(colorString: String): Int {
99
val completeColorString = if (colorString.first() == '#') colorString else "#$colorString"
10-
println("🌈 hexToColor: $colorString, completeColorString: $completeColorString")
1110
return android.graphics.Color.parseColor(completeColorString)
1211
}
1312

colorpicker/src/main/java/com/smarttoolfactory/colorpicker/util/RGBConversionUtil.kt

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -220,9 +220,10 @@ fun rgbToHex(
220220
green: Int,
221221
blue: Int
222222
): String {
223-
return "#${Integer.toHexString(red)}" +
224-
Integer.toHexString(green) +
225-
Integer.toHexString(blue)
223+
return "#" +
224+
Integer.toHexString(red).toStringComponent() +
225+
Integer.toHexString(green).toStringComponent() +
226+
Integer.toHexString(blue).toStringComponent()
226227
}
227228

228229
/**
@@ -234,9 +235,10 @@ fun rgbToHex(
234235
* ```
235236
*/
236237
fun rgbToHex(rgb: IntArray): String {
237-
return "#${Integer.toHexString(rgb[0])}" +
238-
Integer.toHexString(rgb[1]) +
239-
Integer.toHexString(rgb[2])
238+
return "#" +
239+
Integer.toHexString(rgb[0]).toStringComponent() +
240+
Integer.toHexString(rgb[1]).toStringComponent() +
241+
Integer.toHexString(rgb[2]).toStringComponent()
240242
}
241243

242244
/**
@@ -247,9 +249,10 @@ fun rgbToHex(
247249
green: Float,
248250
blue: Float
249251
): String {
250-
return "#${Integer.toHexString(red.fractionToRGBRange())}" +
251-
Integer.toHexString(green.fractionToRGBRange()) +
252-
Integer.toHexString(blue.fractionToRGBRange())
252+
return "#" +
253+
Integer.toHexString(red.fractionToRGBRange()).toStringComponent() +
254+
Integer.toHexString(green.fractionToRGBRange()).toStringComponent() +
255+
Integer.toHexString(blue.fractionToRGBRange()).toStringComponent()
253256
}
254257

255258

@@ -311,10 +314,11 @@ fun argbToHex(
311314
green: Int,
312315
blue: Int
313316
): String {
314-
return "#${Integer.toHexString(alpha)}" +
315-
Integer.toHexString(red) +
316-
Integer.toHexString(green) +
317-
Integer.toHexString(blue)
317+
return "#" +
318+
Integer.toHexString(alpha).toStringComponent() +
319+
Integer.toHexString(red).toStringComponent() +
320+
Integer.toHexString(green).toStringComponent() +
321+
Integer.toHexString(blue).toStringComponent()
318322
}
319323

320324
/**
@@ -333,10 +337,11 @@ fun argbToHex(
333337
green: Float,
334338
blue: Float
335339
): String {
336-
return "#${Integer.toHexString(alpha.fractionToRGBRange())}" +
337-
Integer.toHexString(red.fractionToRGBRange()) +
338-
Integer.toHexString(green.fractionToRGBRange()) +
339-
Integer.toHexString(blue.fractionToRGBRange())
340+
return "#" +
341+
Integer.toHexString(alpha.fractionToRGBRange()).toStringComponent() +
342+
Integer.toHexString(red.fractionToRGBRange()).toStringComponent() +
343+
Integer.toHexString(green.fractionToRGBRange()).toStringComponent() +
344+
Integer.toHexString(blue.fractionToRGBRange()).toStringComponent()
340345
}
341346

342347
/*
@@ -363,6 +368,9 @@ fun Int.toArgbString(): String =
363368
blue.toStringComponent()
364369
).uppercase(Locale.getDefault())
365370

371+
private fun String.toStringComponent() =
372+
this.let { if (it.length == 1) "0${it}" else it }
373+
366374
private fun Int.toStringComponent(): String =
367375
this.toString(16).let { if (it.length == 1) "0${it}" else it }
368376

colorpicker/src/main/java/com/smarttoolfactory/colorpicker/widget/HexText.kt renamed to colorpicker/src/main/java/com/smarttoolfactory/colorpicker/widget/HexTextField.kt

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,22 @@ import androidx.compose.ui.unit.dp
2222
import androidx.compose.ui.unit.sp
2323
import com.smarttoolfactory.colorpicker.ui.Grey400
2424
import com.smarttoolfactory.colorpicker.ui.Red400
25+
import com.smarttoolfactory.colorpicker.util.hexRegex
2526
import com.smarttoolfactory.colorpicker.util.hexRegexSingleChar
2627
import com.smarttoolfactory.colorpicker.util.hexToColor
2728
import com.smarttoolfactory.colorpicker.util.hexWithAlphaRegex
2829

30+
/**
31+
* [TextField] that displays color in hex representation either with #RRGGBB or ##AARRGGBB
32+
* depending on [useAlpha] flag.
33+
*
34+
* @param hexString
35+
* @param useAlpha
36+
* @param onTextChange
37+
* @param onColorChange
38+
*/
2939
@Composable
30-
fun HexAlphaTextField(
40+
fun HexTextField(
3141
modifier: Modifier = Modifier,
3242
hexString: String,
3343
textStyle: TextStyle = TextStyle(fontSize = 24.sp),
@@ -37,21 +47,23 @@ fun HexAlphaTextField(
3747
unfocusedIndicatorColor = Color.Transparent
3848
),
3949
shape: Shape = RoundedCornerShape(25),
50+
useAlpha: Boolean = false,
4051
onTextChange: (String) -> Unit,
4152
onColorChange: (Color) -> Unit
4253
) {
54+
val hex = if (useAlpha) hexWithAlphaRegex else hexRegex
4355
OutlinedTextField(
4456
modifier = modifier
4557
.widthIn(min = 80.dp)
4658
.drawBehind {
4759
drawLine(
48-
if (hexWithAlphaRegex.matches(hexString)) Grey400 else Red400,
60+
if (hex.matches(hexString)) Grey400 else Red400,
4961
start = Offset(0f, size.height),
5062
end = Offset(size.width, size.height),
5163
strokeWidth = 5f
5264
)
5365
},
54-
visualTransformation = HexVisualTransformation(),
66+
visualTransformation = HexVisualTransformation(useAlpha),
5567
textStyle = textStyle,
5668
colors = colors,
5769
shape = shape,
@@ -60,7 +72,7 @@ fun HexAlphaTextField(
6072
value = hexString.removePrefix("#"),
6173
onValueChange = {
6274

63-
if (it.length <= 8) {
75+
if (it.length <= if (useAlpha) 8 else 6) {
6476
if (it.isNotEmpty()) {
6577
val lastChar = it.last()
6678
val isHexChar = hexRegexSingleChar.matches(lastChar.toString())
@@ -72,7 +84,7 @@ fun HexAlphaTextField(
7284
}
7385

7486
// Hex String with 6 or 8 chars matches a Color
75-
if (hexWithAlphaRegex.matches(it)) {
87+
if (hex.matches(it)) {
7688
onColorChange(hexToColor(it))
7789
}
7890
}
@@ -125,23 +137,47 @@ private fun BasicHexTextField(
125137
}
126138
}
127139

128-
private class HexVisualTransformation : VisualTransformation {
140+
private class HexVisualTransformation(private val useAlpha: Boolean) : VisualTransformation {
129141

130142
override fun filter(text: AnnotatedString): TransformedText {
131143

132-
val trimmed = if (text.text.length >= 8) text.text.substring(0..7) else text.text
144+
val limit = if (useAlpha) 8 else 6
145+
146+
val trimmed =
147+
if (text.text.length >= limit) text.text.substring(0 until limit) else text.text
133148

134149
val output = if (trimmed.isEmpty()) {
135150
trimmed
136151
} else {
137152
"#${trimmed.uppercase()}"
138153
}
139154

140-
return TransformedText(AnnotatedString(output), hexOffsetMapping)
155+
return TransformedText(
156+
AnnotatedString(output),
157+
if (useAlpha) hexAlphaOffsetMapping else hexOffsetMapping
158+
)
141159
}
142160

143161
private val hexOffsetMapping = object : OffsetMapping {
144162

163+
override fun originalToTransformed(offset: Int): Int {
164+
165+
// when empty return only 1 char for #
166+
if (offset == 0) return offset
167+
if (offset <= 5) return offset + 1
168+
return 7
169+
}
170+
171+
override fun transformedToOriginal(offset: Int): Int {
172+
if (offset == 0) return offset
173+
// #ABCABC
174+
if (offset <= 6) return offset - 1
175+
return 6
176+
}
177+
}
178+
179+
private val hexAlphaOffsetMapping = object : OffsetMapping {
180+
145181
override fun originalToTransformed(offset: Int): Int {
146182

147183
// when empty return only 1 char for #
Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,24 @@
11
package com.smarttoolfactory.colorpicker.widget
22

33
import androidx.compose.foundation.layout.*
4-
import androidx.compose.runtime.Composable
4+
import androidx.compose.runtime.*
55
import androidx.compose.ui.Alignment
66
import androidx.compose.ui.Modifier
77
import androidx.compose.ui.graphics.Color
88
import androidx.compose.ui.unit.dp
99
import com.smarttoolfactory.colorpicker.slider.CircleDisplay
10+
import com.smarttoolfactory.colorpicker.util.colorToHex
1011

1112
@Composable
12-
fun HexTextWithCircleDisplay(
13+
fun HexTextFieldWithCircleDisplay(
1314
modifier: Modifier = Modifier,
1415
circleModifier: Modifier = Modifier,
1516
color: Color,
16-
hexString: String,
17-
onTextChange: (String) -> Unit,
1817
onColorChange: (Color) -> Unit
1918
) {
2019

20+
var hexString by remember(color) { mutableStateOf(colorToHex(color)) }
21+
2122
Row(
2223
modifier = modifier.requiredHeightIn(min = 100.dp),
2324
verticalAlignment = Alignment.CenterVertically
@@ -30,10 +31,12 @@ fun HexTextWithCircleDisplay(
3031
color = color
3132
)
3233
Spacer(modifier = Modifier.width(10.dp))
33-
HexAlphaTextField(
34+
HexTextField(
3435
modifier = Modifier.weight(1f),
3536
hexString = hexString,
36-
onTextChange = onTextChange,
37+
onTextChange = {
38+
hexString = it
39+
},
3740
onColorChange = onColorChange
3841
)
3942
}
248 KB
Loading

0 commit comments

Comments
 (0)