diff --git a/base-filters/src/main/java/ru/touchin/roboswag/base_filters/select_list_item/ListSelectionView.kt b/base-filters/src/main/java/ru/touchin/roboswag/base_filters/select_list_item/ListSelectionView.kt index 6adfcc6..3e9e903 100644 --- a/base-filters/src/main/java/ru/touchin/roboswag/base_filters/select_list_item/ListSelectionView.kt +++ b/base-filters/src/main/java/ru/touchin/roboswag/base_filters/select_list_item/ListSelectionView.kt @@ -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 = (items: List) -> class ListSelectionView @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 { + enum class SelectionType { SINGLE_SELECT, MULTI_SELECT } + + constructor(context: Context, @StyleRes themeResId: Int) : this(ContextThemeWrapper(context, themeResId)) + private var mutableItems: List = emptyList() private var selectionType = SelectionType.SINGLE_SELECT @@ -44,6 +51,11 @@ class ListSelectionView @JvmOverloads constructor( private var onSelectedItemsChanged: OnSelectedItemsListener? = null private var factory: HolderFactoryType = getDefaultFactory() + init { + layoutParams = ViewGroup.LayoutParams(MATCH_PARENT, WRAP_CONTENT) + layoutManager = LinearLayoutManager(context) + } + private fun getDefaultFactory(): HolderFactoryType = { parent, clickListener, selectionType -> SelectionItemViewHolder( binding = SelectionItemBinding.inflate(LayoutInflater.from(parent.context), parent, false), @@ -52,9 +64,7 @@ class ListSelectionView @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 @JvmOverloads constructor( onSelectedItemsChanged?.invoke(mutableItems) } + fun updateItems(items: List) { + mutableItems = items + updateList() + } + private fun updateList() { - adapter.submitList(mutableItems) + selectionAdapter.submitList(mutableItems) } private fun updateAfterSelection(selectedItem: ItemType) { @@ -99,7 +114,7 @@ class ListSelectionView @JvmOverloads constructor( } fun addItemDecoration(itemDecoration: RecyclerView.ItemDecoration) = apply { - binding.itemsRecycler.addItemDecoration(itemDecoration) + this@ListSelectionView.addItemDecoration(itemDecoration) } fun onSelectedItemListener(listener: OnSelectedItemListener) = apply { @@ -115,7 +130,7 @@ class ListSelectionView @JvmOverloads constructor( } fun build() = this@ListSelectionView.also { - binding.itemsRecycler.adapter = adapter + it.adapter = selectionAdapter updateList() } } diff --git a/base-filters/src/main/java/ru/touchin/roboswag/base_filters/tags/TagLayoutView.kt b/base-filters/src/main/java/ru/touchin/roboswag/base_filters/tags/TagLayoutView.kt index 8c169b5..2c20c82 100644 --- a/base-filters/src/main/java/ru/touchin/roboswag/base_filters/tags/TagLayoutView.kt +++ b/base-filters/src/main/java/ru/touchin/roboswag/base_filters/tags/TagLayoutView.kt @@ -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)) } } } diff --git a/base-filters/src/main/res/layout/single_selection_layout.xml b/base-filters/src/main/res/layout/single_selection_layout.xml deleted file mode 100644 index 2db23f9..0000000 --- a/base-filters/src/main/res/layout/single_selection_layout.xml +++ /dev/null @@ -1,10 +0,0 @@ - -