Skip to content

Commit

Permalink
#Multi Selection List View
Browse files Browse the repository at this point in the history
  • Loading branch information
MalaRuparel2023 committed May 8, 2024
1 parent befffb9 commit 0c38a02
Show file tree
Hide file tree
Showing 6 changed files with 218 additions and 178 deletions.
4 changes: 2 additions & 2 deletions app/src/main/java/com/ss/smartfilter/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ class MainActivity : ComponentActivity() {
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)

binding.multiSelectionListView.setOnMultiSelectionClicked() {
showToast("MultiSelection", this)
binding.multiSelectionListView.setOnMultiSelection {
showToast( it.joinToString { it.name } , this)
}

}
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
android:layout_height="match_parent"
android:background="@color/white"
app:ss_Listitem="@array/ss_array"
app:ss_Orientation="0"

/>

</LinearLayout>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.ss.smartfilterlib

import RadioGroupCallback
import android.content.Context
import android.graphics.Typeface
import android.util.AttributeSet
import android.widget.CheckedTextView
import androidx.recyclerview.widget.RecyclerView
import com.ss.smartfilterlib.singlechoice.radiogroup.data.RadioGroupData
import com.ss.smartfilterlib.singlechoice.util.Constant
import com.ss.smartfilterlib.singlechoice.util.PaddingAttributes
import com.ss.smartfilterlib.singlechoice.util.TextAttributes

/**
* created by Mala Ruparel ON 08/05/24
*/
abstract class BaseClass<T> : RecyclerView {


protected var primaryTextColor: Int = Constant.PRIMARY_TEXT_COLOR
protected var orientation: Int = SmartOrientation.VERTICAL
protected var checkSelector: Int = 0
protected var paddingAttributes: PaddingAttributes = PaddingAttributes()
protected var textAttributes: TextAttributes = TextAttributes()
protected var onMultiSelectionClicked: ((List<RadioGroupData>) -> Unit)? = null
protected var onSingleSelectionClicked: RadioGroupCallback? = null
protected var dataFromXml: Int = 0
protected var data: List<T> = emptyList()
protected val selectedItemsPositions = mutableListOf<Int>()
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)

// Common methods
protected abstract fun initAttributes(attrs: AttributeSet?)
protected abstract fun initializeView()

protected fun applyTextAttributes(textView: CheckedTextView) {
textAttributes.let { attributes ->
textView.apply {
textSize = attributes.textSize
typeface = Typeface.create(Typeface.DEFAULT, attributes.fontFamily)
}
}
}
protected fun applyPaddingAttributes(textView: CheckedTextView) {
paddingAttributes.let { attributes ->
textView.setPadding(
attributes.paddingStart,
attributes.paddingTop,
attributes.paddingEnd,
attributes.paddingBottom
)
}
}
protected fun setData(data: RadioGroupData) = data.name
}
Original file line number Diff line number Diff line change
@@ -1,98 +1,89 @@
package com.ss.smartfilterlib

import android.content.Context
import android.content.res.ColorStateList
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.CheckedTextView
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.card.MaterialCardView
import com.ss.smartfilterlib.singlechoice.radiogroup.data.RadioGroupData
import com.ss.smartfilterlib.singlechoice.util.PaddingAttributes


/**
* created by Mala Ruparel ON 02/05/24
*/
class MultiSelectionListView @JvmOverloads constructor( context: Context,attrs: AttributeSet? = null,defStyle: Int = 0) : RecyclerView(context, attrs, defStyle) {
class MultiSelectionListView @JvmOverloads constructor( context: Context,attrs: AttributeSet? = null,defStyle: Int = 0) : BaseClass<RadioGroupData>(context, attrs, defStyle){

private var textSelectorColor: ColorStateList? = null
private var bgSelector: Drawable? = null
private var orientation: Int = com.ss.smartfilterlib.singlechoice.util.Orientation.VERTICAL
private var checkDrawableSelector: Int = 0
private var paddingAttributes: PaddingAttributes = PaddingAttributes()
private var onMultiSelectionClicked: ((List<RadioGroupData>) -> Unit)? = null

private var dataFromXml: Int = 0
private val selectedItemsPositions = mutableListOf<Int>()

init {
initAttrs(attrs)
setupView()
setDataFromAttrs()
initAttributes(attrs=attrs)
initializeView()
populateDataFromAttributes()
}

private fun setDataFromAttrs() {
if (dataFromXml != 0) {
val mData = resources.getStringArray(dataFromXml);
val data = ArrayList<RadioGroupData>()
for (i in mData.indices) {
data.add(RadioGroupData(name = mData[i]))
}
configureView(data,orientation,checkDrawableSelector,textSelectorColor,onMultiSelectionClicked)

private fun populateDataFromAttributes() {
val mData = resources.getStringArray(dataFromXml);
val data = mData.map { RadioGroupData(name = it) } as ArrayList<RadioGroupData>
configureView(
data = data,
orientation = orientation,
checkSelector = checkSelector,
primaryTextColor = primaryTextColor,
onCheckedChangeListener = onMultiSelectionClicked
)

}
}

private fun setupView() {
override fun initializeView() {
layoutManager = when (orientation) {
com.ss.smartfilterlib.singlechoice.util.Orientation.VERTICAL -> LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
else -> LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
SmartOrientation.VERTICAL -> LinearLayoutManager(context, VERTICAL, false)
else -> LinearLayoutManager(context, HORIZONTAL, false)
}

}

private fun initAttrs(attrs: AttributeSet?) {
override fun initAttributes(attrs: AttributeSet?) {
val typedArray = context.obtainStyledAttributes(attrs, R.styleable.SingleSelectionView)
try {
bgSelector = typedArray.getDrawable(R.styleable.SingleSelectionView_ss_Background)
textSelectorColor = typedArray.getColorStateList(R.styleable.SingleSelectionView_ss_TextSelector)
primaryTextColor = typedArray.getColor(R.styleable.SingleSelectionView_ss_TextSelector, primaryTextColor)
orientation = typedArray.getInt(R.styleable.SingleSelectionView_ss_Orientation,RecyclerView.VERTICAL)
checkDrawableSelector = typedArray.getResourceId(R.styleable.SingleSelectionView_ss_checkDrawableSelector,R.drawable.ic_check_selector)
checkSelector = typedArray.getResourceId(R.styleable.SingleSelectionView_ss_checkDrawableSelector,R.drawable.ic_check_selector)
dataFromXml = typedArray.getResourceId(R.styleable.SingleSelectionView_ss_Listitem, 0)
} finally {
typedArray.recycle()
}
}

fun configureView(
mData: ArrayList<RadioGroupData>,
data: ArrayList<RadioGroupData>,
orientation: Int,
checkSelector: Int, textSelector: ColorStateList?, onCheckedChangeListener: ((List<RadioGroupData>) -> Unit)?
checkSelector: Int, primaryTextColor: Int, onCheckedChangeListener: ((List<RadioGroupData>) -> Unit)?
) {

this.orientation = orientation
this.onMultiSelectionClicked = onCheckedChangeListener
setupView()
adapter = CustomAdapter(checkSelector, textSelector)
setItems(mData)
updateValue(orientation, checkSelector, primaryTextColor, onCheckedChangeListener)
initializeView()
setItems(data)
}

private fun updateValue(
orientation: Int,
checkSelector: Int,
primaryTextColor: Int,
onCheckedChangeListener: ((List<RadioGroupData>) -> Unit)?
) {
this.onMultiSelectionClicked = onCheckedChangeListener
this.orientation = orientation
this.checkSelector = checkSelector
this.primaryTextColor = primaryTextColor
}
private fun setItems(items: List<RadioGroupData>) {
(adapter as? CustomAdapter)?.data = items
adapter = MultiSelectionListAdapter().apply { data = items }
}

private inner class CustomAdapter(
var checkSelector: Int,
var textSelector: ColorStateList?,

) : RecyclerView.Adapter<CustomAdapter.CustomViewHolder>() {
private inner class MultiSelectionListAdapter() : RecyclerView.Adapter<MultiSelectionListAdapter.MultiselectionViewHolder>() {

private var selectedItemPosition: Int = RecyclerView.NO_POSITION

Expand All @@ -102,35 +93,32 @@ class MultiSelectionListView @JvmOverloads constructor( context: Context,attrs:
notifyDataSetChanged()
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CustomViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_simple_list_checkable, parent, false)
return CustomViewHolder(view)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MultiselectionViewHolder {
val view = LayoutInflater.from(parent.context) .inflate(R.layout.item_simple_list_checkable, parent, false)
return MultiselectionViewHolder(view)
}

override fun onBindViewHolder(holder: CustomViewHolder, position: Int) {
holder.bind(data[position],
position == selectedItemPosition
)
override fun onBindViewHolder(holder: MultiselectionViewHolder, position: Int) {
holder.bind(data[position],position == selectedItemPosition)
}

override fun getItemCount(): Int = data.size

inner class CustomViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
inner class MultiselectionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

val cardView: MaterialCardView by lazy { MaterialCardView(itemView.context) }
val textView: CheckedTextView by lazy { CheckedTextView(itemView.context) }

private val cardView = MaterialCardView(itemView.context)
private val textView = CheckedTextView(itemView.context)

init {
cardView.apply {
with(cardView) {
layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
addView(textView)
}


(itemView as ViewGroup).addView(cardView)

itemView.setOnClickListener {
Expand All @@ -144,29 +132,25 @@ class MultiSelectionListView @JvmOverloads constructor( context: Context,attrs:

fun bind(data: RadioGroupData, isSelected: Boolean) {
textView.apply {

setPadding(
paddingAttributes.paddingStart,
paddingAttributes.paddingTop,
paddingAttributes.paddingEnd,
paddingAttributes.paddingBottom
) // Set
text = data.name
applySelector(this)
// setTextColor(textSelector)
isChecked = adapterPosition == selectedItemPosition
checkDrawableSelector = checkSelector
setCheckMarkDrawable(checkDrawableSelector)
checkMarkDrawable?.setBounds(
40,
400,
checkMarkDrawable.intrinsicWidth,
checkMarkDrawable.intrinsicHeight
)
isChecked = selectedItemsPositions.contains(adapterPosition)
applyTextAttributes(this)
applyPaddingAttributes(this)
text = setData(data)
applySelector(this)
extracted()
}

}
private fun CheckedTextView.extracted() {
checkMarkDrawable?.setBounds(
0,
0,
checkMarkDrawable.intrinsicWidth,
checkMarkDrawable.intrinsicHeight
)
gravity = Gravity.CENTER_VERTICAL
setPadding(10, 10, 10, 10)
}
}

private fun toggleItemSelection(position: Int) {
Expand All @@ -181,20 +165,13 @@ class MultiSelectionListView @JvmOverloads constructor( context: Context,attrs:
}
}
private fun applySelector(textView: CheckedTextView) {
with(textView) {
setTextColor(textSelectorColor ?: setDefaultTextColor())
// radioButton.buttonDrawable = checkDrawableSelector?.constantState?.newDrawable()?.mutate()
}
}
private fun setDefaultTextColor(): ColorStateList? {
return ContextCompat.getColorStateList(context, R.color.black)?.let {
it
} ?: run {
null
}

textView.setTextColor(primaryTextColor)
textView.setCheckMarkDrawable(checkSelector)

}

fun setOnMultiSelectionClicked(callback: (List<RadioGroupData>) -> Unit) {
fun setOnMultiSelection(callback: (List<RadioGroupData>) -> Unit) {
onMultiSelectionClicked = callback
}
}
Loading

0 comments on commit 0c38a02

Please sign in to comment.