ListViewの中に編集可能なTextView(EditText)

編集可能な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 をそれぞれに持たせる感じなのか?まだ勉強が足りません。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です