Filters with flexible adapter

This commit is contained in:
len
2017-01-14 22:38:31 +01:00
parent 7b9f5d0e9f
commit 90a99dde1f
26 changed files with 752 additions and 209 deletions

View File

@@ -237,10 +237,10 @@ open class CatalogueFragment : BaseRxFragment<CataloguePresenter>(), FlexibleVie
}
navView.onSearchClicked = {
val allDefault = navView.adapter.items.hasSameState(presenter.source.getFilterList())
val allDefault = presenter.sourceFilters == presenter.source.getFilterList()
showProgressBar()
adapter.clear()
presenter.setSourceFilter(if (allDefault) FilterList() else navView.adapter.items)
presenter.setSourceFilter(if (allDefault) FilterList() else presenter.sourceFilters)
}
navView.onResetClicked = {

View File

@@ -1,29 +1,24 @@
package eu.kanade.tachiyomi.ui.catalogue
import android.content.Context
import android.support.graphics.drawable.VectorDrawableCompat
import android.support.v4.content.ContextCompat
import android.support.v7.widget.RecyclerView
import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import android.widget.*
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.IFlexible
import eu.davidea.flexibleadapter.items.ISectionable
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.source.model.Filter
import eu.kanade.tachiyomi.data.source.model.FilterList
import eu.kanade.tachiyomi.util.dpToPx
import eu.kanade.tachiyomi.util.getResourceColor
import eu.kanade.tachiyomi.ui.catalogue.filter.*
import eu.kanade.tachiyomi.util.inflate
import eu.kanade.tachiyomi.widget.IgnoreFirstSpinnerListener
import eu.kanade.tachiyomi.widget.SimpleNavigationView
import eu.kanade.tachiyomi.widget.SimpleTextWatcher
import kotlinx.android.synthetic.main.catalogue_drawer_content.view.*
class CatalogueNavigationView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null)
: SimpleNavigationView(context, attrs) {
val adapter = Adapter()
val adapter = FlexibleAdapter<IFlexible<*>>(null)
var onSearchClicked = {}
@@ -32,170 +27,52 @@ class CatalogueNavigationView @JvmOverloads constructor(context: Context, attrs:
init {
recycler.adapter = adapter
val view = inflate(R.layout.catalogue_drawer_content)
(view as ViewGroup).addView(recycler)
((view as ViewGroup).getChildAt(1) as ViewGroup).addView(recycler)
addView(view)
search_btn.setOnClickListener { onSearchClicked() }
reset_btn.setOnClickListener { onResetClicked() }
adapter.setDisplayHeadersAtStartUp(true)
adapter.setStickyHeaders(true)
}
fun setFilters(items: FilterList) {
adapter.items = items
adapter.notifyDataSetChanged()
}
inner class Adapter : RecyclerView.Adapter<Holder>() {
var items: FilterList = FilterList()
override fun getItemCount(): Int {
return items.size
}
override fun getItemViewType(position: Int): Int {
return when (items[position]) {
is Filter.Header -> VIEW_TYPE_HEADER
is Filter.Separator -> VIEW_TYPE_SEPARATOR
is Filter.CheckBox -> VIEW_TYPE_CHECKBOX
is Filter.TriState -> VIEW_TYPE_MULTISTATE
is Filter.List<*> -> VIEW_TYPE_LIST
is Filter.Text -> VIEW_TYPE_TEXT
is Filter.Sort<*> -> VIEW_TYPE_SORT
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
return when (viewType) {
VIEW_TYPE_HEADER -> HeaderHolder(parent)
VIEW_TYPE_SEPARATOR -> SeparatorHolder(parent)
VIEW_TYPE_CHECKBOX -> CheckboxHolder(parent, null)
VIEW_TYPE_MULTISTATE -> MultiStateHolder(parent, null).apply {
// Adjust view with checkbox
text.setPadding(4.dpToPx, 0, 0, 0)
text.compoundDrawablePadding = 20.dpToPx
}
VIEW_TYPE_LIST -> SpinnerHolder(parent)
VIEW_TYPE_TEXT -> EditTextHolder(parent)
VIEW_TYPE_SORT -> SortHolder(parent)
else -> throw Exception("Unknown view type")
}
}
override fun onBindViewHolder(holder: Holder, position: Int) {
val filter = items[position]
when (filter) {
is Filter.Header -> {
val view = holder.itemView as TextView
view.visibility = if (filter.name.isEmpty()) View.GONE else View.VISIBLE
view.text = filter.name
}
is Filter.CheckBox -> {
val view = (holder as CheckboxHolder).check
view.text = filter.name
view.isChecked = filter.state
holder.itemView.setOnClickListener {
view.toggle()
filter.state = view.isChecked
}
}
is Filter.TriState -> {
val view = (holder as MultiStateHolder).text
view.text = filter.name
fun getIcon() = VectorDrawableCompat.create(view.resources, when (filter.state) {
Filter.TriState.STATE_IGNORE -> R.drawable.ic_check_box_outline_blank_24dp
Filter.TriState.STATE_INCLUDE -> R.drawable.ic_check_box_24dp
Filter.TriState.STATE_EXCLUDE -> R.drawable.ic_check_box_x_24dp
else -> throw Exception("Unknown state")
}, null)?.apply {
val color = if (filter.state == Filter.TriState.STATE_INCLUDE)
R.attr.colorAccent
else
android.R.attr.textColorSecondary
setTint(view.context.getResourceColor(color))
}
view.setCompoundDrawablesWithIntrinsicBounds(getIcon(), null, null, null)
holder.itemView.setOnClickListener {
filter.state = (filter.state + 1) % 3
view.setCompoundDrawablesWithIntrinsicBounds(getIcon(), null, null, null)
}
}
is Filter.List<*> -> {
holder as SpinnerHolder
holder.text.text = filter.name + ": "
val spinner = holder.spinner
spinner.prompt = filter.name
spinner.adapter = ArrayAdapter<Any>(holder.itemView.context,
android.R.layout.simple_spinner_item, filter.values).apply {
setDropDownViewResource(R.layout.spinner_item)
}
spinner.onItemSelectedListener = IgnoreFirstSpinnerListener { position ->
filter.state = position
}
spinner.setSelection(filter.state)
}
is Filter.Text -> {
holder as EditTextHolder
holder.wrapper.visibility = if (filter.name.isEmpty()) View.GONE else View.VISIBLE
holder.wrapper.hint = filter.name
holder.edit.setText(filter.state)
holder.edit.addTextChangedListener(object : SimpleTextWatcher() {
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
filter.state = s.toString()
}
})
}
is Filter.Sort<*> -> {
val view = (holder as SortHolder).sortView
view.removeAllViews()
if (!filter.name.isEmpty()) {
val header = HeaderHolder(view)
(header.itemView as TextView).text = filter.name
view.addView(header.itemView)
}
val holders = Array<MultiStateHolder>(filter.values.size, { MultiStateHolder(view, null) })
for ((i, rb) in holders.withIndex()) {
rb.text.text = filter.values[i].toString()
fun getIcon() = when (filter.state) {
Filter.Sort.Selection(i, false) -> VectorDrawableCompat.create(view.resources, R.drawable.ic_keyboard_arrow_down_black_32dp, null)
?.apply { setTint(view.context.getResourceColor(R.attr.colorAccent)) }
Filter.Sort.Selection(i, true) -> VectorDrawableCompat.create(view.resources, R.drawable.ic_keyboard_arrow_up_black_32dp, null)
?.apply { setTint(view.context.getResourceColor(R.attr.colorAccent)) }
else -> ContextCompat.getDrawable(context, R.drawable.empty_drawable_32dp)
}
rb.text.setCompoundDrawablesWithIntrinsicBounds(getIcon(), null, null, null)
rb.itemView.setOnClickListener {
val pre = filter.state?.index ?: i
if (pre != i) {
holders[pre].text.setCompoundDrawablesWithIntrinsicBounds(getIcon(), null, null, null)
filter.state = Filter.Sort.Selection(i, false)
} else {
filter.state = Filter.Sort.Selection(i, filter.state?.ascending == false)
}
rb.text.setCompoundDrawablesWithIntrinsicBounds(getIcon(), null, null, null)
}
view.addView(rb.itemView)
}
}
}
}
}
val VIEW_TYPE_SORT = 0
private class SortHolder(parent: ViewGroup, val sortView: SortView = SortView(parent)) : Holder(sortView) {
class SortView(parent: ViewGroup) : LinearLayout(parent.context) {
init {
orientation = LinearLayout.VERTICAL
fun setFilters(filters: FilterList) {
val items = filters.mapNotNull {
when (it) {
is Filter.Header -> HeaderItem(it)
is Filter.Separator -> SeparatorItem(it)
is Filter.CheckBox -> CheckboxItem(it)
is Filter.TriState -> TriStateItem(it)
is Filter.Text -> TextItem(it)
is Filter.Select<*> -> SelectItem(it)
is Filter.Group<*> -> {
val group = GroupItem(it)
val subItems = it.state.mapNotNull {
when (it) {
is Filter.CheckBox -> CheckboxSectionItem(it)
is Filter.TriState -> TriStateSectionItem(it)
is Filter.Text -> TextSectionItem(it)
is Filter.Select<*> -> SelectSectionItem(it)
else -> null
} as? ISectionable<*, *>
}
subItems.forEach { it.header = group }
group.subItems = subItems
group
}
is Filter.Sort -> {
val group = SortGroup(it)
val subItems = it.values.mapNotNull {
SortItem(it, group)
}
group.subItems = subItems
group
}
else -> null
}
}
adapter.updateDataSet(items)
}
}

View File

@@ -0,0 +1,49 @@
package eu.kanade.tachiyomi.ui.catalogue.filter
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.CheckBox
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import eu.davidea.viewholders.FlexibleViewHolder
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.source.model.Filter
open class CheckboxItem(val filter: Filter.CheckBox) : AbstractFlexibleItem<CheckboxItem.Holder>() {
override fun getLayoutRes(): Int {
return R.layout.navigation_view_checkbox
}
override fun createViewHolder(adapter: FlexibleAdapter<*>, inflater: LayoutInflater, parent: ViewGroup): Holder {
return Holder(inflater.inflate(layoutRes, parent, false), adapter)
}
override fun bindViewHolder(adapter: FlexibleAdapter<*>, holder: Holder, position: Int, payloads: List<Any?>?) {
val view = holder.check
view.text = filter.name
view.isChecked = filter.state
holder.itemView.setOnClickListener {
view.toggle()
filter.state = view.isChecked
}
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other is CheckboxItem) {
return filter == other.filter
}
return false
}
override fun hashCode(): Int {
return filter.hashCode()
}
class Holder(view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter) {
val check = itemView.findViewById(R.id.nav_view_item) as CheckBox
}
}

View File

@@ -0,0 +1,56 @@
package eu.kanade.tachiyomi.ui.catalogue.filter
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.AbstractExpandableHeaderItem
import eu.davidea.flexibleadapter.items.ISectionable
import eu.davidea.viewholders.ExpandableViewHolder
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.source.model.Filter
import eu.kanade.tachiyomi.util.setVectorCompat
class GroupItem(val filter: Filter.Group<*>) : AbstractExpandableHeaderItem<GroupItem.Holder, ISectionable<*, *>>() {
override fun getLayoutRes(): Int {
return R.layout.navigation_view_group
}
override fun createViewHolder(adapter: FlexibleAdapter<*>, inflater: LayoutInflater, parent: ViewGroup): Holder {
return Holder(inflater.inflate(layoutRes, parent, false), adapter)
}
override fun bindViewHolder(adapter: FlexibleAdapter<*>, holder: Holder, position: Int, payloads: List<Any?>?) {
holder.title.text = filter.name
holder.icon.setVectorCompat(if (isExpanded)
R.drawable.ic_expand_more_white_24dp
else
R.drawable.ic_chevron_right_white_24dp)
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other is GroupItem) {
return filter == other.filter
}
return false
}
override fun hashCode(): Int {
return filter.hashCode()
}
class Holder(view: View, adapter: FlexibleAdapter<*>) : ExpandableViewHolder(view, adapter, true) {
val title = itemView.findViewById(R.id.title) as TextView
val icon = itemView.findViewById(R.id.expand_icon) as ImageView
override fun shouldNotifyParentOnClick(): Boolean {
return true
}
}
}

View File

@@ -0,0 +1,44 @@
package eu.kanade.tachiyomi.ui.catalogue.filter
import android.annotation.SuppressLint
import android.support.design.R
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.AbstractHeaderItem
import eu.davidea.viewholders.FlexibleViewHolder
import eu.kanade.tachiyomi.data.source.model.Filter
class HeaderItem(val filter: Filter.Header) : AbstractHeaderItem<HeaderItem.Holder>() {
@SuppressLint("PrivateResource")
override fun getLayoutRes(): Int {
return R.layout.design_navigation_item_subheader
}
override fun createViewHolder(adapter: FlexibleAdapter<*>, inflater: LayoutInflater, parent: ViewGroup): Holder {
return Holder(inflater.inflate(layoutRes, parent, false), adapter)
}
override fun bindViewHolder(adapter: FlexibleAdapter<*>, holder: Holder, position: Int, payloads: List<Any?>?) {
val view = holder.itemView as TextView
view.visibility = if (filter.name.isEmpty()) View.GONE else View.VISIBLE
view.text = filter.name
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other is HeaderItem) {
return filter == other.filter
}
return false
}
override fun hashCode(): Int {
return filter.hashCode()
}
class Holder(view: View, val adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter)
}

View File

@@ -0,0 +1,48 @@
package eu.kanade.tachiyomi.ui.catalogue.filter
import eu.davidea.flexibleadapter.items.ISectionable
import eu.kanade.tachiyomi.data.source.model.Filter
class TriStateSectionItem(filter: Filter.TriState) : TriStateItem(filter), ISectionable<TriStateItem.Holder, GroupItem> {
private var head: GroupItem? = null
override fun getHeader(): GroupItem? = head
override fun setHeader(header: GroupItem?) {
head = header
}
}
class TextSectionItem(filter: Filter.Text) : TextItem(filter), ISectionable<TextItem.Holder, GroupItem> {
private var head: GroupItem? = null
override fun getHeader(): GroupItem? = head
override fun setHeader(header: GroupItem?) {
head = header
}
}
class CheckboxSectionItem(filter: Filter.CheckBox) : CheckboxItem(filter), ISectionable<CheckboxItem.Holder, GroupItem> {
private var head: GroupItem? = null
override fun getHeader(): GroupItem? = head
override fun setHeader(header: GroupItem?) {
head = header
}
}
class SelectSectionItem(filter: Filter.Select<*>) : SelectItem(filter), ISectionable<SelectItem.Holder, GroupItem> {
private var head: GroupItem? = null
override fun getHeader(): GroupItem? = head
override fun setHeader(header: GroupItem?) {
head = header
}
}

View File

@@ -0,0 +1,58 @@
package eu.kanade.tachiyomi.ui.catalogue.filter
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.Spinner
import android.widget.TextView
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import eu.davidea.viewholders.FlexibleViewHolder
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.source.model.Filter
import eu.kanade.tachiyomi.widget.IgnoreFirstSpinnerListener
open class SelectItem(val filter: Filter.Select<*>) : AbstractFlexibleItem<SelectItem.Holder>() {
override fun getLayoutRes(): Int {
return R.layout.navigation_view_spinner
}
override fun createViewHolder(adapter: FlexibleAdapter<*>, inflater: LayoutInflater, parent: ViewGroup): Holder {
return Holder(inflater.inflate(layoutRes, parent, false), adapter)
}
override fun bindViewHolder(adapter: FlexibleAdapter<*>, holder: Holder, position: Int, payloads: List<Any?>?) {
holder.text.text = filter.name + ": "
val spinner = holder.spinner
spinner.prompt = filter.name
spinner.adapter = ArrayAdapter<Any>(holder.itemView.context,
android.R.layout.simple_spinner_item, filter.values).apply {
setDropDownViewResource(R.layout.spinner_item)
}
spinner.onItemSelectedListener = IgnoreFirstSpinnerListener { position ->
filter.state = position
}
spinner.setSelection(filter.state)
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other is SelectItem) {
return filter == other.filter
}
return false
}
override fun hashCode(): Int {
return filter.hashCode()
}
class Holder(view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter) {
val text = itemView.findViewById(R.id.nav_view_item_text) as TextView
val spinner = itemView.findViewById(R.id.nav_view_item) as Spinner
}
}

View File

@@ -0,0 +1,41 @@
package eu.kanade.tachiyomi.ui.catalogue.filter
import android.annotation.SuppressLint
import android.support.design.R
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.AbstractHeaderItem
import eu.davidea.viewholders.FlexibleViewHolder
import eu.kanade.tachiyomi.data.source.model.Filter
class SeparatorItem(val filter: Filter.Separator) : AbstractHeaderItem<SeparatorItem.Holder>() {
@SuppressLint("PrivateResource")
override fun getLayoutRes(): Int {
return R.layout.design_navigation_item_separator
}
override fun createViewHolder(adapter: FlexibleAdapter<*>, inflater: LayoutInflater, parent: ViewGroup): Holder {
return Holder(inflater.inflate(layoutRes, parent, false), adapter)
}
override fun bindViewHolder(adapter: FlexibleAdapter<*>, holder: Holder, position: Int, payloads: List<Any?>?) {
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other is SeparatorItem) {
return filter == other.filter
}
return false
}
override fun hashCode(): Int {
return filter.hashCode()
}
class Holder(view: View, val adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter)
}

View File

@@ -0,0 +1,57 @@
package eu.kanade.tachiyomi.ui.catalogue.filter
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.AbstractExpandableHeaderItem
import eu.davidea.flexibleadapter.items.ISectionable
import eu.davidea.viewholders.ExpandableViewHolder
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.source.model.Filter
import eu.kanade.tachiyomi.util.setVectorCompat
class SortGroup(val filter: Filter.Sort) : AbstractExpandableHeaderItem<SortGroup.Holder, ISectionable<*, *>>() {
override fun getLayoutRes(): Int {
return R.layout.navigation_view_sort
}
override fun createViewHolder(adapter: FlexibleAdapter<*>, inflater: LayoutInflater, parent: ViewGroup): Holder {
return Holder(inflater.inflate(layoutRes, parent, false), adapter)
}
override fun bindViewHolder(adapter: FlexibleAdapter<*>, holder: Holder, position: Int, payloads: List<Any?>?) {
holder.title.text = filter.name
holder.icon.setVectorCompat(if (isExpanded)
R.drawable.ic_expand_more_white_24dp
else
R.drawable.ic_chevron_right_white_24dp)
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other is SortGroup) {
return filter == other.filter
}
return false
}
override fun hashCode(): Int {
return filter.hashCode()
}
class Holder(view: View, adapter: FlexibleAdapter<*>) : ExpandableViewHolder(view, adapter, true) {
val title = itemView.findViewById(R.id.title) as TextView
val icon = itemView.findViewById(R.id.expand_icon) as ImageView
override fun shouldNotifyParentOnClick(): Boolean {
return true
}
}
}

View File

@@ -0,0 +1,73 @@
package eu.kanade.tachiyomi.ui.catalogue.filter
import android.support.graphics.drawable.VectorDrawableCompat
import android.support.v4.content.ContextCompat
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.CheckedTextView
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.AbstractSectionableItem
import eu.davidea.viewholders.FlexibleViewHolder
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.source.model.Filter
import eu.kanade.tachiyomi.util.getResourceColor
class SortItem(val name: String, val group: SortGroup) : AbstractSectionableItem<SortItem.Holder, SortGroup>(group) {
override fun getLayoutRes(): Int {
return R.layout.navigation_view_sort_item
}
override fun createViewHolder(adapter: FlexibleAdapter<*>, inflater: LayoutInflater, parent: ViewGroup): Holder {
return Holder(inflater.inflate(layoutRes, parent, false), adapter)
}
override fun bindViewHolder(adapter: FlexibleAdapter<*>, holder: Holder, position: Int, payloads: List<Any?>?) {
val view = holder.text
view.text = name
val filter = group.filter
val i = filter.values.indexOf(name)
fun getIcon() = when (filter.state) {
Filter.Sort.Selection(i, false) -> VectorDrawableCompat.create(view.resources, R.drawable.ic_keyboard_arrow_down_black_32dp, null)
?.apply { setTint(view.context.getResourceColor(R.attr.colorAccent)) }
Filter.Sort.Selection(i, true) -> VectorDrawableCompat.create(view.resources, R.drawable.ic_keyboard_arrow_up_black_32dp, null)
?.apply { setTint(view.context.getResourceColor(R.attr.colorAccent)) }
else -> ContextCompat.getDrawable(view.context, R.drawable.empty_drawable_32dp)
}
view.setCompoundDrawablesWithIntrinsicBounds(getIcon(), null, null, null)
holder.itemView.setOnClickListener {
val pre = filter.state?.index ?: i
if (pre != i) {
filter.state = Filter.Sort.Selection(i, false)
} else {
filter.state = Filter.Sort.Selection(i, filter.state?.ascending == false)
}
group.subItems.forEach { adapter.notifyItemChanged(adapter.getGlobalPositionOf(it)) }
}
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other is SortItem) {
return name == other.name && group == other.group
}
return false
}
override fun hashCode(): Int {
var result = name.hashCode()
result = 31 * result + group.hashCode()
return result
}
class Holder(view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter) {
val text = itemView.findViewById(R.id.nav_view_item) as CheckedTextView
}
}

View File

@@ -0,0 +1,53 @@
package eu.kanade.tachiyomi.ui.catalogue.filter
import android.support.design.widget.TextInputLayout
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.EditText
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import eu.davidea.viewholders.FlexibleViewHolder
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.source.model.Filter
import eu.kanade.tachiyomi.widget.SimpleTextWatcher
open class TextItem(val filter: Filter.Text) : AbstractFlexibleItem<TextItem.Holder>() {
override fun getLayoutRes(): Int {
return R.layout.navigation_view_text
}
override fun createViewHolder(adapter: FlexibleAdapter<*>, inflater: LayoutInflater, parent: ViewGroup): Holder {
return Holder(inflater.inflate(layoutRes, parent, false), adapter)
}
override fun bindViewHolder(adapter: FlexibleAdapter<*>, holder: Holder, position: Int, payloads: List<Any?>?) {
holder.wrapper.visibility = if (filter.name.isEmpty()) View.GONE else View.VISIBLE
holder.wrapper.hint = filter.name
holder.edit.setText(filter.state)
holder.edit.addTextChangedListener(object : SimpleTextWatcher() {
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
filter.state = s.toString()
}
})
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other is TextItem) {
return filter == other.filter
}
return false
}
override fun hashCode(): Int {
return filter.hashCode()
}
class Holder(view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter) {
val wrapper = itemView.findViewById(R.id.nav_view_item_wrapper) as TextInputLayout
val edit = itemView.findViewById(R.id.nav_view_item) as EditText
}
}

View File

@@ -0,0 +1,75 @@
package eu.kanade.tachiyomi.ui.catalogue.filter
import android.support.design.R
import android.support.graphics.drawable.VectorDrawableCompat
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.CheckedTextView
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import eu.davidea.viewholders.FlexibleViewHolder
import eu.kanade.tachiyomi.data.source.model.Filter
import eu.kanade.tachiyomi.util.dpToPx
import eu.kanade.tachiyomi.util.getResourceColor
import eu.kanade.tachiyomi.R as TR
open class TriStateItem(val filter: Filter.TriState) : AbstractFlexibleItem<TriStateItem.Holder>() {
override fun getLayoutRes(): Int {
return TR.layout.navigation_view_checkedtext
}
override fun createViewHolder(adapter: FlexibleAdapter<*>, inflater: LayoutInflater, parent: ViewGroup?): Holder {
return Holder(inflater.inflate(layoutRes, parent, false), adapter)
}
override fun bindViewHolder(adapter: FlexibleAdapter<*>, holder: Holder, position: Int, payloads: List<Any?>?) {
val view = holder.text
view.text = filter.name
fun getIcon() = VectorDrawableCompat.create(view.resources, when (filter.state) {
Filter.TriState.STATE_IGNORE -> TR.drawable.ic_check_box_outline_blank_24dp
Filter.TriState.STATE_INCLUDE -> TR.drawable.ic_check_box_24dp
Filter.TriState.STATE_EXCLUDE -> TR.drawable.ic_check_box_x_24dp
else -> throw Exception("Unknown state")
}, null)?.apply {
val color = if (filter.state == Filter.TriState.STATE_INCLUDE)
R.attr.colorAccent
else
android.R.attr.textColorSecondary
setTint(view.context.getResourceColor(color))
}
view.setCompoundDrawablesWithIntrinsicBounds(getIcon(), null, null, null)
holder.itemView.setOnClickListener {
filter.state = (filter.state + 1) % 3
view.setCompoundDrawablesWithIntrinsicBounds(getIcon(), null, null, null)
}
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other is TriStateItem) {
return filter == other.filter
}
return false
}
override fun hashCode(): Int {
return filter.hashCode()
}
class Holder(view: View, val adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter) {
val text = itemView.findViewById(TR.id.nav_view_item) as CheckedTextView
init {
// Align with native checkbox
text.setPadding(4.dpToPx, 0, 0, 0)
text.compoundDrawablePadding = 20.dpToPx
}
}
}

View File

@@ -17,7 +17,6 @@ class CategoryAdapter(private val activity: CategoryActivity) :
* Called when item is released.
*/
fun onItemReleased() {
// Update database
activity.onItemReleased()
}