Skip to content

Commit 5f54378

Browse files
authored
Merge pull request #12 from KvColorPalette/feature/blend-color-picker
Feature/blend color picker
2 parents def8ec0 + 698177d commit 5f54378

File tree

11 files changed

+285
-25
lines changed

11 files changed

+285
-25
lines changed

README.md

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,13 @@ Add the following dependency to your `build.gradle` / `build.gradle.kts` file:
3333
For Groovy - `build.gradle`:
3434
````
3535
dependencies {
36-
implementation 'com.github.KvColorPalette:KvColorPicker-Android:2.2.0'
36+
implementation 'com.github.KvColorPalette:KvColorPicker-Android:3.0.0'
3737
}
3838
````
3939
For Kotlin DSL - `build.gradle.kts`:
4040
````
4141
dependencies {
42-
implementation("com.github.KvColorPalette:KvColorPicker-Android:2.2.0")
42+
implementation("com.github.KvColorPalette:KvColorPicker-Android:3.0.0")
4343
}
4444
````
4545

@@ -74,9 +74,9 @@ if (showSheet.value) {
7474
}
7575
```
7676
#### The way it works
77-
|RGB-A Picker |GRID Picker |HSL-A Picker |
78-
|-------------|------------|--------------|
79-
|![](images/RGB-A-Picker.gif) |![](images/GRID-Picker.gif) |![](images/HSL-A-Picker.gif) |
77+
|RGB-A Picker |GRID Picker |HSL-A Picker | BLEND Picker |
78+
|-------------|------------|--------------|------------------------------|
79+
|![](images/RGB-A-Picker.gif) |![](images/GRID-Picker.gif) |![](images/HSL-A-Picker.gif) | ![](images/BLEND-Picker.gif) |
8080

8181
### Use color picker UI components in existing UI
8282
Developer can add the each color picker (`RGB-A Picker`, `Grid Picker` and `HSL-A Picker`) separately in their own UI. Because `KvColorPicker-Android`
@@ -109,6 +109,16 @@ HSLAColorPicker(
109109
)
110110
```
111111

112+
#### BLEND Picker
113+
```
114+
BlendColorPicker(
115+
modifier = Modifier,
116+
onColorSelected = { selectedColor ->
117+
// Action with selected color
118+
}
119+
)
120+
```
121+
112122
# Contribution
113123
We welcome contributions! Please fork the repository, make your changes, and submit a pull request. Ensure your code adheres to the established guidelines.
114124

images/BLEND-Picker.gif

2.51 MB
Loading

kv-color-picker/gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
kvColorPaletteGroupId=com.github.KvColorPalette
22
kvColorPickerArtifactId=KvColorPicker-Android
3-
kvColorPickerVersion=2.2.0
3+
kvColorPickerVersion=3.0.0

kv-color-picker/src/main/kotlin/com/kavi/droid/color/picker/ui/KvColorPickerBottomSheet.kt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import androidx.compose.ui.unit.sp
3636
import com.kavi.droid.color.palette.util.ColorUtil
3737
import com.kavi.droid.color.picker.R
3838
import com.kavi.droid.color.picker.ui.common.SelectedColorDetail
39+
import com.kavi.droid.color.picker.ui.pickers.BlendColorPicker
3940
import com.kavi.droid.color.picker.ui.pickers.GridColorPicker
4041
import com.kavi.droid.color.picker.ui.pickers.HSLAColorPicker
4142
import com.kavi.droid.color.picker.ui.pickers.RGBAColorPicker
@@ -76,7 +77,8 @@ fun KvColorPickerBottomSheet(
7677
val tabs = listOf(
7778
stringResource(R.string.label_rgba),
7879
stringResource(R.string.label_grid),
79-
stringResource(R.string.label_hsla)
80+
stringResource(R.string.label_hsla),
81+
stringResource(R.string.label_blend)
8082
)
8183

8284
Text(
@@ -142,6 +144,13 @@ fun KvColorPickerBottomSheet(
142144
colorHex.value = TextFieldValue(ColorUtil.getHex(it))
143145
}
144146
)
147+
3 -> BlendColorPicker(
148+
modifier = Modifier.padding(16.dp),
149+
onColorSelected = {
150+
selectedColor = it
151+
colorHex.value = TextFieldValue(ColorUtil.getHex(it))
152+
}
153+
)
145154
}
146155

147156
Column (
Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
package com.kavi.droid.color.picker.ui.pickers
2+
3+
import androidx.compose.foundation.background
4+
import androidx.compose.foundation.border
5+
import androidx.compose.foundation.layout.Arrangement
6+
import androidx.compose.foundation.layout.Box
7+
import androidx.compose.foundation.layout.Column
8+
import androidx.compose.foundation.layout.Row
9+
import androidx.compose.foundation.layout.Spacer
10+
import androidx.compose.foundation.layout.fillMaxWidth
11+
import androidx.compose.foundation.layout.height
12+
import androidx.compose.foundation.layout.padding
13+
import androidx.compose.foundation.layout.size
14+
import androidx.compose.foundation.layout.width
15+
import androidx.compose.foundation.shape.RoundedCornerShape
16+
import androidx.compose.material3.Icon
17+
import androidx.compose.material3.MaterialTheme
18+
import androidx.compose.material3.Slider
19+
import androidx.compose.material3.Text
20+
import androidx.compose.runtime.Composable
21+
import androidx.compose.runtime.LaunchedEffect
22+
import androidx.compose.runtime.derivedStateOf
23+
import androidx.compose.runtime.getValue
24+
import androidx.compose.runtime.mutableFloatStateOf
25+
import androidx.compose.runtime.mutableStateOf
26+
import androidx.compose.runtime.remember
27+
import androidx.compose.runtime.setValue
28+
import androidx.compose.ui.Alignment
29+
import androidx.compose.ui.Modifier
30+
import androidx.compose.ui.draw.shadow
31+
import androidx.compose.ui.graphics.Color
32+
import androidx.compose.ui.res.painterResource
33+
import androidx.compose.ui.res.stringResource
34+
import androidx.compose.ui.text.style.TextAlign
35+
import androidx.compose.ui.unit.dp
36+
import androidx.compose.ui.unit.sp
37+
import com.kavi.droid.color.palette.extension.hsl
38+
import com.kavi.droid.color.palette.util.ColorUtil
39+
import com.kavi.droid.color.picker.R
40+
import com.kavi.droid.color.picker.ui.common.SliderHue
41+
42+
/**
43+
* A composable function that creates a color picker UI to select color by selecting two colors and blend.
44+
* This component contains two color spectrum(s) to select first and second color to blend and one slider, that consumer
45+
* can change how blended color bias to first or second color.
46+
* By selecting first and second color then by adjusting color bias value, consumer can select or generate their desired color.
47+
*
48+
* @param modifier: Modifier: The modifier to apply to this layout.
49+
* @param onColorSelected: (selectedColor: Color) -> Unit: Callback to invoke when a color is selected.
50+
*
51+
* @return @Composable: A color picker UI for selecting blended color.
52+
*/
53+
@Composable
54+
fun BlendColorPicker(
55+
modifier: Modifier = Modifier,
56+
onColorSelected: (selectedColor: Color) -> Unit
57+
) {
58+
// State variables for first color hue and second color hue
59+
val firstHue = remember { mutableFloatStateOf(Color.White.hsl.hue) }
60+
val secondHue = remember { mutableFloatStateOf(Color.White.hsl.hue) }
61+
62+
val firstBlendColor = remember { mutableStateOf(Color.White) }
63+
val firstBlendColorHex = remember { mutableStateOf(ColorUtil.getHex(Color.White)) }
64+
val secondBlendColor = remember { mutableStateOf(Color.White) }
65+
val secondBlendColorHex = remember { mutableStateOf(ColorUtil.getHex(Color.White)) }
66+
67+
var colorBias by remember { mutableFloatStateOf(.5f) }
68+
69+
// Derived state for the color based on blending selected first and second color
70+
val color by remember {
71+
derivedStateOf {
72+
ColorUtil.blendColors(firstBlendColor.value, secondBlendColor.value, bias = colorBias)
73+
}
74+
}
75+
76+
// Launch an effect to invoke the provided callback with the selected color
77+
LaunchedEffect(color) {
78+
onColorSelected.invoke(color)
79+
}
80+
81+
Column (modifier = modifier, verticalArrangement = Arrangement.spacedBy(8.dp)) {
82+
Column (
83+
modifier = Modifier
84+
.border(1.dp, Color.White, shape = RoundedCornerShape(8.dp))
85+
.shadow(
86+
elevation = 10.dp,
87+
shape = RoundedCornerShape(8.dp)
88+
)
89+
.background(Color.White)
90+
.padding(start = 12.dp, end = 12.dp, top = 12.dp, bottom = 12.dp)
91+
) {
92+
93+
Text(
94+
text = stringResource(R.string.phrase_select_color_blend),
95+
textAlign = TextAlign.Start,
96+
modifier = Modifier
97+
.fillMaxWidth().padding(start = 12.dp, end = 12.dp, top = 12.dp),
98+
color = Color.Gray,
99+
style = MaterialTheme.typography.bodySmall,
100+
fontSize = 12.sp
101+
)
102+
103+
Row (
104+
modifier = Modifier
105+
.padding(top = 8.dp)
106+
.fillMaxWidth(),
107+
verticalAlignment = Alignment.CenterVertically,
108+
horizontalArrangement = Arrangement.Center
109+
) {
110+
Column(
111+
modifier = Modifier.weight(.5f),
112+
horizontalAlignment = Alignment.CenterHorizontally,
113+
verticalArrangement = Arrangement.Center
114+
) {
115+
SliderHue(Modifier.padding(top = 4.dp, bottom = 4.dp), onColorSelect = { selectedColor ->
116+
firstHue.floatValue = selectedColor.hsl.hue
117+
firstBlendColor.value = selectedColor
118+
firstBlendColorHex.value = ColorUtil.getHex(selectedColor)
119+
})
120+
121+
Text(text = firstBlendColorHex.value)
122+
}
123+
124+
Spacer(modifier = Modifier.width(8.dp))
125+
126+
Column(
127+
modifier = Modifier.weight(.5f),
128+
horizontalAlignment = Alignment.CenterHorizontally,
129+
verticalArrangement = Arrangement.Center
130+
) {
131+
SliderHue(Modifier.padding(top = 4.dp, bottom = 4.dp), onColorSelect = { selectedColor ->
132+
secondHue.floatValue = selectedColor.hsl.hue
133+
secondBlendColor.value = selectedColor
134+
secondBlendColorHex.value = ColorUtil.getHex(selectedColor)
135+
})
136+
137+
Text(text = secondBlendColorHex.value)
138+
}
139+
}
140+
141+
Row (
142+
modifier = Modifier
143+
.padding(top = 8.dp)
144+
.fillMaxWidth(),
145+
verticalAlignment = Alignment.CenterVertically,
146+
horizontalArrangement = Arrangement.Center
147+
) {
148+
Column(
149+
modifier = Modifier
150+
.weight(.2f),
151+
horizontalAlignment = Alignment.Start,
152+
verticalArrangement = Arrangement.Center
153+
) {
154+
Box(
155+
modifier = Modifier
156+
.padding(4.dp)
157+
.height(50.dp)
158+
.width(50.dp)
159+
.background(
160+
firstBlendColor.value,
161+
shape = MaterialTheme.shapes.large
162+
)
163+
.border(
164+
2.dp,
165+
MaterialTheme.colorScheme.primary,
166+
RoundedCornerShape(12.dp)
167+
)
168+
)
169+
}
170+
171+
Spacer(modifier = Modifier.width(4.dp))
172+
173+
Row (
174+
modifier = Modifier.weight(.7f),
175+
verticalAlignment = Alignment.CenterVertically
176+
) {
177+
Icon(
178+
painter = painterResource(R.drawable.icon_left_arrow),
179+
contentDescription = "Left arrow",
180+
Modifier
181+
.weight(.25f)
182+
.size(40.dp)
183+
)
184+
185+
Slider(
186+
modifier = Modifier
187+
.height(50.dp)
188+
.weight(.7f),
189+
value = colorBias,
190+
valueRange = 0f..1f,
191+
onValueChange = {
192+
colorBias = it
193+
},
194+
)
195+
Icon(
196+
painter = painterResource(R.drawable.icon_right_arrow),
197+
contentDescription = "Right arrow",
198+
Modifier
199+
.weight(.25f)
200+
.size(40.dp)
201+
)
202+
}
203+
204+
Spacer(modifier = Modifier.width(4.dp))
205+
206+
Column(
207+
modifier = Modifier
208+
.weight(.2f),
209+
horizontalAlignment = Alignment.End,
210+
verticalArrangement = Arrangement.Center
211+
) {
212+
Box(
213+
modifier = Modifier
214+
.padding(4.dp)
215+
.height(50.dp)
216+
.width(50.dp)
217+
.background(
218+
secondBlendColor.value,
219+
shape = MaterialTheme.shapes.large
220+
)
221+
.border(
222+
2.dp,
223+
MaterialTheme.colorScheme.primary,
224+
RoundedCornerShape(12.dp)
225+
)
226+
)
227+
}
228+
}
229+
}
230+
}
231+
}

kv-color-picker/src/main/kotlin/com/kavi/droid/color/picker/ui/pickers/GridColorPicker.kt

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,15 @@ import androidx.compose.ui.Modifier
2323
import androidx.compose.ui.draw.shadow
2424
import androidx.compose.ui.graphics.Color
2525
import androidx.compose.ui.res.stringResource
26-
import androidx.compose.ui.text.input.TextFieldValue
2726
import androidx.compose.ui.text.style.TextAlign
2827
import androidx.compose.ui.unit.dp
2928
import androidx.compose.ui.unit.sp
3029
import com.kavi.droid.color.palette.color.MatPackage
31-
import com.kavi.droid.color.palette.util.ColorUtil
3230
import com.kavi.droid.color.picker.R
3331
import com.kavi.droid.color.picker.ui.common.ColorColum
3432

3533
/**
36-
* A composable function that creates a grid grid to select colors. This color grid is created with
34+
* A composable function that creates a grid to select colors. This color grid is created with
3735
* 16 predefined major colors and those color's 10 color variances.
3836
*
3937
* @param modifier: Modifier: The modifier to apply to this layout.
@@ -51,11 +49,9 @@ fun GridColorPicker(
5149
) {
5250

5351
var selectedColor by remember { mutableStateOf(lastSelectedColor) }
54-
val colorHex = remember { mutableStateOf(TextFieldValue(ColorUtil.getHex(lastSelectedColor))) }
5552

5653
val onSelectColor: (color: Color) -> Unit = {
5754
selectedColor = it
58-
colorHex.value = TextFieldValue(ColorUtil.getHex(it))
5955
}
6056

6157
// Launch an effect to invoke the provided callback with the selected color

kv-color-picker/src/main/kotlin/com/kavi/droid/color/picker/ui/pickers/HSLAColorPicker.kt

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,16 @@ import androidx.compose.runtime.LaunchedEffect
1515
import androidx.compose.runtime.derivedStateOf
1616
import androidx.compose.runtime.getValue
1717
import androidx.compose.runtime.mutableFloatStateOf
18-
import androidx.compose.runtime.mutableStateOf
1918
import androidx.compose.runtime.remember
2019
import androidx.compose.runtime.saveable.rememberSaveable
2120
import androidx.compose.ui.Modifier
2221
import androidx.compose.ui.draw.shadow
2322
import androidx.compose.ui.graphics.Color
2423
import androidx.compose.ui.res.stringResource
25-
import androidx.compose.ui.text.input.TextFieldValue
2624
import androidx.compose.ui.text.style.TextAlign
2725
import androidx.compose.ui.unit.dp
2826
import androidx.compose.ui.unit.sp
2927
import com.kavi.droid.color.palette.extension.hsl
30-
import com.kavi.droid.color.palette.util.ColorUtil
3128
import com.kavi.droid.color.picker.R
3229
import com.kavi.droid.color.picker.ui.common.AlphaSlider
3330
import com.kavi.droid.color.picker.ui.common.ColorSaturationAndLightnessSlider
@@ -57,9 +54,7 @@ fun HSLAColorPicker(
5754
val lightness = rememberSaveable { mutableFloatStateOf(lastSelectedColor.hsl.lightness) }
5855
val alpha = rememberSaveable { mutableFloatStateOf(lastSelectedColor.alpha) }
5956

60-
val colorHex = remember { mutableStateOf(TextFieldValue("")) }
61-
62-
// Derived state for the color based on RGBA values
57+
// Derived state for the color based on HSL-A values
6358
val color by remember {
6459
derivedStateOf {
6560
Color.hsl(hue = hue.floatValue, saturation = saturation.floatValue, lightness = lightness.floatValue, alpha.floatValue)
@@ -68,7 +63,6 @@ fun HSLAColorPicker(
6863

6964
// Launch an effect to invoke the provided callback with the selected color
7065
LaunchedEffect(color) {
71-
colorHex.value = TextFieldValue(ColorUtil.getHex(color = color))
7266
onColorSelected.invoke(color)
7367
}
7468

0 commit comments

Comments
 (0)