I would like to understand why my textwatchers in my listview adapter cannot be triggered when i'm typing on the keyboard.
As you can se we have different field inside many cards. The main purpose to this class is to complet my viewmodel.
The function witch complet my correct object inside the viewmodel is working perfectly but for some reason it's not possible to complet the different variable of my object.
Some body have an idea ?
This is my adapter class :
class SheetsTargetCustomListAdapter(
private val context: Context,
private var targetCards: List<TargetCard>,
private val viewModel: SharedViewModel,
private val designations: List<Designation>
) : BaseAdapter() {
override fun getCount(): Int = targetCards.size
override fun getItem(position: Int): TargetCard = targetCards[position]
override fun getItemId(position: Int): Long = position.toLong()
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
val view: View = convertView ?: LayoutInflater.from(context).inflate(R.layout.antenote_sheet_phyto_measurement_target_card, parent, false)
val targetCard = targetCards[position]
val designationEditText = view.findViewById<TextInputEditText>(R.id.et_selectDesa)
designationEditText.tag = position
val uniteEditText = view.findViewById<TextInputEditText>(R.id.et_unite)
uniteEditText.tag = position
val valeurMinEditText = view.findViewById<TextInputEditText>(R.id.et_valMin)
valeurMinEditText.tag = position
val valeurMaxEditText = view.findViewById<TextInputEditText>(R.id.et_valMax)
valeurMaxEditText.tag = position
val checkBox = view.findViewById<CheckBox>(R.id.cb_saisielibre)
val ficheNumberTextView = view.findViewById<TextView>(R.id.tv_status)
ficheNumberTextView.text = targetCard.ficheNumber
checkBox.setOnCheckedChangeListener(null)
checkBox.isChecked = targetCard.designationCheckbox
checkBox.setOnCheckedChangeListener { _, isChecked ->
viewModel.updateCardField(position) { it.designationCheckbox = isChecked }
if (isChecked) {
designationEditText.isFocusableInTouchMode = true
designationEditText.isFocusable = true
} else {
designationEditText.isFocusable = false
designationEditText.isFocusableInTouchMode = false
}
}
designationEditText.setText(targetCard.designation)
uniteEditText.setText(targetCard.unite)
valeurMinEditText.setText(targetCard.valeurMin.toString())
valeurMaxEditText.setText(targetCard.valeurMax.toString())
/*setupTextWatcher(designationEditText, designationTextWatcher)
setupTextWatcher(uniteEditText, uniteTextWatcher)
setupTextWatcher(valeurMinEditText, valeurMinTextWatcher)
setupTextWatcher(valeurMaxEditText, valeurMaxTextWatcher)*/
clearTextWatchers(view)
setupTextWatcher(designationEditText, position, "designation")
setupTextWatcher(uniteEditText, position, "unite")
setupTextWatcher(valeurMinEditText, position, "valeurMin")
setupTextWatcher(valeurMaxEditText, position, "valeurMax")
designationEditText.setOnClickListener {
if (!checkBox.isChecked) {
showDesignationPopup(designationEditText, position)
}
}
designationEditText.removeTextChangedListener(designationEditText.tag as? TextWatcher)
uniteEditText.removeTextChangedListener(uniteEditText.tag as? TextWatcher)
valeurMinEditText.removeTextChangedListener(valeurMinEditText.tag as? TextWatcher)
valeurMaxEditText.removeTextChangedListener(valeurMaxEditText.tag as? TextWatcher)
return view
}
private fun setupTextWatcher(editText: TextInputEditText, position: Int, field: String) {
val textWatcher = object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
override fun afterTextChanged(s: Editable?) {
val newValue = s.toString()
when (field) {
"designation" -> viewModel.updateCardField(position) { it.designation = newValue }
"unite" -> viewModel.updateCardField(position) { it.unite = newValue }
"valeurMin" -> viewModel.updateCardField(position) { it.valeurMin = newValue.toDoubleOrNull() ?: 0.0 }
"valeurMax" -> viewModel.updateCardField(position) { it.valeurMax = newValue.toDoubleOrNull() ?: 0.0 }
}
}
}
editText.addTextChangedListener(textWatcher)
editText.tag = textWatcher // Store TextWatcher in tag for future removal
}
private fun clearTextWatchers(view: View) {
// Liste des IDs de vos TextInputEditText pour lesquels vous voulez retirer les TextWatchers
val editTextIds = listOf(R.id.et_selectDesa, R.id.et_unite, R.id.et_valMin, R.id.et_valMax)
// Itération sur chaque ID pour trouver le TextInputEditText correspondant et retirer son TextWatcher
editTextIds.forEach { editTextId ->
val editText = view.findViewById<TextInputEditText>(editTextId)
val textWatcher = editText.tag as? TextWatcher
if (textWatcher != null) {
editText.removeTextChangedListener(textWatcher)
editText.tag = null // Enlève la référence au TextWatcher pour éviter les fuites de mémoire
}
}
}
/*private val designationTextWatcher = object : TextWatcher {
var oldValue = ""
fun updateTargetCard(targetCard: TargetCard, position: Int, newValue: String) {
if (newValue != oldValue) {
targetCard.designation = newValue
viewModel.updateCardField(position) { it.designation = newValue }
oldValue = newValue
}
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
override fun afterTextChanged(s: Editable?) {
val newValue = s.toString()
val position = (s as? View)?.getTag(R.id.et_selectDesa) as? Int
if (position != null) {
targetCards.getOrNull(position)?.let { targetCard ->
updateTargetCard(targetCard, position, newValue)
}
}
}
}
private val uniteTextWatcher = object : TextWatcher {
var oldValue = ""
fun updateTargetCard(targetCard: TargetCard, position: Int, newValue: String) {
if (newValue != oldValue) {
targetCard.unite = newValue
viewModel.updateCardField(position) { it.unite = newValue }
oldValue = newValue
}
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
override fun afterTextChanged(s: Editable?) {
val newValue = s.toString()
val editText = s as? View
val position = editText?.getTag(R.id.et_unite) as? Int
if (position != null) {
targetCards.getOrNull(position)?.let { targetCard ->
updateTargetCard(targetCard, position, newValue)
}
}
}
}
private val valeurMinTextWatcher = object : TextWatcher {
var oldValue = ""
fun updateTargetCard(targetCard: TargetCard, position: Int, newValue: String) {
if (newValue != oldValue) {
targetCard.valeurMin = newValue.toDouble()
viewModel.updateCardField(position) { it.valeurMin = newValue.toDouble() }
oldValue = newValue
}
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
override fun afterTextChanged(s: Editable?) {
val newValue = s.toString()
val position = (s as? View)?.getTag(R.id.et_valMin) as? Int
if (position != null) {
targetCards.getOrNull(position)?.let { targetCard ->
updateTargetCard(targetCard, position, newValue)
}
}
}
}
private val valeurMaxTextWatcher = object : TextWatcher {
var oldValue = ""
fun updateTargetCard(targetCard: TargetCard, position: Int, newValue: String) {
if (newValue != oldValue) {
targetCard.valeurMax = newValue.toDouble()
viewModel.updateCardField(position) { it.valeurMax = newValue.toDouble() }
oldValue = newValue
}
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
override fun afterTextChanged(s: Editable?) {
val newValue = s.toString()
val position = (s as? View)?.getTag(R.id.et_valMax) as? Int
if (position != null) {
targetCards.getOrNull(position)?.let { targetCard ->
updateTargetCard(targetCard, position, newValue)
}
}
}
}
private fun setupTextWatcher(editText: TextInputEditText, textWatcher: TextWatcher) {
editText.addTextChangedListener(textWatcher)
}*/
private fun showDesignationPopup(view: TextInputEditText, position: Int) {
val popupMenu = PopupMenu(view.context, view)
designations.forEachIndexed { index, designation ->
popupMenu.menu.add(0, index, index, designation.description)
}
popupMenu.setOnMenuItemClickListener { menuItem ->
val selectedDesignation = designations[menuItem.itemId].description
view.setText(selectedDesignation)
viewModel.updateCardField(position) { it.designation = selectedDesignation }
true
}
popupMenu.show()
}
fun updateData(newData: List<TargetCard>) {
this.targetCards = newData
notifyDataSetChanged()
}
}
Also my viewmodel to understand what it realy does :
fun updateCardField(position: Int, field: (TargetCard) -> Unit) {
val updatedList = cardTarget.value?.toMutableList()
updatedList?.get(position)?.let {
field(it)
cardTarget.value = updatedList
}
Log.d("SharedViewModel", "updateCardField = ${cardTarget.value}")
}
Can you help me to understand what happen to this code ? Many thanks
- i try to replace the textwatchers by individual textwatcher but it doesn't works.