aboutsummaryrefslogtreecommitdiff
path: root/library/src/main/kotlin/ca
diff options
context:
space:
mode:
authorAllan Wang <me@allanwang.ca>2017-06-27 20:00:44 -0700
committerAllan Wang <me@allanwang.ca>2017-06-27 20:00:44 -0700
commita6ee77a4f1d78252b15059d51f2533fa03483d8c (patch)
treeb27b4a9cddfccce6f1edcdcdffba92c08bf33642 /library/src/main/kotlin/ca
parent8179e50208192e2b18b4df3bfc100d9cf779891a (diff)
downloadkau-a6ee77a4f1d78252b15059d51f2533fa03483d8c.tar.gz
kau-a6ee77a4f1d78252b15059d51f2533fa03483d8c.tar.bz2
kau-a6ee77a4f1d78252b15059d51f2533fa03483d8c.zip
Testing about activity and chained adapters
Diffstat (limited to 'library/src/main/kotlin/ca')
-rw-r--r--library/src/main/kotlin/ca/allanwang/kau/about/AboutActivity.kt33
-rw-r--r--library/src/main/kotlin/ca/allanwang/kau/about/AboutActivityBase.kt86
-rw-r--r--library/src/main/kotlin/ca/allanwang/kau/about/LibraryItem.kt73
-rw-r--r--library/src/main/kotlin/ca/allanwang/kau/about/MainItem.kt59
-rw-r--r--library/src/main/kotlin/ca/allanwang/kau/adapters/ChainedAdapters.kt88
-rw-r--r--library/src/main/kotlin/ca/allanwang/kau/changelog/Changelog.kt2
-rw-r--r--library/src/main/kotlin/ca/allanwang/kau/kpref/KPrefActivity.kt7
-rw-r--r--library/src/main/kotlin/ca/allanwang/kau/kpref/KPrefBinder.kt4
-rw-r--r--library/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt4
-rw-r--r--library/src/main/kotlin/ca/allanwang/kau/utils/PackageUtils.kt4
-rw-r--r--library/src/main/kotlin/ca/allanwang/kau/views/KauTextSlider.kt125
-rw-r--r--library/src/main/kotlin/ca/allanwang/kau/views/TextSlider.kt127
12 files changed, 443 insertions, 169 deletions
diff --git a/library/src/main/kotlin/ca/allanwang/kau/about/AboutActivity.kt b/library/src/main/kotlin/ca/allanwang/kau/about/AboutActivity.kt
deleted file mode 100644
index ce81c29..0000000
--- a/library/src/main/kotlin/ca/allanwang/kau/about/AboutActivity.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-package ca.allanwang.kau.about
-
-import android.os.Bundle
-import android.support.v7.app.AppCompatActivity
-import android.support.v7.widget.RecyclerView
-import android.support.v7.widget.Toolbar
-import android.view.animation.Animation
-import android.view.animation.AnimationUtils
-import ca.allanwang.kau.R
-import ca.allanwang.kau.utils.bindView
-import ca.allanwang.kau.views.TextSlider
-
-/**
- * Created by Allan Wang on 2017-06-26.
- */
-open class AboutActivity : AppCompatActivity() {
-
- val toolbar: Toolbar by bindView(R.id.kau_toolbar)
- val toolbarText: TextSlider by bindView(R.id.kau_toolbar_text)
- val recycler: RecyclerView by bindView(R.id.kau_recycler)
-
- protected val SLIDE_IN_UP: Animation by lazy { AnimationUtils.loadAnimation(this, R.anim.kau_slide_in_top) }
- protected val SLIDE_IN_DOWN: Animation by lazy { AnimationUtils.loadAnimation(this, R.anim.kau_slide_in_bottom) }
-
- protected val SLIDE_OUT_UP: Animation by lazy { AnimationUtils.loadAnimation(this, R.anim.kau_slide_out_top) }
- protected val SLIDE_OUT_DOWN: Animation by lazy { AnimationUtils.loadAnimation(this, R.anim.kau_slide_out_bottom) }
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.kau_activity_about)
-
- }
-} \ No newline at end of file
diff --git a/library/src/main/kotlin/ca/allanwang/kau/about/AboutActivityBase.kt b/library/src/main/kotlin/ca/allanwang/kau/about/AboutActivityBase.kt
new file mode 100644
index 0000000..f469028
--- /dev/null
+++ b/library/src/main/kotlin/ca/allanwang/kau/about/AboutActivityBase.kt
@@ -0,0 +1,86 @@
+package ca.allanwang.kau.about
+
+import android.os.Bundle
+import android.os.PersistableBundle
+import android.support.v7.app.AppCompatActivity
+import android.support.v7.widget.RecyclerView
+import android.support.v7.widget.Toolbar
+import ca.allanwang.kau.R
+import ca.allanwang.kau.adapters.ChainedAdapters
+import ca.allanwang.kau.logging.KL
+import ca.allanwang.kau.utils.bindView
+import ca.allanwang.kau.utils.string
+import ca.allanwang.kau.views.KauTextSlider
+import com.mikepenz.aboutlibraries.Libs
+import com.mikepenz.aboutlibraries.entity.Library
+import com.mikepenz.fastadapter.adapters.HeaderAdapter
+import com.mikepenz.fastadapter.adapters.ItemAdapter
+import org.jetbrains.anko.doAsync
+import org.jetbrains.anko.uiThread
+
+/**
+ * Created by Allan Wang on 2017-06-26.
+ *
+ * Customizable About Activity
+ * Will automatically include a section containing all of the libraries registered under About Libraries
+ * Takes in [rClass], which is the R.string::class.java for your app
+ * It is used to get the libs dynamically
+ * Make sure to add the following if you are using proguard:
+ * # About library
+ * -keep class .R
+ * -keep class **.R$* {
+ * <fields>;
+ * }
+ *
+ */
+open class AboutActivityBase(val rClass: Class<*>) : AppCompatActivity() {
+
+ val toolbar: Toolbar by bindView(R.id.kau_toolbar)
+ val toolbarText: KauTextSlider by bindView(R.id.kau_toolbar_text)
+ val recycler: RecyclerView by bindView(R.id.kau_recycler)
+ val libSection: Pair<String, HeaderAdapter<LibraryItem>> by lazy { string(R.string.kau_dependencies_used) to HeaderAdapter<LibraryItem>() }
+ val sectionsChain: ChainedAdapters<String> = ChainedAdapters()
+
+ fun addLibsAsync() {
+ doAsync {
+ val libs = Libs(this@AboutActivityBase, Libs.toStringArray(rClass.fields))
+ val items = getLibraries(libs)
+ uiThread {
+ KL.e("Coun ${items.count()}")
+ libSection.second.add(items.map { LibraryItem(it) })
+ }
+ }
+ }
+
+ /**
+ * By default, the libraries will be extracted dynamically and sorted
+ * Override this to define your own list
+ */
+ open fun getLibraries(libs: Libs): List<Library> = libs.prepareLibraries(this@AboutActivityBase, null, null, true, true)
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.kau_activity_about)
+ val sections = onCreateSections()
+ sectionsChain.add(sections)
+ if (!sections.contains(libSection)) sectionsChain.add(libSection)
+ sectionsChain.bindRecyclerView(recycler) {
+ item, _, dy ->
+ if (dy > 0) toolbarText.setNextText(item)
+ else toolbarText.setPrevText()
+ }
+ toolbarText.setCurrentText(sectionsChain[0].first)
+ }
+
+ override fun onPostCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
+ super.onPostCreate(savedInstanceState, persistentState)
+ addLibsAsync()
+ }
+
+ /**
+ * Get all the header adapters
+ * The adapters should be listed in the order that they appear,
+ * and if the [libSection] shouldn't be at the end, it should be added in this list
+ */
+ open fun onCreateSections(): List<Pair<String, HeaderAdapter<*>>> = listOf(libSection)
+} \ No newline at end of file
diff --git a/library/src/main/kotlin/ca/allanwang/kau/about/LibraryItem.kt b/library/src/main/kotlin/ca/allanwang/kau/about/LibraryItem.kt
new file mode 100644
index 0000000..560eb82
--- /dev/null
+++ b/library/src/main/kotlin/ca/allanwang/kau/about/LibraryItem.kt
@@ -0,0 +1,73 @@
+package ca.allanwang.kau.about
+
+/**
+ * Created by Allan Wang on 2017-06-27.
+ */
+
+import android.os.Build
+import android.support.v7.widget.CardView
+import android.support.v7.widget.RecyclerView
+import android.text.Html
+import android.view.View
+import android.widget.LinearLayout
+import android.widget.TextView
+import ca.allanwang.kau.R
+import ca.allanwang.kau.utils.bindView
+import ca.allanwang.kau.utils.gone
+import ca.allanwang.kau.utils.visible
+import com.mikepenz.aboutlibraries.entity.Library
+import com.mikepenz.fastadapter.items.AbstractItem
+
+
+/**
+ * Created by mikepenz on 28.12.15.
+ */
+class LibraryItem(val lib: Library) : AbstractItem<LibraryItem, LibraryItem.ViewHolder>() {
+
+ override fun getType(): Int = R.id.kau_item_about_library
+
+ override fun getLayoutRes(): Int = R.layout.kau_about_item_library
+
+ override fun isSelectable(): Boolean = false
+
+ override fun bindView(holder: ViewHolder, payloads: MutableList<Any>?) {
+ super.bindView(holder, payloads)
+ with(holder) {
+ name.text = lib.libraryName
+ creator.text = lib.author
+ description.text = if (lib.libraryDescription.isBlank()) lib.libraryDescription
+ else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
+ Html.fromHtml(lib.libraryDescription, Html.FROM_HTML_MODE_LEGACY)
+ else Html.fromHtml(lib.libraryDescription)
+ bottomDivider.gone()
+ bottomContainer.gone()
+ if (lib.libraryVersion?.isNotBlank() ?: false) {
+ bottomDivider.visible()
+ bottomContainer.visible()
+ version.text = lib.libraryVersion
+ }
+ if (lib.license?.licenseName?.isNotBlank() ?: false) {
+ bottomDivider.visible()
+ bottomContainer.visible()
+ license.text = lib.license?.licenseName
+ }
+ }
+ }
+
+
+ override fun getViewHolder(v: View): ViewHolder = ViewHolder(v)
+
+ class ViewHolder(v: View) : RecyclerView.ViewHolder(v) {
+ val card: CardView by bindView(R.id.rippleForegroundListenerView)
+ val name: TextView by bindView(R.id.libraryName)
+ val creator: TextView by bindView(R.id.libraryCreator)
+ val description: TextView by bindView(R.id.libraryDescription)
+ val version: TextView by bindView(R.id.libraryVersion)
+ val license: TextView by bindView(R.id.libraryLicense)
+ val bottomContainer: LinearLayout by bindView(R.id.libraryBottomContainer)
+
+ val divider: View by bindView(R.id.libraryDescriptionDivider)
+ val bottomDivider: View by bindView(R.id.libraryBottomDivider)
+ }
+
+} \ No newline at end of file
diff --git a/library/src/main/kotlin/ca/allanwang/kau/about/MainItem.kt b/library/src/main/kotlin/ca/allanwang/kau/about/MainItem.kt
new file mode 100644
index 0000000..decacfc
--- /dev/null
+++ b/library/src/main/kotlin/ca/allanwang/kau/about/MainItem.kt
@@ -0,0 +1,59 @@
+package ca.allanwang.kau.about
+
+import android.graphics.drawable.Drawable
+import android.support.v7.widget.CardView
+import android.support.v7.widget.RecyclerView
+import android.view.View
+import android.widget.LinearLayout
+import android.widget.TextView
+import ca.allanwang.kau.R
+import ca.allanwang.kau.utils.bindView
+import com.mikepenz.fastadapter.items.AbstractItem
+
+/**
+ * Created by Allan Wang on 2017-06-27.
+ */
+class MainItem(builder: Config.() -> Unit) : AbstractItem<MainItem, MainItem.ViewHolder>() {
+
+ val configs = Config().apply { builder() }
+
+ class Config {
+ var icon: Drawable? = null
+ var title: String = "App Title"
+ var author: String? = null
+ var description: String? = null
+ var version: String? = null
+ var githubLink: String? = null
+ }
+
+ override fun getType(): Int = R.id.kau_item_about_main
+
+ override fun getLayoutRes(): Int = R.layout.kau_about_item_main
+
+ override fun isSelectable(): Boolean = false
+
+ override fun getViewHolder(v: View): ViewHolder = ViewHolder(v)
+
+ override fun bindView(holder: ViewHolder, payloads: MutableList<Any>?) {
+ super.bindView(holder, payloads)
+ with (holder) {
+ title.text = configs.title
+ creator.text = configs.author
+ description.text = configs.description
+// license.text = configs.description
+ }
+ }
+
+ class ViewHolder(v: View) : RecyclerView.ViewHolder(v) {
+ val card: CardView by bindView(R.id.container)
+ val title: TextView by bindView(R.id.title)
+ val creator: TextView by bindView(R.id.creator)
+ val description: TextView by bindView(R.id.description)
+ val version: TextView by bindView(R.id.version)
+ val license: TextView by bindView(R.id.license)
+ val bottomContainer: LinearLayout by bindView(R.id.bottom_container)
+
+ val divider: View by bindView(R.id.top_divider)
+ val bottomDivider: View by bindView(R.id.bottom_divider)
+ }
+}
diff --git a/library/src/main/kotlin/ca/allanwang/kau/adapters/ChainedAdapters.kt b/library/src/main/kotlin/ca/allanwang/kau/adapters/ChainedAdapters.kt
new file mode 100644
index 0000000..aaa0fb0
--- /dev/null
+++ b/library/src/main/kotlin/ca/allanwang/kau/adapters/ChainedAdapters.kt
@@ -0,0 +1,88 @@
+package ca.allanwang.kau.adapters
+
+import android.support.v7.widget.LinearLayoutManager
+import android.support.v7.widget.RecyclerView
+import ca.allanwang.kau.logging.KL
+import com.mikepenz.fastadapter.IItem
+import com.mikepenz.fastadapter.adapters.HeaderAdapter
+import com.mikepenz.fastadapter.commons.adapters.FastItemAdapter
+import org.jetbrains.anko.collections.forEachReversedWithIndex
+import java.util.*
+
+/**
+ * Created by Allan Wang on 2017-06-27.
+ *
+ * Once bounded to a [RecyclerView], this will
+ * - Chain together a list of [HeaderAdapter]s, backed by a generic [FastItemAdapter]
+ * - Add a [LinearLayoutManager] to the recycler
+ * - Add a listener for when a new adapter segment is being used
+ */
+class ChainedAdapters<T>(vararg items: Pair<T, HeaderAdapter<*>>) {
+ private val chain: MutableList<Pair<T, HeaderAdapter<*>>> = mutableListOf(*items)
+ val baseAdapter: FastItemAdapter<IItem<*, *>> = FastItemAdapter()
+ private val indexStack = Stack<Int>()
+ var recycler: RecyclerView? = null
+ val firstVisibleItemPosition: Int
+ get() = (recycler?.layoutManager as LinearLayoutManager?)?.findFirstVisibleItemPosition() ?: throw IllegalArgumentException("No recyclerview was bounded to the chain adapters")
+
+ fun add(vararg items: Pair<T, HeaderAdapter<*>>) = add(items.toList())
+
+ fun add(items: Collection<Pair<T, HeaderAdapter<*>>>): ChainedAdapters<T> {
+ if (recycler != null) throw IllegalAccessException("Chain adapter is already bounded to a recycler; cannot add directly.")
+ chain.addAll(items)
+ return this
+ }
+
+ operator fun get(index: Int) = chain[index]
+
+ /**
+ * Attaches the chain to a recycler
+ * After this stage, any modifications to the adapters must be done through external references
+ * You may still get the generic header adapters through the get operator
+ * Binding the recycler also involves supplying a callback, which returns
+ * the item (T) associated with the adapter,
+ * the index (Int) of the current adapter
+ * and the dy (Int) as given by the scroll listener
+ */
+ fun bindRecyclerView(recyclerView: RecyclerView, onAdapterSectionChanged: (item: T, index: Int, dy: Int) -> Unit) {
+ if (recycler != null) throw IllegalStateException("Chain adapter is already bounded")
+ if (chain.isEmpty()) throw IllegalArgumentException("No adapters have been added to the adapters list")
+ //wrap adapters
+ chain.map { it.second }.forEachReversedWithIndex { i, headerAdapter ->
+ if (i == chain.size - 1) headerAdapter.wrap(baseAdapter)
+ else headerAdapter.wrap(chain[i + 1].second)
+ if (i < chain.size - 1) KL.e("${chain[i].first} ${chain[i + 1].first}")
+ }
+ recycler = recyclerView
+ indexStack.push(0)
+ with(recyclerView) {
+ layoutManager = LinearLayoutManager(context)
+ adapter = chain.first().second
+ addOnScrollListener(object : RecyclerView.OnScrollListener() {
+ override fun onScrolled(rv: RecyclerView, dx: Int, dy: Int) {
+ super.onScrolled(rv, dx, dy)
+ val topPosition = firstVisibleItemPosition
+ val currentAdapterIndex = indexStack.peek()
+ if (dy > 0) {
+ //look ahead from current adapter
+ val nextAdapterIndex = (currentAdapterIndex until chain.size).asSequence()
+ .firstOrNull {
+ val adapter = chain[it].second
+ KL.e("A $it ${adapter.adapterItemCount} ${adapter.getGlobalPosition(0)} $topPosition $currentAdapterIndex")
+ adapter.adapterItemCount > 0 && adapter.getGlobalPosition(0) >= topPosition
+ } ?: currentAdapterIndex
+ KL.e("Next $nextAdapterIndex")
+ if (nextAdapterIndex == currentAdapterIndex) return
+ indexStack.push(nextAdapterIndex)
+ onAdapterSectionChanged(chain[indexStack.peek()].first, indexStack.peek(), dy)
+ } else if (currentAdapterIndex == 0) {
+ return //All adapters may be empty; in this case, if we are already at the beginning, don't bother checking
+ } else if (chain[currentAdapterIndex].second.getGlobalPosition(0) > topPosition) {
+ indexStack.pop()
+ onAdapterSectionChanged(chain[indexStack.peek()].first, indexStack.peek(), dy)
+ }
+ }
+ })
+ }
+ }
+} \ No newline at end of file
diff --git a/library/src/main/kotlin/ca/allanwang/kau/changelog/Changelog.kt b/library/src/main/kotlin/ca/allanwang/kau/changelog/Changelog.kt
index 24e6358..a91d0af 100644
--- a/library/src/main/kotlin/ca/allanwang/kau/changelog/Changelog.kt
+++ b/library/src/main/kotlin/ca/allanwang/kau/changelog/Changelog.kt
@@ -42,7 +42,7 @@ fun Context.showChangelog(@XmlRes xmlRes: Int, @ColorInt textColor: Int? = null,
/**
* Internals of the changelog dialog
- * Contains an adapter for each item, as well as the tags to parse
+ * Contains an mainAdapter for each item, as well as the tags to parse
*/
internal class ChangelogAdapter(val items: List<Pair<String, ChangelogType>>, @ColorInt val textColor: Int? = null) : RecyclerView.Adapter<ChangelogAdapter.ChangelogVH>() {
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 96b1237..193ca58 100644
--- a/library/src/main/kotlin/ca/allanwang/kau/kpref/KPrefActivity.kt
+++ b/library/src/main/kotlin/ca/allanwang/kau/kpref/KPrefActivity.kt
@@ -13,13 +13,12 @@ import android.widget.FrameLayout
import android.widget.ViewAnimator
import ca.allanwang.kau.R
import ca.allanwang.kau.kpref.items.KPrefItemCore
-import ca.allanwang.kau.logging.KL
import ca.allanwang.kau.utils.bindView
import ca.allanwang.kau.utils.resolveColor
import ca.allanwang.kau.utils.statusBarColor
import ca.allanwang.kau.utils.string
+import ca.allanwang.kau.views.KauTextSlider
import ca.allanwang.kau.views.RippleCanvas
-import ca.allanwang.kau.views.TextSlider
import com.mikepenz.fastadapter.commons.adapters.FastItemAdapter
abstract class KPrefActivity : AppCompatActivity(), KPrefActivityContract {
@@ -33,13 +32,13 @@ abstract class KPrefActivity : AppCompatActivity(), KPrefActivityContract {
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 toolbarTitle: TextSlider by bindView(R.id.kau_toolbar_text)
+ val toolbarTitle: KauTextSlider by bindView(R.id.kau_toolbar_text)
val prefHolder: ViewAnimator by bindView(R.id.kau_holder)
private lateinit var globalOptions: GlobalOptions
var animate: Boolean = true
set(value) {
field = value
- toolbarTitle.animate = value
+ toolbarTitle.animationType = if (value) KauTextSlider.ANIMATION_SLIDE_HORIZONTAL else KauTextSlider.ANIMATION_NONE
}
private val SLIDE_IN_LEFT_ITEMS: Animation by lazy { AnimationUtils.loadAnimation(this, R.anim.kau_slide_in_left) }
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 5fdb6bc..7f42d2a 100644
--- a/library/src/main/kotlin/ca/allanwang/kau/kpref/KPrefBinder.kt
+++ b/library/src/main/kotlin/ca/allanwang/kau/kpref/KPrefBinder.kt
@@ -12,11 +12,11 @@ import org.jetbrains.anko.uiThread
/**
* Created by Allan Wang on 2017-06-08.
*
- * Houses all the components that can be called externally to setup the kpref adapter
+ * Houses all the components that can be called externally to setup the kpref mainAdapter
*/
/**
- * Base extension that will register the layout manager and adapter with the given items
+ * Base extension that will register the layout manager and mainAdapter with the given items
* Returns FastAdapter
*/
fun RecyclerView.setKPrefAdapter(globalOptions: GlobalOptions, builder: KPrefAdapterBuilder.() -> Unit): FastItemAdapter<KPrefItemCore> {
diff --git a/library/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt b/library/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt
index 5936a07..29c2223 100644
--- a/library/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt
+++ b/library/src/main/kotlin/ca/allanwang/kau/searchview/SearchView.kt
@@ -114,7 +114,7 @@ class SearchView @JvmOverloads constructor(
*/
var transitionDuration: Long = 100L
/**
- * Defines whether the edit text and adapter should clear themselves when the searchView is closed
+ * Defines whether the edit text and mainAdapter should clear themselves when the searchView is closed
*/
var shouldClearOnClose: Boolean = false
/**
@@ -184,7 +184,7 @@ class SearchView @JvmOverloads constructor(
}
/**
- * Contract for adapter items
+ * Contract for mainAdapter items
* Setting results will ensure that the values are sent on the UI thread
*/
var results: List<SearchItem>
diff --git a/library/src/main/kotlin/ca/allanwang/kau/utils/PackageUtils.kt b/library/src/main/kotlin/ca/allanwang/kau/utils/PackageUtils.kt
index f2703dc..837c209 100644
--- a/library/src/main/kotlin/ca/allanwang/kau/utils/PackageUtils.kt
+++ b/library/src/main/kotlin/ca/allanwang/kau/utils/PackageUtils.kt
@@ -3,6 +3,7 @@ package ca.allanwang.kau.utils
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
+import android.support.annotation.RequiresApi
/**
* Created by Allan Wang on 2017-06-23.
@@ -31,6 +32,9 @@ val buildIsLollipopAndUp: Boolean
val buildIsMarshmallowAndUp: Boolean
get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
+val buildIsNougatAndUp: Boolean
+ get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
+
const val INSTALLER_GOOGLE_PLAY_VENDING = "com.android.vending"
const val INSTALLER_GOOGLE_PLAY_FEEDBACK = "com.google.android.feedback"
diff --git a/library/src/main/kotlin/ca/allanwang/kau/views/KauTextSlider.kt b/library/src/main/kotlin/ca/allanwang/kau/views/KauTextSlider.kt
new file mode 100644
index 0000000..8294f9f
--- /dev/null
+++ b/library/src/main/kotlin/ca/allanwang/kau/views/KauTextSlider.kt
@@ -0,0 +1,125 @@
+package ca.allanwang.kau.views
+
+import android.content.Context
+import android.graphics.Color
+import android.support.v4.widget.TextViewCompat
+import android.text.TextUtils
+import android.util.AttributeSet
+import android.view.Gravity
+import android.view.animation.Animation
+import android.view.animation.AnimationUtils
+import android.widget.TextSwitcher
+import android.widget.TextView
+import ca.allanwang.kau.R
+import java.util.*
+
+/**
+ * Created by Allan Wang on 2017-06-21.
+ *
+ * Text switcher with global text color and embedded sliding animations
+ * Also has a stack to keep track of title changes
+ */
+class KauTextSlider @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null
+) : TextSwitcher(context, attrs) {
+
+ val titleStack: Stack<CharSequence?> = Stack()
+
+ /**
+ * Holds a mapping of animation types to their respective animations
+ */
+ val animationMap = mapOf(
+ ANIMATION_NONE to null,
+ ANIMATION_SLIDE_HORIZONTAL to AnimationBundle(
+ R.anim.kau_slide_in_right, R.anim.kau_slide_out_left,
+ R.anim.kau_slide_in_left, R.anim.kau_slide_out_right),
+ ANIMATION_SLIDE_VERTICAL to AnimationBundle(
+ R.anim.kau_slide_in_bottom, R.anim.kau_slide_out_top,
+ R.anim.kau_slide_in_top, R.anim.kau_slide_out_bottom
+ )
+ )
+
+ /**
+ * Holds lazy instances of the animations
+ */
+ inner class AnimationBundle(private val nextIn: Int, private val nextOut: Int, private val prevIn: Int, private val prevOut: Int) {
+ val NEXT_IN: Animation by lazy { AnimationUtils.loadAnimation(context, nextIn) }
+ val NEXT_OUT: Animation by lazy { AnimationUtils.loadAnimation(context, nextOut) }
+ val PREV_IN: Animation by lazy { AnimationUtils.loadAnimation(context, prevIn) }
+ val PREV_OUT: Animation by lazy { AnimationUtils.loadAnimation(context, prevOut) }
+ }
+
+ companion object {
+ const val ANIMATION_NONE = 1000
+ const val ANIMATION_SLIDE_HORIZONTAL = 1001
+ const val ANIMATION_SLIDE_VERTICAL = 1002
+ }
+
+ var animationType: Int = ANIMATION_SLIDE_HORIZONTAL
+
+ var textColor: Int = Color.WHITE
+ get() = field
+ set(value) {
+ field = value
+ (getChildAt(0) as TextView).setTextColor(value)
+ (getChildAt(1) as TextView).setTextColor(value)
+ }
+ val isRoot: Boolean
+ get() = titleStack.size <= 1
+
+ init {
+ if (attrs != null) {
+ val styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.KauTextSlider)
+ animationType = styledAttrs.getInteger(R.styleable.KauTextSlider_kau_animation_type, ANIMATION_SLIDE_HORIZONTAL)
+ styledAttrs.recycle()
+ }
+ }
+
+ override fun setText(text: CharSequence?) {
+ if ((currentView as TextView).text == text) return
+ super.setText(text)
+ }
+
+ override fun setCurrentText(text: CharSequence?) {
+ if (titleStack.isNotEmpty()) titleStack.pop()
+ titleStack.push(text)
+ super.setCurrentText(text)
+ }
+
+ fun setNextText(text: CharSequence?) {
+ if (titleStack.isEmpty()) {
+ setCurrentText(text)
+ return
+ }
+ titleStack.push(text)
+ val anim = animationMap[animationType]
+ inAnimation = anim?.NEXT_IN
+ outAnimation = anim?.NEXT_OUT
+ setText(text)
+ }
+
+ /**
+ * Sets the text as the previous title
+ * No further checks are done, so be sure to verify with [isRoot]
+ */
+ @Throws(EmptyStackException::class)
+ fun setPrevText() {
+ titleStack.pop()
+ val anim = animationMap[animationType]
+ inAnimation = anim?.PREV_IN
+ outAnimation = anim?.PREV_OUT
+ val text = titleStack.peek()
+ setText(text)
+ }
+
+ init {
+ setFactory {
+ TextView(context).apply {
+ //replica of toolbar title
+ gravity = Gravity.START
+ setSingleLine()
+ ellipsize = TextUtils.TruncateAt.END
+ TextViewCompat.setTextAppearance(this, R.style.TextAppearance_AppCompat_Title)
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/library/src/main/kotlin/ca/allanwang/kau/views/TextSlider.kt b/library/src/main/kotlin/ca/allanwang/kau/views/TextSlider.kt
deleted file mode 100644
index b8735bb..0000000
--- a/library/src/main/kotlin/ca/allanwang/kau/views/TextSlider.kt
+++ /dev/null
@@ -1,127 +0,0 @@
-package ca.allanwang.kau.views
-
-import android.content.Context
-import android.graphics.Color
-import android.support.annotation.AnimRes
-import android.support.v4.widget.TextViewCompat
-import android.text.TextUtils
-import android.util.AttributeSet
-import android.view.Gravity
-import android.view.animation.Animation
-import android.view.animation.AnimationUtils
-import android.widget.TextSwitcher
-import android.widget.TextView
-import ca.allanwang.kau.R
-import java.util.*
-
-/**
- * Created by Allan Wang on 2017-06-21.
- *
- * Text switcher with global text color and embedded sliding animations
- * Also has a stack to keep track of title changes
- */
-class TextSlider @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null
-) : TextSwitcher(context, attrs) {
-
- val titleStack: Stack<CharSequence?> = Stack()
-
- inner class Animations(
- private @param: AnimRes val nextIn: Int,
- private @param: AnimRes val nextOut: Int,
- private @param: AnimRes val prevIn: Int,
- private @param: AnimRes val prevOut: Int
- ) {
-
- val NEXT_IN: Animation by lazy { AnimationUtils.loadAnimation(context, R.anim.kau_slide_in_left) }
- val NEXT_OUT: Animation by lazy { AnimationUtils.loadAnimation(context, R.anim.kau_slide_in_right) }
- val PREV_IN: Animation by lazy { AnimationUtils.loadAnimation(context, R.anim.kau_slide_in_top) }
- val PREV_OUT: Animation by lazy { AnimationUtils.loadAnimation(context, R.anim.kau_slide_in_bottom) }
-
- }
-
- private val SLIDE_IN_LEFT: Animation by lazy { AnimationUtils.loadAnimation(context, R.anim.kau_slide_in_left) }
- private val SLIDE_IN_RIGHT: Animation by lazy { AnimationUtils.loadAnimation(context, R.anim.kau_slide_in_right) }
- private val SLIDE_IN_TOP: Animation by lazy { AnimationUtils.loadAnimation(context, R.anim.kau_slide_in_top) }
- private val SLIDE_IN_BOTTOM: Animation by lazy { AnimationUtils.loadAnimation(context, R.anim.kau_slide_in_bottom) }
-
- private val SLIDE_OUT_LEFT: Animation by lazy { AnimationUtils.loadAnimation(context, R.anim.kau_slide_out_left) }
- private val SLIDE_OUT_RIGHT: Animation by lazy { AnimationUtils.loadAnimation(context, R.anim.kau_slide_out_right) }
- private val SLIDE_OUT_TOP: Animation by lazy { AnimationUtils.loadAnimation(context, R.anim.kau_slide_out_top) }
- private val SLIDE_OUT_BOTTOM: Animation by lazy { AnimationUtils.loadAnimation(context, R.anim.kau_slide_out_bottom) }
-
- var animate: Boolean = true
- var horizontal: Boolean = true
-
- var textColor: Int = Color.WHITE
- get() = field
- set(value) {
- field = value
- (getChildAt(0) as TextView).setTextColor(value)
- (getChildAt(1) as TextView).setTextColor(value)
- }
- val isRoot: Boolean
- get() = titleStack.size <= 1
-
- override fun setText(text: CharSequence?) {
- if ((currentView as TextView).text == text) return
- super.setText(text)
- }
-
- fun setTextSlideUp(text: CharSequence?) {
- inAnimation = if (animate) SLIDE_IN_BOTTOM else null
- outAnimation = if (animate) SLIDE_OUT_TOP else null
- setText(text)
- }
-
- fun setTextSlideDown(text: CharSequence?) {
- inAnimation = if (animate) SLIDE_IN_TOP else null
- outAnimation = if (animate) SLIDE_OUT_BOTTOM else null
- setText(text)
- }
-
- fun setTextSlideLeft(text: CharSequence?) {
- inAnimation = if (animate) SLIDE_IN_RIGHT else null
- outAnimation = if (animate) SLIDE_OUT_LEFT else null
- setText(text)
- }
-
- fun setTextSlideRight(text: CharSequence?) {
- inAnimation = if (animate) SLIDE_IN_LEFT else null
- outAnimation = if (animate) SLIDE_OUT_RIGHT else null
- setText(text)
- }
-
- override fun setCurrentText(text: CharSequence?) {
- if (titleStack.isNotEmpty()) titleStack.pop()
- titleStack.push(text)
- super.setCurrentText(text)
- }
-
- fun setNextText(text: CharSequence?) {
- titleStack.push(text)
- if (horizontal) setTextSlideLeft(text) else setTextSlideUp(text)
- }
-
- /**
- * Sets the text as the previous title
- * No further checks are done, so be sure to verify with [isRoot]
- */
- @Throws(EmptyStackException::class)
- fun setPrevText() {
- titleStack.pop()
- val text = titleStack.peek()
- if (horizontal) setTextSlideRight(text) else setTextSlideDown(text)
- }
-
- init {
- setFactory {
- TextView(context).apply {
- //replica of toolbar title
- gravity = Gravity.START
- setSingleLine()
- ellipsize = TextUtils.TruncateAt.END
- TextViewCompat.setTextAppearance(this, R.style.TextAppearance_AppCompat)
- }
- }
- }
-} \ No newline at end of file