Merge branch 'tag_filters' of github.com:TouchInstinct/RoboSwag into range_filter
This commit is contained in:
commit
42b3df50fe
|
|
@ -2,11 +2,15 @@ package ru.touchin.roboswag.base_filters.select_list_item
|
|||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.ContextThemeWrapper
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.FrameLayout
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
||||
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
import androidx.annotation.StyleRes
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import ru.touchin.roboswag.base_filters.databinding.SelectionItemBinding
|
||||
import ru.touchin.roboswag.base_filters.databinding.SingleSelectionLayoutBinding
|
||||
import ru.touchin.roboswag.base_filters.select_list_item.adapter.BaseSelectionViewHolder
|
||||
import ru.touchin.roboswag.base_filters.select_list_item.adapter.HolderFactoryType
|
||||
import ru.touchin.roboswag.base_filters.select_list_item.adapter.SelectionItemViewHolder
|
||||
|
|
@ -31,12 +35,15 @@ private typealias OnSelectedItemsListener<ItemType> = (items: List<ItemType>) ->
|
|||
class ListSelectionView<ItemType, HolderType> @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0,
|
||||
defStyleRes: Int = 0
|
||||
) : FrameLayout(context, attrs, defStyleAttr, defStyleRes)
|
||||
defStyleAttr: Int = 0
|
||||
) : RecyclerView(context, attrs, defStyleAttr)
|
||||
where ItemType : BaseSelectionItem,
|
||||
HolderType : BaseSelectionViewHolder<ItemType> {
|
||||
|
||||
enum class SelectionType { SINGLE_SELECT, MULTI_SELECT }
|
||||
|
||||
constructor(context: Context, @StyleRes themeResId: Int) : this(ContextThemeWrapper(context, themeResId))
|
||||
|
||||
private var mutableItems: List<ItemType> = emptyList()
|
||||
private var selectionType = SelectionType.SINGLE_SELECT
|
||||
|
||||
|
|
@ -44,6 +51,11 @@ class ListSelectionView<ItemType, HolderType> @JvmOverloads constructor(
|
|||
private var onSelectedItemsChanged: OnSelectedItemsListener<ItemType>? = null
|
||||
private var factory: HolderFactoryType<ItemType> = getDefaultFactory()
|
||||
|
||||
init {
|
||||
layoutParams = ViewGroup.LayoutParams(MATCH_PARENT, WRAP_CONTENT)
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
}
|
||||
|
||||
private fun getDefaultFactory(): HolderFactoryType<ItemType> = { parent, clickListener, selectionType ->
|
||||
SelectionItemViewHolder(
|
||||
binding = SelectionItemBinding.inflate(LayoutInflater.from(parent.context), parent, false),
|
||||
|
|
@ -52,9 +64,7 @@ class ListSelectionView<ItemType, HolderType> @JvmOverloads constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private val binding = SingleSelectionLayoutBinding.inflate(LayoutInflater.from(context), this, true)
|
||||
|
||||
private val adapter by lazy {
|
||||
private val selectionAdapter by lazy {
|
||||
SheetSelectionAdapter(
|
||||
onItemSelectAction = onItemSelectedListener,
|
||||
selectionType = selectionType,
|
||||
|
|
@ -68,8 +78,13 @@ class ListSelectionView<ItemType, HolderType> @JvmOverloads constructor(
|
|||
onSelectedItemsChanged?.invoke(mutableItems)
|
||||
}
|
||||
|
||||
fun updateItems(items: List<ItemType>) {
|
||||
mutableItems = items
|
||||
updateList()
|
||||
}
|
||||
|
||||
private fun updateList() {
|
||||
adapter.submitList(mutableItems)
|
||||
selectionAdapter.submitList(mutableItems)
|
||||
}
|
||||
|
||||
private fun updateAfterSelection(selectedItem: ItemType) {
|
||||
|
|
@ -99,7 +114,7 @@ class ListSelectionView<ItemType, HolderType> @JvmOverloads constructor(
|
|||
}
|
||||
|
||||
fun addItemDecoration(itemDecoration: RecyclerView.ItemDecoration) = apply {
|
||||
binding.itemsRecycler.addItemDecoration(itemDecoration)
|
||||
this@ListSelectionView.addItemDecoration(itemDecoration)
|
||||
}
|
||||
|
||||
fun onSelectedItemListener(listener: OnSelectedItemListener<ItemType>) = apply {
|
||||
|
|
@ -115,7 +130,7 @@ class ListSelectionView<ItemType, HolderType> @JvmOverloads constructor(
|
|||
}
|
||||
|
||||
fun build() = this@ListSelectionView.also {
|
||||
binding.itemsRecycler.adapter = adapter
|
||||
it.adapter = selectionAdapter
|
||||
updateList()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,13 +2,17 @@ package ru.touchin.roboswag.base_filters.tags
|
|||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.LayoutRes
|
||||
import androidx.core.view.children
|
||||
import com.google.android.material.chip.ChipGroup
|
||||
import ru.touchin.roboswag.base_filters.R
|
||||
import ru.touchin.roboswag.base_filters.SelectionType
|
||||
import ru.touchin.roboswag.base_filters.databinding.LayoutMultiLineTagGroupBinding
|
||||
import ru.touchin.roboswag.base_filters.databinding.LayoutSingleLineTagGroupBinding
|
||||
import ru.touchin.roboswag.base_filters.tags.model.FilterItem
|
||||
import ru.touchin.roboswag.base_filters.tags.model.FilterProperty
|
||||
import ru.touchin.roboswag.components.utils.UiUtils
|
||||
|
|
@ -45,40 +49,45 @@ class TagLayoutView @JvmOverloads constructor(
|
|||
@LayoutRes
|
||||
private var moreTagLayout: Int = tagLayout
|
||||
|
||||
private fun inflateAndGetChipGroup(isSingleLine: Boolean): ChipGroup {
|
||||
val layoutId = if (isSingleLine) R.layout.layout_single_line_tag_group else R.layout.layout_multi_line_tag_group
|
||||
return UiUtils.inflate(layoutId, this)
|
||||
.also { addView(it) }
|
||||
.findViewById(R.id.tag_group)
|
||||
private fun inflateAndGetChipGroup(isSingleLine: Boolean): ChipGroup = when (isSingleLine) {
|
||||
true -> LayoutSingleLineTagGroupBinding.inflate(LayoutInflater.from(context), this, true).tagGroup
|
||||
false -> LayoutMultiLineTagGroupBinding.inflate(LayoutInflater.from(context), this, true).tagGroup
|
||||
}
|
||||
|
||||
private fun createTag(property: FilterProperty): TagView =
|
||||
(UiUtils.inflate(tagLayout, this) as? TagView)?.apply {
|
||||
text = property.title
|
||||
isChecked = property.isSelected
|
||||
tagId = property.id
|
||||
private fun createTag(property: FilterProperty): TagView {
|
||||
val tagView = UiUtils.inflate(tagLayout, this)
|
||||
require(tagView is TagView) { "Layout for tag must contain TagView as root view" }
|
||||
|
||||
setOnCheckAction { view, isChecked ->
|
||||
when {
|
||||
selectionType == SelectionType.SINGLE_SELECT && isChecked -> clearCheck(property.id)
|
||||
selectionType == SelectionType.MULTI_SELECT && isChecked -> clearExcludedCheck(property)
|
||||
}
|
||||
view.isChecked = isChecked
|
||||
propertySelectedAction?.invoke(property.copyWithSelected(isSelected = isChecked))
|
||||
return tagView.apply {
|
||||
text = property.title
|
||||
isChecked = property.isSelected
|
||||
tagId = property.id
|
||||
|
||||
setOnCheckAction { view, isChecked ->
|
||||
when {
|
||||
selectionType == SelectionType.SINGLE_SELECT && isChecked -> clearCheck(property.id)
|
||||
selectionType == SelectionType.MULTI_SELECT && isChecked -> clearExcludedCheck(property)
|
||||
}
|
||||
} ?: throw IllegalArgumentException("Layout for tag must be extended from TagView")
|
||||
|
||||
private fun createMoreChip(filter: FilterItem): View? =
|
||||
(UiUtils.inflate(moreTagLayout, this) as? TextView)?.apply {
|
||||
text = moreTagText
|
||||
setOnClickListener { moreValuesAction?.invoke(filter) }
|
||||
view.isChecked = isChecked
|
||||
propertySelectedAction?.invoke(property.copyWithSelected(isSelected = isChecked))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createMoreTag(filter: FilterItem): View {
|
||||
val moreTag = UiUtils.inflate(moreTagLayout, this)
|
||||
require(moreTag is TextView) { "Layout for more tag must contain TextView as root view" }
|
||||
|
||||
return moreTag.apply {
|
||||
text = moreTagText
|
||||
setOnClickListener { moreValuesAction?.invoke(filter) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun clearCheck(selectedId: Int) {
|
||||
for (i in 0 until tagsContainer.childCount) {
|
||||
val child = tagsContainer.getChildAt(i)
|
||||
if (child is TagView && child.tagId != selectedId) {
|
||||
child.isChecked = false
|
||||
tagsContainer.children.forEach { tagView ->
|
||||
if (tagView is TagView && tagView.tagId != selectedId) {
|
||||
tagView.isChecked = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -86,10 +95,9 @@ class TagLayoutView @JvmOverloads constructor(
|
|||
private fun clearExcludedCheck(property: FilterProperty) {
|
||||
val excludingIds = property.excludes.map { it.id }
|
||||
|
||||
for (i in 0 until tagsContainer.childCount) {
|
||||
val child = tagsContainer.getChildAt(i)
|
||||
if (child is TagView && child.tagId in excludingIds) {
|
||||
child.isChecked = false
|
||||
tagsContainer.children.forEach { tagView ->
|
||||
if (tagView is TagView && tagView.tagId in excludingIds) {
|
||||
tagView.isChecked = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -155,7 +163,7 @@ class TagLayoutView @JvmOverloads constructor(
|
|||
}
|
||||
|
||||
if (filterItem.properties.size > maxTagCount) {
|
||||
createMoreChip(filterItem)?.let { addView(it) }
|
||||
addView(createMoreTag(filterItem))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/items_recycler"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipToPadding="false"
|
||||
android:nestedScrollingEnabled="false"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
|
||||
Loading…
Reference in New Issue