I am building app which user is required fill some data in order to post something, so a fragment consists of edit texts ,radio buttons and spinner along with recyclerview which dynamically renders a number of child layout containing TextView and editText. So when user select category from spinner, some properties which are related to that category are displayed in RecyclerView and user can optionally fill some of them. I have tried to implement this functionality using callback and TextWatcher but I don't get the values I want.
CallBack
interface PropertiesCallback {
fun addProp(position: Int, title: String, value: String)
}
Adapter
class PropertiesAdapter(private val propertiesCallback: PropertiesCallback)
: RecyclerView.Adapter<PropertiesAdapter.ViewHolder>() {
private var list = listOf<CategoriesAndSubcategoriesQuery.Property>()
fun setData(listOfProps: List<CategoriesAndSubcategoriesQuery.Property>) {
this.list = listOfProps
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.z_property_input, parent, false)
return ViewHolder(view)
}
override fun getItemCount(): Int = list.size
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(list[position], position)
}
inner class ViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
private val label: TextView = view.findViewById(R.id.label)
private val input: EditText = view.findViewById(R.id.input)
fun bind(prop: CategoriesAndSubcategoriesQuery.Property, position: Int) {
label.text = prop.title()
prop.hint()?.let { input.hint = prop.hint() }
input.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
propertiesCallback.addProp(position, prop.title(), input.text.toString())
}
})
}
}
}
In Fragment
private var propertiesList = mutableListOf<CategoriesAndSubcategoriesQuery.Property>()
private var propertiesInputList = mutableListOf<ProductPropertiesInput>()
private fun setUpSubcategorySpinner() {
subcategoriesAdapter = ArrayAdapter(
this@AddProductFragment.context!!,
android.R.layout.simple_spinner_item,
subcategoriesList
)
//Subcategories
subcategoriesAdapter.setDropDownViewResource(android.R.layout.simple_dropdown_item_1line)
subcategory_spinner.adapter = subcategoriesAdapter
subcategory_spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>, view: View, position: Int, id: Long) {
subcategoryId = subcategoriesList[position].id()
//Adding properties
subcategoriesList[position].properties()?.let {
//Clear previous properties data of another subcategory.
propertiesInputList.clear()
propertiesList.clear()
propertiesList.addAll(it)
propertiesAdapter.setData(propertiesList)
propertiesAdapter.notifyDataSetChanged()
}
}
override fun onNothingSelected(parent: AdapterView<*>) {}
}
}
overide
override fun addProp(position: Int, title: String, value: String) {
val prop = ProductPropertiesInput
.builder()
.title(title)
.value(value)
.build()
propertiesInputList.add(prop)
//Log.d(TAG, "prop: ${prop.title()} : ${prop.value()}")
}
submit fun
private fun submitProduct() {
//Initializing properties.
val properties: Any
//The keys needed in final list.
val propertyKeys = propertiesList.map { it.title() }
//Removing objects which keys are not needed.
propertiesInputList.removeAll { it.title() !in propertyKeys }
Log.d(TAG, "propertiesInputList: $propertiesInputList")
//Removing duplicate and assign result in properties var.
properties = propertiesInputList
.distinctBy { it.title() }
Log.d(TAG, "properties: $properties")
for (prop in properties) {
Log.d(TAG, "properties , title: ${prop.title()}, value: ${prop.value()} ")
}
}
Above codes is intended to work as. When user types a value in one of the editText in recyclerView the value will be taken to fragment and added to an object which takes title and value and then added to propertiesInputList.
Problem 1: propertiesInputList will have so many duplicates objects with the same title and I thought best soulution was using distinctBy.
Problem 2: When user fill a number of edittexts which related to lets say category1 and changes his mind and select another category from spinner. The previous values which not part of new chosen category remain in propertiesInputList list. So I thought best solution was to clear propertiesInputList and using removeAll with the titles related to category to filter unwanted objects.
But now I get only the first letter user types. If user types shoes I get s. So it seems distinctBy returns the first object but I want to get exactly last word user typed and If user typed and erased everything i want blank.
Is there a better solution to handle this? Like looping recyclerView only when user press submit instead of textwatcher? Or which part should I fix to make this work?
from Getting EditTexts Values From RecyclerView
No comments:
Post a Comment