Material Spinner view using check on the left side

Like a yee old build of tachij2k for category sorting
Or the menu for sorting your library is google photos
This commit is contained in:
Jays2Kings 2021-03-30 12:43:32 -04:00
parent 7796243017
commit 91a5274660
2 changed files with 46 additions and 16 deletions

View File

@ -4,6 +4,7 @@ import android.text.Spannable
import android.text.SpannableString import android.text.SpannableString
import android.text.Spanned import android.text.Spanned
import android.text.style.BackgroundColorSpan import android.text.style.BackgroundColorSpan
import android.text.style.ForegroundColorSpan
import androidx.annotation.ColorInt import androidx.annotation.ColorInt
import kotlin.math.floor import kotlin.math.floor
@ -62,6 +63,12 @@ fun String.compareToCaseInsensitiveNaturalOrder(other: String): Int {
return String.CASE_INSENSITIVE_ORDER.then(naturalOrder()).compare(this, other) return String.CASE_INSENSITIVE_ORDER.then(naturalOrder()).compare(this, other)
} }
fun CharSequence.tintText(@ColorInt color: Int): Spanned {
val s = SpannableString(this)
s.setSpan(ForegroundColorSpan(color), 0, this.length, 0)
return s
}
fun String.highlightText(highlight: String, @ColorInt color: Int): Spanned { fun String.highlightText(highlight: String, @ColorInt color: Int): Spanned {
val wordToSpan: Spannable = SpannableString(this) val wordToSpan: Spannable = SpannableString(this)
indexesOf(highlight).forEach { indexesOf(highlight).forEach {

View File

@ -1,17 +1,24 @@
package eu.kanade.tachiyomi.widget package eu.kanade.tachiyomi.widget
import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.graphics.drawable.Drawable
import android.util.AttributeSet import android.util.AttributeSet
import android.view.Gravity import android.view.Gravity
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.MenuItem import android.view.MenuItem
import android.widget.FrameLayout import android.widget.FrameLayout
import androidx.annotation.ArrayRes import androidx.annotation.ArrayRes
import androidx.appcompat.view.menu.MenuBuilder
import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.PopupMenu
import androidx.core.content.ContextCompat
import androidx.core.view.forEach
import androidx.core.view.get import androidx.core.view.get
import com.tfcporciuncula.flow.Preference import com.tfcporciuncula.flow.Preference
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.databinding.MaterialSpinnerViewBinding import eu.kanade.tachiyomi.databinding.MaterialSpinnerViewBinding
import eu.kanade.tachiyomi.util.lang.tintText
import eu.kanade.tachiyomi.util.system.getResourceColor
import kotlin.math.max import kotlin.math.max
class MaterialSpinnerView @JvmOverloads constructor(context: Context, attrs: AttributeSet?) : class MaterialSpinnerView @JvmOverloads constructor(context: Context, attrs: AttributeSet?) :
@ -53,12 +60,16 @@ class MaterialSpinnerView @JvmOverloads constructor(context: Context, attrs: Att
} }
fun setSelection(selection: Int) { fun setSelection(selection: Int) {
popup?.menu?.get(selectedPosition)?.isCheckable = false popup?.menu?.get(selectedPosition)?.let {
popup?.menu?.get(selectedPosition)?.isChecked = false it.icon = ContextCompat.getDrawable(context, R.drawable.ic_blank_24dp)
it.title = entries[selectedPosition]
}
selectedPosition = selection selectedPosition = selection
popup?.menu?.get(selectedPosition)?.let {
it.icon = tintedCheck()
it.title = it.title?.tintText(context.getResourceColor(android.R.attr.colorAccent))
}
binding.detailView.text = entries.getOrNull(selection).orEmpty() binding.detailView.text = entries.getOrNull(selection).orEmpty()
popup?.menu?.get(selectedPosition)?.isCheckable = true
popup?.menu?.get(selectedPosition)?.isChecked = true
} }
fun bindToPreference(pref: Preference<Int>, offset: Int = 0, block: ((Int) -> Unit)? = null) { fun bindToPreference(pref: Preference<Int>, offset: Int = 0, block: ((Int) -> Unit)? = null) {
@ -99,14 +110,14 @@ class MaterialSpinnerView @JvmOverloads constructor(context: Context, attrs: Att
// Set a listener so we are notified if a menu item is clicked // Set a listener so we are notified if a menu item is clicked
popup.setOnMenuItemClickListener { menuItem -> popup.setOnMenuItemClickListener { menuItem ->
val pos = popup.menuClicked(menuItem) val pos = menuClicked(menuItem)
onItemSelectedListener?.invoke(pos) onItemSelectedListener?.invoke(pos)
true true
} }
// Set a listener so we are notified if a menu item is clicked // Set a listener so we are notified if a menu item is clicked
popup.setOnMenuItemClickListener { menuItem -> popup.setOnMenuItemClickListener { menuItem ->
val enumConstants = T::class.java.enumConstants val enumConstants = T::class.java.enumConstants
val pos = popup.menuClicked(menuItem) val pos = menuClicked(menuItem)
enumConstants?.get(pos)?.let { preference.set(it) } enumConstants?.get(pos)?.let { preference.set(it) }
true true
} }
@ -117,7 +128,7 @@ class MaterialSpinnerView @JvmOverloads constructor(context: Context, attrs: Att
val popup = popup() val popup = popup()
// Set a listener so we are notified if a menu item is clicked // Set a listener so we are notified if a menu item is clicked
popup.setOnMenuItemClickListener { menuItem -> popup.setOnMenuItemClickListener { menuItem ->
val pos = popup.menuClicked(menuItem) val pos = menuClicked(menuItem)
preference.set(intValues[pos] ?: 0) preference.set(intValues[pos] ?: 0)
block?.invoke(pos) block?.invoke(pos)
true true
@ -129,7 +140,7 @@ class MaterialSpinnerView @JvmOverloads constructor(context: Context, attrs: Att
val popup = popup() val popup = popup()
// Set a listener so we are notified if a menu item is clicked // Set a listener so we are notified if a menu item is clicked
popup.setOnMenuItemClickListener { menuItem -> popup.setOnMenuItemClickListener { menuItem ->
val pos = popup.menuClicked(menuItem) val pos = menuClicked(menuItem)
preference.set(pos + offset) preference.set(pos + offset)
block?.invoke(pos) block?.invoke(pos)
true true
@ -142,30 +153,42 @@ class MaterialSpinnerView @JvmOverloads constructor(context: Context, attrs: Att
// Set a listener so we are notified if a menu item is clicked // Set a listener so we are notified if a menu item is clicked
popup.setOnMenuItemClickListener { menuItem -> popup.setOnMenuItemClickListener { menuItem ->
val pos = popup.menuClicked(menuItem) val pos = menuClicked(menuItem)
onItemSelectedListener?.invoke(pos) onItemSelectedListener?.invoke(pos)
true true
} }
return popup return popup
} }
fun PopupMenu.menuClicked(menuItem: MenuItem): Int { fun menuClicked(menuItem: MenuItem): Int {
val pos = menuItem.itemId val pos = menuItem.itemId
menu[selectedPosition].isCheckable = false
menu[selectedPosition].isChecked = false
setSelection(pos) setSelection(pos)
menu[pos].isCheckable = true
menu[pos].isChecked = true
return pos return pos
} }
@SuppressLint("RestrictedApi")
fun popup(): PopupMenu { fun popup(): PopupMenu {
val popup = PopupMenu(context, this, Gravity.END) val popup = PopupMenu(context, this, Gravity.END)
entries.forEachIndexed { index, entry -> entries.forEachIndexed { index, entry ->
popup.menu.add(0, index, 0, entry) popup.menu.add(0, index, 0, entry)
} }
popup.menu[selectedPosition].isCheckable = true if (popup.menu is MenuBuilder) {
popup.menu[selectedPosition].isChecked = true val m = popup.menu as MenuBuilder
m.setOptionalIconsVisible(true)
}
popup.menu.forEach {
it.icon = ContextCompat.getDrawable(context, R.drawable.ic_blank_24dp)
}
popup.menu[selectedPosition].icon = tintedCheck()
popup.menu[selectedPosition].title =
popup.menu[selectedPosition].title?.tintText(context.getResourceColor(android.R.attr.colorAccent))
return popup return popup
} }
private fun tintedCheck(): Drawable? {
return ContextCompat.getDrawable(context, R.drawable.ic_check_24dp)?.mutate()?.apply {
setTint(context.getResourceColor(android.R.attr.colorAccent))
}
}
} }