Search code examples
androidkotlinandroid-recyclerviewlistenertextwatcher

addTextChangedListener is triggered immediately


I have a problem with addTextChangedListener. addTextChangedListener is triggered immediately when I launch the app (after touch the screen).

addTextChangedListener is in a ViewHolder Class in a recyclerview with a custom adapter.

I have tried to move both setOnClickListener1() and setOnClickListener2() from onBindViewHolder to onCreateViewHolder but it is worst (triggered immediately after launching the app).

here is my adapter code

import android.text.Editable
import android.text.TextWatcher
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.EditText
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView

open class CustomAdapter(private val data: DataClass, private val activity: MainActivity) :
        RecyclerView.Adapter<CustomAdapter.ViewHolder>() {

    init {
        setHasStableIds(true)
    }


    override fun onCreateViewHolder(
            parent: ViewGroup,
            viewType: Int
    ): ViewHolder {

        val rowItem: View =
                LayoutInflater.from(parent.context).inflate(com.example.essai2.R.layout.list_item_view, parent, false)

        var myview= ViewHolder(rowItem)

      //myview.setOnClickListener1()
      //myview.setOnClickListener2()

        return myview


    }

    override fun onBindViewHolder(
            holder: ViewHolder,
            position: Int
    ) {

        holder.editText.setText(data.list1[position])
        holder.editText2.setText(data.list2[position])
        holder.textview.setText(data.list3[position])
        holder.setOnClickListener1()
        holder.setOnClickListener2()
    }

    override fun getItemId(position: Int): Long {
        return position.toLong()
    }

    override fun getItemCount(): Int {
        return data.list1.size
    }

   inner class ViewHolder(rowItem: View) : RecyclerView.ViewHolder(rowItem) {

        val textview : TextView = rowItem.findViewById(com.example.essai2.R.id.textview)
        val editText : EditText= rowItem.findViewById(com.example.essai2.R.id.editText)
        val editText2 : EditText= rowItem.findViewById(com.example.essai2.R.id.editText2)


        fun fonction3(position: Int)
        {
              if (position >=1 && position <=98) {
                  data.list3[position] = (0.5 * (data.list2[position - 1].toDouble() + data.list2[position + 1].toDouble())).toString()
                  //activity.Update()
              }
        }

        fun setOnClickListener1() {

            editText.addTextChangedListener(object : TextWatcher {

                override fun afterTextChanged(p0: Editable?) {
                   data.list1[getAdapterPosition()]= editText.text.toString()
                  // activity.fonction()
                }
                override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
                }
                override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                }
            })
        }

        fun setOnClickListener2() {
            editText2.addTextChangedListener(object : TextWatcher {

                override fun afterTextChanged(p0: Editable?) {
                    data.list2[getAdapterPosition()] = editText2.text.toString()
                    activity.fonction2()
                    fonction3(getAdapterPosition())

                }
                override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
                }
                override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                }
            })
        }
    }

}

here is my activity code

import android.os.Bundle
import android.widget.EditText
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView


class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val recyclerView = findViewById<RecyclerView>(R.id.recycler_view)
        recyclerView.layoutManager = LinearLayoutManager(this)

        recyclerView.adapter = CustomAdapter(DataClass(),this)

        recyclerView.addItemDecoration(DividerItemDecoration(this, DividerItemDecoration.VERTICAL))

        var textView2: TextView
        textView2 = findViewById(R.id.textView)
        var editText : EditText
    }

    fun Update()
    {
       // findViewById<RecyclerView>(R.id.recycler_view).getAdapter()?.notifyDataSetChanged()
        val recyclerView = findViewById<RecyclerView>(R.id.recycler_view)
        recyclerView.adapter=CustomAdapter(DataClass(),this)
        (recyclerView.adapter as CustomAdapter).notifyDataSetChanged()
    }


    fun fonction ()
    {
        var textView2: TextView
        textView2 = findViewById(R.id.textView)
        textView2.text="!!!!!!"
    }


    fun fonction2 ()
    {
        var textView2: TextView
        textView2 = findViewById(R.id.textView)
        textView2.text="?????"
    }

    private fun generateData(): List<String> {
        val data: MutableList<String> = ArrayList()
        for (i in 0..99) {
            data.add(i.toString() + "th Element")
        }
        return data
    }
}

class DataClass(){
    var list1: MutableList<String> = generateData2() as MutableList<String>
    var list2: MutableList<String> = generateData3() as MutableList<String>
    var list3: MutableList<String> = generateData4() as MutableList<String>

    private fun generateData2(): List<String> {
        val data: MutableList<String> = mutableListOf()
        for (i in 0..99) {
            data.add(i.toString())
        }
        return data
    }

    private fun generateData3(): List<String> {
        val data: MutableList<String> =mutableListOf()
        for (i in 0..99) {
            data.add((10*i).toString())
        }
        return data
    }

    private fun generateData4(): List<String> {
        val data: MutableList<String> = mutableListOf()
        for (i in 0..99) {
            data.add("none")
        }

        return data
    }

}

Thanks in advance for your help

EDIT : here is the list_item_view.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        app:layout_constraintBottom_toBottomOf="parent"

        tools:ignore="MissingConstraints">

        <TextView
            android:id="@+id/textview2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="TextView"
            android:textSize="16dp" />

        <TextView
            android:id="@+id/textview"
            android:layout_width="wrap_content"
            android:layout_height="35dp"
            android:text="TextView"
            android:textSize="16dp" />


        <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/editText2"
            android:layout_width="196dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:focusableInTouchMode="true"
            android:focusedByDefault="false"
            android:hint="hint" />

        <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/editText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:focusedByDefault="false"
            android:hint="hint" />

    </LinearLayout>



</androidx.constraintlayout.widget.ConstraintLayout>

Solution

  • I just changed my answer based on our conversation below.

    First of all, here is you XML file (I just changed the id of the views and nothing else):

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="50dp"
            app:layout_constraintBottom_toBottomOf="parent"
            tools:ignore="MissingConstraints">
    
            <TextView
                android:id="@+id/tv2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="TextView2"
                android:textSize="16dp" />
    
            <TextView
                android:id="@+id/tv1"
                android:layout_width="wrap_content"
                android:layout_height="35dp"
                android:text="TextView1"
                android:textSize="16dp" />
            
            <com.google.android.material.textfield.TextInputEditText
                android:id="@+id/et2"
                android:layout_width="196dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:focusableInTouchMode="true"
                android:focusedByDefault="false"
                android:hint="hint" />
    
            <com.google.android.material.textfield.TextInputEditText
                android:id="@+id/et1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:focusedByDefault="false"
                android:hint="hint" />
    
        </LinearLayout>
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    And here is your adapter (I checked everything and there was no errors):

    import android.content.Context
    import android.text.Editable
    import android.text.TextWatcher
    import android.view.LayoutInflater
    import android.view.View
    import android.view.ViewGroup
    import androidx.recyclerview.widget.RecyclerView
    import kotlinx.android.synthetic.main.list_item_view.view.*
    
    class CustomAdapter(private val data : DataClass, private val context : Context) :
        RecyclerView.Adapter<CustomAdapter.ViewHolder>() {
    
        init {
            setHasStableIds(true)
        }
    
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    
            val rowItem: View = LayoutInflater.from(context).inflate(R.layout.list_item_view, parent, false)
    
            return ViewHolder(rowItem)
        }
    
        override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    
            holder.itemView.tv1.setText(data.list3[position])
    
            holder.itemView.et1.setText(data.list1[position])
            holder.itemView.et2.setText(data.list2[position])
    
            holder.itemView.et1.addTextChangedListener(object : TextWatcher {
    
                override fun afterTextChanged(p0: Editable?) {
                    data.list1[position]= holder.itemView.et1.text.toString()
                    // activity.fonction()
                }
                override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
                }
                override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                }
            })
            holder.itemView.et2.addTextChangedListener(object : TextWatcher {
    
                override fun afterTextChanged(p0: Editable?) {
                    data.list2[position] = holder.itemView.et2.text.toString()
    
                    //this is instead of `fonction2()`
                    holder.itemView.tv2.text = "?????"
                    //fonction2()
    
                    fonction3(position)
                }
    
                override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
                }
    
                override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                }
            })
        }
    
        override fun getItemId(position: Int): Long {
            return position.toLong()
        }
    
        override fun getItemCount(): Int {
            return data.list1.size
        }
    
        inner class ViewHolder(rowItem: View) : RecyclerView.ViewHolder(rowItem) {
    
        }
    
        fun fonction3(position: Int) {
            if (position in 1..98) {
                data.list3[position] = (0.5 * (data.list2[position - 1].toDouble() + data.list2[position + 1].toDouble())).toString()
                //activity.Update()
            }
        }
    }