ListView套用EditText完美解決方案
阿新 • • 發佈:2019-01-31
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>