Skip to content

Commit 57301c5

Browse files
add HexTextFieldWithClipboard
1 parent 1c00735 commit 57301c5

File tree

11 files changed

+636
-124
lines changed

11 files changed

+636
-124
lines changed

app/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ dependencies {
6363
implementation "androidx.compose.material:material:$compose_version"
6464
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
6565

66+
6667
def accompanist_version = "0.24.6-alpha"
6768
// Accompanist
6869
implementation "com.google.accompanist:accompanist-systemuicontroller:$accompanist_version"

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -663,7 +663,7 @@ private fun DialogMaterial3(
663663
backgroundColor = Color.Transparent
664664
)
665665
) {
666-
Text(text = "Material Design2 Dialog")
666+
Text(text = "Material Design3 Dialog")
667667
}
668668

669669
if (showDialog) {

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

Lines changed: 61 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import androidx.compose.ui.text.font.FontWeight
1313
import androidx.compose.ui.unit.dp
1414
import androidx.compose.ui.unit.sp
1515
import com.smarttoolfactory.colorpicker.widget.HexTextField
16+
import com.smarttoolfactory.colorpicker.widget.HexTextFieldWithClipboard
17+
import com.smarttoolfactory.colorpicker.widget.HexTextFieldWithLabelClipboard
1618
import com.smarttoolfactory.composecolorpicker.ui.theme.backgroundColor
1719
import com.smarttoolfactory.extendedcolors.util.ColorUtil
1820

@@ -27,29 +29,75 @@ fun HexConversionDemo() {
2729
horizontalAlignment = Alignment.CenterHorizontally
2830
) {
2931

30-
var color by remember {
31-
mutableStateOf(
32-
Color.hsl(0f, 0.5f, 0.5f)
33-
)
34-
}
32+
var color1 by remember { mutableStateOf(Color.hsl(0f, 0.5f, 0.5f)) }
33+
var hexString1 by remember { mutableStateOf(ColorUtil.colorToHexAlpha(color1)) }
3534

36-
var hexString by remember { mutableStateOf(ColorUtil.colorToHexAlpha(color)) }
35+
var color2 by remember { mutableStateOf(Color.hsl(0f, 0.5f, 0.5f)) }
36+
var hexString2 by remember { mutableStateOf(ColorUtil.colorToHexAlpha(color2)) }
37+
38+
var color3 by remember { mutableStateOf(Color.hsl(0f, 0.5f, 0.5f)) }
39+
var hexString3 by remember { mutableStateOf(ColorUtil.colorToHex(color3)) }
40+
41+
Spacer(modifier = Modifier.height(50.dp))
3742

3843
Text(
39-
"HEX: $hexString",
40-
color = color,
44+
"HEX: $hexString1",
45+
color = color1,
4146
fontWeight = FontWeight.Bold,
4247
fontSize = 30.sp
4348
)
44-
Spacer(modifier = Modifier.height(16.dp))
49+
50+
Spacer(modifier = Modifier.height(10.dp))
4551

4652
HexTextField(
47-
hexString = hexString,
53+
hexString = hexString1,
54+
useAlpha = true,
55+
onTextChange = {
56+
hexString1 = it
57+
},
58+
onColorChange = {
59+
color1 = it
60+
}
61+
)
62+
63+
Spacer(modifier = Modifier.height(30.dp))
64+
Text(
65+
"HEX: $hexString2",
66+
color = color2,
67+
fontWeight = FontWeight.Bold,
68+
fontSize = 30.sp
69+
)
70+
71+
Spacer(modifier = Modifier.height(10.dp))
72+
73+
HexTextFieldWithClipboard(
74+
hexString = hexString2,
4875
useAlpha = true,
4976
onTextChange = {
50-
hexString = it
51-
}, onColorChange = {
52-
color = it
77+
hexString2 = it
78+
},
79+
onColorChange = {
80+
color2 = it
81+
}
82+
)
83+
84+
Spacer(modifier = Modifier.height(30.dp))
85+
Text(
86+
"HEX: $hexString3",
87+
color = color3,
88+
fontWeight = FontWeight.Bold,
89+
fontSize = 30.sp
90+
)
91+
92+
Spacer(modifier = Modifier.height(10.dp))
93+
94+
HexTextFieldWithLabelClipboard(
95+
hexString = hexString3,
96+
onTextChange = {
97+
hexString3 = it
98+
},
99+
onColorChange = {
100+
color3 = it
53101
}
54102
)
55103
}

colorpicker/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ dependencies {
5858
implementation "androidx.compose.material:material:$compose_version"
5959
implementation "androidx.compose.runtime:runtime:$compose_version"
6060
implementation "androidx.compose.material:material-icons-extended:$compose_version"
61+
implementation "androidx.compose.material3:material3:1.0.0-alpha12"
6162

6263
testImplementation 'junit:junit:4.13.2'
6364
androidTestImplementation 'androidx.test.ext:junit:1.1.3'

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

Lines changed: 8 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,31 @@
11
package com.smarttoolfactory.colorpicker.picker
22

3-
import android.widget.Toast
43
import androidx.compose.foundation.background
54
import androidx.compose.foundation.clickable
65
import androidx.compose.foundation.layout.*
76
import androidx.compose.foundation.lazy.grid.GridCells
87
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
98
import androidx.compose.foundation.lazy.grid.itemsIndexed
109
import androidx.compose.foundation.shape.RoundedCornerShape
11-
import androidx.compose.material.*
10+
import androidx.compose.material.Icon
11+
import androidx.compose.material.Tab
12+
import androidx.compose.material.TabRow
13+
import androidx.compose.material.Text
1214
import androidx.compose.material.icons.Icons
1315
import androidx.compose.material.icons.filled.Check
14-
import androidx.compose.material.icons.filled.ContentCopy
1516
import androidx.compose.runtime.*
1617
import androidx.compose.ui.Alignment
1718
import androidx.compose.ui.Modifier
1819
import androidx.compose.ui.draw.clip
1920
import androidx.compose.ui.graphics.Color
2021
import androidx.compose.ui.platform.LocalClipboardManager
2122
import androidx.compose.ui.platform.LocalContext
22-
import androidx.compose.ui.text.AnnotatedString
2323
import androidx.compose.ui.text.font.FontWeight
2424
import androidx.compose.ui.text.style.TextAlign
2525
import androidx.compose.ui.unit.dp
2626
import androidx.compose.ui.unit.sp
27+
import com.smarttoolfactory.colordetector.ColorData
28+
import com.smarttoolfactory.colorpicker.widget.ColorDisplayWithClipboard
2729
import com.smarttoolfactory.extendedcolors.ColorSwatch
2830
import com.smarttoolfactory.extendedcolors.parser.rememberColorParser
2931
import com.smarttoolfactory.extendedcolors.util.ColorUtil
@@ -37,10 +39,6 @@ import kotlinx.coroutines.flow.mapLatest
3739

3840
@Composable
3941
fun M3ColorPicker(onColorChange: (Color) -> Unit) {
40-
41-
val clipboardManager = LocalClipboardManager.current
42-
val context = LocalContext.current
43-
4442
Column(
4543
modifier = Modifier
4644
.fillMaxSize()
@@ -209,11 +207,7 @@ fun M3ColorPicker(onColorChange: (Color) -> Unit) {
209207
onColorChange(item)
210208
}
211209

212-
213210
Spacer(modifier = Modifier.height(30.dp))
214-
val lightness = ColorUtil.colorToHSL(currentColor)[2]
215-
val textColor = if (lightness < .6f) Color.White else Color.Black
216-
217211

218212
Text(
219213
text = colorName,
@@ -226,33 +220,8 @@ fun M3ColorPicker(onColorChange: (Color) -> Unit) {
226220
color = Color.White
227221
)
228222

229-
230-
Row(
231-
modifier = Modifier
232-
.padding(8.dp)
233-
.background(color = currentColor, RoundedCornerShape(50))
234-
.padding(horizontal = 20.dp, vertical = 10.dp),
235-
verticalAlignment = Alignment.CenterVertically
236-
) {
237-
238-
val hexText = ColorUtil.colorToHex(color = currentColor)
239-
Text(
240-
text = hexText,
241-
fontSize = 24.sp,
242-
color = textColor
243-
)
244-
Spacer(modifier = Modifier.width(20.dp))
245-
IconButton(onClick = {
246-
Toast.makeText(context, "Copied $hexText", Toast.LENGTH_SHORT).show()
247-
clipboardManager.setText(AnnotatedString(hexText))
248-
}) {
249-
Icon(
250-
tint = textColor,
251-
imageVector = Icons.Default.ContentCopy,
252-
contentDescription = "clipboard"
253-
)
254-
}
255-
}
223+
Spacer(modifier = Modifier.height(20.dp))
224+
ColorDisplayWithClipboard(colorData = ColorData(currentColor, colorName))
256225
}
257226
}
258227

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.smarttoolfactory.colorpicker.util
2+
3+
// Regex for checking if this string is a 6 char hex or 8 char hex
4+
val hexWithAlphaRegex = "^#?([0-9a-fA-F]{6}|[0-9a-fA-F]{8})\$".toRegex()
5+
val hexRegex = "^#?([0-9a-fA-F]{6})\$".toRegex()
6+
7+
// Check only on char if it's in range of 0-9, a-f, A-F
8+
val hexRegexSingleChar = "[a-fA-F0-9]".toRegex()
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package com.smarttoolfactory.colorpicker.util
2+
3+
import androidx.compose.ui.text.AnnotatedString
4+
import androidx.compose.ui.text.input.OffsetMapping
5+
import androidx.compose.ui.text.input.TransformedText
6+
import androidx.compose.ui.text.input.VisualTransformation
7+
8+
class HexVisualTransformation(private val useAlpha: Boolean) : VisualTransformation {
9+
10+
override fun filter(text: AnnotatedString): TransformedText {
11+
12+
val limit = if (useAlpha) 8 else 6
13+
14+
val trimmed =
15+
if (text.text.length >= limit) text.text.substring(0 until limit) else text.text
16+
17+
val output = if (trimmed.isEmpty()) {
18+
trimmed
19+
} else {
20+
if (!useAlpha || trimmed.length < 7) {
21+
"#${trimmed.uppercase()}"
22+
} else {
23+
"#${
24+
trimmed.substring(0, 2).lowercase() +
25+
trimmed.substring(2, trimmed.length).uppercase()
26+
}"
27+
}
28+
}
29+
30+
return TransformedText(
31+
AnnotatedString(output),
32+
if (useAlpha) hexAlphaOffsetMapping else hexOffsetMapping
33+
)
34+
}
35+
36+
private val hexOffsetMapping = object : OffsetMapping {
37+
38+
override fun originalToTransformed(offset: Int): Int {
39+
40+
// when empty return only 1 char for #
41+
if (offset == 0) return offset
42+
if (offset <= 5) return offset + 1
43+
return 7
44+
}
45+
46+
override fun transformedToOriginal(offset: Int): Int {
47+
if (offset == 0) return offset
48+
// #ABCABC
49+
if (offset <= 6) return offset - 1
50+
return 6
51+
}
52+
}
53+
54+
private val hexAlphaOffsetMapping = object : OffsetMapping {
55+
56+
override fun originalToTransformed(offset: Int): Int {
57+
58+
// when empty return only 1 char for #
59+
if (offset == 0) return offset
60+
if (offset <= 7) return offset + 1
61+
return 9
62+
}
63+
64+
override fun transformedToOriginal(offset: Int): Int {
65+
if (offset == 0) return offset
66+
// #ffABCABC
67+
if (offset <= 8) return offset - 1
68+
return 8
69+
}
70+
}
71+
}

0 commit comments

Comments
 (0)