編集可能なTextViewがListViewの中にある場合が今回の問題です。
class GroupListAdapter(context: Context, var groups: MutableList<MemoGroup>) : ArrayAdapter<MemoGroup> (context, 0, groups) { data class ViewHolder(val textView: TextView) private val layoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { var view = convertView var holder: ViewHolder if (view == null) { view = layoutInflater.inflate(R.layout.view_group_setting, null) holder = ViewHolder( view.findViewById(R.id.textView) ) view.tag = holder holder.textView.addTextChangedListener(object: TextWatcher { override fun afterTextChanged(p0: Editable?) { if(p0 != null) { groups[position].title = p0.toString() } } override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {} override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {} }) } else { holder = view.tag as ViewHolder } holder.textView.text = groups[position].title return view!! } }
本当はもうちょっとごちゃごちゃしているのですが、多少見やすいように修正しました。
さて、これだと何度もafterTextChangedが呼ばれて、しかもpositionもp0.toString()も思った値が取れない。
ここを参考にして解決しました。
class GroupListAdapter(context: Context, var groups: MutableList<MemoGroup>) : ArrayAdapter<MemoGroup> (context, 0, groups) { inner class MutableWatcher : TextWatcher { var position: Int = 0 var active: Boolean = false 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) { if (active) { groups[position].title = s.toString() } } } data class ViewHolder(val textView: TextView, val watcher:MutableWatcher) private val layoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { var view = convertView var holder: ViewHolder if (view == null) { view = layoutInflater.inflate(R.layout.view_group_setting, null) holder = ViewHolder( view.findViewById(R.id.textView), MutableWatcher() ) view.tag = holder holder.textView.addTextChangedListener(holder.watcher) } else { holder = view.tag as ViewHolder } holder.watcher.active = false holder.textView.text = groups[position].title holder.watcher.position = position holder.watcher.active = true return view!! } }
textView.textに代入してもafterTextChangedが呼ばれるので、その時は無視するようにして、TextWatcher をそれぞれに持たせる感じなのか?まだ勉強が足りません。