From 621c083b4ee1a81c67665ebf4b442f0ea98b5d4a Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Wed, 21 Jun 2017 21:10:18 -0700 Subject: Remapped kprefs to support sub items --- library/build.gradle | 2 + .../kotlin/ca/allanwang/kau/kpref/KPrefActivity.kt | 77 ++++++++++++++++++++-- .../kotlin/ca/allanwang/kau/kpref/KPrefBinder.kt | 29 +++++--- .../allanwang/kau/kpref/items/KPrefColorPicker.kt | 5 +- .../ca/allanwang/kau/kpref/items/KPrefItemBase.kt | 5 +- .../ca/allanwang/kau/kpref/items/KPrefItemCore.kt | 10 +-- .../ca/allanwang/kau/kpref/items/KPrefSubItems.kt | 44 +++++++++++++ .../ca/allanwang/kau/kpref/items/KPrefText.kt | 5 +- .../kotlin/ca/allanwang/kau/utils/ViewUtils.kt | 8 +-- library/src/main/res/layout/kau_activity_kpref.xml | 4 +- .../kotlin/ca/allanwang/kau/sample/MainActivity.kt | 7 +- sample/src/main/res/menu/menu_main.xml | 7 +- 12 files changed, 166 insertions(+), 37 deletions(-) create mode 100644 library/src/main/kotlin/ca/allanwang/kau/kpref/items/KPrefSubItems.kt diff --git a/library/build.gradle b/library/build.gradle index 0f1282b..feeefa8 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -59,6 +59,8 @@ dependencies { compile "com.mikepenz:iconics-core:${ICONICS}@aar" compile "com.jakewharton.timber:timber:${TIMBER}" + + compile "com.mikepenz:itemanimators:0.5.0@aar" } // build a jar with source files diff --git a/library/src/main/kotlin/ca/allanwang/kau/kpref/KPrefActivity.kt b/library/src/main/kotlin/ca/allanwang/kau/kpref/KPrefActivity.kt index f2f045b..7c4efee 100644 --- a/library/src/main/kotlin/ca/allanwang/kau/kpref/KPrefActivity.kt +++ b/library/src/main/kotlin/ca/allanwang/kau/kpref/KPrefActivity.kt @@ -6,6 +6,9 @@ import android.support.v7.app.AppCompatActivity import android.support.v7.widget.RecyclerView import android.support.v7.widget.Toolbar import android.view.View +import android.view.animation.AnimationUtils +import android.widget.FrameLayout +import android.widget.ViewAnimator import ca.allanwang.kau.R import ca.allanwang.kau.kpref.items.KPrefItemCore import ca.allanwang.kau.utils.bindView @@ -14,13 +17,35 @@ import ca.allanwang.kau.utils.statusBarColor import ca.allanwang.kau.views.RippleCanvas import com.mikepenz.fastadapter.commons.adapters.FastItemAdapter -abstract class KPrefActivity : AppCompatActivity() { +abstract class KPrefActivity : AppCompatActivity(), KPrefActivityContract { - lateinit var adapter: FastItemAdapter - val recycler: RecyclerView by bindView(R.id.kau_recycler) + val adapter: FastItemAdapter + get() = recycler.adapter as FastItemAdapter + val recycler: RecyclerView + get() = prefHolder.currentView as RecyclerView + lateinit var baseRecycler: RecyclerView val bgCanvas: RippleCanvas by bindView(R.id.kau_ripple) val toolbarCanvas: RippleCanvas by bindView(R.id.kau_toolbar_ripple) val toolbar: Toolbar by bindView(R.id.kau_toolbar) + val prefHolder: ViewAnimator by bindView(R.id.kau_holder) + private lateinit var globalOptions: GlobalOptions + + /** + * Core attribute builder that is consistent throughout all items + * Leave blank to use defaults + */ + abstract fun kPrefCoreAttributes(): CoreAttributeContract.() -> Unit + + init { + setup() + } + + private fun setup() { + val core = CoreAttributeBuilder() + val builder = kPrefCoreAttributes() + core.builder() + globalOptions = GlobalOptions(core, this) + } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -30,15 +55,42 @@ abstract class KPrefActivity : AppCompatActivity() { with(supportActionBar!!) { setDisplayHomeAsUpEnabled(true) setDisplayShowHomeEnabled(true) - toolbar.setNavigationOnClickListener { - onBackPressed() - } + toolbar.setNavigationOnClickListener { onBackPressed() } } window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION statusBarColor = 0x30000000 toolbarCanvas.set(resolveColor(R.attr.colorPrimary)) bgCanvas.set(resolveColor(android.R.attr.colorBackground)) - adapter = recycler.setKPrefAdapter(onCreateKPrefs(savedInstanceState)) + with(prefHolder) { + animateFirstView = false + inAnimation = AnimationUtils.loadAnimation(context, R.anim.kau_slide_in_right) + outAnimation = AnimationUtils.loadAnimation(context, R.anim.kau_slide_out_left) + } + showNextPrefs(onCreateKPrefs(savedInstanceState)) + baseRecycler = recycler + } + + override fun showNextPrefs(builder: KPrefAdapterBuilder.() -> Unit) { + val rv = RecyclerView(this).apply { + layoutParams = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT) + setKPrefAdapter(globalOptions, builder) + } + with(prefHolder) { + inAnimation = AnimationUtils.loadAnimation(context, R.anim.kau_slide_in_right) + outAnimation = AnimationUtils.loadAnimation(context, R.anim.kau_slide_out_left) + addView(rv) + showNext() + } + } + + override fun showPrevPrefs() { + val current = prefHolder.currentView + with(prefHolder) { + inAnimation = AnimationUtils.loadAnimation(context, R.anim.kau_slide_in_left) + outAnimation = AnimationUtils.loadAnimation(context, R.anim.kau_slide_out_right) + showPrevious() + removeView(current) + } } fun reload(vararg index: Int) { @@ -56,5 +108,16 @@ abstract class KPrefActivity : AppCompatActivity() { abstract fun onCreateKPrefs(savedInstanceState: Bundle?): KPrefAdapterBuilder.() -> Unit + override fun onBackPressed() { + if (!backPress()) super.onBackPressed() + } + + fun backPress(): Boolean { + if (baseRecycler != recycler) { + showPrevPrefs() + return true + } + return false + } } diff --git a/library/src/main/kotlin/ca/allanwang/kau/kpref/KPrefBinder.kt b/library/src/main/kotlin/ca/allanwang/kau/kpref/KPrefBinder.kt index 75c24bc..53cba99 100644 --- a/library/src/main/kotlin/ca/allanwang/kau/kpref/KPrefBinder.kt +++ b/library/src/main/kotlin/ca/allanwang/kau/kpref/KPrefBinder.kt @@ -16,11 +16,11 @@ import com.mikepenz.fastadapter.commons.adapters.FastItemAdapter /** * Base extension that will register the layout manager and adapter with the given items */ -fun RecyclerView.setKPrefAdapter(builder: KPrefAdapterBuilder.() -> Unit): FastItemAdapter { +fun RecyclerView.setKPrefAdapter(globalOptions: GlobalOptions, builder: KPrefAdapterBuilder.() -> Unit): FastItemAdapter { layoutManager = LinearLayoutManager(context) val adapter = FastItemAdapter() adapter.withOnClickListener { v, _, item, _ -> item.onClick(v, v.findViewById(R.id.kau_pref_inner_content)) } - val items = KPrefAdapterBuilder() + val items = KPrefAdapterBuilder(globalOptions) builder.invoke(items) adapter.add(items.list) this.adapter = adapter @@ -43,22 +43,32 @@ class CoreAttributeBuilder : CoreAttributeContract { override var accentColor: (() -> Int)? = null } +interface KPrefActivityContract { + fun showNextPrefs(builder: KPrefAdapterBuilder.() -> Unit) + fun showPrevPrefs() +} + + +class GlobalOptions(core: CoreAttributeContract, activity: KPrefActivityContract +) : CoreAttributeContract by core, KPrefActivityContract by activity + + /** * Builder for kpref items * Contains DSLs for every possible item * The arguments are all the mandatory values plus an optional builder housing all the possible configurations * The mandatory values are final so they cannot be edited in the builder */ -class KPrefAdapterBuilder : CoreAttributeContract by CoreAttributeBuilder() { +class KPrefAdapterBuilder(internal val globalOptions: GlobalOptions) { fun header(@StringRes title: Int) - = list.add(KPrefHeader(KPrefItemCore.CoreBuilder(this, title))) + = list.add(KPrefHeader(KPrefItemCore.CoreBuilder(globalOptions, title))) fun checkbox(@StringRes title: Int, getter: (() -> Boolean), setter: ((value: Boolean) -> Unit), builder: KPrefItemBase.BaseContract.() -> Unit = {}) - = list.add(KPrefCheckbox(KPrefItemBase.BaseBuilder(this, title, getter, setter) + = list.add(KPrefCheckbox(KPrefItemBase.BaseBuilder(globalOptions, title, getter, setter) .apply { builder() })) @@ -66,16 +76,19 @@ class KPrefAdapterBuilder : CoreAttributeContract by CoreAttributeBuilder() { getter: (() -> Int), setter: ((value: Int) -> Unit), builder: KPrefColorPicker.KPrefColorContract.() -> Unit = {}) - = list.add(KPrefColorPicker(KPrefColorPicker.KPrefColorBuilder(this, title, getter, setter) + = list.add(KPrefColorPicker(KPrefColorPicker.KPrefColorBuilder(globalOptions, title, getter, setter) .apply { builder() })) fun text(@StringRes title: Int, getter: (() -> T), setter: ((value: T) -> Unit), builder: KPrefText.KPrefTextContract.() -> Unit = {}) - = list.add(KPrefText(KPrefText.KPrefTextBuilder(this, title, getter, setter) + = list.add(KPrefText(KPrefText.KPrefTextBuilder(globalOptions, title, getter, setter) .apply { builder() })) - internal val list: MutableList = mutableListOf() + fun subItems(@StringRes title:Int, + itemBuilder:KPrefAdapterBuilder.()->Unit) + = list.add(KPrefSubItems(KPrefSubItems.KPrefSubItemsBuilder(globalOptions, title, itemBuilder))) + internal val list: MutableList = mutableListOf() } \ No newline at end of file diff --git a/library/src/main/kotlin/ca/allanwang/kau/kpref/items/KPrefColorPicker.kt b/library/src/main/kotlin/ca/allanwang/kau/kpref/items/KPrefColorPicker.kt index 2ec0a34..b22c4b3 100644 --- a/library/src/main/kotlin/ca/allanwang/kau/kpref/items/KPrefColorPicker.kt +++ b/library/src/main/kotlin/ca/allanwang/kau/kpref/items/KPrefColorPicker.kt @@ -7,6 +7,7 @@ import ca.allanwang.kau.dialogs.color.ColorBuilder import ca.allanwang.kau.dialogs.color.ColorContract import ca.allanwang.kau.dialogs.color.colorPickerDialog import ca.allanwang.kau.kpref.CoreAttributeContract +import ca.allanwang.kau.kpref.GlobalOptions /** * Created by Allan Wang on 2017-06-07. @@ -57,11 +58,11 @@ class KPrefColorPicker(val builder: KPrefColorContract) : KPrefItemBase(bui /** * Default implementation of [KPrefColorContract] */ - class KPrefColorBuilder(attributes: CoreAttributeContract, + class KPrefColorBuilder(globalOptions: GlobalOptions, override var titleRes: Int, getter: () -> Int, setter: (value: Int) -> Unit - ) : KPrefColorContract, BaseContract by BaseBuilder(attributes, titleRes, getter, setter), + ) : KPrefColorContract, BaseContract by BaseBuilder(globalOptions, titleRes, getter, setter), ColorContract by ColorBuilder() { override var showPreview: Boolean = true } diff --git a/library/src/main/kotlin/ca/allanwang/kau/kpref/items/KPrefItemBase.kt b/library/src/main/kotlin/ca/allanwang/kau/kpref/items/KPrefItemBase.kt index 76fa01e..949ae59 100644 --- a/library/src/main/kotlin/ca/allanwang/kau/kpref/items/KPrefItemBase.kt +++ b/library/src/main/kotlin/ca/allanwang/kau/kpref/items/KPrefItemBase.kt @@ -4,6 +4,7 @@ import android.support.annotation.CallSuper import android.view.View import ca.allanwang.kau.R import ca.allanwang.kau.kpref.CoreAttributeContract +import ca.allanwang.kau.kpref.GlobalOptions import ca.allanwang.kau.utils.resolveDrawable /** @@ -72,11 +73,11 @@ abstract class KPrefItemBase(val base: BaseContract) : KPrefItemCore(base) /** * Default implementation of [BaseContract] */ - class BaseBuilder(attributes: CoreAttributeContract, + class BaseBuilder(globalOptions: GlobalOptions, titleRes: Int, override val getter: () -> T, override val setter: (value: T) -> Unit - ) : CoreContract by CoreBuilder(attributes, titleRes), BaseContract { + ) : CoreContract by CoreBuilder(globalOptions, titleRes), BaseContract { override var enabler: () -> Boolean = { true } override var onClick: ((itemView: View, innerContent: View?, item: KPrefItemBase) -> Boolean)? = null override var onDisabledClick: ((itemView: View, innerContent: View?, item: KPrefItemBase) -> Boolean)? = null diff --git a/library/src/main/kotlin/ca/allanwang/kau/kpref/items/KPrefItemCore.kt b/library/src/main/kotlin/ca/allanwang/kau/kpref/items/KPrefItemCore.kt index 2d3c714..faf451f 100644 --- a/library/src/main/kotlin/ca/allanwang/kau/kpref/items/KPrefItemCore.kt +++ b/library/src/main/kotlin/ca/allanwang/kau/kpref/items/KPrefItemCore.kt @@ -11,7 +11,7 @@ import android.widget.ImageView import android.widget.LinearLayout import android.widget.TextView import ca.allanwang.kau.R -import ca.allanwang.kau.kpref.CoreAttributeContract +import ca.allanwang.kau.kpref.GlobalOptions import ca.allanwang.kau.utils.* import com.mikepenz.fastadapter.items.AbstractItem import com.mikepenz.iconics.typeface.IIcon @@ -39,12 +39,12 @@ abstract class KPrefItemCore(val core: CoreContract) : AbstractItem Unit + } + + /** + * Default implementation of [KPrefTextContract] + */ + class KPrefSubItemsBuilder( + globalOptions: GlobalOptions, + titleRes: Int, + override val itemBuilder: KPrefAdapterBuilder.() -> Unit + ) : KPrefSubItemsContract, CoreContract by CoreBuilder(globalOptions, titleRes) + + override fun getType(): Int = R.id.kau_item_pref_checkbox + +} \ No newline at end of file diff --git a/library/src/main/kotlin/ca/allanwang/kau/kpref/items/KPrefText.kt b/library/src/main/kotlin/ca/allanwang/kau/kpref/items/KPrefText.kt index 0daa054..b93dbed 100644 --- a/library/src/main/kotlin/ca/allanwang/kau/kpref/items/KPrefText.kt +++ b/library/src/main/kotlin/ca/allanwang/kau/kpref/items/KPrefText.kt @@ -4,6 +4,7 @@ import android.view.View import android.widget.TextView import ca.allanwang.kau.R import ca.allanwang.kau.kpref.CoreAttributeContract +import ca.allanwang.kau.kpref.GlobalOptions import ca.allanwang.kau.utils.toast /** @@ -39,11 +40,11 @@ class KPrefText(val builder: KPrefTextContract) : KPrefItemBase(builder * Default implementation of [KPrefTextContract] */ class KPrefTextBuilder( - attributes: CoreAttributeContract, + globalOptions: GlobalOptions, titleRes: Int, getter: () -> T, setter: (value: T) -> Unit - ) : KPrefTextContract, BaseContract by BaseBuilder(attributes, titleRes, getter, setter) { + ) : KPrefTextContract, BaseContract by BaseBuilder(globalOptions, titleRes, getter, setter) { override var textGetter: (T) -> String? = { it?.toString() } } diff --git a/library/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt b/library/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt index 72b8573..c64220c 100644 --- a/library/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt +++ b/library/src/main/kotlin/ca/allanwang/kau/utils/ViewUtils.kt @@ -6,6 +6,7 @@ import android.support.annotation.StringRes import android.support.design.widget.Snackbar import android.view.View import android.view.ViewGroup +import android.widget.FrameLayout import android.widget.ImageView import android.widget.TextView import com.mikepenz.iconics.IconicsDrawable @@ -34,13 +35,6 @@ fun View.isVisible(): Boolean = visibility == View.VISIBLE fun View.isInvisible(): Boolean = visibility == View.INVISIBLE fun View.isGone(): Boolean = visibility == View.GONE -fun View.matchParent() { - with(layoutParams) { - height = ViewGroup.LayoutParams.MATCH_PARENT - width = ViewGroup.LayoutParams.MATCH_PARENT - } -} - fun View.snackbar(text: String, duration: Int = Snackbar.LENGTH_LONG, builder: (Snackbar) -> Unit = {}) { val snackbar = Snackbar.make(this, text, duration) builder.invoke(snackbar) diff --git a/library/src/main/res/layout/kau_activity_kpref.xml b/library/src/main/res/layout/kau_activity_kpref.xml index 4135edc..390674f 100644 --- a/library/src/main/res/layout/kau_activity_kpref.xml +++ b/library/src/main/res/layout/kau_activity_kpref.xml @@ -32,8 +32,8 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/kau_toolbar" /> - Unit = { + override fun kPrefCoreAttributes(): CoreAttributeContract.() -> Unit = { textColor = { KPrefSample.textColor } accentColor = { KPrefSample.accentColor } + } + + override fun onCreateKPrefs(savedInstanceState: android.os.Bundle?): KPrefAdapterBuilder.() -> Unit = { header(R.string.header) @@ -105,6 +109,7 @@ class MainActivity : KPrefActivity() { when (item.itemId) { R.id.action_settings -> startActivity(AnimActivity::class.java, clearStack = true) R.id.action_email -> sendEmail(R.string.your_email, R.string.your_subject) + R.id.test -> prefHolder.showNext() else -> return super.onOptionsItemSelected(item) } return true diff --git a/sample/src/main/res/menu/menu_main.xml b/sample/src/main/res/menu/menu_main.xml index caafd48..dd07031 100644 --- a/sample/src/main/res/menu/menu_main.xml +++ b/sample/src/main/res/menu/menu_main.xml @@ -9,8 +9,13 @@ app:showAsAction="never" /> + -- cgit v1.2.3