Home > Enterprise >  Get multiple / dynamic EditText value in RecyclerView
Get multiple / dynamic EditText value in RecyclerView

Time:02-08

I'm new with these case and I want to try to get the value of dynamic EditText(s) from RecyclerView.

here is the pic example

And in the layout :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_marginTop="@dimen/_10sdp"
    android:layout_height="wrap_content">

    <androidx.appcompat.widget.AppCompatTextView
        android:id="@ id/tv_question"
        style="@style/textH4"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:gravity="bottom"
        android:text="Ini adalah tempat pertanyaan pertama" />

    <androidx.appcompat.widget.AppCompatEditText
        android:id="@ id/et_answer"
        android:layout_width="match_parent"
        android:layout_height="@dimen/_120sdp"
        android:hint="Tulis jawaban anda"
        style="@style/EdittextPrimary"
        android:gravity="top"
        android:background="@drawable/bg_outline_grey"
        android:inputType="textMultiLine"
        android:layout_marginTop="@dimen/_10sdp"/>

</LinearLayout>

The question is.. how do I get the EditText value and put it in an ArrayList ?

Update codes : I add my Recycler Adapter, and tried these :

class RequestJoinAdapter(
    private val onClickedItem: (ArrayList<String>) -> Unit
) :
    RecyclerView.Adapter<RequestJoinAdapter.ViewHolder>() {

    var listData: MutableList<KeamananModel> = ArrayList()

    var listJawaban: MutableList<Jawaban> = ArrayList()

    private var textValue = ""

    fun insertAll(data: List<KeamananModel>) {
        data.forEach {
            listData.add(it)
            notifyItemInserted(listData.size - 1)
        }
    }

    fun clear() {
        if (listData.isNotEmpty()) {
            listData.clear()
            notifyDataSetChanged()
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(
            ItemRequestJoinBinding.inflate(
                LayoutInflater.from(parent.context),
                parent,
                false
            )
        )
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val item = listData[position]
        holder.bindTo(item)

    }

    override fun getItemCount() = listData.size

    inner class ViewHolder(val binding: ItemRequestJoinBinding) :
        RecyclerView.ViewHolder(binding.root) {

        fun bindTo(item: KeamananModel) {

            val context = binding.root.context

            binding.tvQuestion.text = item.qt

            binding.etAnswer.addTextChangedListener(object : TextWatcher {
                override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
                override fun afterTextChanged(s: Editable?) {
                    if (textValue.isNotEmpty()) {
                        isLog(textValue)
                    } else {

                    }
                    listJawaban.add(Jawaban(pertanyaan_no = adapterPosition 1, jawaban = textValue))
                    isLog(listJawaban.toString())
                }

                override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                    textValue = s.toString().toLowerCase()
                }
            })
        }

    }

    private fun isLog(msg: String) {
        Log.e("join grup:", msg)
    }

}

I tried to get the values using addTextChangedListener above, but if I check the log, the result is like [Jawaban(pertanyaan_no=1, jawaban=t), Jawaban(pertanyaan_no=1, jawaban=te), Jawaban(pertanyaan_no=1, jawaban=tes), Jawaban(pertanyaan_no=1, jawaban=test)], I need to change its data into a List only.

CodePudding user response:

The simplest answer is to implement a TextWatcher to your EditText and have it return your data when your text is changed.

Now you may ask how can I get such data in my activty? Well it's pretty simple. Create an interface in your adapter to communicate with your activity.

Pass your interface as a constructor parameter so when you initialize your adapter in the activity your methods are implemented.

Another solution for you is to add a button in each item of your list and call your interface method in the button's OnClickListener.

EDIT: In the snippet below I have used a lambda function for when the text changes.

    class RequestJoinAdapter(
      private val onClickedItem: (ArrayList<String>)->Unit,
      val onTextChanged: (text:String,position:Int)->Unit
    ):
      RecyclerView.Adapter<RequestJoinAdapter.ViewHolder>() {
    
      var listData: MutableList<KeamananModel> = ArrayList()
    
      var listJawaban: MutableList<Jawaban> = ArrayList()
    
      private var textValue = ""
    
      fun insertAll(data: List<KeamananModel>) {
        data.forEach {
          listData.add(it)
          notifyItemInserted(listData.size - 1)
        }
      }
    
      fun clear() {
        if (listData.isNotEmpty()) {
          listData.clear()
          notifyDataSetChanged()
        }
      }
    
      override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(
          ItemRequestJoinBinding.inflate(
            LayoutInflater.from(parent.context),
            parent,
            false
          )
        )
      }
    
      override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val item = listData[position]
        holder.bindTo(item)
    
      }
    
      override fun getItemCount() = listData.size
    
      inner class ViewHolder(val binding: ItemRequestJoinBinding):
        RecyclerView.ViewHolder(binding.root) {
    
        fun bindTo(item: KeamananModel) {
    
          val context = binding.root.context
    
          binding.tvQuestion.text = item.qt
          
          binding.etAnswer.addTextChangedListener(object: TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
            override fun afterTextChanged(s: Editable?) {
              if (textValue.isNotEmpty()) {
                isLog(textValue)
                
                onTextChanged.invoke(s,absoluteAdapterPosition)
              } else {
    
              }
              listJawaban.add(Jawaban(pertanyaan_no = adapterPosition   1, jawaban = textValue))
              isLog(listJawaban.toString())
            }
        override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
          textValue = s.toString().toLowerCase()
        }
      })
    }

  }

  private fun isLog(msg: String) {
    Log.e("join grup:", msg)
  }

}

Pay attention to the onTextChanged.invoke() method. This lambda function can be used like an interface to communicate between your adapter and your view. It will be triggered every time your text is changed.

Finally instantiate your adapter like below:

val adapter = RequestJoinAdapter({

    }, { text, position ->
        //onTextChanged
    })

The position argument is there to help you know which TextView was changed

CodePudding user response:

when you want get data, use the following code.

val list = ArrayList<String>()
for(index in 0 until adapter.itemCount){
    val viewHolder = recyclerView.findViewHolderForAdapterPosition(index)
    val editText = viewHolder.itemView.findViewById(//editTextId)
    list.add(editText.text.toString())
}
return list
  •  Tags:  
  • Related