From bafc1996d803862d30a2c7d0c402d30c79c4f647 Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Thu, 3 Aug 2017 15:18:20 -0700 Subject: 3.2.2 - Create faq parser and update sample (#19) * Test emulator * Update readme * Update fastadapter and about listing * Make faq parser asynchronous * Modularize about panels * Add basis for faq * Test and finalize the faq panel * Update readme * Update changelog * Remove emulator for now * Update sample --- .../ca/allanwang/kau/about/AboutActivityBase.kt | 184 +++++++------------ .../ca/allanwang/kau/about/AboutPanelDelegate.kt | 198 +++++++++++++++++++++ .../ca/allanwang/kau/about/CollapsibleTextView.kt | 33 ++++ .../kotlin/ca/allanwang/kau/about/CutoutIItem.kt | 12 +- .../main/kotlin/ca/allanwang/kau/about/FaqIItem.kt | 86 +++++++++ .../kotlin/ca/allanwang/kau/about/LibraryIItem.kt | 34 ++-- about/src/main/res/layout/kau_iitem_faq.xml | 37 ++++ about/src/main/res/values/strings.xml | 1 + about/src/main/res/values/strings_about.xml | 2 +- 9 files changed, 435 insertions(+), 152 deletions(-) create mode 100644 about/src/main/kotlin/ca/allanwang/kau/about/AboutPanelDelegate.kt create mode 100644 about/src/main/kotlin/ca/allanwang/kau/about/CollapsibleTextView.kt create mode 100644 about/src/main/kotlin/ca/allanwang/kau/about/FaqIItem.kt create mode 100644 about/src/main/res/layout/kau_iitem_faq.xml (limited to 'about/src') diff --git a/about/src/main/kotlin/ca/allanwang/kau/about/AboutActivityBase.kt b/about/src/main/kotlin/ca/allanwang/kau/about/AboutActivityBase.kt index 61a3bb2..442821f 100644 --- a/about/src/main/kotlin/ca/allanwang/kau/about/AboutActivityBase.kt +++ b/about/src/main/kotlin/ca/allanwang/kau/about/AboutActivityBase.kt @@ -4,8 +4,6 @@ import android.graphics.drawable.Drawable import android.os.Bundle import android.support.v4.view.PagerAdapter import android.support.v4.view.ViewPager -import android.support.v7.app.AppCompatActivity -import android.support.v7.widget.RecyclerView import android.transition.TransitionInflater import android.view.LayoutInflater import android.view.View @@ -13,19 +11,15 @@ import android.view.ViewGroup import ca.allanwang.kau.adapters.FastItemThemedAdapter import ca.allanwang.kau.adapters.ThemableIItemColors import ca.allanwang.kau.adapters.ThemableIItemColorsDelegate -import ca.allanwang.kau.animators.FadeScaleAnimatorAdd -import ca.allanwang.kau.animators.KauAnimator -import ca.allanwang.kau.iitems.HeaderIItem import ca.allanwang.kau.internal.KauBaseActivity import ca.allanwang.kau.ui.widgets.ElasticDragDismissFrameLayout import ca.allanwang.kau.ui.widgets.InkPageIndicator -import ca.allanwang.kau.utils.* +import ca.allanwang.kau.utils.AnimHolder +import ca.allanwang.kau.utils.bindView +import ca.allanwang.kau.utils.dimenPixelSize import com.mikepenz.aboutlibraries.Libs import com.mikepenz.aboutlibraries.entity.Library import com.mikepenz.fastadapter.IItem -import org.jetbrains.anko.doAsync -import org.jetbrains.anko.uiThread -import java.security.InvalidParameterException /** * Created by Allan Wang on 2017-06-28. @@ -38,26 +32,21 @@ import java.security.InvalidParameterException * Note that for the auto detection to work, the R fields must be excluded from Proguard * Manual lib listings and other extra modifications can be done so by overriding the open functions */ -abstract class AboutActivityBase(val rClass: Class<*>?, val configBuilder: Configs.() -> Unit = {}) : KauBaseActivity(), ViewPager.OnPageChangeListener { +abstract class AboutActivityBase(val rClass: Class<*>?, private val configBuilder: Configs.() -> Unit = {}) : KauBaseActivity(), ViewPager.OnPageChangeListener { + + private val draggableFrame: ElasticDragDismissFrameLayout by bindView(R.id.about_draggable_frame) + private val pager: ViewPager by bindView(R.id.about_pager) + private val indicator: InkPageIndicator by bindView(R.id.about_indicator) + + val currentPage + get() = pager.currentItem - val draggableFrame: ElasticDragDismissFrameLayout by bindView(R.id.about_draggable_frame) - val pager: ViewPager by bindView(R.id.about_pager) - val indicator: InkPageIndicator by bindView(R.id.about_indicator) /** * Holds some common configurations that may be added directly from the constructor * Applied lazily since it needs the context to fetch resources */ val configs: Configs by lazy { Configs().apply { configBuilder() } } - /** - * Number of pages in the adapter - * Defaults to just the main view and lib view - */ - open val pageCount: Int = 2 - /** - * Page position for the libs - * This is generated automatically if [inflateLibPage] is called - */ - private var libPage: Int = -2 + /** * Holds that status of each page * 0 means nothing has happened @@ -65,98 +54,65 @@ abstract class AboutActivityBase(val rClass: Class<*>?, val configBuilder: Confi * The rest is up to you */ lateinit var pageStatus: IntArray - /** - * Holds the lib items once they are fetched asynchronously - */ - var libItems: List? = null - /** - * Holds the adapter for the library page; this is generated later because it uses the config colors - */ - lateinit var libAdapter: FastItemThemedAdapter> - /** - * Global reference of the library recycler - * This is set by default through [inflateLibPage] and is used to stop scrolling - * When the draggable frame exits - * It is not required, hence its nullability - */ - private var libRecycler: RecyclerView? = null + + val panels: List by lazy { + val defaultPanels = mutableListOf(AboutPanelMain(), AboutPanelLibs()) + if (configs.faqXmlRes != -1) defaultPanels.add(AboutPanelFaqs()) + defaultPanels + } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.kau_activity_about) - pageStatus = IntArray(pageCount) - libAdapter = FastItemThemedAdapter(configs) - LibraryIItem.bindClickEvents(libAdapter) + pageStatus = IntArray(panels.size) + pageStatus[0] = 2 //the first page is instantly visible if (configs.textColor != null) indicator.setColour(configs.textColor!!) with(pager) { adapter = AboutPagerAdapter() pageMargin = dimenPixelSize(R.dimen.kau_spacing_normal) + offscreenPageLimit = panels.size - 1 addOnPageChangeListener(this@AboutActivityBase) } indicator.setViewPager(pager) draggableFrame.addListener(object : ElasticDragDismissFrameLayout.SystemChromeFader(this) { override fun onDragDismissed() { window.returnTransition = TransitionInflater.from(this@AboutActivityBase) - .inflateTransition(if (draggableFrame.translationY > 0) configs.transitionExitBottom else configs.transitionExitTop) - - libRecycler?.stopScroll() + .inflateTransition(if (draggableFrame.translationY > 0) R.transition.kau_exit_slide_bottom else R.transition.kau_exit_slide_top) + panels[currentPage].recycler?.stopScroll() finishAfterTransition() } }) + panels.forEachIndexed { index, contract -> contract.loadItems(this, index) } } - inner class Configs : ThemableIItemColors by ThemableIItemColorsDelegate() { + class Configs : ThemableIItemColors by ThemableIItemColorsDelegate() { var cutoutTextRes: Int = -1 var cutoutText: String? = null var cutoutDrawableRes: Int = -1 var cutoutDrawable: Drawable? = null var cutoutForeground: Int? = null - var libPageTitleRes: Int = -1 - var libPageTitle: String? = string(R.string.kau_about_libraries_intro) //This is in the string by default since it's lower priority - - var transitionExitTop: Int = R.transition.kau_exit_slide_top - var transitionExitBottom: Int = R.transition.kau_exit_slide_bottom - } - - /** - * Method to fetch the library list - * This is fetched asynchronously and you may override it to customize the list - */ - open fun getLibraries(libs: Libs): List = libs.prepareLibraries(this, null, null, true, true)!! - - /** - * Gets the view associated with the given page position - * Keep in mind that when inflating, do NOT add the view to the viewgroup - * Use layoutInflater.inflate(id, parent, false) - */ - open fun getPage(position: Int, layoutInflater: LayoutInflater, parent: ViewGroup): View { - return when (position) { - 0 -> inflateMainPage(layoutInflater, parent, position) - pageCount - 1 -> inflateLibPage(layoutInflater, parent, position) - else -> throw InvalidParameterException() - } - } - - /** - * Create the main view with the cutout - */ - open fun inflateMainPage(layoutInflater: LayoutInflater, parent: ViewGroup, position: Int): View { - val fastAdapter = FastItemThemedAdapter>(configs) - val recycler = fullLinearRecycler(fastAdapter) - fastAdapter.add(CutoutIItem { - with(configs) { - text = string(cutoutTextRes, cutoutText) - drawable = drawable(cutoutDrawableRes, cutoutDrawable) - if (configs.cutoutForeground != null) foregroundColor = configs.cutoutForeground!! + var libPageTitleRes: Int = R.string.kau_about_libraries_intro + var libPageTitle: String? = null + set(value) { + field = value + libPageTitleRes = -1 //reset res so we don't use our default } - }.apply { - themeEnabled = configs.cutoutForeground == null - }) - postInflateMainPage(fastAdapter) - return recycler + var faqXmlRes: Int = -1 + var faqPageTitleRes: Int = R.string.kau_about_faq_intro + var faqPageTitle: String? = null + set(value) { + field = value + faqPageTitleRes = -1 //reset res so we don't use our default + } + /** + * Whether new lines should be included + */ + var faqParseNewLine: Boolean = true } /** + * For [mainPanel] + * * Open hook called just before the main page view is returned * Feel free to add your own items to the adapter in here */ @@ -165,32 +121,23 @@ abstract class AboutActivityBase(val rClass: Class<*>?, val configBuilder: Confi } /** - * Create the lib view with the list of libraries + * For [libPanel] + * + * Method to fetch the library list + * This is fetched asynchronously and you may override it to customize the list + */ + open fun getLibraries(libs: Libs): List = libs.prepareLibraries(this, null, null, true, true)!! + + /* + * ------------------------------------------------------------------- + * Page 3: FAQ + * ------------------------------------------------------------------- */ - open fun inflateLibPage(layoutInflater: LayoutInflater, parent: ViewGroup, position: Int): View { - libPage = position - val v = layoutInflater.inflate(R.layout.kau_recycler_detached_background, parent, false) - val recycler = v.findViewById(R.id.kau_recycler_detached) - libRecycler = recycler - recycler.withMarginDecoration(16, KAU_BOTTOM) - recycler.adapter = libAdapter - recycler.itemAnimator = KauAnimator(addAnimator = FadeScaleAnimatorAdd(scaleFactor = 0.7f, itemDelayFactor = 0.2f)).apply { addDuration = 300; interpolator = AnimHolder.decelerateInterpolator(this@AboutActivityBase) } - val background = v.findViewById(R.id.kau_recycler_detached_background) - if (configs.backgroundColor != null) background.setBackgroundColor(configs.backgroundColor!!.colorToForeground()) - doAsync { - libItems = getLibraries( - if (rClass == null) Libs(this@AboutActivityBase) else Libs(this@AboutActivityBase, Libs.toStringArray(rClass.fields)) - ).map { LibraryIItem(it) } - if (libPage >= 0 && pageStatus[libPage] == 1) - uiThread { addLibItems() } - } - return v - } - inner class AboutPagerAdapter : PagerAdapter() { + private inner class AboutPagerAdapter : PagerAdapter() { private val layoutInflater: LayoutInflater = LayoutInflater.from(this@AboutActivityBase) - private val views = Array(pageCount) { null } + private val views = Array(panels.size) { null } override fun instantiateItem(collection: ViewGroup, position: Int): Any { val layout = getPage(position, collection) @@ -203,7 +150,7 @@ abstract class AboutActivityBase(val rClass: Class<*>?, val configBuilder: Confi views[position] = null } - override fun getCount(): Int = pageCount + override fun getCount(): Int = panels.size override fun isViewFromObject(view: View, `object`: Any): Boolean = view === `object` @@ -211,7 +158,8 @@ abstract class AboutActivityBase(val rClass: Class<*>?, val configBuilder: Confi * Only get page if view does not exist */ private fun getPage(position: Int, parent: ViewGroup): View { - if (views[position] == null) views[position] = getPage(position, layoutInflater, parent) + if (views[position] == null) views[position] = panels[position] + .inflatePage(this@AboutActivityBase, parent, position) return views[position]!! } } @@ -222,19 +170,7 @@ abstract class AboutActivityBase(val rClass: Class<*>?, val configBuilder: Confi override fun onPageSelected(position: Int) { if (pageStatus[position] == 0) pageStatus[position] = 1 // mark as seen if previously null - if (position == libPage && libItems != null && pageStatus[position] == 1) { - pageStatus[position] = 2 //add libs and mark as such - postDelayed(300) { addLibItems() } //delay so that the animations occur once the page is fully switched - } - } - - /** - * Function that is called when the view is ready to add the lib items - * Feel free to add your own items here - */ - open fun addLibItems() { - libAdapter.add(HeaderIItem(text = configs.libPageTitle, textRes = configs.libPageTitleRes)) - .add(libItems) + if (pageStatus[position] == 1) panels[position].addItems(this, position) } override fun onDestroy() { diff --git a/about/src/main/kotlin/ca/allanwang/kau/about/AboutPanelDelegate.kt b/about/src/main/kotlin/ca/allanwang/kau/about/AboutPanelDelegate.kt new file mode 100644 index 0000000..47b9ac4 --- /dev/null +++ b/about/src/main/kotlin/ca/allanwang/kau/about/AboutPanelDelegate.kt @@ -0,0 +1,198 @@ +package ca.allanwang.kau.about + +import android.support.v7.widget.RecyclerView +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import ca.allanwang.kau.adapters.FastItemThemedAdapter +import ca.allanwang.kau.animators.FadeScaleAnimatorAdd +import ca.allanwang.kau.animators.KauAnimator +import ca.allanwang.kau.animators.NoAnimatorChange +import ca.allanwang.kau.iitems.HeaderIItem +import ca.allanwang.kau.utils.* +import ca.allanwang.kau.xml.kauParseFaq +import com.mikepenz.aboutlibraries.Libs +import com.mikepenz.fastadapter.IItem +import org.jetbrains.anko.doAsync +import org.jetbrains.anko.uiThread + +/** + * Created by Allan Wang on 2017-08-02. + * + * The core logic for pages used in [AboutActivityBase] + */ +interface AboutPanelContract { + /** + * Model list to be added to [adapter] + */ + var items: List>? + /** + * The adapter, will be late initialized as it depends on configs + */ + var adapter: FastItemThemedAdapter> + /** + * Reference to the recyclerview, will be used to stop scrolling upon exit + */ + var recycler: RecyclerView? + + /** + * The base inflation method that will be called for new pages from the page adapter + * Keep in mind that when inflating, do NOT add the view to the viewgroup + * Use layoutInflater.inflate(id, parent, false) + */ + fun inflatePage(activity: AboutActivityBase, parent: ViewGroup, position: Int): View + + /** + * Convenience method called during [inflatePage] + * No return value necessary + */ + fun onInflatingPage(activity: AboutActivityBase, recycler: RecyclerView, position: Int) + + /** + * Triggers start of item loading + * Typically called with [inflatePage] + */ + fun loadItems(activity: AboutActivityBase, position: Int) + + /** + * Called when the [adapter] should take in the items + * This typically happens once the user has scroll to the page, + * so they may see a transition + * + * [AboutActivityBase.pageStatus] should be updated accordingly, + * as triggering this does not necessarily mean that the items are added + */ + fun addItems(activity: AboutActivityBase, position: Int) +} + +abstract class AboutPanelRecycler : AboutPanelContract { + + override var items: List>? = null + + override lateinit var adapter: FastItemThemedAdapter> + + override var recycler: RecyclerView? = null + + override fun onInflatingPage(activity: AboutActivityBase, recycler: RecyclerView, position: Int) { + recycler.adapter = adapter + recycler.itemAnimator = KauAnimator( + addAnimator = FadeScaleAnimatorAdd(scaleFactor = 0.7f, itemDelayFactor = 0.2f), + changeAnimator = NoAnimatorChange() + ).apply { addDuration = 300; interpolator = AnimHolder.decelerateInterpolator(recycler.context) } + } + + override fun inflatePage(activity: AboutActivityBase, parent: ViewGroup, position: Int): View { + val v = LayoutInflater.from(activity).inflate(R.layout.kau_recycler_detached_background, parent, false) + adapter = FastItemThemedAdapter(activity.configs) + recycler = v.findViewById(R.id.kau_recycler_detached) + onInflatingPage(activity, recycler!!, position) + val background = v.findViewById(R.id.kau_recycler_detached_background) + if (activity.configs.backgroundColor != null) background.setBackgroundColor(activity.configs.backgroundColor!!.colorToForeground()) + loadItems(activity, position) + return v + } + + override fun addItems(activity: AboutActivityBase, position: Int) { + if (items == null) return + activity.pageStatus[position] = 2 + postDelayed(300) { addItemsImpl(activity, position) } + } + + abstract fun addItemsImpl(activity: AboutActivityBase, position: Int) +} + +/** + * Panel delegate for the main page + * The loading is synchronous, so it is done on inflation + * All other loading and adding methods are overridden to do nothing + * There is a [AboutActivityBase.postInflateMainPage] hook that can be overridden + * to update this panel without extending the whole delegate + */ +open class AboutPanelMain : AboutPanelRecycler() { + + override fun onInflatingPage(activity: AboutActivityBase, recycler: RecyclerView, position: Int) {} + + override fun inflatePage(activity: AboutActivityBase, parent: ViewGroup, position: Int): View { + with(activity) { + adapter = FastItemThemedAdapter>(configs) + recycler = fullLinearRecycler(adapter) + adapter.add(CutoutIItem { + with(configs) { + text = string(cutoutTextRes, cutoutText) + drawable = drawable(cutoutDrawableRes, cutoutDrawable) + if (configs.cutoutForeground != null) foregroundColor = configs.cutoutForeground!! + } + }.apply { + themeEnabled = configs.cutoutForeground == null + }) + postInflateMainPage(adapter) + return recycler!! + } + } + + override fun loadItems(activity: AboutActivityBase, position: Int) {} + override fun addItems(activity: AboutActivityBase, position: Int) { + activity.pageStatus[position] = 2 + } + + override fun addItemsImpl(activity: AboutActivityBase, position: Int) {} + +} + +/** + * Panel for loading libraries + * There is a [AboutActivityBase.getLibraries] hook that can be overridden + * to customize the libraries listed + */ +open class AboutPanelLibs : AboutPanelRecycler() { + + override fun onInflatingPage(activity: AboutActivityBase, recycler: RecyclerView, position: Int) { + super.onInflatingPage(activity, recycler, position) + recycler.withMarginDecoration(16, KAU_BOTTOM) + LibraryIItem.bindEvents(adapter) + } + + override fun loadItems(activity: AboutActivityBase, position: Int) { + doAsync { + with(activity) { + items = getLibraries(if (rClass == null) Libs(activity) else Libs(this, Libs.toStringArray(rClass.fields))) + .map { LibraryIItem(it) } + if (pageStatus[position] == 1) + uiThread { addItems(activity, position) } + } + } + } + + override fun addItemsImpl(activity: AboutActivityBase, position: Int) { + with(activity.configs) { + adapter.add(HeaderIItem(text = libPageTitle, textRes = libPageTitleRes)) + .add(items) + } + } +} + +open class AboutPanelFaqs : AboutPanelRecycler() { + + override fun onInflatingPage(activity: AboutActivityBase, recycler: RecyclerView, position: Int) { + super.onInflatingPage(activity, recycler, position) + FaqIItem.bindEvents(adapter) + } + + override fun loadItems(activity: AboutActivityBase, position: Int) { + with(activity) { + kauParseFaq(configs.faqXmlRes, configs.faqParseNewLine) { + items = it.map { FaqIItem(it) } + if (pageStatus[position] == 1) + addItems(activity, position) + } + } + } + + override fun addItemsImpl(activity: AboutActivityBase, position: Int) { + with(activity.configs) { + adapter.add(HeaderIItem(text = faqPageTitle, textRes = faqPageTitleRes)) + .add(items) + } + } + +} \ No newline at end of file diff --git a/about/src/main/kotlin/ca/allanwang/kau/about/CollapsibleTextView.kt b/about/src/main/kotlin/ca/allanwang/kau/about/CollapsibleTextView.kt new file mode 100644 index 0000000..32573bc --- /dev/null +++ b/about/src/main/kotlin/ca/allanwang/kau/about/CollapsibleTextView.kt @@ -0,0 +1,33 @@ +package ca.allanwang.kau.about + +import android.content.Context +import android.content.res.Configuration +import android.util.AttributeSet +import android.widget.LinearLayout +import android.widget.TextView +import ca.allanwang.kau.ui.views.CollapsibleView +import ca.allanwang.kau.ui.views.CollapsibleViewDelegate + +/** + * Created by Allan Wang on 2017-08-02. + * + */ +class CollapsibleTextView @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 +) : TextView(context, attrs, defStyleAttr), CollapsibleView by CollapsibleViewDelegate() { + + init { + initCollapsible(this) + } + + override fun onConfigurationChanged(newConfig: Configuration?) { + resetCollapsibleAnimation() + super.onConfigurationChanged(newConfig) + } + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec) + val result = getCollapsibleDimension() + setMeasuredDimension(result.first, result.second) + } +} \ No newline at end of file diff --git a/about/src/main/kotlin/ca/allanwang/kau/about/CutoutIItem.kt b/about/src/main/kotlin/ca/allanwang/kau/about/CutoutIItem.kt index 1ba5815..3f764d3 100644 --- a/about/src/main/kotlin/ca/allanwang/kau/about/CutoutIItem.kt +++ b/about/src/main/kotlin/ca/allanwang/kau/about/CutoutIItem.kt @@ -4,6 +4,7 @@ import android.support.v7.widget.RecyclerView import android.view.View import ca.allanwang.kau.adapters.ThemableIItem import ca.allanwang.kau.adapters.ThemableIItemDelegate +import ca.allanwang.kau.iitems.KauIItem import ca.allanwang.kau.ui.views.CutoutView import ca.allanwang.kau.utils.bindView import com.mikepenz.fastadapter.items.AbstractItem @@ -13,12 +14,9 @@ import com.mikepenz.fastadapter.items.AbstractItem * * Just a cutout item with some defaults in [R.layout.kau_iitem_cutout] */ -class CutoutIItem(val config: CutoutView.() -> Unit = {} -) : AbstractItem(), ThemableIItem by ThemableIItemDelegate() { - - override fun getType(): Int = R.id.kau_item_cutout - - override fun getLayoutRes(): Int = R.layout.kau_iitem_cutout +class CutoutIItem(val config: CutoutView.() -> Unit = {}) : KauIItem( + R.layout.kau_iitem_cutout, {ViewHolder(it)}, R.id.kau_item_cutout +), ThemableIItem by ThemableIItemDelegate() { override fun isSelectable(): Boolean = false @@ -38,8 +36,6 @@ class CutoutIItem(val config: CutoutView.() -> Unit = {} } } - override fun getViewHolder(v: View): ViewHolder = ViewHolder(v) - class ViewHolder(v: View) : RecyclerView.ViewHolder(v) { val cutout: CutoutView by bindView(R.id.kau_cutout) } diff --git a/about/src/main/kotlin/ca/allanwang/kau/about/FaqIItem.kt b/about/src/main/kotlin/ca/allanwang/kau/about/FaqIItem.kt new file mode 100644 index 0000000..5e00447 --- /dev/null +++ b/about/src/main/kotlin/ca/allanwang/kau/about/FaqIItem.kt @@ -0,0 +1,86 @@ +package ca.allanwang.kau.about + +import android.support.v7.widget.RecyclerView +import android.text.method.LinkMovementMethod +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import ca.allanwang.kau.adapters.ThemableIItem +import ca.allanwang.kau.adapters.ThemableIItemDelegate +import ca.allanwang.kau.iitems.KauIItem +import ca.allanwang.kau.utils.bindView +import ca.allanwang.kau.utils.dpToPx +import ca.allanwang.kau.utils.parentViewGroup +import ca.allanwang.kau.utils.setPaddingLeft +import ca.allanwang.kau.xml.FaqItem +import com.mikepenz.fastadapter.FastAdapter +import com.mikepenz.fastadapter.IItem +import com.mikepenz.fastadapter.listeners.ClickEventHook + +/** + * Created by Allan Wang on 2017-08-02. + */ +class FaqIItem(val content: FaqItem) : KauIItem( + R.layout.kau_iitem_faq, { ViewHolder(it) }, R.id.kau_item_faq +), ThemableIItem by ThemableIItemDelegate() { + + companion object { + + + @JvmStatic fun bindEvents(fastAdapter: FastAdapter>) { + fastAdapter.withSelectable(false) + .withEventHook(object : ClickEventHook>() { + + override fun onBind(viewHolder: RecyclerView.ViewHolder): View? + = (viewHolder as? ViewHolder)?.questionContainer + + override fun onClick(v: View, position: Int, adapter: FastAdapter>, item: IItem<*, *>) { + if (item !is FaqIItem) return + item.isExpanded = !item.isExpanded + v.parentViewGroup.findViewById(R.id.faq_item_answer).setExpanded(item.isExpanded) + } + + }) + } + } + + private var isExpanded = false + + override fun bindView(holder: ViewHolder, payloads: MutableList?) { + super.bindView(holder, payloads) + with(holder) { + number.text = "${content.number}." + question.text = content.question + answer.setExpanded(isExpanded, false) + if (accentColor != null) answer.setLinkTextColor(accentColor!!) + answer.text = content.answer + answer.post { answer.setPaddingLeft(16.dpToPx + number.width) } + bindTextColor(number, question) + bindTextColorSecondary(answer) + bindDividerColor(answer) + bindBackgroundRipple(questionContainer) + } + } + + override fun unbindView(holder: ViewHolder) { + super.unbindView(holder) + with(holder) { + number.text = null + question.text = null + answer.text = null + } + } + + class ViewHolder(v: View) : RecyclerView.ViewHolder(v) { + val container: ViewGroup by bindView(R.id.faq_item) + val questionContainer: ViewGroup by bindView(R.id.faq_item_question_container) + val number: TextView by bindView(R.id.faq_item_number) + val question: TextView by bindView(R.id.faq_item_question) + val answer: CollapsibleTextView by bindView(R.id.faq_item_answer) + + init { + answer.movementMethod = LinkMovementMethod.getInstance() + } + } + +} \ No newline at end of file diff --git a/about/src/main/kotlin/ca/allanwang/kau/about/LibraryIItem.kt b/about/src/main/kotlin/ca/allanwang/kau/about/LibraryIItem.kt index 518cd54..e50460e 100644 --- a/about/src/main/kotlin/ca/allanwang/kau/about/LibraryIItem.kt +++ b/about/src/main/kotlin/ca/allanwang/kau/about/LibraryIItem.kt @@ -8,6 +8,7 @@ import android.view.View import android.widget.TextView import ca.allanwang.kau.adapters.ThemableIItem import ca.allanwang.kau.adapters.ThemableIItemDelegate +import ca.allanwang.kau.iitems.KauIItem import ca.allanwang.kau.utils.bindView import ca.allanwang.kau.utils.gone import ca.allanwang.kau.utils.startLink @@ -15,33 +16,30 @@ import ca.allanwang.kau.utils.visible import com.mikepenz.aboutlibraries.entity.Library import com.mikepenz.fastadapter.FastAdapter import com.mikepenz.fastadapter.IItem -import com.mikepenz.fastadapter.items.AbstractItem /** * Created by Allan Wang on 2017-06-27. */ -class LibraryIItem(val lib: Library -) : AbstractItem(), ThemableIItem by ThemableIItemDelegate() { +class LibraryIItem(val lib: Library) : KauIItem( + R.layout.kau_iitem_library, { ViewHolder(it) }, R.id.kau_item_library +), ThemableIItem by ThemableIItemDelegate() { companion object { - @JvmStatic fun bindClickEvents(fastAdapter: FastAdapter>) { - fastAdapter.withOnClickListener { v, _, item, _ -> - if (item !is LibraryIItem) false - else { - val c = v.context - with(item.lib) { - c.startLink(libraryWebsite, repositoryLink, authorWebsite) + @JvmStatic fun bindEvents(fastAdapter: FastAdapter>) { + fastAdapter.withSelectable(false) + .withOnClickListener { v, _, item, _ -> + if (item !is LibraryIItem) false + else { + val c = v.context + with(item.lib) { + c.startLink(libraryWebsite, repositoryLink, authorWebsite) + } + true + } } - true - } - } } } - override fun getType(): Int = R.id.kau_item_library - - override fun getLayoutRes(): Int = R.layout.kau_iitem_library - override fun isSelectable(): Boolean = false override fun bindView(holder: ViewHolder, payloads: MutableList?) { @@ -83,8 +81,6 @@ class LibraryIItem(val lib: Library } } - override fun getViewHolder(v: View): ViewHolder = ViewHolder(v) - class ViewHolder(v: View) : RecyclerView.ViewHolder(v) { val card: CardView by bindView(R.id.lib_item_card) val name: TextView by bindView(R.id.lib_item_name) diff --git a/about/src/main/res/layout/kau_iitem_faq.xml b/about/src/main/res/layout/kau_iitem_faq.xml new file mode 100644 index 0000000..4a0f7fc --- /dev/null +++ b/about/src/main/res/layout/kau_iitem_faq.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/about/src/main/res/values/strings.xml b/about/src/main/res/values/strings.xml index 509b56c..164c0c8 100644 --- a/about/src/main/res/values/strings.xml +++ b/about/src/main/res/values/strings.xml @@ -1,4 +1,5 @@ This app would not be possible without the following great libraries. + FAQ \ No newline at end of file diff --git a/about/src/main/res/values/strings_about.xml b/about/src/main/res/values/strings_about.xml index 8f10d31..8c3dc59 100644 --- a/about/src/main/res/values/strings_about.xml +++ b/about/src/main/res/values/strings_about.xml @@ -1,5 +1,5 @@ - 3.0 + 3.2.3 Allan Wang https://www.allanwang.ca/dev/ -- cgit v1.2.3