aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--android-lib.gradle8
-rw-r--r--buildSrc/src/main/groovy/ca/allanwang/kau/Dependencies.groovy2
-rw-r--r--buildSrc/src/main/groovy/ca/allanwang/kau/Versions.groovy4
-rw-r--r--colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/CircleView.kt17
-rw-r--r--colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/ColorPickerDialog.kt23
-rw-r--r--colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/ColorPickerView.kt190
-rw-r--r--core/build.gradle1
-rw-r--r--core/src/androidTest/kotlin/ca/allanwang/kau/xml/ChangelogTest.kt19
-rw-r--r--core/src/androidTest/kotlin/ca/allanwang/kau/xml/FaqTest.kt16
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/kotlin/Debouncer.kt6
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/kotlin/LazyContext.kt1
-rw-r--r--core/src/main/kotlin/ca/allanwang/kau/ui/ProgressAnimator.kt4
-rw-r--r--docs/Changelog.md10
-rw-r--r--kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/KPrefBinder.kt2
-rw-r--r--kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefItemCore.kt2
-rw-r--r--sample/build.gradle18
-rw-r--r--sample/src/androidTest/kotlin/ca/allanwang/kau/sample/ColorPickerTest.kt61
-rw-r--r--sample/src/main/res/xml/kau_changelog.xml6
-rw-r--r--searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt2
19 files changed, 232 insertions, 160 deletions
diff --git a/android-lib.gradle b/android-lib.gradle
index 86c0067..2be7c46 100644
--- a/android-lib.gradle
+++ b/android-lib.gradle
@@ -81,10 +81,10 @@ android {
}
dependencies {
- androidTestImplementation("com.android.support.test:runner:${kau.testRunner}") {
- exclude group: 'com.android.support', module: 'support-annotations'
- }
- androidTestImplementation kauDependency.kotlinTest
testImplementation kauDependency.kotlinTest
testImplementation kauDependency.junit
+
+ androidTestImplementation kauDependency.kotlinTest
+ androidTestImplementation kauDependency.espresso
+ androidTestImplementation kauDependency.testRunner
} \ No newline at end of file
diff --git a/buildSrc/src/main/groovy/ca/allanwang/kau/Dependencies.groovy b/buildSrc/src/main/groovy/ca/allanwang/kau/Dependencies.groovy
index 368b0a8..ec3d208 100644
--- a/buildSrc/src/main/groovy/ca/allanwang/kau/Dependencies.groovy
+++ b/buildSrc/src/main/groovy/ca/allanwang/kau/Dependencies.groovy
@@ -7,4 +7,6 @@ class Dependencies {
static def kotlin = "org.jetbrains.kotlin:kotlin-stdlib:${Versions.kotlin}"
static def kotlinTest = "org.jetbrains.kotlin:kotlin-test-junit:${Versions.kotlin}"
static def junit = "junit:junit:${Versions.junit}"
+ static def espresso = "com.android.support.test.espresso:espresso-core:${Versions.espresso}"
+ static def testRunner = "com.android.support.test:runner:${Versions.testRunner}"
} \ No newline at end of file
diff --git a/buildSrc/src/main/groovy/ca/allanwang/kau/Versions.groovy b/buildSrc/src/main/groovy/ca/allanwang/kau/Versions.groovy
index 36e444d..ac38509 100644
--- a/buildSrc/src/main/groovy/ca/allanwang/kau/Versions.groovy
+++ b/buildSrc/src/main/groovy/ca/allanwang/kau/Versions.groovy
@@ -25,9 +25,9 @@ class Versions {
static def materialDialog = '0.9.6.0'
- static def espresso = '3.0.0'
+ static def espresso = '3.0.1'
static def junit = '4.12'
- static def testRunner = '1.0.0'
+ static def testRunner = '1.0.1'
static def gradlePlugin = '3.0.1'
static def mavenPlugin = '2.0'
diff --git a/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/CircleView.kt b/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/CircleView.kt
index c74cba1..fe7a7a6 100644
--- a/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/CircleView.kt
+++ b/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/CircleView.kt
@@ -45,6 +45,8 @@ class CircleView @JvmOverloads constructor(context: Context, attrs: AttributeSet
private val outerPaint: Paint = Paint().apply { isAntiAlias = true }
private val whitePaint: Paint = Paint().apply { isAntiAlias = true; color = Color.WHITE }
private val innerPaint: Paint = Paint().apply { isAntiAlias = true }
+ val colorSelected: Boolean
+ get() = selected
private var selected: Boolean = false
var withBorder: Boolean = false
set(value) {
@@ -107,25 +109,16 @@ class CircleView @JvmOverloads constructor(context: Context, attrs: AttributeSet
fun animateSelected(selected: Boolean) {
if (this.selected == selected) return
- this.selected = true // We need to draw the other bands
+ this.selected = selected // We need to draw the other bands
val range = if (selected) Pair(-borderWidthSmall, borderWidthLarge) else Pair(borderWidthLarge, -borderWidthSmall)
- val animator = ValueAnimator.ofFloat(range.first, range.second)
- with(animator) {
+ ValueAnimator.ofFloat(range.first, range.second).apply {
reverse()
duration = 150L
addUpdateListener { animation ->
whiteOuterBound = animation.animatedValue as Float
invalidate()
+
}
- addListener(object : AnimatorListenerAdapter() {
- override fun onAnimationEnd(animation: Animator) {
- this@CircleView.selected = selected
- }
-
- override fun onAnimationCancel(animation: Animator) {
- this@CircleView.selected = selected
- }
- })
start()
}
}
diff --git a/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/ColorPickerDialog.kt b/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/ColorPickerDialog.kt
index a3dcc2d..ccebb71 100644
--- a/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/ColorPickerDialog.kt
+++ b/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/ColorPickerDialog.kt
@@ -31,19 +31,26 @@ class ColorBuilder : ColorContract {
interface ColorContract {
var title: String?
- var titleRes: Int @StringRes set
+ @setparam:StringRes
+ var titleRes: Int
var allowCustom: Boolean
var allowCustomAlpha: Boolean
var isAccent: Boolean
- var defaultColor: Int @StringRes set
- var doneText: Int @StringRes set
- var backText: Int @StringRes set
- var cancelText: Int @StringRes set
+ @setparam:StringRes
+ var defaultColor: Int
+ @setparam:StringRes
+ var doneText: Int
+ @setparam:StringRes
+ var backText: Int
+ @setparam:StringRes
+ var cancelText: Int
+ @setparam:StringRes
var presetText: Int
- @StringRes set
- var customText: Int @StringRes set
+ @setparam:StringRes
+ var customText: Int
var dynamicButtonColors: Boolean
- var circleSizeRes: Int @DimenRes set
+ @setparam:DimenRes
+ var circleSizeRes: Int
var colorCallback: ((selectedColor: Int) -> Unit)?
var colorsTop: IntArray?
var colorsSub: Array<IntArray>?
diff --git a/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/ColorPickerView.kt b/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/ColorPickerView.kt
index 778b775..dfb0773 100644
--- a/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/ColorPickerView.kt
+++ b/colorpicker/src/main/kotlin/ca/allanwang/kau/colorpicker/ColorPickerView.kt
@@ -26,21 +26,23 @@ import java.util.*
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()
+ val selectedColor: Int
+ get() = _selectedColor
+ private var _selectedColor: Int = -1
+ private var isInSub: Boolean = false
+ private var isInCustom: Boolean = false
+ private var circleSize: Int = context.dimen(R.dimen.kau_color_circle_size).toInt()
@SuppressLint("PrivateResource")
- val backgroundColor = context.resolveColor(R.attr.md_background_color,
+ private val backgroundColor = context.resolveColor(R.attr.md_background_color,
if (context.resolveColor(android.R.attr.textColorPrimary).isColorDark) Color.WHITE else 0xff424242.toInt())
- val backgroundColorTint = backgroundColor.colorToForeground()
- lateinit var dialog: MaterialDialog
- lateinit var builder: ColorContract
- lateinit var colorsTop: IntArray
- var colorsSub: Array<IntArray>? = null
- var topIndex: Int = -1
- var subIndex: Int = -1
- var colorIndex: Int
+ private val backgroundColorTint = backgroundColor.colorToForeground()
+ private lateinit var dialog: MaterialDialog
+ private lateinit var builder: ColorContract
+ private lateinit var colorsTop: IntArray
+ private var colorsSub: Array<IntArray>? = null
+ private var topIndex: Int = -1
+ private var subIndex: Int = -1
+ private var colorIndex: Int
get() = if (isInSub) subIndex else topIndex
set(value) {
if (isInSub) subIndex = value
@@ -54,24 +56,29 @@ internal class ColorPickerView @JvmOverloads constructor(
}
}
- 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)
+ private val gridView: FillGridView by bindView(R.id.md_grid)
+ private val customFrame: LinearLayout by bindView(R.id.md_colorChooserCustomFrame)
+ private val customColorIndicator: View by bindView(R.id.md_colorIndicator)
+ private val hexInput: EditText by bindView(R.id.md_hexInput)
+ private val alphaLabel: TextView by bindView(R.id.md_colorALabel)
+ private val alphaSeekbar: SeekBar by bindView(R.id.md_colorA)
+ private val alphaValue: TextView by bindView(R.id.md_colorAValue)
+ private val redSeekbar: SeekBar by bindView(R.id.md_colorR)
+ private val redValue: TextView by bindView(R.id.md_colorRValue)
+ private val greenSeekbar: SeekBar by bindView(R.id.md_colorG)
+ private val greenValue: TextView by bindView(R.id.md_colorGValue)
+ private val blueSeekbar: SeekBar by bindView(R.id.md_colorB)
+ private val blueValue: TextView by bindView(R.id.md_colorBValue)
- var customHexTextWatcher: TextWatcher? = null
- var customRgbListener: SeekBar.OnSeekBarChangeListener? = null
+ private var customHexTextWatcher: TextWatcher? = null
+ private var customRgbListener: SeekBar.OnSeekBarChangeListener? = null
init {
+ init()
+ }
+
+ @SuppressLint("PrivateResource")
+ private fun init() {
View.inflate(context, R.layout.md_dialog_colorchooser, this)
}
@@ -79,29 +86,33 @@ internal class ColorPickerView @JvmOverloads constructor(
this.builder = builder
this.dialog = dialog
this.colorsTop = with(builder) {
- if (colorsTop != null) colorsTop!!
- else if (isAccent) ColorPalette.ACCENT_COLORS
- else ColorPalette.PRIMARY_COLORS
+ when {
+ colorsTop != null -> colorsTop!!
+ isAccent -> ColorPalette.ACCENT_COLORS
+ else -> ColorPalette.PRIMARY_COLORS
+ }
}
this.colorsSub = with(builder) {
- if (colorsTop != null) colorsSub
- else if (isAccent) ColorPalette.ACCENT_COLORS_SUB
- else ColorPalette.PRIMARY_COLORS_SUB
+ when {
+ colorsTop != null -> colorsSub
+ isAccent -> ColorPalette.ACCENT_COLORS_SUB
+ else -> ColorPalette.PRIMARY_COLORS_SUB
+ }
}
- this.selectedColor = builder.defaultColor
+ this._selectedColor = builder.defaultColor
if (builder.allowCustom) {
if (!builder.allowCustomAlpha) {
alphaLabel.gone()
alphaSeekbar.gone()
alphaValue.gone()
- hexInput.hint = String.format("%06X", selectedColor)
+ hexInput.hint = String.format("%06X", _selectedColor)
hexInput.filters = arrayOf(InputFilter.LengthFilter(6))
} else {
- hexInput.hint = String.format("%08X", selectedColor)
+ hexInput.hint = String.format("%08X", _selectedColor)
hexInput.filters = arrayOf(InputFilter.LengthFilter(8))
}
}
- if (findColor(builder.defaultColor) || !builder.allowCustom) isInCustom = true //when toggled this will be false
+ if (findColor(_selectedColor) || !builder.allowCustom) isInCustom = true // when toggled this will be false
toggleCustom()
}
@@ -127,21 +138,20 @@ internal class ColorPickerView @JvmOverloads constructor(
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
- selectedColor = try {
+ _selectedColor = try {
Color.parseColor("#$s")
} catch (e: IllegalArgumentException) {
Color.BLACK
}
-
- customColorIndicator.setBackgroundColor(selectedColor)
+ customColorIndicator.setBackgroundColor(_selectedColor)
if (alphaSeekbar.isVisible) {
- val alpha = Color.alpha(selectedColor)
+ 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)
+ redSeekbar.progress = Color.red(_selectedColor)
+ greenSeekbar.progress = Color.green(_selectedColor)
+ blueSeekbar.progress = Color.blue(_selectedColor)
isInSub = false
topIndex = -1
subIndex = -1
@@ -150,7 +160,7 @@ internal class ColorPickerView @JvmOverloads constructor(
override fun afterTextChanged(s: Editable?) {}
}
- hexInput.setText(selectedColor.toHexString(builder.allowCustomAlpha, false))
+ hexInput.setText(_selectedColor.toHexString(builder.allowCustomAlpha, false))
hexInput.addTextChangedListener(customHexTextWatcher)
customRgbListener = object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
@@ -181,11 +191,11 @@ internal class ColorPickerView @JvmOverloads constructor(
blueSeekbar.setOnSeekBarChangeListener(customRgbListener)
if (alphaSeekbar.isVisible)
alphaSeekbar.setOnSeekBarChangeListener(customRgbListener)
- hexInput.setText(selectedColor.toHexString(alphaSeekbar.isVisible, false))
+ hexInput.setText(_selectedColor.toHexString(alphaSeekbar.isVisible, false))
gridView.fadeOut(onFinish = { gridView.gone() })
customFrame.fadeIn()
} else {
- findColor(selectedColor)
+ findColor(_selectedColor)
if (builder.allowCustom) dialog.setActionButton(DialogAction.NEUTRAL, builder.customText)
dialog.setActionButton(DialogAction.NEGATIVE, if (isInSub) builder.backText else builder.cancelText)
gridView.fadeIn(onStart = this::invalidateGrid)
@@ -201,9 +211,9 @@ internal class ColorPickerView @JvmOverloads constructor(
}
fun refreshColors() {
- if (!isInCustom) findColor(selectedColor)
- //Ensure that our tinted color is still visible against the background
- val visibleColor = if (selectedColor.isColorVisibleOn(backgroundColor)) selectedColor else backgroundColorTint
+ if (!isInCustom) findColor(_selectedColor)
+ // Ensure that our tinted color is still visible against the background
+ val visibleColor = if (_selectedColor.isColorVisibleOn(backgroundColor)) _selectedColor else backgroundColorTint
if (builder.dynamicButtonColors) {
dialog.getActionButton(DialogAction.POSITIVE).setTextColor(visibleColor)
dialog.getActionButton(DialogAction.NEGATIVE).setTextColor(visibleColor)
@@ -222,11 +232,8 @@ internal class ColorPickerView @JvmOverloads constructor(
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
+ // First check for sub colors, then if the top color matches
+ if (findSubColor(color, index) || topColor == color) {
topIndex = index
return true
}
@@ -235,14 +242,8 @@ internal class ColorPickerView @JvmOverloads constructor(
}
private 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
+ subIndex = colorsSub?.getOrNull(topIndex)?.indexOfFirst { color == it } ?: -1
+ return subIndex != -1
}
private fun invalidateGrid() {
@@ -256,50 +257,53 @@ internal class ColorPickerView @JvmOverloads constructor(
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(":")
- if (colorIndex == tags[0].toInt()) {
- colorIndex = tags[0].toInt() //Go to sub list if exists
- return
- }
- if (colorIndex != -1) (gridView.getChildAt(colorIndex) as CircleView).animateSelected(false)
- selectedColor = tags[1].toInt()
- refreshColors()
- val currentSub = isInSub
- colorIndex = tags[0].toInt()
- if (currentSub == isInSub) (gridView.getChildAt(colorIndex) as CircleView).animateSelected(true)
- //Otherwise we are invalidating our grid, so there is no point in animating
- }
+ val (pos, color) = v.tagData ?: return
+ if (colorIndex == pos && isInSub)
+ return
+ circleAt(colorIndex)?.animateSelected(false)
+ _selectedColor = color
+ colorIndex = pos
+ refreshColors()
+ if (isInSub)
+ circleAt(colorIndex)?.animateSelected(true)
+ // Otherwise we are invalidating our grid, so there is no point in animating
}
- 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
+ private fun circleAt(index: Int): CircleView? =
+ if (index == -1) null
+ else gridView.getChildAt(index) as? CircleView
+
+ private val View.tagData: Pair<Int, Int>?
+ get() {
+ val tags = (tag as? String)?.split(":") ?: return null
+ val pos = tags[0].toIntOrNull() ?: return null
+ val color = tags[1].toIntOrNull() ?: return null
+ return pos to color
}
- return false
+
+ override fun onLongClick(v: View): Boolean {
+ val (_, color) = v.tagData ?: return false
+ (v as? CircleView)?.showHint(color) ?: return false
+ return true
}
- override fun getItem(position: Int): Any = if (isInSub) colorsSub!![topIndex][position] else colorsTop[position]
+ override fun getItem(position: Int): Int = 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]
+ val view: CircleView = convertView as? CircleView ?: CircleView(context).apply {
+ layoutParams = AbsListView.LayoutParams(circleSize, circleSize)
+ setOnClickListener(this@ColorGridAdapter)
+ setOnLongClickListener(this@ColorGridAdapter)
+ }
+ val color: Int = getItem(position)
return view.apply {
setBackgroundColor(color)
isSelected = colorIndex == position
tag = "$position:$color"
- setOnClickListener(this@ColorGridAdapter)
- setOnLongClickListener(this@ColorGridAdapter)
}
}
}
diff --git a/core/build.gradle b/core/build.gradle
index a2d1dd3..046a734 100644
--- a/core/build.gradle
+++ b/core/build.gradle
@@ -5,6 +5,7 @@ apply from: '../android-lib.gradle'
dependencies {
api kauDependency.kotlin
+ api "com.android.support:support-annotations:${kau.supportLibs}"
api "com.android.support:appcompat-v7:${kau.supportLibs}"
api "com.android.support:support-v13:${kau.supportLibs}"
api "com.android.support:design:${kau.supportLibs}"
diff --git a/core/src/androidTest/kotlin/ca/allanwang/kau/xml/ChangelogTest.kt b/core/src/androidTest/kotlin/ca/allanwang/kau/xml/ChangelogTest.kt
deleted file mode 100644
index 1a0eaac..0000000
--- a/core/src/androidTest/kotlin/ca/allanwang/kau/xml/ChangelogTest.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-package ca.allanwang.kau.xml
-
-import android.support.test.filters.MediumTest
-import android.support.test.runner.AndroidJUnit4
-import org.junit.runner.RunWith
-
-/**
- * Created by Allan Wang on 2017-07-31.
- */
-@RunWith(AndroidJUnit4::class)
-@MediumTest
-class ChangelogTest {
-
- // @Test //todo internal function sharing is only available on gradle 3.0.0+
- fun simpleTest() {
-// val data = parse(InstrumentationRegistry.getTargetContext(), R.xml.test_changelog)
- }
-
-} \ No newline at end of file
diff --git a/core/src/androidTest/kotlin/ca/allanwang/kau/xml/FaqTest.kt b/core/src/androidTest/kotlin/ca/allanwang/kau/xml/FaqTest.kt
index c2ffa8a..b396985 100644
--- a/core/src/androidTest/kotlin/ca/allanwang/kau/xml/FaqTest.kt
+++ b/core/src/androidTest/kotlin/ca/allanwang/kau/xml/FaqTest.kt
@@ -19,10 +19,10 @@ class FaqTest {
fun simpleTest() {
InstrumentationRegistry.getTargetContext().kauParseFaq(R.xml.test_faq) { data ->
assertEquals(2, data.size, "FAQ size is incorrect")
- assertEquals("1. This is a question", data.first().first.toString(), "First question does not match")
- assertEquals("This is an answer", data.first().second.toString(), "First answer does not match")
- assertEquals("2. This is another question", data.last().first.toString(), "Second question does not match")
- assertEquals("This is another answer", data.last().second.toString(), "Second answer does not match")
+ assertEquals("1. This is a question", data.first().question.toString(), "First question does not match")
+ assertEquals("This is an answer", data.first().answer.toString(), "First answer does not match")
+ assertEquals("2. This is another question", data.last().question.toString(), "Second question does not match")
+ assertEquals("This is another answer", data.last().answer.toString(), "Second answer does not match")
}
}
@@ -30,10 +30,10 @@ class FaqTest {
fun withoutNumbering() {
InstrumentationRegistry.getTargetContext().kauParseFaq(R.xml.test_faq, false) { data ->
assertEquals(2, data.size, "FAQ size is incorrect")
- assertEquals("This is a question", data.first().first.toString(), "First question does not match")
- assertEquals("This is an answer", data.first().second.toString(), "First answer does not match")
- assertEquals("This is another question", data.last().first.toString(), "Second question does not match")
- assertEquals("This is another answer", data.last().second.toString(), "Second answer does not match")
+ assertEquals("This is a question", data.first().question.toString(), "First question does not match")
+ assertEquals("This is an answer", data.first().answer.toString(), "First answer does not match")
+ assertEquals("This is another question", data.last().question.toString(), "Second question does not match")
+ assertEquals("This is another answer", data.last().answer.toString(), "Second answer does not match")
}
}
diff --git a/core/src/main/kotlin/ca/allanwang/kau/kotlin/Debouncer.kt b/core/src/main/kotlin/ca/allanwang/kau/kotlin/Debouncer.kt
index 4c27e19..de5d148 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/kotlin/Debouncer.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/kotlin/Debouncer.kt
@@ -40,7 +40,11 @@ open class Debouncer(var interval: Long) {
* Call to cancel all pending requests and shutdown the thread pool
* The debouncer cannot be used after this
*/
- fun terminate() = sched.shutdownNow()
+ fun terminate() {
+ task?.invalidate()
+ task = null
+ sched.shutdownNow()
+ }
/**
* Invalidate any pending tasks
diff --git a/core/src/main/kotlin/ca/allanwang/kau/kotlin/LazyContext.kt b/core/src/main/kotlin/ca/allanwang/kau/kotlin/LazyContext.kt
index 7e0fe70..ab531bd 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/kotlin/LazyContext.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/kotlin/LazyContext.kt
@@ -14,7 +14,6 @@ import android.view.animation.Interpolator
* Items are retrieved using delegateName(context)
*
*/
-
fun lazyInterpolator(@InterpolatorRes id: Int) = lazyContext<Interpolator> { AnimationUtils.loadInterpolator(it, id) }
fun lazyAnimation(@AnimRes id: Int) = lazyContext<Animation> { AnimationUtils.loadAnimation(it, id) }
diff --git a/core/src/main/kotlin/ca/allanwang/kau/ui/ProgressAnimator.kt b/core/src/main/kotlin/ca/allanwang/kau/ui/ProgressAnimator.kt
index dc10e71..e37e59f 100644
--- a/core/src/main/kotlin/ca/allanwang/kau/ui/ProgressAnimator.kt
+++ b/core/src/main/kotlin/ca/allanwang/kau/ui/ProgressAnimator.kt
@@ -77,6 +77,10 @@ class ProgressAnimator private constructor(private vararg val values: Float) {
override fun onAnimationEnd(animation: Animator?) {
endActions.forEach { it() }
}
+
+ override fun onAnimationCancel(animation: Animator?) {
+ endActions.forEach { it() }
+ }
})
extraConfigs()
start()
diff --git a/docs/Changelog.md b/docs/Changelog.md
index 782db6e..d5b8d5b 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -1,5 +1,13 @@
# Changelog
+## v3.6.4
+* :core: Fix potential NPE in restart()
+* :core: Create restartApplication()
+* :colorpicker: Rewrote implementation to be null and parse safe
+* :colorpicker: Added more encapsulation to CircleView (selected -> colorSelected; all others are private)
+* :colorpicker:
+* Update documentation
+
## v3.6.3
* :core: Check for tablet in email builder
* :kpref-activity: Simplify internal code and add better encapsulation
@@ -211,5 +219,5 @@
## v1.0
* Initial Changelog
* Create many extension functions
-* Port changelog builer
+* Port changelog builder
* Port ripple canvas
diff --git a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/KPrefBinder.kt b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/KPrefBinder.kt
index 637af03..a9e21ff 100644
--- a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/KPrefBinder.kt
+++ b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/KPrefBinder.kt
@@ -77,7 +77,7 @@ class KPrefAdapterBuilder(val globalOptions: GlobalOptions) {
getter: (() -> T),
setter: ((value: T) -> Unit),
builder: KPrefText.KPrefTextContract<T>.() -> Unit = {})
- = list.add(KPrefText<T>(KPrefText.KPrefTextBuilder<T>(globalOptions, title, getter, setter)
+ = list.add(KPrefText(KPrefText.KPrefTextBuilder(globalOptions, title, getter, setter)
.apply { builder() }))
@KPrefMarker
diff --git a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefItemCore.kt b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefItemCore.kt
index 2afdd2e..992dd28 100644
--- a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefItemCore.kt
+++ b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefItemCore.kt
@@ -4,6 +4,7 @@ import android.annotation.SuppressLint
import android.support.annotation.CallSuper
import android.support.annotation.IdRes
import android.support.annotation.LayoutRes
+import android.support.annotation.StringRes
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
@@ -100,6 +101,7 @@ abstract class KPrefItemCore(val core: CoreContract) : AbstractItem<KPrefItemCor
val globalOptions: GlobalOptions
val titleId: Int
var titleFun: () -> Int
+ @setparam:StringRes
var descRes: Int
var descFun: () -> Int
var iicon: IIcon?
diff --git a/sample/build.gradle b/sample/build.gradle
index 5bbdbb0..fb55b94 100644
--- a/sample/build.gradle
+++ b/sample/build.gradle
@@ -95,13 +95,17 @@ dependencies {
implementation project(':searchview')
implementation project(':mediapicker')
- androidTestImplementation("com.android.support.test.espresso:espresso-core:${kau.espresso}") {
- exclude group: 'com.android.support', module: 'support-annotations'
- }
- androidTestImplementation("com.android.support.test:runner:${kau.testRunner}") {
- exclude group: 'com.android.support', module: 'support-annotations'
- }
- androidTestImplementation kauDependency.kotlinTest
+// androidTestImplementation("com.android.support.test.espresso:espresso-core:${kau.espresso}") {
+// exclude group: 'com.android.support', module: 'support-annotations'
+// }
+// androidTestImplementation("com.android.support.test:runner:${kau.testRunner}") {
+// exclude group: 'com.android.support', module: 'support-annotations'
+// }
+// androidTestImplementation kauDependency.kotlinTest
testImplementation kauDependency.kotlinTest
testImplementation kauDependency.junit
+
+ androidTestImplementation kauDependency.kotlinTest
+ androidTestImplementation kauDependency.espresso
+ androidTestImplementation kauDependency.testRunner
}
diff --git a/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/ColorPickerTest.kt b/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/ColorPickerTest.kt
new file mode 100644
index 0000000..39aee93
--- /dev/null
+++ b/sample/src/androidTest/kotlin/ca/allanwang/kau/sample/ColorPickerTest.kt
@@ -0,0 +1,61 @@
+package ca.allanwang.kau.sample
+
+import android.support.test.espresso.DataInteraction
+import android.support.test.espresso.Espresso.onData
+import android.support.test.espresso.Espresso.onView
+import android.support.test.espresso.ViewAssertion
+import android.support.test.espresso.action.ViewActions.click
+import android.support.test.espresso.matcher.ViewMatchers.withId
+import android.support.test.espresso.matcher.ViewMatchers.withText
+import android.support.test.filters.MediumTest
+import android.support.test.rule.ActivityTestRule
+import android.support.test.runner.AndroidJUnit4
+import android.view.View
+import ca.allanwang.kau.colorpicker.CircleView
+import org.hamcrest.Matchers.anything
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import kotlin.test.assertEquals
+import kotlin.test.fail
+
+
+/**
+ * Created by Allan Wang on 22/02/2018.
+ */
+@RunWith(AndroidJUnit4::class)
+@MediumTest
+class ColorPickerTest {
+
+ @get:Rule
+ val activity: ActivityTestRule<MainActivity> = ActivityTestRule(MainActivity::class.java)
+
+ private fun DataInteraction.click(position: Int) =
+ atPosition(position).perform(click())
+
+ private fun View.colorSelected(selected: Boolean) {
+ val circle = this as? CircleView ?: fail("View is not a CircleView")
+ assertEquals(selected, circle.colorSelected, "CircleView ${circle.tag} ${if (selected) "is not" else "is"} actually selected")
+ }
+
+ private val colorSelected = ViewAssertion { view, _ -> view.colorSelected(true) }
+
+ private val colorNotSelected = ViewAssertion { view, _ -> view.colorSelected(false) }
+
+ @Test
+ fun test() {
+ onView(withText(R.string.accent_color)).perform(click())
+ val colors = onData(anything()).inAdapterView(withId(R.id.md_grid))
+
+ colors.click(0).check(colorNotSelected) // enter sub grid
+ colors.click(0).check(colorSelected) // click first grid item
+ colors.atPosition(1).check(colorNotSelected)
+ colors.atPosition(2).check(colorNotSelected)
+ .perform(click()).check(colorSelected)
+ colors.atPosition(0).check(colorNotSelected)
+ .perform(click()).check(colorSelected)
+ // first item is now selected
+ }
+
+
+}
diff --git a/sample/src/main/res/xml/kau_changelog.xml b/sample/src/main/res/xml/kau_changelog.xml
index 146042c..40ca6a0 100644
--- a/sample/src/main/res/xml/kau_changelog.xml
+++ b/sample/src/main/res/xml/kau_changelog.xml
@@ -9,7 +9,9 @@
<version title="v3.6.4" />
<item text=":core: Fix potential NPE in restart()" />
<item text=":core: Create restartApplication()" />
- <item text="" />
+ <item text=":colorpicker: Rewrote implementation to be null and parse safe" />
+ <item text=":colorpicker: Added more encapsulation to CircleView (selected -> colorSelected; all others are private)" />
+ <item text=":colorpicker:" />
<item text="Update documentation" />
<item text="" />
@@ -224,6 +226,6 @@
<version title="v1.0" />
<item text="Initial Changelog" />
<item text="Create many extension functions" />
- <item text="Port changelog builer" />
+ <item text="Port changelog builder" />
<item text="Port ripple canvas" />
</resources> \ No newline at end of file
diff --git a/searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt b/searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt
index 19f1a36..52a88a0 100644
--- a/searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt
+++ b/searchview/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt
@@ -230,7 +230,7 @@ class SearchView @JvmOverloads constructor(
}
private val configs = Configs()
- //views
+ // views
private val shadow: View by bindView(R.id.kau_search_shadow)
private val card: BoundedCardView by bindView(R.id.kau_search_cardview)
private val iconNav: ImageView by bindView(R.id.kau_search_nav)