diff options
author | Allan Wang <me@allanwang.ca> | 2017-06-27 20:00:44 -0700 |
---|---|---|
committer | Allan Wang <me@allanwang.ca> | 2017-06-27 20:00:44 -0700 |
commit | a6ee77a4f1d78252b15059d51f2533fa03483d8c (patch) | |
tree | b27b4a9cddfccce6f1edcdcdffba92c08bf33642 | |
parent | 8179e50208192e2b18b4df3bfc100d9cf779891a (diff) | |
download | kau-a6ee77a4f1d78252b15059d51f2533fa03483d8c.tar.gz kau-a6ee77a4f1d78252b15059d51f2533fa03483d8c.tar.bz2 kau-a6ee77a4f1d78252b15059d51f2533fa03483d8c.zip |
Testing about activity and chained adapters
27 files changed, 728 insertions, 192 deletions
diff --git a/docs/Changelog.md b/docs/Changelog.md index fe3e1bb..080b100 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -20,7 +20,7 @@ * Attached source files * Created color dialog * Added more utilities -* Fixed stack clearing when starting activity +* Fixed indexStack clearing when starting activity ## v1.0 * Initial Changelog diff --git a/library/progress-proguard.txt b/library/progress-proguard.txt index a68e6b0..8b13789 100644 --- a/library/progress-proguard.txt +++ b/library/progress-proguard.txt @@ -1,5 +1 @@ -# About library --keep class .R --keep class **.R$* { - <fields>; -} + 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 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 @@ +<?xml version="1.0" encoding="utf-8"?> +<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:id="@id/rippleForegroundListenerView" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="8dp" + android:layout_marginTop="8dp" + android:clickable="true" + android:foreground="?selectableItemBackground" + android:layoutDirection="ltr"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:padding="6dp"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:gravity="center_vertical" + android:orientation="horizontal" + android:paddingLeft="8dp" + android:paddingRight="8dp"> + + <TextView + android:id="@+id/libraryName" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="5" + android:ellipsize="end" + android:gravity="start" + android:maxLines="1" + android:textSize="@dimen/textSizeLarge_openSource" + android:textStyle="normal" + tools:text="Library name" /> + + <TextView + android:id="@+id/libraryCreator" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginTop="2dp" + android:layout_weight="2" + android:gravity="end" + android:maxLines="2" + android:textSize="@dimen/textSizeSmall_openSource" + android:textStyle="normal" + tools:text="Creator" /> + </LinearLayout> + + <View + android:id="@+id/libraryDescriptionDivider" + android:layout_width="match_parent" + android:layout_height="1px" + android:layout_marginTop="4dp" /> + + <TextView + android:id="@+id/libraryDescription" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:maxLines="20" + android:padding="8dp" + android:textSize="@dimen/textSizeSmall_openSource" + android:textStyle="normal" + tools:text="Description"/> + + <View + android:id="@+id/libraryBottomDivider" + android:layout_width="match_parent" + android:layout_height="1px" + android:layout_marginTop="4dp" /> + + <LinearLayout + android:id="@+id/libraryBottomContainer" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:gravity="center_vertical" + android:orientation="horizontal" + android:paddingLeft="8dp" + android:paddingRight="8dp" + android:paddingTop="4dp"> + + <TextView + android:id="@+id/libraryVersion" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:gravity="start" + android:maxLines="1" + android:textSize="@dimen/textSizeSmall_openSource" + android:textStyle="normal" + tools:text="Version" /> + + <TextView + android:id="@+id/libraryLicense" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:gravity="end" + android:maxLines="1" + android:textSize="@dimen/textSizeSmall_openSource" + android:textStyle="normal" + tools:text="License" /> + </LinearLayout> + </LinearLayout> +</android.support.v7.widget.CardView>
\ 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 @@ +<?xml version="1.0" encoding="utf-8"?> +<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="8dp" + android:layout_marginTop="8dp" + android:clickable="true" + android:background="?selectableItemBackground"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:padding="6dp"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:gravity="center_vertical" + android:orientation="horizontal" + android:paddingLeft="8dp" + android:paddingRight="8dp"> + + <TextView + android:id="@+id/title" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="5" + android:ellipsize="end" + android:gravity="start" + android:maxLines="1" + android:textSize="@dimen/textSizeLarge_openSource" + android:textStyle="normal" + tools:text="App name" /> + + <TextView + android:id="@+id/creator" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginTop="2dp" + android:layout_weight="2" + android:gravity="end" + android:maxLines="2" + android:textSize="@dimen/textSizeSmall_openSource" + android:textStyle="normal" + tools:text="Creator" /> + </LinearLayout> + + <View + android:id="@+id/top_divider" + android:layout_width="match_parent" + android:layout_height="1px" + android:layout_marginTop="4dp" /> + + <TextView + android:id="@+id/description" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:maxLines="20" + android:padding="8dp" + android:textSize="@dimen/textSizeSmall_openSource" + android:textStyle="normal" + tools:text="Description"/> + + <View + android:id="@+id/bottom_divider" + android:layout_width="match_parent" + android:layout_height="1px" + android:layout_marginTop="4dp" /> + + <LinearLayout + android:id="@+id/bottom_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:gravity="center_vertical" + android:orientation="horizontal" + android:paddingLeft="8dp" + android:paddingRight="8dp" + android:paddingTop="4dp"> + + <TextView + android:id="@+id/version" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:gravity="start" + android:maxLines="1" + android:textSize="@dimen/textSizeSmall_openSource" + android:textStyle="normal" + tools:text="Version" /> + + <TextView + android:id="@+id/license" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:gravity="end" + android:maxLines="1" + android:textSize="@dimen/textSizeSmall_openSource" + android:textStyle="normal" + tools:text="License" /> + </LinearLayout> + </LinearLayout> +</android.support.v7.widget.CardView>
\ 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"> - <ca.allanwang.kau.views.TextSlider + <ca.allanwang.kau.views.KauTextSlider android:id="@+id/kau_toolbar_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" - android:textAppearance="@style/TextAppearance.AppCompat.Title" /> + app:kau_animation_type="slide_vertical" /> </android.support.v7.widget.Toolbar> 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"> - <ca.allanwang.kau.views.TextSlider + <ca.allanwang.kau.views.KauTextSlider android:id="@+id/kau_toolbar_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" - android:textAppearance="@style/TextAppearance.AppCompat.Title" - android:textColor="@android:color/white" /> + app:kau_animation_type="slide_horizontal" /> </android.support.v7.widget.Toolbar> 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 @@ <attr name="kau_maxHeightPercent" format="float" /> </declare-styleable> + <declare-styleable name="KauTextSlider"> + <attr name="kau_animation_type" format="enum"> + <enum name="none" value="1000" /> + <enum name="slide_horizontal" value="1001" /> + <enum name="slide_vertical" value="1002" /> + </attr> + </declare-styleable> + </resources>
\ 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 @@ <item name="kau_item_pref_sub_item" type="id" /> <item name="kau_item_pref_plain_text" type="id" /> <item name="kau_item_search" type="id" /> + <item name="kau_item_about_library" type="id" /> + <item name="kau_item_about_main" type="id" /> </resources>
\ 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 @@ <resources xmlns:tools="http://schemas.android.com/tools"> - <string name="define_int_kau" tools:ignore="ResourceName" /> + <string name="kau_dependencies_used">Dependencies Used</string> + + <string name="define_kau" tools:ignore="ResourceName" /> <!-- Author section --> <string name="library_kau_author" tools:ignore="ResourceName">Allan Wang</string> <string name="library_kau_authorWebsite" tools:ignore="ResourceName">https://www.allanwang.ca/dev/</string> 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 @@ -<?xml version="1.0" encoding="utf-8"?> -<resources> - - <style name="KauSearchView" parent="Widget.AppCompat.SearchView.ActionBar"> - - </style> - -</resources>
\ No newline at end of file diff --git a/sample/proguard-rules.pro b/sample/proguard-rules.pro index 2b766bc..b76c0ff 100644 --- a/sample/proguard-rules.pro +++ b/sample/proguard-rules.pro @@ -17,9 +17,15 @@ #} # Uncomment this to preserve the line number information for -# debugging stack traces. +# debugging indexStack traces. #-keepattributes SourceFile,LineNumberTable # If you keep the line number information, uncomment this to # hide the original source file name. #-renamesourcefileattribute SourceFile + +# About library +-keep class .R +-keep class **.R$* { + <fields>; +}
\ No newline at end of file diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml index b8b54bf..2a55f62 100644 --- a/sample/src/main/AndroidManifest.xml +++ b/sample/src/main/AndroidManifest.xml @@ -22,6 +22,9 @@ <activity android:name=".AnimActivity" android:theme="@style/AppTheme.Slide" /> + <activity + android:name=".AboutActivity" + android:theme="@style/Theme.AppCompat.NoActionBar" /> </application> </manifest>
\ No newline at end of file diff --git a/sample/src/main/kotlin/ca/allanwang/kau/sample/AboutActivity.kt b/sample/src/main/kotlin/ca/allanwang/kau/sample/AboutActivity.kt new file mode 100644 index 0000000..574922d --- /dev/null +++ b/sample/src/main/kotlin/ca/allanwang/kau/sample/AboutActivity.kt @@ -0,0 +1,34 @@ +package ca.allanwang.kau.sample + +import android.os.Bundle +import android.os.PersistableBundle +import ca.allanwang.kau.about.AboutActivityBase +import ca.allanwang.kau.about.MainItem +import ca.allanwang.kau.utils.string +import com.mikepenz.fastadapter.adapters.HeaderAdapter + +/** + * Created by Allan Wang on 2017-06-27. + */ +class AboutActivity : AboutActivityBase(R.string::class.java) { + + val mainHeader = HeaderAdapter<MainItem>() + +// override fun onCreateSections(): List<Pair<String, HeaderAdapter<*>>> = listOf( +// String.format(string(R.string.kau_about_x), "KAU") to mainHeader +// ) + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) +// mainHeader.add(MainItem { +// title = string(R.string.app_name) +// author = "Allan Wang" +// version = BuildConfig.VERSION_NAME +// }) + } + + override fun onPostCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) { + super.onPostCreate(savedInstanceState, persistentState) + recycler.adapter.notifyDataSetChanged() + } +}
\ 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 3cd714e..d8e7e33 100644 --- a/sample/src/main/kotlin/ca/allanwang/kau/sample/MainActivity.kt +++ b/sample/src/main/kotlin/ca/allanwang/kau/sample/MainActivity.kt @@ -3,6 +3,7 @@ package ca.allanwang.kau.sample import android.os.Bundle import android.view.Menu import android.view.MenuItem +import ca.allanwang.kau.about.AboutActivityBase import ca.allanwang.kau.email.sendEmail import ca.allanwang.kau.kpref.CoreAttributeContract import ca.allanwang.kau.kpref.KPrefActivity @@ -146,7 +147,13 @@ class MainActivity : KPrefActivity() { descRes = R.string.sub_item_desc } - plainText(R.string.kau_lorem_ipsum) + plainText(R.string.kau_lorem_ipsum) { + onClick = { + _, _, _ -> + startActivity(AboutActivity::class.java) + false + } + } } diff --git a/sample/src/main/res/xml/changelog.xml b/sample/src/main/res/xml/changelog.xml index 003ee8b..b3dcdde 100644 --- a/sample/src/main/res/xml/changelog.xml +++ b/sample/src/main/res/xml/changelog.xml @@ -33,7 +33,7 @@ <item text="Attached source files" /> <item text="Created color dialog" /> <item text="Added more utilities" /> - <item text="Fixed stack clearing when starting activity" /> + <item text="Fixed indexStack clearing when starting activity" /> <version title="v1.0" /> <item text="Initial Changelog" /> |