From 1a509b896aa670da4ab3e2f039140ad7608387e9 Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Sun, 24 Sep 2017 16:41:13 -0400 Subject: Feature/kpref time picker (#64) * Init kpref time builder and open up other builders * Enable self refresh * Add readme * Update changelog * Update readme --- core/README.md | 4 +- core/src/main/res/values/ids.xml | 1 + docs/Changelog.md | 1 + kpref-activity/README.md | 2 + .../ca/allanwang/kau/kpref/activity/KPrefBinder.kt | 8 +++ .../kau/kpref/activity/items/KPrefColorPicker.kt | 2 +- .../kau/kpref/activity/items/KPrefPlainText.kt | 2 +- .../kau/kpref/activity/items/KPrefSubItems.kt | 2 +- .../kau/kpref/activity/items/KPrefText.kt | 2 +- .../kau/kpref/activity/items/KPrefTimePicker.kt | 64 ++++++++++++++++++++++ .../kotlin/ca/allanwang/kau/sample/KPrefSample.kt | 3 + .../kotlin/ca/allanwang/kau/sample/MainActivity.kt | 31 ++++++----- sample/src/main/res/values/strings.xml | 3 + sample/src/main/res/xml/kau_changelog.xml | 8 ++- 14 files changed, 110 insertions(+), 23 deletions(-) create mode 100644 kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefTimePicker.kt diff --git a/core/README.md b/core/README.md index 4cb68d0..39899dd 100644 --- a/core/README.md +++ b/core/README.md @@ -178,7 +178,7 @@ KAU's swipe is a Kotlin rewrite, along with support for all directions and weakl # Debounce Debouncing is a means of throttling a function so that it is called no more than once in a given instance of time. -An example where you'd like this behaviour is the searchview; you want to deliver search results quickly, +An example where you'd like this behaviour is the searchview: you want to deliver search results quickly, but you don't want to update your response with each new character. Instead, you can wait until a user finishes their query, then search for the results. @@ -210,7 +210,7 @@ Include your email and subject, along with other optional configurations such as ## Extension Functions > "[Extensions](https://kotlinlang.org/docs/reference/extensions.html) provide the ability to extend a class with new functionality without having to inherit from the class" -Note that since KAU depends on [ANKO](https://github.com/Kotlin/anko), all of the extensions in its core package is also in KAU. +
Note that since KAU depends on [ANKO](https://github.com/Kotlin/anko), all of the extensions in its core package is also in KAU. KAU's vast collection of extensions is one of its strongest features. There are too many to explain here, but you may check out the [utils package](https://github.com/AllanWang/KAU/tree/master/core/src/main/kotlin/ca/allanwang/kau/utils) diff --git a/core/src/main/res/values/ids.xml b/core/src/main/res/values/ids.xml index c4912e2..28ff9d9 100644 --- a/core/src/main/res/values/ids.xml +++ b/core/src/main/res/values/ids.xml @@ -14,6 +14,7 @@ + diff --git a/docs/Changelog.md b/docs/Changelog.md index 70a61ee..6c5bb11 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -3,6 +3,7 @@ ## v3.4.1 * Validate context before showing dialogs * Add intent resolver checks prior to all executions. +* Fix bundle NPE when starting activity ## v3.4.0 * Update to gradle 4.x; api and implementation rather than compile diff --git a/kpref-activity/README.md b/kpref-activity/README.md index a9aac89..69d4892 100644 --- a/kpref-activity/README.md +++ b/kpref-activity/README.md @@ -30,6 +30,7 @@ Contract | Mandatory | Optional | Description `KPrefSeekbarContract` | `NA` | `min` `max` `increments` `toText` `textViewConfigs` | Addtional configurations for a seekbar, as well as text to be displayed on the side. `KPrefSubItemsContract` | `itemBuilder` | `NA` | Contains a new list for the adapter to load when clicked `KPrefTextContract` | `NA` | `textGetter` | Additional configurations for the text item +`KPrefTimeContract` | `NA` | `use24HourFormat` | Additional configurations for time picker The kpref items are as followed: @@ -41,6 +42,7 @@ Item | Implements | Description `header` | `CoreContract` | Header; just a title that isn't clickable `text` | `CoreContract` `BaseContract` `KPrefTextContract` | Text item; displays the kpref as a String on the right; does not have click implementation by default `plainText` | `CoreContract` `BaseContract` | Plain text item; like `text` but does not deal with any preferences directly, so it doesn't need a getter or setter +`timePicker` | `CoreContract` `BaseContract` `KPrefTextContract`, `KPrefTimeContract` | Extension ot `text` that will open and save a time picker This can be used to display text or deal with preference that are completely handed within the click event (eg a dialog). `subItems` | `CoreContract` `KPrefSubItemsContract` | Sub items; contains a new page for the activity to load when clicked 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 35821fd..637af03 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 @@ -101,6 +101,14 @@ class KPrefAdapterBuilder(val globalOptions: GlobalOptions) { = list.add(KPrefSeekbar(KPrefSeekbar.KPrefSeekbarBuilder(globalOptions, title, getter, setter) .apply { builder() })) + @KPrefMarker + fun timePicker(@StringRes title: Int, + getter: (() -> Int), + setter: ((value: Int) -> Unit), + builder: KPrefTimePicker.KPrefTimeContract.() -> Unit = {}) + = list.add(KPrefTimePicker(KPrefTimePicker.KPrefTimeBuilder(globalOptions, title, getter, setter) + .apply { builder() })) + @KPrefMarker val list: MutableList = mutableListOf() } \ No newline at end of file diff --git a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefColorPicker.kt b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefColorPicker.kt index 315d67b..1950589 100644 --- a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefColorPicker.kt +++ b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefColorPicker.kt @@ -14,7 +14,7 @@ import ca.allanwang.kau.kpref.activity.R * ColorPicker preference * When a color is successfully selected in the dialog, it will be saved as an int */ -open class KPrefColorPicker(val builder: KPrefColorContract) : KPrefItemBase(builder) { +open class KPrefColorPicker(open val builder: KPrefColorContract) : KPrefItemBase(builder) { override fun onPostBindView(viewHolder: ViewHolder, textColor: Int?, accentColor: Int?) { super.onPostBindView(viewHolder, textColor, accentColor) diff --git a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefPlainText.kt b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefPlainText.kt index b83df69..d2e49d8 100644 --- a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefPlainText.kt +++ b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefPlainText.kt @@ -12,7 +12,7 @@ import ca.allanwang.kau.kpref.activity.R * and when the preference is completely handled by the click * */ -open class KPrefPlainText(val builder: KPrefPlainTextBuilder) : KPrefItemBase(builder) { +open class KPrefPlainText(open val builder: KPrefPlainTextBuilder) : KPrefItemBase(builder) { override fun defaultOnClick(itemView: View, innerContent: View?): Boolean { //nothing diff --git a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefSubItems.kt b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefSubItems.kt index 1bf0ffc..7c2979c 100644 --- a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefSubItems.kt +++ b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefSubItems.kt @@ -12,7 +12,7 @@ import ca.allanwang.kau.kpref.activity.R * When clicked, will navigate to a new set of preferences and add the old list to a stack * */ -open class KPrefSubItems(val builder: KPrefSubItemsContract) : KPrefItemCore(builder) { +open class KPrefSubItems(open val builder: KPrefSubItemsContract) : KPrefItemCore(builder) { override fun onClick(itemView: View, innerContent: View?): Boolean { builder.globalOptions.showNextPrefs(builder.titleRes, builder.itemBuilder) diff --git a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefText.kt b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefText.kt index 45c9a5d..29dd007 100644 --- a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefText.kt +++ b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefText.kt @@ -14,7 +14,7 @@ import ca.allanwang.kau.utils.toast * This is still a generic preference * */ -open class KPrefText(val builder: KPrefTextContract) : KPrefItemBase(builder) { +open class KPrefText(open val builder: KPrefTextContract) : KPrefItemBase(builder) { /** * Automatically reload on set diff --git a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefTimePicker.kt b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefTimePicker.kt new file mode 100644 index 0000000..d4f854b --- /dev/null +++ b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefTimePicker.kt @@ -0,0 +1,64 @@ +package ca.allanwang.kau.kpref.activity.items + +import android.app.TimePickerDialog +import android.view.View +import android.widget.TimePicker +import ca.allanwang.kau.kpref.activity.GlobalOptions +import ca.allanwang.kau.kpref.activity.R +import java.util.* + +/** + * Created by Allan Wang on 2017-06-14. + * + * Text preference + * Holds a textview to display data on the right + * This is still a generic preference + * + */ +open class KPrefTimePicker(override val builder: KPrefTimeContract) : KPrefText(builder) { + + interface KPrefTimeContract : KPrefText.KPrefTextContract { + var use24HourFormat: Boolean + } + + /** + * Default implementation of [KPrefTimeContract] + */ + class KPrefTimeBuilder( + globalOptions: GlobalOptions, + titleRes: Int, + getter: () -> Int, + setter: (value: Int) -> Unit + ) : KPrefTimeContract, BaseContract by BaseBuilder(globalOptions, titleRes, getter, setter), TimePickerDialog.OnTimeSetListener { + + override var use24HourFormat: Boolean = false + + override fun onTimeSet(view: TimePicker, hourOfDay: Int, minute: Int) { + setter((hourOfDay to minute).mergeTime) + reloadSelf() + } + + override var textGetter: (Int) -> String? = { + val (hour, min) = it.splitTime + if (use24HourFormat) + String.format(Locale.CANADA, "%d:%02d", hour, min) + else + String.format(Locale.CANADA, "%d:%02d %s", hour % 12, min, if (hour >= 12) "PM" else "AM") + } + + override var onClick: ((itemView: View, innerContent: View?, item: KPrefItemBase) -> Boolean)? = { itemView, _, item -> + val (hour, min) = item.pref.splitTime + TimePickerDialog(itemView.context, this, hour, min, use24HourFormat).show() + true + } + + private val Int.splitTime: Pair + get() = Pair(this / 100, this % 100) + + private val Pair.mergeTime: Int + get() = first * 100 + second + } + + override fun getType(): Int = R.id.kau_item_pref_time_picker + +} \ No newline at end of file diff --git a/sample/src/main/kotlin/ca/allanwang/kau/sample/KPrefSample.kt b/sample/src/main/kotlin/ca/allanwang/kau/sample/KPrefSample.kt index 9adabed..0c243e4 100644 --- a/sample/src/main/kotlin/ca/allanwang/kau/sample/KPrefSample.kt +++ b/sample/src/main/kotlin/ca/allanwang/kau/sample/KPrefSample.kt @@ -17,4 +17,7 @@ object KPrefSample : KPref() { var check3: Boolean by kpref("check3", false) var text: String by kpref("text", "empty") var seekbar: Int by kpref("seekbar", 20) + var time12: Int by kpref("time_12", 315) + var time24: Int by kpref("time_24", 2220) + } \ No newline at end of file diff --git a/sample/src/main/kotlin/ca/allanwang/kau/sample/MainActivity.kt b/sample/src/main/kotlin/ca/allanwang/kau/sample/MainActivity.kt index 1528970..ca75ebb 100644 --- a/sample/src/main/kotlin/ca/allanwang/kau/sample/MainActivity.kt +++ b/sample/src/main/kotlin/ca/allanwang/kau/sample/MainActivity.kt @@ -107,8 +107,7 @@ class MainActivity : KPrefActivity() { checkbox(R.string.checkbox_3, { KPrefSample.check3 }, { KPrefSample.check3 = it }) { descRes = R.string.desc_dependent enabler = { KPrefSample.check2 } - onDisabledClick = { - itemView, _, _ -> + onDisabledClick = { itemView, _, _ -> itemView.context.toast("I am still disabled") true } @@ -140,8 +139,7 @@ class MainActivity : KPrefActivity() { text(R.string.text, { KPrefSample.text }, { KPrefSample.text = it }) { descRes = R.string.text_desc - onClick = { - itemView, _, item -> + onClick = { itemView, _, item -> itemView.context.materialDialog { title("Type Text") input("Type here", item.pref, { _, input -> item.pref = input.toString() }) @@ -193,17 +191,25 @@ class MainActivity : KPrefActivity() { textGetter = { string(R.string.kau_lorem_ipsum) } } + timePicker(R.string.time, { KPrefSample.time12 }, { KPrefSample.time12 = it }) { + descRes = R.string.time_desc_12 + use24HourFormat = false + } + + timePicker(R.string.time, { KPrefSample.time24 }, { KPrefSample.time24 = it }) { + descRes = R.string.time_desc_24 + use24HourFormat = true + } + } fun subPrefs(): KPrefAdapterBuilder.() -> Unit = { text(R.string.text, { KPrefSample.text }, { KPrefSample.text = it }) { descRes = R.string.text_desc - onClick = { - itemView, _, item -> + onClick = { itemView, _, item -> itemView.context.materialDialog { title("Type Text") - input("Type here", item.pref, { - _, input -> + input("Type here", item.pref, { _, input -> item.pref = input.toString() reloadSelf() }) @@ -237,21 +243,18 @@ class MainActivity : KPrefActivity() { menuInflater.inflate(R.menu.menu_main, menu) if (searchView == null) searchView = bindSearchView(menu, R.id.action_search) { - textCallback = { - query, searchView -> + textCallback = { query, searchView -> val items = wordBank.filter { it.contains(query) }.sorted().map { SearchItem(it) } searchView.results = items } - searchCallback = { - query, _ -> + searchCallback = { query, _ -> toast("Enter pressed for $query") true } textDebounceInterval = 0 noResultsFound = R.string.kau_no_results_found shouldClearOnClose = false - onItemClick = { - _, _, content, searchView -> + onItemClick = { _, _, content, searchView -> toast(content) searchView.revealClose() } diff --git a/sample/src/main/res/values/strings.xml b/sample/src/main/res/values/strings.xml index a887ad3..1e3361e 100644 --- a/sample/src/main/res/values/strings.xml +++ b/sample/src/main/res/values/strings.xml @@ -15,6 +15,9 @@ Text Pref Saves the text Seekbar + Time Pref + AM PM version + 24h version Sub Item Pref Press this to view the next subset of preferences your.email@here.com diff --git a/sample/src/main/res/xml/kau_changelog.xml b/sample/src/main/res/xml/kau_changelog.xml index 53dfe99..a33edbd 100644 --- a/sample/src/main/res/xml/kau_changelog.xml +++ b/sample/src/main/res/xml/kau_changelog.xml @@ -7,9 +7,11 @@ --> - - - + + + + + -- cgit v1.2.3