Я создаю приложение, в котором пользователю необходимо заполнить некоторые данные для публикации чего-либо, поэтому фрагмент состоит из EditText
, переключателей и Spinner
вместе с RecyclerView
, который динамически отображает несколько дочерних макетовсодержащие TextView
и EditText
.
Поэтому, когда пользователь выбирает категорию из Spinner
, некоторые свойства, связанные с этой категорией, отображаются в RecyclerView
, и пользователь может по желанию заполнить некоторые из них.
Я пытался реализоватьэта функция использует обратный вызов и TextWatcher
, но я не получаю нужные значения.
CallBack
interface PropertiesCallback {
fun addProp(position: Int, title: String, value: String)
}
Адаптер
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()} ")
}
}
Выше коды предназначены для работы в качестве.Когда пользователь вводит значение в один из EditText
в RecyclerView
, оно будет фрагментировано и добавлено к объекту, который получает заголовок и значение, а затем добавлено к propertiesInputList
.
Задача 1: propertiesInputList
будет иметь так много дубликатов объектов с одинаковым названием, и я подумал, что лучшим решением было бы использовать distinctBy
.
Задача 2: Когда пользователь заполняетчисло EditText
, которое связано, скажем, с category1
и передумает и выберите другую категорию из Spinner
.Предыдущие значения, которые не являются частью новой выбранной категории , остаются в списке propertiesInputList
.Поэтому я подумал, что лучшим решением было бы очистить propertiesInputList
и использовать removeAll
с заголовками, относящимися к категории, для фильтрации нежелательных объектов.
Но теперь я получаю только первые буквы пользовательских типов.Если пользователь наберет обувь , я получу с .Таким образом, кажется, distinctBy
возвращает первый объект, но я хочу, чтобы пользователь точно набрал последнее слово, и если пользователь напечатал и удалил все, что я хочу, пустым.
Есть ли лучшее решение для этого?Как зацикливание recyclerView
только когда пользователь нажимает «отправить» вместо TextWatcher
?Или какую часть я должен исправить, чтобы сделать эту работу?