zoukankan      html  css  js  c++  java
  • android ListView与EditText共存错位

    在一个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_itemSPINNER_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.itemnull);
                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(listthis);
            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再也不会错乱.
     







    qq3061280@163.com
  • 相关阅读:
    PHP $_SERVER['HTTP_REFERER'] 获取前一页面的 URL 地址
    LAMP与LNMP架构的区别及其具体的选择说明
    LNMP 与 LAMP 架构的区别及配置解决方案
    LAMP和LNMP,你更愿意选择谁,为什么?
    Storm流计算从入门到精通之技术篇(高并发策略、批处理事务、Trident精解、运维监控、企业场景)
    Zookeeper从入门到精通(开发详解,案例实战,Web界面监控)
    基于Greenplum Hadoop分布式平台的大数据解决方案及商业应用案例剖析
    深入浅出Hive企业级架构优化、Hive Sql优化、压缩和分布式缓存(企业Hadoop应用核心产品)
    深入浅出OpenStack云计算平台管理(nova-compute/network)
    玩转大数据:深入浅出大数据挖掘技术(Apriori算法、Tanagra工具、决策树)
  • 原文地址:https://www.cnblogs.com/aibuli/p/d8d7b51178969492b0f544b78ca0b4d1.html
Copyright © 2011-2022 走看看