aboutsummaryrefslogtreecommitdiff
path: root/library/src/main/kotlin/ca/allanwang/kau/dialogs/color
diff options
context:
space:
mode:
Diffstat (limited to 'library/src/main/kotlin/ca/allanwang/kau/dialogs/color')
-rw-r--r--library/src/main/kotlin/ca/allanwang/kau/dialogs/color/ColorPalette.kt349
-rw-r--r--library/src/main/kotlin/ca/allanwang/kau/dialogs/color/ColorPickerDialog.kt352
-rw-r--r--library/src/main/kotlin/ca/allanwang/kau/dialogs/color/ColorPickerPreference.kt72
3 files changed, 773 insertions, 0 deletions
diff --git a/library/src/main/kotlin/ca/allanwang/kau/dialogs/color/ColorPalette.kt b/library/src/main/kotlin/ca/allanwang/kau/dialogs/color/ColorPalette.kt
new file mode 100644
index 0000000..22bd0d4
--- /dev/null
+++ b/library/src/main/kotlin/ca/allanwang/kau/dialogs/color/ColorPalette.kt
@@ -0,0 +1,349 @@
+package ca.allanwang.kau.dialogs.color
+
+import android.graphics.Color
+
+/**
+ * @author Aidan Follestad (afollestad)
+ */
+internal object ColorPalette {
+
+ val PRIMARY_COLORS: IntArray by lazy {
+ colorArrayOf(
+ "#F44336",
+ "#E91E63",
+ "#9C27B0",
+ "#673AB7",
+ "#3F51B5",
+ "#2196F3",
+ "#03A9F4",
+ "#00BCD4",
+ "#009688",
+ "#4CAF50",
+ "#8BC34A",
+ "#CDDC39",
+ "#FFEB3B",
+ "#FFC107",
+ "#FF9800",
+ "#FF5722",
+ "#795548",
+ "#9E9E9E",
+ "#607D8B")
+ }
+
+ val PRIMARY_COLORS_SUB: Array<IntArray> by lazy {
+ arrayOf(colorArrayOf(
+ "#FFEBEE",
+ "#FFCDD2",
+ "#EF9A9A",
+ "#E57373",
+ "#EF5350",
+ "#F44336",
+ "#E53935",
+ "#D32F2F",
+ "#C62828",
+ "#B71C1C"
+ ), colorArrayOf(
+ "#FCE4EC",
+ "#F8BBD0",
+ "#F48FB1",
+ "#F06292",
+ "#EC407A",
+ "#E91E63",
+ "#D81B60",
+ "#C2185B",
+ "#AD1457",
+ "#880E4F"
+ ), colorArrayOf(
+ "#F3E5F5",
+ "#E1BEE7",
+ "#CE93D8",
+ "#BA68C8",
+ "#AB47BC",
+ "#9C27B0",
+ "#8E24AA",
+ "#7B1FA2",
+ "#6A1B9A",
+ "#4A148C"
+ ), colorArrayOf(
+ "#EDE7F6",
+ "#D1C4E9",
+ "#B39DDB",
+ "#9575CD",
+ "#7E57C2",
+ "#673AB7",
+ "#5E35B1",
+ "#512DA8",
+ "#4527A0",
+ "#311B92"
+ ), colorArrayOf(
+ "#E8EAF6",
+ "#C5CAE9",
+ "#9FA8DA",
+ "#7986CB",
+ "#5C6BC0",
+ "#3F51B5",
+ "#3949AB",
+ "#303F9F",
+ "#283593",
+ "#1A237E"
+ ), colorArrayOf(
+ "#E3F2FD",
+ "#BBDEFB",
+ "#90CAF9",
+ "#64B5F6",
+ "#42A5F5",
+ "#2196F3",
+ "#1E88E5",
+ "#1976D2",
+ "#1565C0",
+ "#0D47A1"
+ ), colorArrayOf(
+ "#E1F5FE",
+ "#B3E5FC",
+ "#81D4FA",
+ "#4FC3F7",
+ "#29B6F6",
+ "#03A9F4",
+ "#039BE5",
+ "#0288D1",
+ "#0277BD",
+ "#01579B"
+ ), colorArrayOf(
+ "#E0F7FA",
+ "#B2EBF2",
+ "#80DEEA",
+ "#4DD0E1",
+ "#26C6DA",
+ "#00BCD4",
+ "#00ACC1",
+ "#0097A7",
+ "#00838F",
+ "#006064"
+ ), colorArrayOf(
+ "#E0F2F1",
+ "#B2DFDB",
+ "#80CBC4",
+ "#4DB6AC",
+ "#26A69A",
+ "#009688",
+ "#00897B",
+ "#00796B",
+ "#00695C",
+ "#004D40"
+ ), colorArrayOf(
+ "#E8F5E9",
+ "#C8E6C9",
+ "#A5D6A7",
+ "#81C784",
+ "#66BB6A",
+ "#4CAF50",
+ "#43A047",
+ "#388E3C",
+ "#2E7D32",
+ "#1B5E20"
+ ), colorArrayOf(
+ "#F1F8E9",
+ "#DCEDC8",
+ "#C5E1A5",
+ "#AED581",
+ "#9CCC65",
+ "#8BC34A",
+ "#7CB342",
+ "#689F38",
+ "#558B2F",
+ "#33691E"
+ ), colorArrayOf(
+ "#F9FBE7",
+ "#F0F4C3",
+ "#E6EE9C",
+ "#DCE775",
+ "#D4E157",
+ "#CDDC39",
+ "#C0CA33",
+ "#AFB42B",
+ "#9E9D24",
+ "#827717"
+ ), colorArrayOf(
+ "#FFFDE7",
+ "#FFF9C4",
+ "#FFF59D",
+ "#FFF176",
+ "#FFEE58",
+ "#FFEB3B",
+ "#FDD835",
+ "#FBC02D",
+ "#F9A825",
+ "#F57F17"
+ ), colorArrayOf(
+ "#FFF8E1",
+ "#FFECB3",
+ "#FFE082",
+ "#FFD54F",
+ "#FFCA28",
+ "#FFC107",
+ "#FFB300",
+ "#FFA000",
+ "#FF8F00",
+ "#FF6F00"
+ ), colorArrayOf(
+ "#FFF3E0",
+ "#FFE0B2",
+ "#FFCC80",
+ "#FFB74D",
+ "#FFA726",
+ "#FF9800",
+ "#FB8C00",
+ "#F57C00",
+ "#EF6C00",
+ "#E65100"
+ ), colorArrayOf(
+ "#FBE9E7",
+ "#FFCCBC",
+ "#FFAB91",
+ "#FF8A65",
+ "#FF7043",
+ "#FF5722",
+ "#F4511E",
+ "#E64A19",
+ "#D84315",
+ "#BF360C"
+ ), colorArrayOf(
+ "#EFEBE9",
+ "#D7CCC8",
+ "#BCAAA4",
+ "#A1887F",
+ "#8D6E63",
+ "#795548",
+ "#6D4C41",
+ "#5D4037",
+ "#4E342E",
+ "#3E2723"
+ ), colorArrayOf(
+ "#FAFAFA",
+ "#F5F5F5",
+ "#EEEEEE",
+ "#E0E0E0",
+ "#BDBDBD",
+ "#9E9E9E",
+ "#757575",
+ "#616161",
+ "#424242",
+ "#212121"
+ ), colorArrayOf(
+ "#ECEFF1",
+ "#CFD8DC",
+ "#B0BEC5",
+ "#90A4AE",
+ "#78909C",
+ "#607D8B",
+ "#546E7A",
+ "#455A64",
+ "#37474F",
+ "#263238"))
+ }
+
+ val ACCENT_COLORS: IntArray by lazy {
+ colorArrayOf(
+ "#FF1744",
+ "#F50057",
+ "#D500F9",
+ "#651FFF",
+ "#3D5AFE",
+ "#2979FF",
+ "#00B0FF",
+ "#00E5FF",
+ "#1DE9B6",
+ "#00E676",
+ "#76FF03",
+ "#C6FF00",
+ "#FFEA00",
+ "#FFC400",
+ "#FF9100",
+ "#FF3D00")
+ }
+
+ val ACCENT_COLORS_SUB: Array<IntArray> by lazy {
+ arrayOf(colorArrayOf("#FF8A80",
+ "#FF5252",
+ "#FF1744",
+ "#D50000"
+ ), colorArrayOf(
+ "#FF80AB",
+ "#FF4081",
+ "#F50057",
+ "#C51162"
+ ), colorArrayOf(
+ "#EA80FC",
+ "#E040FB",
+ "#D500F9",
+ "#AA00FF"
+ ), colorArrayOf(
+ "#B388FF",
+ "#7C4DFF",
+ "#651FFF",
+ "#6200EA"
+ ), colorArrayOf(
+ "#8C9EFF",
+ "#536DFE",
+ "#3D5AFE",
+ "#304FFE"
+ ), colorArrayOf(
+ "#82B1FF",
+ "#448AFF",
+ "#2979FF",
+ "#2962FF"
+ ), colorArrayOf(
+ "#80D8FF",
+ "#40C4FF",
+ "#00B0FF",
+ "#0091EA"
+ ), colorArrayOf(
+ "#84FFFF",
+ "#18FFFF",
+ "#00E5FF",
+ "#00B8D4"
+ ), colorArrayOf(
+ "#A7FFEB",
+ "#64FFDA",
+ "#1DE9B6",
+ "#00BFA5"
+ ), colorArrayOf(
+ "#B9F6CA",
+ "#69F0AE",
+ "#00E676",
+ "#00C853"
+ ), colorArrayOf(
+ "#CCFF90",
+ "#B2FF59",
+ "#76FF03",
+ "#64DD17"
+ ), colorArrayOf(
+ "#F4FF81",
+ "#EEFF41",
+ "#C6FF00",
+ "#AEEA00"
+ ), colorArrayOf(
+ "#FFFF8D",
+ "#FFFF00",
+ "#FFEA00",
+ "#FFD600"
+ ), colorArrayOf(
+ "#FFE57F",
+ "#FFD740",
+ "#FFC400",
+ "#FFAB00"
+ ), colorArrayOf(
+ "#FFD180",
+ "#FFAB40",
+ "#FF9100",
+ "#FF6D00"
+ ), colorArrayOf(
+ "#FF9E80",
+ "#FF6E40",
+ "#FF3D00",
+ "#DD2C00"))
+ }
+
+ fun colorArrayOf(vararg colors: String) = colors.map { Color.parseColor(it) }.toIntArray()
+}
+
diff --git a/library/src/main/kotlin/ca/allanwang/kau/dialogs/color/ColorPickerDialog.kt b/library/src/main/kotlin/ca/allanwang/kau/dialogs/color/ColorPickerDialog.kt
new file mode 100644
index 0000000..f78cde0
--- /dev/null
+++ b/library/src/main/kotlin/ca/allanwang/kau/dialogs/color/ColorPickerDialog.kt
@@ -0,0 +1,352 @@
+package ca.allanwang.kau.dialogs.color
+
+import android.content.Context
+import android.graphics.Color
+import android.support.annotation.ColorInt
+import android.support.v4.content.res.ResourcesCompat
+import android.text.Editable
+import android.text.InputFilter
+import android.text.TextWatcher
+import android.util.AttributeSet
+import android.view.View
+import android.view.ViewGroup
+import android.widget.*
+import ca.allanwang.kau.R
+import ca.allanwang.kau.logging.SL
+import ca.allanwang.kau.utils.*
+import com.afollestad.materialdialogs.DialogAction
+import com.afollestad.materialdialogs.MaterialDialog
+import com.afollestad.materialdialogs.Theme
+import com.afollestad.materialdialogs.color.CircleView
+import com.afollestad.materialdialogs.color.FillGridView
+import java.util.*
+
+/**
+ * Created by Allan Wang on 2017-06-08.
+ */
+internal class ColorPickerView @JvmOverloads constructor(
+ context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
+) : ScrollView(context, attrs, defStyleAttr) {
+ var selectedColor: Int = -1
+ var isInSub: Boolean = false
+ var isInCustom: Boolean = false
+ var circleSize: Int = context.dimen(R.dimen.kau_color_circle_size).toInt()
+ lateinit var dialog: MaterialDialog
+ lateinit var builder: Builder
+ lateinit var colorsTop: IntArray
+ var colorsSub: Array<IntArray>? = null
+ var topIndex: Int = -1
+ var subIndex: Int = -1
+ var colorIndex: Int
+ get() = if (isInSub) subIndex else topIndex
+ set(value) {
+ if (isInSub) subIndex = value
+ else {
+ topIndex = value
+ if (colorsSub != null && colorsSub!!.size > value) {
+ dialog.setActionButton(DialogAction.NEGATIVE, builder.backText)
+ isInSub = true
+ }
+ }
+ }
+
+
+ val gridView: FillGridView by bindView(R.id.md_grid)
+ val customFrame: LinearLayout by bindView(R.id.md_colorChooserCustomFrame)
+ val customColorIndicator: View by bindView(R.id.md_colorIndicator)
+ val hexInput: EditText by bindView(R.id.md_hexInput)
+ val alphaLabel: TextView by bindView(R.id.md_colorALabel)
+ val alphaSeekbar: SeekBar by bindView(R.id.md_colorA)
+ val alphaValue: TextView by bindView(R.id.md_colorAValue)
+ val redSeekbar: SeekBar by bindView(R.id.md_colorR)
+ val redValue: TextView by bindView(R.id.md_colorRValue)
+ val greenSeekbar: SeekBar by bindView(R.id.md_colorG)
+ val greenValue: TextView by bindView(R.id.md_colorGValue)
+ val blueSeekbar: SeekBar by bindView(R.id.md_colorB)
+ val blueValue: TextView by bindView(R.id.md_colorBValue)
+
+ var customHexTextWatcher: TextWatcher? = null
+ var customRgbListener: SeekBar.OnSeekBarChangeListener? = null
+
+ init {
+ View.inflate(context, R.layout.md_dialog_colorchooser, this)
+ }
+
+ fun bind(builder: Builder, dialog: MaterialDialog) {
+ this.builder = builder
+ this.dialog = dialog
+ this.colorsTop = builder.colorsTop()
+ this.colorsSub = builder.colorsSub()
+ this.selectedColor = builder.defaultColor
+ if (builder.allowCustom) {
+ if (!builder.allowCustomAlpha) {
+ alphaLabel.gone()
+ alphaSeekbar.gone()
+ alphaValue.gone()
+ hexInput.hint = String.format("%06X", selectedColor)
+ hexInput.filters = arrayOf(InputFilter.LengthFilter(6))
+ } else {
+ hexInput.hint = String.format("%08X", selectedColor)
+ hexInput.filters = arrayOf(InputFilter.LengthFilter(8))
+ }
+ }
+ if (findColor(builder.defaultColor)) isInCustom = true //when toggled this will be false
+ toggleCustom()
+ }
+
+ fun backOrCancel() {
+ if (isInSub) {
+ dialog.setActionButton(DialogAction.NEGATIVE, builder.cancelText)
+ //to top
+ isInSub = false
+ subIndex = -1
+ invalidateGrid()
+ } else {
+ dialog.cancel()
+ }
+ }
+
+ fun toggleCustom() {
+ isInCustom = !isInCustom
+ if (isInCustom) {
+ isInSub = false
+ dialog.setActionButton(DialogAction.NEUTRAL, builder.presetText)
+ dialog.setActionButton(DialogAction.NEGATIVE, builder.cancelText)
+ customHexTextWatcher = object : TextWatcher {
+ override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
+
+ override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
+ try {
+ selectedColor = Color.parseColor("#" + s.toString())
+ } catch (e: IllegalArgumentException) {
+ selectedColor = Color.BLACK
+ }
+
+ customColorIndicator.setBackgroundColor(selectedColor)
+ if (alphaSeekbar.isVisible()) {
+ val alpha = Color.alpha(selectedColor)
+ alphaSeekbar.progress = alpha
+ alphaValue.text = String.format(Locale.CANADA, "%d", alpha)
+ }
+ redSeekbar.progress = Color.red(selectedColor)
+ greenSeekbar.progress = Color.green(selectedColor)
+ blueSeekbar.progress = Color.blue(selectedColor)
+ isInSub = false
+ topIndex = -1
+ subIndex = -1
+ refreshColors()
+ }
+
+ override fun afterTextChanged(s: Editable?) {}
+ }
+ hexInput.setText(selectedColor.toHexString(builder.allowCustomAlpha, false))
+ hexInput.addTextChangedListener(customHexTextWatcher)
+ customRgbListener = object : SeekBar.OnSeekBarChangeListener {
+ override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
+ SL.d("Progress $progress")
+ if (fromUser) {
+ val color = if (builder.allowCustomAlpha)
+ Color.argb(alphaSeekbar.progress,
+ redSeekbar.progress,
+ greenSeekbar.progress,
+ blueSeekbar.progress)
+ else Color.rgb(redSeekbar.progress,
+ greenSeekbar.progress,
+ blueSeekbar.progress)
+
+ hexInput.setText(color.toHexString(builder.allowCustomAlpha, false))
+ }
+ if (builder.allowCustomAlpha) alphaValue.text = alphaSeekbar.progress.toString()
+ redValue.text = redSeekbar.progress.toString()
+ greenValue.text = greenSeekbar.progress.toString()
+ blueValue.text = blueSeekbar.progress.toString()
+ }
+
+ override fun onStartTrackingTouch(seekBar: SeekBar) {}
+
+ override fun onStopTrackingTouch(seekBar: SeekBar) {}
+ }
+ redSeekbar.setOnSeekBarChangeListener(customRgbListener)
+ greenSeekbar.setOnSeekBarChangeListener(customRgbListener)
+ blueSeekbar.setOnSeekBarChangeListener(customRgbListener)
+ if (alphaSeekbar.isVisible())
+ alphaSeekbar.setOnSeekBarChangeListener(customRgbListener)
+ hexInput.setText(selectedColor.toHexString(alphaSeekbar.isVisible(), false))
+ gridView.fadeOut(onFinish = { gridView.gone() })
+ customFrame.fadeIn()
+ } else {
+ findColor(selectedColor)
+ dialog.setActionButton(DialogAction.NEUTRAL, builder.customText)
+ dialog.setActionButton(DialogAction.NEGATIVE, if (isInSub) builder.backText else builder.cancelText)
+ gridView.fadeIn(onStart = { invalidateGrid() })
+ customFrame.fadeOut(onFinish = { customFrame.gone() })
+ hexInput.removeTextChangedListener(customHexTextWatcher)
+ customHexTextWatcher = null
+ alphaSeekbar.setOnSeekBarChangeListener(null)
+ redSeekbar.setOnSeekBarChangeListener(null)
+ greenSeekbar.setOnSeekBarChangeListener(null)
+ blueSeekbar.setOnSeekBarChangeListener(null)
+ customRgbListener = null
+ }
+ }
+
+ fun refreshColors() {
+ if (!isInCustom) findColor(selectedColor)
+ if (builder.dynamicButtonColors) {
+ dialog.getActionButton(DialogAction.POSITIVE).setTextColor(selectedColor)
+ dialog.getActionButton(DialogAction.NEGATIVE).setTextColor(selectedColor)
+ dialog.getActionButton(DialogAction.NEUTRAL).setTextColor(selectedColor)
+ }
+ if (!builder.allowCustom || !isInCustom) return
+ // Once we get close to white or transparent,
+ // the action buttons and seekbars will be a very light gray.
+ // TODO change by dialog theme
+ val visibleColor = if (Color.alpha(selectedColor) < 64 ||
+ Color.red(selectedColor) > 247 && Color.green(selectedColor) > 247 && Color.blue(selectedColor) > 247)
+ "#DEDEDE".toColor() else selectedColor
+
+ if (builder.allowCustomAlpha)
+ alphaSeekbar.visible().tint(visibleColor)
+ redSeekbar.tint(visibleColor)
+ greenSeekbar.tint(visibleColor)
+ blueSeekbar.tint(visibleColor)
+ hexInput.tint(visibleColor)
+ }
+
+ fun findColor(@ColorInt color: Int): Boolean {
+ topIndex = -1
+ subIndex = -1
+ colorsTop.forEachIndexed {
+ index, topColor ->
+ if (findSubColor(color, index)) {
+ topIndex = index
+ return true
+ }
+ if (topColor == color) { // If no sub colors exists and top color matches
+ topIndex = index
+ return true
+ }
+ }
+ return false
+ }
+
+ fun findSubColor(@ColorInt color: Int, topIndex: Int): Boolean {
+ if (colorsSub == null || colorsSub!!.size <= topIndex) return false
+ colorsSub!![topIndex].forEachIndexed {
+ index, subColor ->
+ if (subColor == color) {
+ subIndex = index
+ return true
+ }
+ }
+ return false
+ }
+
+ fun invalidateGrid() {
+ if (gridView.adapter == null) {
+ gridView.adapter = ColorGridAdapter()
+ gridView.selector = ResourcesCompat.getDrawable(resources, R.drawable.kau_transparent, null)
+ } else {
+ (gridView.adapter as BaseAdapter).notifyDataSetChanged()
+ }
+ }
+
+ inner class ColorGridAdapter : BaseAdapter(), OnClickListener, OnLongClickListener {
+ override fun onClick(v: View) {
+ if (v.tag != null && v.tag is String) {
+ val tags = (v.tag as String).split(":")
+ colorIndex = tags[0].toInt()
+ selectedColor = tags[1].toInt()
+ refreshColors()
+ invalidateGrid()
+ }
+ }
+
+ override fun onLongClick(v: View): Boolean {
+ if (v.tag != null && v.tag is String) {
+ val tag = (v.tag as String).split(":")
+ val color = tag[1].toInt()
+ (v as CircleView).showHint(color)
+ return true
+ }
+ return false
+ }
+
+ override fun getItem(position: Int): Any = if (isInSub) colorsSub!![topIndex][position] else colorsTop[position]
+
+ override fun getCount(): Int = if (isInSub) colorsSub!![topIndex].size else colorsTop.size
+
+ override fun getItemId(position: Int): Long = position.toLong()
+
+ override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
+ val view: CircleView = if (convertView == null)
+ CircleView(context).apply { layoutParams = AbsListView.LayoutParams(circleSize, circleSize) }
+ else
+ convertView as CircleView
+ val color: Int = if (isInSub) colorsSub!![topIndex][position] else colorsTop[position]
+ return view.apply {
+ setBackgroundColor(color)
+ isSelected = (if (isInSub) subIndex else topIndex) == position
+ tag = "$position:$color"
+ setOnClickListener(this@ColorGridAdapter)
+ setOnLongClickListener(this@ColorGridAdapter)
+ }
+ }
+
+ }
+}
+
+class Builder {
+ var title: String? = null
+ var titleRes: Int = -1
+ var allowCustom: Boolean = true
+ var allowCustomAlpha: Boolean = false
+ var isAccent: Boolean = false
+ var defaultColor: Int = Color.BLACK
+ var doneText: Int = R.string.kau_done
+ var backText: Int = R.string.kau_back
+ var cancelText: Int = R.string.kau_cancel
+ var presetText: Int = R.string.kau_md_presets
+ var customText: Int = R.string.kau_md_custom
+ get() = if (allowCustom) field else 0
+ var dynamicButtonColors: Boolean = true
+ var circleSizeRes: Int = R.dimen.kau_color_circle_size
+ var colorCallbacks: MutableList<((selectedColor: Int) -> Unit)> = mutableListOf()
+ var colorsTop: IntArray? = null
+ internal fun colorsTop(): IntArray =
+ if (colorsTop != null) colorsTop!!
+ else if (isAccent) ColorPalette.ACCENT_COLORS
+ else ColorPalette.PRIMARY_COLORS
+
+ var colorsSub: Array<IntArray>? = null
+ internal fun colorsSub(): Array<IntArray>? =
+ if (colorsTop != null) colorsSub
+ else if (isAccent) ColorPalette.ACCENT_COLORS_SUB
+ else ColorPalette.PRIMARY_COLORS_SUB
+
+ var theme: Theme? = null
+
+}
+
+
+fun Context.colorPickerDialog(action: Builder.() -> Unit): MaterialDialog {
+ val b = Builder()
+ b.action()
+ val view = ColorPickerView(this)
+ val dialog = with(MaterialDialog.Builder(this)) {
+ title(string(b.titleRes, b.title) ?: string(R.string.kau_md_color_palette))
+ customView(view, false)
+ autoDismiss(false)
+ positiveText(b.doneText)
+ negativeText(b.cancelText)
+ neutralText(b.presetText)
+ onPositive { dialog, _ -> b.colorCallbacks.forEach { it.invoke(view.selectedColor) }; dialog.dismiss() }
+ onNegative { dialog, _ -> view.backOrCancel() }
+ if (b.allowCustom) onNeutral { dialog, _ -> view.toggleCustom() }
+ showListener { view.refreshColors() }
+ if (b.theme != null) theme(b.theme!!)
+ build()
+ }
+ view.bind(b, dialog)
+ return dialog
+} \ No newline at end of file
diff --git a/library/src/main/kotlin/ca/allanwang/kau/dialogs/color/ColorPickerPreference.kt b/library/src/main/kotlin/ca/allanwang/kau/dialogs/color/ColorPickerPreference.kt
new file mode 100644
index 0000000..043e287
--- /dev/null
+++ b/library/src/main/kotlin/ca/allanwang/kau/dialogs/color/ColorPickerPreference.kt
@@ -0,0 +1,72 @@
+package ca.allanwang.kau.dialogs.color
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.graphics.Color
+import android.os.Build
+import android.os.Bundle
+import android.os.Parcelable
+import android.support.annotation.ColorInt
+import android.support.annotation.StringRes
+import android.support.v4.content.res.ResourcesCompat
+import android.support.v7.app.AppCompatActivity
+import android.support.v7.preference.Preference
+import android.text.Editable
+import android.text.TextWatcher
+import android.util.AttributeSet
+import android.view.View
+import android.view.ViewGroup
+import android.widget.*
+import ca.allanwang.kau.R
+import ca.allanwang.kau.utils.ANDROID_NAMESPACE
+import ca.allanwang.kau.utils.integer
+import ca.allanwang.kau.utils.resolveColor
+import ca.allanwang.kau.utils.toColor
+import com.afollestad.materialdialogs.DialogAction
+import com.afollestad.materialdialogs.MaterialDialog
+import com.afollestad.materialdialogs.color.CircleView
+import com.afollestad.materialdialogs.color.ColorChooserDialog
+import com.afollestad.materialdialogs.internal.MDTintHelper
+import com.afollestad.materialdialogs.util.DialogUtils
+import java.util.*
+
+/**
+ * Created by Allan Wang on 2017-06-08.
+ */
+class ColorPickerPreference @JvmOverloads constructor(
+ context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0, defStyleRes: Int = 0
+) : Preference(context, attrs, defStyleAttr, defStyleRes), Preference.OnPreferenceClickListener {
+
+ var defaultColor: Int = Color.BLACK
+ var currentColor: Int
+ var accentMode = false
+ var dialogTitle: Int = 0
+
+ init {
+ onPreferenceClickListener = this
+ if (attrs != null) {
+ val defaultValue = attrs.getAttributeValue(ANDROID_NAMESPACE, "defaultValue")
+ if (defaultValue?.startsWith("#") ?: false) {
+ try {
+ defaultColor = defaultValue.toColor()
+ } catch (e: IllegalArgumentException) {
+ throw IllegalArgumentException("ColorPickerPreference $key has a default value that is not a color resource: $defaultValue")
+ }
+ } else {
+ val resourceId = attrs.getAttributeResourceValue(ANDROID_NAMESPACE, "defaultValue", 0)
+ if (resourceId != 0)
+ defaultColor = context.integer(resourceId)
+ else
+ throw IllegalArgumentException("ColorPickerPreference $key has a default value that is not a color resource: $defaultValue")
+ }
+ }
+ currentColor = getPersistedInt(defaultColor)
+ }
+
+ override fun onPreferenceClick(preference: Preference): Boolean {
+ context.colorPickerDialog {
+
+ }.show()
+ return true
+ }
+} \ No newline at end of file