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>