A modern, Compose-first Android color picker library with interactive color wheels, sliders, and comprehensive Material Design 3 support.
- 100% Jetpack Compose - Modern declarative UI
- Reactive State Management - Compose-native state with
@Stableoptimization - Flow-Based Events - Reactive event handling with Kotlin SharedFlow
- Material Design 3 - Full Material3 theming support
- Multiple Wheel Types - Flower (organic) and Circle (precise) rendering styles
- Complete Customization - Alpha, lightness, density, colors all configurable
- Dialog & Preference Support - Ready-to-use dialog and DataStore integration
- Comprehensive Testing - 50+ snapshot tests with Roborazzi and automated CI/CD
- PR-Based Snapshot Updates - Update visual baselines via
/record-snapshotscomment - RTL Support - Right-to-left layout support
- Accessibility - Full semantic annotations for screen readers
This library uses modern Android architecture patterns:
- ColorPickerState - Immutable data class with
@Stableannotation for Compose optimization - rememberColorPickerState() - Composable state factory following Compose best practices
- Smart recomposition ensures only affected UI components update
- Flow-based events - Uses Kotlin
SharedFlowfor reactive event handling - Two event types:
ColorChanged- Emitted during user interaction (dragging, sliding)ColorSelected- Emitted when user finalizes selection (touch release)
- Coroutine-friendly with suspend functions
- Strategy Pattern - Pluggable renderers for different wheel types
- Canvas-based - High-performance hardware-accelerated drawing
- HSV Color Space - Intuitive hue-saturation-value selection
- Two implementations:
FlowerColorWheelRenderer- Organic petal-like appearanceSimpleColorWheelRenderer- Clean uniform circles
All components are Composable functions following Material Design 3:
ColorPicker- Complete color picking interfaceColorWheel- Interactive HSV color wheelLightnessSlider- Brightness adjustmentAlphaSlider- Transparency controlColorPreviewBox- Visual color displayColorPickerDialog- Material3 AlertDialog wrapperColorPickerPreference- DataStore preference integration
- Minimum SDK: Android API 24+ (Android 7.0)
- Kotlin: 2.2.20+
- Compose BOM: 2025.09.01+
- Java: 17+
This library is not released in Maven Central, but you can use JitPack.
Add JitPack repository in your root settings.gradle.kts:
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven { url = uri("https://jitpack.io") }
}
}Then add the library dependency in your module build.gradle.kts:
dependencies {
implementation("com.github.QuadFlask:colorpicker:0.0.13")
// Required dependencies
implementation(platform("androidx.compose:compose-bom:2025.09.01"))
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.material3:material3")
implementation("androidx.datastore:datastore-preferences:1.1.1")
}In settings.gradle:
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven { url "https://jitpack.io" }
}
}In build.gradle:
dependencies {
implementation 'com.github.QuadFlask:colorpicker:0.0.13'
// Required dependencies
implementation platform('androidx.compose:compose-bom:2025.09.01')
implementation 'androidx.compose.ui:ui'
implementation 'androidx.compose.material3:material3'
implementation 'androidx.datastore:datastore-preferences:1.1.1'
}Alternatively, download the .aar from releases and add it to your project:
dependencies {
implementation(files("libs/colorpicker.aar"))
}import androidx.compose.runtime.*
import androidx.compose.ui.graphics.Color
import co.csadev.colorpicker.compose.ColorPicker
@Composable
fun MyScreen() {
var selectedColor by remember { mutableStateOf(Color.Blue) }
ColorPicker(
initialColor = selectedColor,
showAlphaSlider = true,
showLightnessSlider = true,
onColorSelected = { color ->
selectedColor = color
}
)
}@Composable
fun DialogExample() {
var showDialog by remember { mutableStateOf(false) }
var selectedColor by remember { mutableStateOf(Color.Green) }
Button(onClick = { showDialog = true }) {
Text("Pick Color")
}
if (showDialog) {
ColorPickerDialog(
onDismissRequest = { showDialog = false },
onColorSelected = { color ->
selectedColor = color
showDialog = false
},
initialColor = selectedColor,
title = "Choose a Color"
)
}
}@Composable
fun EventHandlingExample() {
var currentColor by remember { mutableStateOf(Color.Yellow) }
var previewColor by remember { mutableStateOf(Color.Yellow) }
Column {
// Live preview while dragging
Box(
modifier = Modifier
.fillMaxWidth()
.height(50.dp)
.background(previewColor)
)
ColorPicker(
initialColor = currentColor,
onColorChanged = { color ->
// Called while dragging
previewColor = color
},
onColorSelected = { color ->
// Called when released
currentColor = color
previewColor = color
}
)
}
}@Composable
fun PreferencesExample() {
val context = LocalContext.current
val dataStore = remember { context.dataStore }
val themeColor by dataStore.getColorFlow(
key = "theme_color",
defaultColor = Color.Blue
).collectAsState(initial = Color.Blue)
val scope = rememberCoroutineScope()
ColorPickerPreferenceItem(
title = "Theme Color",
summary = "Choose your app theme color",
color = themeColor,
onColorChange = { newColor ->
scope.launch {
dataStore.saveColor("theme_color", newColor)
}
}
)
}@Composable
fun ColorWheelExample() {
var selectedColor by remember { mutableStateOf(Color.Red) }
ColorWheel(
wheelType = ColorPickerState.WheelType.FLOWER,
density = 12,
lightness = 1f,
alpha = 1f,
onColorSelected = { color ->
selectedColor = color
}
)
}This library includes comprehensive snapshot testing using Roborazzi and the official Android Compose screenshot testing approach to ensure UI consistency:
- ✅ ~50 snapshot tests covering all UI components
- ✅ Multiple device types (phones, tablets, various screen densities)
- ✅ RTL support (Arabic, Hebrew)
- ✅ Light and dark themes Material3 themes
- ✅ Automated CI/CD with GitHub Actions
- ✅ PR-based snapshot updates via comment commands
# Record reference snapshots
./gradlew :library:recordSnapshots
# Verify snapshots match
./gradlew :library:verifySnapshots
# Compare snapshots (generates comparison images)
./gradlew :library:compareSnapshots
# Clean snapshot artifacts
./gradlew :library:cleanSnapshots
# Generate snapshot report
./gradlew :library:snapshotReportThe library includes automated snapshot testing workflows that run on every PR:
Automatic Verification:
- Runs on every PR and push to main/develop branches
- Verifies UI matches reference snapshots
- Uploads comparison images as artifacts on failure
- Posts PR comments with detailed results and instructions
PR Comment Commands:
Control snapshot testing directly from PR comments:
| Command | Description |
|---|---|
/record-snapshots |
Records new snapshots and commits them to the PR |
/update-snapshots |
Alias for /record-snapshots |
/verify-snapshots |
Manually re-runs snapshot verification without making changes |
Example Workflow:
- Make UI changes and push to your PR
- Snapshot tests fail in CI (expected for intentional changes)
- Review the failure artifacts to see visual differences
- If changes are correct, comment
/record-snapshotson the PR - GitHub Actions will automatically:
- Record new baseline snapshots
- Commit them to your PR branch
- Re-run verification tests
- Post results as a PR comment
Manual Re-verification:
If you need to re-run tests without pushing new commits:
/verify-snapshots
This is useful for:
- Checking if a fix resolved snapshot failures
- Re-running tests after infrastructure changes
- Validating snapshots after rebasing
Reference snapshot images are stored in library/src/test/resources/roborazzi/:
- 48+ PNG files - One per test scenario
- Automatically generated - First run of
/record-snapshotscreates baselines - Version controlled - Committed with tests for consistent CI/CD
- Visual regression detection - Pixel-perfect comparison on every PR
For detailed testing documentation, see library/SNAPSHOT_TESTING.md.
The library uses Roborazzi for snapshot testing to prevent visual regressions. All UI components are tested across multiple configurations using JVM-based tests (no emulator required).
Test Coverage:
- Component Tests (~25): Individual UI elements (ColorWheel, Sliders, PreviewBox)
- Various wheel types (Flower, Circle) with different densities
- Sliders with multiple lightness and alpha values
- Color preview boxes with different colors
- ColorPicker Tests (~10): Full picker configurations
- Feature combinations (with/without sliders, color edit)
- Different initial colors and wheel types
- Dialog & Config Tests (~15): Dialogs, preferences, devices, themes, locales
- ColorPickerDialog in various states
- ColorPickerPreferenceItem configurations
- Multiple device sizes (phone, tablet, landscape)
- Light and dark Material3 themes
- RTL locales (Arabic, Hebrew)
GitHub Actions Workflows:
The project includes comprehensive CI/CD workflows in .github/workflows/snapshot-tests.yml:
-
verify-snapshots (Auto-triggered)
- Runs on: PR creation/update, push to main/develop
- Action: Verifies UI matches reference snapshots
- On failure: Uploads artifacts and posts detailed PR comment
-
record-snapshots (Comment-triggered)
- Trigger: Comment
/record-snapshotsor/update-snapshotson PR - Action: Records new baseline snapshots and commits to PR
- Result: Posts confirmation comment with update status
- Trigger: Comment
-
verify-snapshots-on-command (Comment-triggered)
- Trigger: Comment
/verify-snapshotson PR - Action: Manually re-runs verification without changes
- Result: Posts verification results with pass/fail status
- Trigger: Comment
Contributing:
When contributing UI changes:
- Run tests locally:
./gradlew :library:verifySnapshots - If intentional changes cause failures, update locally:
./gradlew :library:recordSnapshots - Commit both code and snapshot changes together
- Alternatively, use
/record-snapshotscommand on your PR
See the Snapshot Testing Guide for comprehensive documentation.
For comprehensive guides and detailed information, see:
-
HOW_TO.md - Complete usage guide with all features and examples
- Installation and setup
- Basic and advanced usage patterns
- State management techniques
- Event handling
- Preferences integration with DataStore
- Migration from View-based library
- Best practices and troubleshooting
-
COLORWHEEL_USAGE.md - Detailed color wheel documentation
- Flower vs Circle wheel types
- Customization options (density, lightness, alpha)
- Synchronized sliders
- Performance tips
- Responsive layouts
-
library/SNAPSHOT_TESTING.md - Testing guide
- Running snapshot tests
- PR-based snapshot updates
- Test coverage details
- CI/CD integration
- Contributing guidelines
-
UpdateCompose.md - Architecture migration details
- Migration strategy from View to Compose
- Technical implementation details
- Phase-by-phase breakdown
- Breaking changes and compatibility
The repository includes a comprehensive sample app (app/ module) demonstrating all features across 8 screens:
- SimplestExampleScreen - Minimal usage
- FullFeaturedScreen - All options enabled
- CustomizableScreen - Individual components
- DialogsScreen - Dialog configurations
- SlidersExampleScreen - Standalone sliders
- EventHandlingScreen - Live vs confirmed colors
- ComparisonScreen - Wheel type comparison
- PreferencesScreen - DataStore persistence
Run the sample app to see all features in action!
✅ Completed:
- ✅ Migrated to Jetpack Compose
- ✅ Modern Kotlin architecture with coroutines and Flow
- ✅ Material Design 3 integration
- ✅ Comprehensive snapshot testing (50+ tests)
- ✅ DataStore preferences support
- ✅ CI/CD with GitHub Actions
- ✅ Full documentation
🚧 In Progress / Future:
- Performance optimization for high-density wheels (100+ density)
- Gradle Maven Central publishing
- Compose Multiplatform support
- Custom color palette management
- Color harmony suggestions (complementary, triadic, etc.)
Copyright 2014-2017 QuadFlask
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.


