Impossible to trigger textWatcher from ListViewAdapter

13 views Asked by At

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.
0

There are 0 answers