Update source filter items

TristateItem now uses TriStateCheckBox to animate between states
SortItem now uses SortTextView
Both views now support textAppearance & drawablePadding via xml
This commit is contained in:
Jays2Kings 2021-08-10 19:29:36 -04:00
parent 8b511b5708
commit 1198c2a77e
9 changed files with 82 additions and 71 deletions

View File

@ -1,17 +1,14 @@
package eu.kanade.tachiyomi.ui.source.filter
import android.view.View
import android.widget.CheckedTextView
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.AbstractSectionableItem
import eu.davidea.flexibleadapter.items.IFlexible
import eu.davidea.viewholders.FlexibleViewHolder
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.widget.SortTextView
class SortItem(val name: String, val group: SortGroup) : AbstractSectionableItem<SortItem.Holder, SortGroup>(group) {
@ -30,29 +27,17 @@ class SortItem(val name: String, val group: SortGroup) : AbstractSectionableItem
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>, holder: Holder, position: Int, payloads: MutableList<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_arrow_downward_32dp, null)
?.apply { setTint(view.context.getResourceColor(R.attr.colorAccent)) }
Filter.Sort.Selection(i, true) ->
VectorDrawableCompat.create(view.resources, R.drawable.ic_arrow_upward_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)
view.state = when (filter.state) {
Filter.Sort.Selection(i, false) -> SortTextView.State.DESCENDING
Filter.Sort.Selection(i, true) -> SortTextView.State.ASCENDING
else -> SortTextView.State.NONE
}
view.setOnSortChangeListener { _, state ->
filter.state = Filter.Sort.Selection(i, state == SortTextView.State.ASCENDING)
group.subItems.forEach { adapter.notifyItemChanged(adapter.getGlobalPositionOf(it)) }
}
}
@ -72,6 +57,6 @@ class SortItem(val name: String, val group: SortGroup) : AbstractSectionableItem
class Holder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>) : FlexibleViewHolder(view, adapter) {
val text: CheckedTextView = itemView.findViewById(R.id.nav_view_item)
val text: SortTextView = itemView.findViewById(R.id.nav_view_item)
}
}

View File

@ -1,23 +1,19 @@
package eu.kanade.tachiyomi.ui.source.filter
import android.view.View
import android.widget.CheckedTextView
import androidx.recyclerview.widget.RecyclerView
import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat
import com.google.android.material.R
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import eu.davidea.flexibleadapter.items.IFlexible
import eu.davidea.viewholders.FlexibleViewHolder
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.widget.TriStateCheckBox
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
return TR.layout.navigation_view_tristatebox
}
override fun getItemViewType(): Int {
@ -31,30 +27,19 @@ open class TriStateItem(val filter: Filter.TriState) : AbstractFlexibleItem<TriS
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>, holder: Holder, position: Int, payloads: MutableList<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
view.state = when (filter.state) {
Filter.TriState.STATE_IGNORE -> TriStateCheckBox.State.UNCHECKED
Filter.TriState.STATE_INCLUDE -> TriStateCheckBox.State.CHECKED
Filter.TriState.STATE_EXCLUDE -> TriStateCheckBox.State.INVERSED
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.setOnCheckedChangeListener { _, state ->
filter.state = when (state) {
TriStateCheckBox.State.UNCHECKED -> Filter.TriState.STATE_IGNORE
TriStateCheckBox.State.CHECKED -> Filter.TriState.STATE_INCLUDE
TriStateCheckBox.State.INVERSED -> Filter.TriState.STATE_EXCLUDE
}
view.setCompoundDrawablesWithIntrinsicBounds(getIcon(), null, null, null)
holder.itemView.setOnClickListener {
filter.state = (filter.state + 1) % 3
view.setCompoundDrawablesWithIntrinsicBounds(getIcon(), null, null, null)
}
}
@ -70,12 +55,6 @@ open class TriStateItem(val filter: Filter.TriState) : AbstractFlexibleItem<TriS
class Holder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>) : FlexibleViewHolder(view, adapter) {
val text: CheckedTextView = itemView.findViewById(TR.id.nav_view_item)
init {
// Align with native checkbox
text.setPadding(4.dpToPx, 0, 0, 0)
text.compoundDrawablePadding = 20.dpToPx
}
val text: TriStateCheckBox = itemView.findViewById(TR.id.nav_view_item)
}
}

View File

@ -6,7 +6,6 @@ import android.util.AttributeSet
import android.view.View
import android.view.ViewGroup
import android.widget.CheckBox
import android.widget.CheckedTextView
import android.widget.EditText
import android.widget.RadioButton
import android.widget.TextView
@ -147,7 +146,7 @@ open class SimpleNavigationView @JvmOverloads constructor(
class MultiStateHolder(parent: ViewGroup, listener: View.OnClickListener?) :
ClickableHolder(parent.inflate(TR.layout.navigation_view_checkedtext), listener) {
val text: CheckedTextView = itemView.findViewById(TR.id.nav_view_item)
val text: TriStateCheckBox = itemView.findViewById(TR.id.nav_view_item)
}
class SpinnerHolder(parent: ViewGroup, listener: OnClickListener? = null) :

View File

@ -4,6 +4,7 @@ import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.FrameLayout
import androidx.core.view.updateLayoutParams
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.databinding.SortTextViewBinding
import eu.kanade.tachiyomi.util.view.setVectorCompat
@ -45,6 +46,18 @@ class SortTextView constructor(context: Context, attrs: AttributeSet?) :
val maxLines = a.getInt(R.styleable.SortTextView_android_maxLines, Int.MAX_VALUE)
binding.textView.maxLines = maxLines
val resourceId = a.getResourceId(R.styleable.SortTextView_android_textAppearance, 0)
if (resourceId != 0) {
binding.textView.setTextAppearance(resourceId)
}
val drawablePadding = a.getDimensionPixelSize(R.styleable.SortTextView_android_drawablePadding, 0)
if (drawablePadding != 0) {
binding.textView.updateLayoutParams<MarginLayoutParams> {
marginStart = drawablePadding
}
}
a.recycle()
setOnClickListener {

View File

@ -10,6 +10,7 @@ import eu.kanade.tachiyomi.databinding.TriStateCheckBoxBinding
import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.util.view.setAnimVectorCompat
import eu.kanade.tachiyomi.util.view.setVectorCompat
import eu.kanade.tachiyomi.util.view.updateLayoutParams
class TriStateCheckBox constructor(context: Context, attrs: AttributeSet?) :
FrameLayout(context, attrs) {
@ -57,6 +58,18 @@ class TriStateCheckBox constructor(context: Context, attrs: AttributeSet?) :
val maxLines = a.getInt(R.styleable.TriStateCheckBox_android_maxLines, Int.MAX_VALUE)
binding.textView.maxLines = maxLines
val resourceId = a.getResourceId(R.styleable.TriStateCheckBox_android_textAppearance, 0)
if (resourceId != 0) {
binding.textView.setTextAppearance(resourceId)
}
val drawablePadding = a.getDimensionPixelSize(R.styleable.TriStateCheckBox_android_drawablePadding, 0)
if (drawablePadding != 0) {
binding.textView.updateLayoutParams<MarginLayoutParams> {
marginStart = drawablePadding
}
}
a.recycle()
setOnClickListener {

View File

@ -8,7 +8,7 @@
android:background="?attr/selectableItemBackground"
android:focusable="true">
<CheckBox
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/nav_view_item"
android:layout_width="0dp"
android:layout_height="match_parent"
@ -17,7 +17,6 @@
android:background="@android:color/transparent"
android:gravity="center_vertical|start"
android:maxLines="1"
android:clickable="false"
android:textAppearance="@style/TextAppearance.AppCompat.Body2" />
android:clickable="false" />
</LinearLayout>

View File

@ -1,21 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="?attr/listPreferredItemHeightSmall"
android:paddingStart="?attr/listPreferredItemPaddingStart"
android:paddingEnd="?attr/listPreferredItemPaddingEnd"
xmlns:tools="http://schemas.android.com/tools"
android:background="?attr/selectableItemBackground"
android:focusable="true">
<CheckedTextView
<eu.kanade.tachiyomi.widget.SortTextView
android:id="@+id/nav_view_item"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:drawablePadding="@dimen/material_component_lists_icon_left_padding"
tools:text="Sorting by"
android:gravity="center_vertical|start"
android:maxLines="1"
android:textAppearance="@style/TextAppearance.AppCompat.Body2" />
android:maxLines="1" />
</LinearLayout>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="?attr/listPreferredItemHeightSmall"
xmlns:tools="http://schemas.android.com/tools"
android:paddingStart="?attr/listPreferredItemPaddingStart"
android:paddingEnd="?attr/listPreferredItemPaddingEnd"
android:background="?attr/selectableItemBackground"
android:focusable="true">
<eu.kanade.tachiyomi.widget.TriStateCheckBox
android:id="@+id/nav_view_item"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:drawablePadding="@dimen/material_component_lists_icon_left_padding"
android:gravity="center_vertical|start"
android:maxLines="1"
tools:text="Item" />
</LinearLayout>

View File

@ -31,12 +31,16 @@
<declare-styleable name="TriStateCheckBox">
<attr name="android:text" format="reference|string"/>
<attr name="android:maxLines"/>
<attr name="android:textAppearance"/>
<attr name="android:drawablePadding"/>
</declare-styleable>
<declare-styleable name="SortTextView">
<attr name="android:text" format="reference|string"/>
<attr name="android:maxLines"/>
<attr name="android:textAppearance"/>
<attr name="android:drawablePadding"/>
</declare-styleable>
<declare-styleable name="MenuSheetItemView">