本人刚开始写博客,欢迎提issure;
面试时遇到直接上机实现用ListView实现同时包含EditText和CheckBox要求不允许有任何的混乱,而且得优化。面试一时没有实现,遂回来写成博客,让大家以后不要再踩此坑。
ListVeiw的Item
<EditText
android:id="@+id/et_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<CheckBox
android:id="@+id/cb_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
首先listView基本写法不讲,内部类尽量采用静态好处也不提了,直接从getView()方法开始讲起,
首先得想办法把checkBox点击状态的存起来,怎么办呢,。用map把所有的状态全存起来,然后点击的时候在checkBox的监听里把被选中的map里对应的值给改成选中状态,重新存储map
然后再从map里面把值取出来设置给checkBox;
***************以上为CheckBox的实现原理***************
通常如果listview中的item内容有edittext的时候,会出现很多问题。
主要有:
1.点击弹出编辑框,edittext会失去焦点。
2.输入内容后,向下滑动因为listview的item重用机制,你在上面输入的内容下面的item也会显示。
3.输入内容后,向下滑动再拉回来原来的数据消失。
4.在需要为edittext设置监听时会出现卡的现象
解决方法:
在EditText被点击的时候获取当前的position,在文本内容改变后把文本内容也用map存起来。然后再从map里取出来再设置给跟position对应的EditText;
原理简单:注意几个点:
1.viewHolder.editText.clearFocus();//防止点击以后弹出键盘,重新getview导致的焦点丢失
2.viewHolder.editText.requestFocus();
3.viewHolder.editText.setText(text[position]);//这一定要放在clearFocus()之后,否则最后输入的内容在拉回来时会消失
*****以上为EditText的实现原理*****
下面贴上完整代码:
MainActivity里:
public class MainActivity extends AppCompatActivity {
private List<String> list;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listview = (ListView) findViewById(R.id.listview);
listview.setAdapter(new MyAdapter(MainActivity.this, getData()));
}
public List<String> getData() {
list = new ArrayList<>();
for (int i = 0; i < 100; i++) {
list.add(null);
}
return list;
}
}
本人用的是外部适配器:
MyAdapter
/**
* HockGod
*
* Created by Administrator on 2016/11/6.
*/
public class MyAdapter extends BaseAdapter {
private Context context;
private List<String> list;
private static int index;
private static HashMap<Integer, Boolean> isSelected; //存放checkBox状态的map。
private static HashMap<Integer, String> text; //存放EditText输入的内容的map
private MyWatcher myWatcher;
public MyAdapter(Context context, List<String> list) {
this.context = context;
this.list = list;
isSelected = new HashMap<Integer, Boolean>();
text = new HashMap<Integer, String>();
// 初始化数据
initDate();
}
// 初始化isSelected的数据
private void initDate() {
for (int i = 0; i < list.size(); i++) {
getIsSelected().put(i, false);
}
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.listview_item, null, false);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
} else {
// 取出holder
holder = (ViewHolder) convertView.getTag();
}
/******一下为CheckBox相关设置监听********/
holder.cb.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (isSelected.get(position)) {
isSelected.put(position, false);
setIsSelected(isSelected);
} else {
isSelected.put(position, true);
setIsSelected(isSelected);
}
Log.e("position=========", position + "");
}
});
// 根据isSelected来设置checkbox的选中状况
holder.cb.setChecked(getIsSelected().get(position));
/*******以下为EditText相关设置监听*********/
holder.editText.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction()==MotionEvent.ACTION_UP){
index=position;
}
return false;
}
});
//设置焦点监听,当获取到焦点的时候才给它设置内容变化监听解决卡的问题
holder.editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
EditText editText= (EditText) v;
if (myWatcher==null){
myWatcher = new MyWatcher();
}
if (hasFocus){
editText.addTextChangedListener(myWatcher);
}else {
editText.removeTextChangedListener(myWatcher);
}
}
});
//防止点击以后弹出键盘,重新getview导致的焦点丢失
holder.editText.clearFocus();
// 如果当前的行下标和点击事件中保存的index一致,手动为EditText设置焦点。
if (index==position) holder.editText.requestFocus();
//这一定要放在clearFocus()之后,否则最后输入的内容在拉回来时会消失
holder.editText.setText(text.get(position));
holder.editText.setSelection(holder.editText.getText().length());
return convertView;
}
public static HashMap<Integer, Boolean> getIsSelected() {
return isSelected;
}
public static void setIsSelected(HashMap<Integer, Boolean> isSelected) {
MyAdapter.isSelected = isSelected;
}
static class ViewHolder {
CheckBox cb;
EditText editText;
public ViewHolder(View view){
cb = (CheckBox) view.findViewById(R.id.cb_select);
editText = (EditText) view.findViewById(R.id.et_text);
}
}
static class MyWatcher implements TextWatcher{
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
//为输入的位置内容设置map,防止item重用机制导致的上下内容一样的问题
text.put(index,s.toString());
}
}
}
如果你有更好的实现请直接贴地址。希望多多交流。不喜欢的请写出原因,本人虚心接受。