ListView套用EditText完美解决方案

时间:2022-07-29 19:38:39

             EditText是安卓的标准输入控件,也是最长用的控件,被认为是很简单的,但是当这个最简单、易用的控件碰上ListView列表控件的时候,坑爹的情况就出现了,焦点获取问题,输入的内容混乱问题、无法正常输入问题等等,总之就是简单的控件让开发变得头疼不已。究其原因,ListView的自条目会复用控件,导致edittext数据混乱,焦点的获取出现问题。遇到过问题的,都明白是怎么回事,这里不再截图展示问题,只是把解决方案和代码共享出来。废话少说,直接上代码:

package com.hongzhen.demo.activity;

import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;

import com.hongzhen.demo.R;
import com.hongzhen.demo.adapter.EdittextAdapter;
import com.hongzhen.demo.bean.ItemBean;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by hongzhen on 2017/9/4.
 */

public class EditTextListViewActivity extends Activity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_edittext_listview);
        ListView listView = (ListView) findViewById(R.id.list_view);
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Toast.makeText(EditTextListViewActivity.this, "toast: " + position, Toast.LENGTH_SHORT).show();
            }
        });

        List<ItemBean> list = new ArrayList<>();
        for (int i = 0; i < 50; i++) {
            ItemBean itemTest = new ItemBean();
            itemTest.setText("第"+i + "项");
            list.add(itemTest);
        }
        EdittextAdapter adapter = new EdittextAdapter( list,this);
        listView.setAdapter(adapter);
    }
}
<?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_height="match_parent">
    <ListView
        android:layout_margin="5dp"
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:dividerHeight="5dp" />
</LinearLayout>

package com.hongzhen.demo.adapter;

import android.content.Context;
import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.Toast;

import com.hongzhen.demo.R;
import com.hongzhen.demo.bean.ItemBean;
import com.hongzhen.demo.watcher.MyTextWatcher;

import java.util.List;

/**
 * Created by hongzhen on 2017/9/4.
 */

public class EdittextAdapter extends BaseAdapter implements View.OnClickListener, View.OnTouchListener, View.OnFocusChangeListener, View.OnLongClickListener {
    private int selectedEditTextPosition = -1;
    private List<ItemBean> mList;
    private Context mContext;

    public EdittextAdapter(List<ItemBean> mList,Context mContext) {
        this.mContext=mContext;
        this.mList = mList;
    }

    @Override
    public int getCount() {
        return mList.size();
    }

    @Override
    public Object getItem(int position) {
        return mList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup viewGroup) {
        ViewHolder vh;
        if (convertView == null) {
            convertView = LayoutInflater.from(mContext).inflate(R.layout.item_edittext_listview, null);
            vh = new ViewHolder(convertView);
            convertView.setTag(vh);
        } else {
            vh = (ViewHolder) convertView.getTag();
        }

        vh.editText.setOnTouchListener(this); // 正确写法
        vh.editText.setOnFocusChangeListener(this);
        vh.editText.setTag(position);

        if (selectedEditTextPosition != -1 && position == selectedEditTextPosition) { // 保证每个时刻只有一个EditText能获取到焦点
            vh.editText.requestFocus();
        } else {
            vh.editText.clearFocus();
        }

        String text = mList.get(position).getText();
        vh.editText.setText(text);
        vh.editText.setSelection(vh.editText.length());

        convertView.setTag(R.id.item_root, position); // 应该在这里让convertView绑定position
        convertView.setOnClickListener(this);
        convertView.setOnLongClickListener(this);
        return convertView;
    }
    private TextWatcher mTextWatcher = new MyTextWatcher() {
        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            if (selectedEditTextPosition != -1) {
                Log.w("MyEditAdapter", "onTextPosiotion " + selectedEditTextPosition);
                ItemBean itemTest = (ItemBean) getItem(selectedEditTextPosition);
                itemTest.setText(s.toString());
            }
        }
    };
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_UP) {
            EditText editText = (EditText) v;
            selectedEditTextPosition = (int) editText.getTag();
        }
        return false;
    }

    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        EditText editText = (EditText) v;
        if (hasFocus) {
            editText.addTextChangedListener(mTextWatcher);
        } else {
            editText.removeTextChangedListener(mTextWatcher);
        }
    }

    @Override
    public void onClick(View view) {
        if (view.getId() == R.id.item_root) {
            int position = (int) view.getTag(R.id.item_root);
            Toast.makeText(mContext, "点击第 " + position + " 个item", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public boolean onLongClick(View view) {
        if (view.getId() == R.id.item_root) {
            int position = (int) view.getTag(R.id.item_root);
            Toast.makeText(mContext, "长按第 " + position + " 个item", Toast.LENGTH_SHORT).show();
        }
        return true;
    }

    public class ViewHolder {
        EditText editText;

        public ViewHolder(View convertView) {
            editText = (EditText) convertView.findViewById(R.id.et_test);
        }
    }
}


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/item_root"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:background="#aaa"
    android:gravity="center"
    android:orientation="vertical">

    <EditText
        android:textColor="#fff"
        android:id="@+id/et_test"
        android:layout_width="200dp"
        android:layout_height="50dp"
        android:layout_gravity="left"
        android:gravity="center"
        android:singleLine="true"
        android:textSize="20dp" />
</LinearLayout>