在一个ListView中,如果里面有EditText会很麻烦,因为修改EditText里面的数据会发生错位现象.

这时候,需要在适配器BaseAdapter的getView中设置setTag(),将position缓存起来.
下面来解决这个问题.

1.打开activity_main.xml .
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.listviewdemo1.MainActivity" >
    <Button 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:id="@+id/btn_addRow"
        android:text="增加一行"
        />
    <ListView 
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:id="@+id/lv"
        android:cacheColorHint="@android:color/transparent"
        ></ListView>
</LinearLayout>
在这个布局中,只有一个简单的Button和一个ListView,Button是用来动态添加  一行记录的.

2.新建一个item.xml,作为listView的子布局.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:descendantFocusability="beforeDescendants"
    android:orientation="horizontal" >
    
    <TextView 
        android:layout_width="10dp"
        android:layout_height="wrap_content"
        android:id="@+id/tv_position"
        />
    <Spinner 
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:id="@+id/sp_type"
        />
    <EditText 
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:id="@+id/et_number"
        />
    <Button 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/btn_delete"
        android:text="删除"
        />
</LinearLayout>
子布局元素也只有四个, 一个TextView用来放索引位置,  Spinner用来显示一个下拉窗口  , 还有一个EditText和一个Button.

3.新建一个NumberInfo.java,用来存储数据的javaBean.
public class NumberInfo {
    private String type;
    private String number;
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public String getNumber() {
        return number;
    }
    public void setNumber(String number) {
        this.number = number;
    }   
}
只有简单的两个属性  

4.新建一个MyAdapter.java 适配器, 用来展示ListView的数据, 解决混乱的重点.
public class MyAdapter extends BaseAdapter {
    private List<NumberInfo> list=new ArrayList<NumberInfo>();
    
    private Context context;
    private OnListRemovedListener mListener;
    
    //下拉列表的适配器
    private ArrayAdapter<String> arrayAdapter;
    //下拉列表的选项
    private static final String[] SPINNER_TIME = {"手机","住宅","其他"};
    
    public void setOnListRemovedListener(OnListRemovedListener listener){
        this.mListener=listener;
    }
    
    public MyAdapter(List<NumberInfo> list,Context context) {
        this.context=context;
        this.list=list;
        arrayAdapter=new ArrayAdapter<String>(context, android.R.layout.simple_spinner_item, SPINNER_TIME);
        arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    }
    
    @Override
    public int getCount() {
        return list.size();
    }
    @Override
    public Object getItem(int arg0) {
        return null;
    }
    @Override
    public long getItemId(int arg0) {
        return 0;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup arg2) {
        ViewHolder holder=null;
        if(convertView==null){
            convertView=LayoutInflater.from(context).inflate(R.layout.item, null);
            holder=new ViewHolder();
            holder.tv_position=(TextView) convertView.findViewById(R.id.tv_position);
            holder.sp_type=(Spinner) convertView.findViewById(R.id.sp_type);
            holder.sp_type.setOnItemSelectedListener(new MySpinnerListener(holder) {
                @Override
                public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2,
                        long arg3, ViewHolder holder) {
                    TextView tv=(TextView) arg1;
                    int position=(Integer) holder.et_number.getTag();
                    NumberInfo n=list.get(position);
                    n.setType(tv.getText().toString());
                    list.set(position, n);
                }
            });
            holder.et_number=(EditText) convertView.findViewById(R.id.et_number);
            holder.et_number.setTag(position);
            holder.et_number.addTextChangedListener(new MyTextWatcher(holder) {
                @Override
                public void afterTextChanged(Editable s, ViewHolder holder) {
                    int position=(Integer) holder.et_number.getTag();
                    NumberInfo n=list.get(position);
                    n.setNumber(s.toString());
                    list.set(position, n);
                }
            });
            holder.btn_delete=(Button) convertView.findViewById(R.id.btn_delete);
            holder.btn_delete.setOnClickListener(new MyOnClickListener(holder) {
                @Override
                public void onClick(View v, ViewHolder holder) {
                    if(mListener!=null){
                        int position=(Integer) holder.et_number.getTag();
                        list.remove(position);
                        mListener.onRemoved();  //通知主线程更新Adapter
                    }
                }
            });
            convertView.setTag(holder);
        }
        else{
            holder=(ViewHolder) convertView.getTag();
            holder.et_number.setTag(position);
        }
        NumberInfo n=list.get(position);
        holder.tv_position.setText(position+1+"");
        holder.sp_type.setAdapter(arrayAdapter);
        holder.et_number.setText(n.getNumber());
        
        int p=getPositionForAdapter(position);
        holder.sp_type.setSelection(p,true);
        
        return convertView;
    }
    
    private int getPositionForAdapter(int po){
        
        NumberInfo  t = list.get(po);
        int p = 0;
        for(int i=0;i<SPINNER_TIME.length;i++){
            if(t.getType().equals(SPINNER_TIME[i])){
                p = i;
            }
        }
        return p;
    }
    
    //动态添加List里面数据
    public void addItem(NumberInfo n){
        list.add(n);
    }
    
    private abstract class MySpinnerListener implements OnItemSelectedListener{
        private ViewHolder holder;
        
        public MySpinnerListener(ViewHolder holder) {
            this.holder=holder;
        }
        @Override
        public void onNothingSelected(AdapterView<?> arg0) {
        }
        @Override
        public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2,
                long arg3) {
            onItemSelected(arg0, arg1, arg2, arg3, holder);
        }
        
        public abstract void onItemSelected(AdapterView<?> arg0, View arg1, int arg2,long arg3,ViewHolder holder);
    }
    
    private abstract class MyTextWatcher implements TextWatcher{
        private ViewHolder mHolder;
        
        public MyTextWatcher(ViewHolder holder) {
            this.mHolder=holder;
        }
        
        @Override
        public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
                int arg3) {
        }
        @Override
        public void onTextChanged(CharSequence arg0, int arg1, int arg2,
                int arg3) {
        }
        @Override
        public void afterTextChanged(Editable s) {
            afterTextChanged(s, mHolder);
        }
        public abstract void afterTextChanged(Editable s,ViewHolder holder);
    }
    
    private abstract class MyOnClickListener implements OnClickListener{
        
        private ViewHolder mHolder;
        
        public MyOnClickListener(ViewHolder holder) {
            this.mHolder=holder;
        }
        
        @Override
        public void onClick(View v) {
            onClick(v, mHolder);
        }
        public abstract void onClick(View v,ViewHolder holder);
        
    }
    private class ViewHolder{
        TextView tv_position;
        Spinner sp_type;
        EditText et_number;
        Button btn_delete;
    }
    
    //删除操作回调
    public interface OnListRemovedListener{
        public void onRemoved();
    }
    
}
仔细看,其实只是对每一个可点击的事件重写了一遍,与原来不同的是,这里多了一个ViewHolder,为什么需要这个,因为这里面存储了每一个Item的Position信息.这样,就可以对item进行准确操作.从而不会发生错乱.

5.打开MainActivity.java
public class MainActivity extends ActionBarActivity implements OnClickListener,OnItemSelectedListener,OnListRemovedListener {
    private List<NumberInfo> list=new ArrayList<NumberInfo>();
    
    ListView lv;
    Button btn_addRow;
    MyAdapter mAdapter;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn_addRow=(Button) findViewById(R.id.btn_addRow);
        btn_addRow.setOnClickListener(this);
        
        lv=(ListView) findViewById(R.id.lv);
        NumberInfo n=new NumberInfo();
        n.setNumber("1");
        n.setType("其他");
        list.add(n);
        
        
        mAdapter=new MyAdapter(list, this);
        lv.setAdapter(mAdapter);
        mAdapter.setOnListRemovedListener(this);
    }
    @Override
    public void onClick(View v) {
        if(v.getId()==R.id.btn_addRow){
            NumberInfo n=new NumberInfo();
            n.setNumber("");
            n.setType("手机");
            mAdapter.addItem(n);
            mAdapter.notifyDataSetChanged();
        }
    }
    @Override
    public void onRemoved() {
        mAdapter.notifyDataSetChanged();
    }
    @Override
    public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2,
            long arg3) {
        
    }
    @Override
    public void onNothingSelected(AdapterView<?> arg0) {
        
    }

}

运行结果:

从此ListView再也不会错乱.
 



android ListView与EditText共存错位的更多相关文章

  1. [问题]Android listView item edittext 不能调用软键盘输入法

    android listview item edittext not  softkeyboard edittext可以获取焦点, 可以触发事件, 但是就是不能调用输入法, 不知道为什么? 难道不能在i ...

  2. 解决Android ListView 和 ScrollView 共存时冲突 问题 方法其一

    转载请注明出处: http://www.goteny.com/articles/2013/11/8.html http://www.cnblogs.com/zjjne/p/3428480.html 当 ...

  3. Android ListView用EditText实现搜索功能

    前言 最近在开发一个IM项目的时候有一个需求就是,好友搜索功能.即在EditText中输入好友名字,ListView列表中动态展示刷选的好友列表.我把这个功能抽取出来了,先贴一下效果图: 分析 在查阅 ...

  4. 【转】Android开发之ListView+EditText-要命的焦点和软键盘问题解决办法

    Android开发之ListView+EditText-要命的焦点和软键盘问题解决办法 [原文链接] 这篇文章完美的解决了我几个月没结论的bug... 感谢热爱分享的技术达人~ 我是怎么走进这个大坑的 ...

  5. Android ListView getView()方法重复调用导致position错位

    问题现状:Android ListView getView()方法重复调用导致position错位 解决办法:把ListView布局文件的layout_height属性改为fill_parent或者m ...

  6. [Android分享] 【转帖】Android ListView的A-Z字母排序和过滤搜索功能

      感谢eoe社区的分享   最近看关于Android实现ListView的功能问题,一直都是小伙伴们关心探讨的Android开发问题之一,今天看到有关ListView实现A-Z字母排序和过滤搜索功能 ...

  7. 【转】android ListView 几个重要属性

    android ListView 几个重要属性 分类: Android2012-03-08 19:25 19324人阅读 评论(5) 收藏 举报 listviewandroid活动javalistnu ...

  8. android ListView 中getview学习总结

    最近在做android相关的开发,ListView中有一个图片错位的问题,今天查了很多人写的一些东西,所以记录下来,算是一种加深理解吧. ListView是一个非常常用的控件,功能可以扩展的很丰富,而 ...

  9. android ListView的介绍和优化

    xml设计 <?xml version="1.0"?> -<RelativeLayout tools:context=".MainActivity&qu ...

随机推荐

  1. <strong>和 <b> 的区别

    前几天,看到这样的一个笑话:甲:“我精通前端开发”,乙:“strong和b的区别是什么?” 甲:.... 其实我也搞不清有什么区别,因此我整理了一下: 一.为什么会有这样一个问题 我们在一个没有附加式 ...

  2. PEP8 常用规范

    PEP8 常用规范 完整的规范移步这里两个传送门 pep8规范 官方文档:https://www.python.org/dev/peps/pep-0008/ PEP8中文翻译:http://www.c ...

  3. TCP心跳的意义

    摘自:https://blog.csdn.net/bjrxyz/article/details/71076442 TCP新手误区–心跳的意义 背景 最近面试了很多的学生,发现很多TCP的新手对于TCP ...

  4. 破解weblogic(数据库)密码

    破解weblogic(数据库)密码所需步骤 注意:本例子本人以本地weblogic为列,必须已经安装weblogic 1.需要问题件 1>.数据源配置文件HKS***-****-jdbc.xml ...

  5. C#基础-hashtable,泛型和字典集合

    hashtable 的存储方式 使用方法: 1.引入包含Hashtable的命名空间 using System.Collections; // 引入Hash所在的命名空间 2.往hash表里面添加数据 ...

  6. JAVA / MySql 编程——第二章 初始MySQL

    1. MySQL:        ●  MySQL是一个关系型数据库管理系统,由瑞典MySQL AB公司开发,目前属于Oracle公司.            MySQL最流行的关系型数据库管理系统, ...

  7. FreeBSD--网络配置

    配置网口:ifconfig |less dc0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500         i ...

  8. 动态代理和AOP

    之前说过了我对IOC的理解,这篇文章说以下我对动态代理和基本的对AOP的理解. 所谓动态代理就是,在运行时,动态创建实现了一组指定接口的实现类对象. 比如有: interface A { } inte ...

  9. html5的canvas绘制线条,moveTo和lineTo详解

    今天在看html5,里面新增的属性有一个canvas,它相当于一个画布你可以用js在里面画你想要的效果!我在w3c的手册里面看到用moveTo和lineTo绘制线条讲的不是很清楚,尤其是moveTo和 ...

  10. 【Kaggle】泰坦尼克号

    引言 Kaggle官方网站 这是泰坦尼克号事件的基本介绍: 我们需要做的就是通过给出的数据集,通过对特征值的分析以及运用机器学习模型,分析什么样的人最可能存活,并给出对测试集合的预测. 对于Kaggl ...