From a6ee77a4f1d78252b15059d51f2533fa03483d8c Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Tue, 27 Jun 2017 20:00:44 -0700 Subject: Testing about activity and chained adapters --- .../kotlin/ca/allanwang/kau/about/AboutActivity.kt | 33 ------ .../ca/allanwang/kau/about/AboutActivityBase.kt | 86 ++++++++++++++ .../kotlin/ca/allanwang/kau/about/LibraryItem.kt | 73 ++++++++++++ .../main/kotlin/ca/allanwang/kau/about/MainItem.kt | 59 ++++++++++ .../ca/allanwang/kau/adapters/ChainedAdapters.kt | 88 ++++++++++++++ .../kotlin/ca/allanwang/kau/changelog/Changelog.kt | 2 +- .../kotlin/ca/allanwang/kau/kpref/KPrefActivity.kt | 7 +- .../kotlin/ca/allanwang/kau/kpref/KPrefBinder.kt | 4 +- .../ca/allanwang/kau/searchview/SearchView.kt | 4 +- .../kotlin/ca/allanwang/kau/utils/PackageUtils.kt | 4 + .../kotlin/ca/allanwang/kau/views/KauTextSlider.kt | 125 ++++++++++++++++++++ .../kotlin/ca/allanwang/kau/views/TextSlider.kt | 127 --------------------- .../src/main/res/layout/kau_about_item_library.xml | 107 +++++++++++++++++ .../src/main/res/layout/kau_about_item_main.xml | 106 +++++++++++++++++ library/src/main/res/layout/kau_activity_about.xml | 4 +- library/src/main/res/layout/kau_activity_kpref.xml | 5 +- library/src/main/res/values/attr.xml | 8 ++ library/src/main/res/values/ids.xml | 2 + library/src/main/res/values/strings_about.xml | 4 +- library/src/main/res/values/styles.xml | 8 -- 20 files changed, 673 insertions(+), 183 deletions(-) delete mode 100644 library/src/main/kotlin/ca/allanwang/kau/about/AboutActivity.kt create mode 100644 library/src/main/kotlin/ca/allanwang/kau/about/AboutActivityBase.kt create mode 100644 library/src/main/kotlin/ca/allanwang/kau/about/LibraryItem.kt create mode 100644 library/src/main/kotlin/ca/allanwang/kau/about/MainItem.kt create mode 100644 library/src/main/kotlin/ca/allanwang/kau/adapters/ChainedAdapters.kt create mode 100644 library/src/main/kotlin/ca/allanwang/kau/views/KauTextSlider.kt delete mode 100644 library/src/main/kotlin/ca/allanwang/kau/views/TextSlider.kt create mode 100644 library/src/main/res/layout/kau_about_item_library.xml create mode 100644 library/src/main/res/layout/kau_about_item_main.xml delete mode 100644 library/src/main/res/values/styles.xml (limited to 'library/src') 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$* { + * ; + * } + * + */ +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> by lazy { string(R.string.kau_dependencies_used) to HeaderAdapter() } + val sectionsChain: ChainedAdapters = 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 = 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>> = 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() { + + 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?) { + 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() { + + 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?) { + 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(vararg items: Pair>) { + private val chain: MutableList>> = mutableListOf(*items) + val baseAdapter: FastItemAdapter> = FastItemAdapter() + private val indexStack = Stack() + 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>) = add(items.toList()) + + fun add(items: Collection>>): ChainedAdapters { + 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>, @ColorInt val textColor: Int? = null) : RecyclerView.Adapter() { 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 { 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 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 = 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 = 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 diff --git a/library/src/main/res/layout/kau_about_item_library.xml b/library/src/main/res/layout/kau_about_item_library.xml new file mode 100644 index 0000000..5730d67 --- /dev/null +++ b/library/src/main/res/layout/kau_about_item_library.xml @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/library/src/main/res/layout/kau_about_item_main.xml b/library/src/main/res/layout/kau_about_item_main.xml new file mode 100644 index 0000000..96ba110 --- /dev/null +++ b/library/src/main/res/layout/kau_about_item_main.xml @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/library/src/main/res/layout/kau_activity_about.xml b/library/src/main/res/layout/kau_activity_about.xml index 21d9306..a42cbe8 100644 --- a/library/src/main/res/layout/kau_activity_about.xml +++ b/library/src/main/res/layout/kau_activity_about.xml @@ -13,12 +13,12 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> - + app:kau_animation_type="slide_vertical" /> diff --git a/library/src/main/res/layout/kau_activity_kpref.xml b/library/src/main/res/layout/kau_activity_kpref.xml index e4e7b97..2281c45 100644 --- a/library/src/main/res/layout/kau_activity_kpref.xml +++ b/library/src/main/res/layout/kau_activity_kpref.xml @@ -24,13 +24,12 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> - + app:kau_animation_type="slide_horizontal" /> diff --git a/library/src/main/res/values/attr.xml b/library/src/main/res/values/attr.xml index 894a069..14ae027 100644 --- a/library/src/main/res/values/attr.xml +++ b/library/src/main/res/values/attr.xml @@ -6,4 +6,12 @@ + + + + + + + + \ No newline at end of file diff --git a/library/src/main/res/values/ids.xml b/library/src/main/res/values/ids.xml index cda9faa..a21175a 100644 --- a/library/src/main/res/values/ids.xml +++ b/library/src/main/res/values/ids.xml @@ -8,4 +8,6 @@ + + \ No newline at end of file diff --git a/library/src/main/res/values/strings_about.xml b/library/src/main/res/values/strings_about.xml index 2c3f9a1..be891d2 100644 --- a/library/src/main/res/values/strings_about.xml +++ b/library/src/main/res/values/strings_about.xml @@ -1,5 +1,7 @@ - + Dependencies Used + + Allan Wang https://www.allanwang.ca/dev/ diff --git a/library/src/main/res/values/styles.xml b/library/src/main/res/values/styles.xml deleted file mode 100644 index c8e2197..0000000 --- a/library/src/main/res/values/styles.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - \ No newline at end of file -- cgit v1.2.3