From fba4ac38a8e2dff6e53ba8ecccc95dac2550a3fa Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Sat, 12 Aug 2017 19:31:55 -0700 Subject: Feature/kpref activity visibility (#38) * Add visibility toggle * Update docs --- kpref-activity/README.md | 17 +++++++--- .../allanwang/kau/kpref/activity/KPrefActivity.kt | 37 ++++++++++++++++++++-- .../ca/allanwang/kau/kpref/activity/KPrefBinder.kt | 1 + .../kau/kpref/activity/items/KPrefItemCore.kt | 2 ++ .../kau/kpref/activity/items/KPrefSeekbar.kt | 20 ++---------- 5 files changed, 53 insertions(+), 24 deletions(-) (limited to 'kpref-activity') diff --git a/kpref-activity/README.md b/kpref-activity/README.md index 015d0d8..a9aac89 100644 --- a/kpref-activity/README.md +++ b/kpref-activity/README.md @@ -1,7 +1,14 @@ # KAU :kpref-activity KAU supports Preferences that are created without xmls and through AppCompat. -The items are backed by a [FastAdapter](https://github.com/mikepenz/FastAdapter) and support [iicons](https://github.com/mikepenz/Android-Iconics) +The items are backed by a [FastAdapter](https://github.com/mikepenz/FastAdapter) and support [iicons](https://github.com/mikepenz/Android-Iconics). +The logic behind kpref items is that most states are based around callbacks. +As a result, we don't need to hold references of items that may change; +we simply reload the list and all states will be refetched. +This is especially powerful when items are interdependent. +Rather than adding a bunch of calls on one item when its state changes (which we can still do in this lib) +and propagating to other items when necessary, +we may instead reload and have each item verify their states themselves. ![KPref Items Gif](https://raw.githubusercontent.com/AllanWang/Storage-Hub/master/kau/kau_kpref_items.gif) @@ -18,10 +25,11 @@ Contract | Mandatory | Optional | Description :--- | :--- | :--- | :--- `CoreAttributeContract` | `NA` | `textColor` `accentColor` | Defines stylings that are added in every item `CoreContract` | `titleRes` | `descRes` `iicon` | Implemented by every item -`BaseContract` | `getter` `setter` | `enabler` `onClick` `onDisabledClick` | Implemented by every preference item +`BaseContract` | `getter` `setter` | `enabler` `onClick` `onDisabledClick`, `visible` | Implemented by every preference item `KPrefColorContract` | `NA` | `showPreview` | Additional configurations for the color picker -`KPrefTextContract` | `NA` | `textGetter` | Additional configurations for the text item +`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 The kpref items are as followed: @@ -29,9 +37,10 @@ Item | Implements | Description :--- | :--- | :--- `checkbox` | `CoreContract` `BaseContract` | Checkbox item; by default, clicking it will toggle the checkbox and the kpref `colorPicker` | `CoreContract` `BaseContract` `KPrefColorContract` | Color picker item; by default, clicking it will open a dialog which will change the color (int) +`seekbar` | `CoreContract` `BaseContract` `KprefSeekbarContract` | Seekbar item. Takes in a given range and will call the setter whenever a user picks a new value. `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` | `BaseContract` | Plain text item; like `text` but does not deal with any preferences directly, so it doesn't need a getter or setter +`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 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/KPrefActivity.kt b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/KPrefActivity.kt index 900b004..4377631 100644 --- a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/KPrefActivity.kt +++ b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/KPrefActivity.kt @@ -85,26 +85,57 @@ abstract class KPrefActivity : KauBaseActivity(), KPrefActivityContract { recycler.itemAnimator = if (animate && !first) recyclerAnimatorNext else null uiThread { adapter.clear() - adapter.add(items.list) + adapter.add(items.list.filter { it.core.visible() }) toolbar.setTitle(toolbarTitleRes) } } } + /** + * Pops the stack and loads the next kpref list + * Indices are not checked so ensure that this is possible first + */ override fun showPrevPrefs() { kprefStack.pop() val (title, list) = kprefStack.peek() recycler.itemAnimator = if (animate) recyclerAnimatorPrev else null adapter.clear() - adapter.add(list) + adapter.add(list.filter { it.core.visible() }) toolbar.setTitle(title) } + /** + * Check if it's possible to go back a stack + */ + override val hasPrevPrefs + get() = kprefStack.size > 1 + + /** + * Reload the current pref list from the stack. + * This will adjust the list of items change in visibility + */ + fun reloadList() { + recycler.itemAnimator = null + val list = kprefStack.peek().second + adapter.setNewList(list.filter { it.core.visible() }) + } + + /** + * Selectively reload an item based on its index. + * Note that this might not behave as expected if certain items are not visible, + * as those items aren't sent to the adapter. + * + * For those cases, consider using [reloadByTitle] + */ fun reload(vararg index: Int) { if (index.isEmpty()) adapter.notifyAdapterDataSetChanged() else index.forEach { adapter.notifyItemChanged(it) } } + /** + * Iterate through all items and reload if it matches any of the titles + * If multiple items have the same title, they will all be reloaded + */ override fun reloadByTitle(@StringRes vararg title: Int) { if (title.isEmpty()) return adapter.adapterItems.forEachIndexed { index, item -> @@ -120,7 +151,7 @@ abstract class KPrefActivity : KauBaseActivity(), KPrefActivityContract { } fun backPress(): Boolean { - if (kprefStack.size > 1) { + if (hasPrevPrefs) { showPrevPrefs() return true } 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 b45e406..35821fd 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 @@ -30,6 +30,7 @@ class CoreAttributeBuilder : CoreAttributeContract { interface KPrefActivityContract { fun showNextPrefs(@StringRes toolbarTitleRes: Int, builder: KPrefAdapterBuilder.() -> Unit) + val hasPrevPrefs: Boolean fun showPrevPrefs() fun reloadByTitle(@StringRes vararg title: Int) } 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 96f8903..dc74c97 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 @@ -84,6 +84,7 @@ abstract class KPrefItemCore(val core: CoreContract) : AbstractItem Boolean /** * Attempts to reload current item by identifying it with its [titleRes] @@ -98,6 +99,7 @@ abstract class KPrefItemCore(val core: CoreContract) : AbstractItem Boolean = { true } override fun reloadSelf() { globalOptions.reloadByTitle(titleRes) diff --git a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefSeekbar.kt b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefSeekbar.kt index f161382..6a9f6b0 100644 --- a/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefSeekbar.kt +++ b/kpref-activity/src/main/kotlin/ca/allanwang/kau/kpref/activity/items/KPrefSeekbar.kt @@ -28,7 +28,7 @@ open class KPrefSeekbar(val builder: KPrefSeekbarContract) : KPrefItemBase( text.tvc() val seekbar = viewHolder.bindLowerView(R.layout.kau_pref_seekbar) { - it.max = builder.range + it.max = builder.max - builder.min it.incrementProgressBy(builder.increments) it.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { override fun onProgressChanged(sb: SeekBar, progress: Int, fromUser: Boolean) { @@ -55,7 +55,6 @@ open class KPrefSeekbar(val builder: KPrefSeekbarContract) : KPrefItemBase( var min: Int var max: Int var increments: Int - var range: Int /** * Once a seekbar is let go, calculates what text to show in the text view */ @@ -74,23 +73,10 @@ open class KPrefSeekbar(val builder: KPrefSeekbarContract) : KPrefItemBase( ) : KPrefSeekbarContract, BaseContract by BaseBuilder(globalOptions, titleRes, getter, setter) { override var min: Int = 0 - set(value) { - field = value - range = -1 - } + override var max: Int = 100 - set(value) { - field = value - range = -1 - } - override var increments: Int = 1 - override var range: Int = max - min - //value doesn't matter; setting will prompt the check - set(value) { - if (max <= min) throw KPrefException("Range min ($min) must be smaller than max ($max)") - field = max - min - } + override var increments: Int = 1 override var toText: (Int) -> String = { it.toString() } -- cgit v1.2.3