ListView 中的 EditText 没有它回收输入 [英] EditText in ListView without it recycling input

查看:21
本文介绍了ListView 中的 EditText 没有它回收输入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

仍然是 android 的新手,甚至是自定义光标适配器的新手,所以我无法理解如何防止我的列表视图回收视图以防止滚动时来自一个编辑文本的输入显示在另一个中.我在其他帖子上看到说要更改 convertview 的名称,但是如何做到这一点我是空白的.我希望这里有人能够根据我迄今为止编写的代码提供更多详细信息或示例.

Still new to android and even more to custom cursor adapter so I'm having trouble understanding how to prevent my listview from recycling views to prevent input from one edittext to show up in another when scrolled. I've seen on other post saying to change the name of convertview but how to do that I'm drawing a blank. I was hoping someone here would be able to give more details or example of how to do based of what code I've wrote so far.

public class editview extends ListActivity {
    private dbadapter mydbhelper;
    private PopupWindow pw;
    public static int editCount;
    public static ListView listView;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mydbhelper = new dbadapter(this);
        mydbhelper.open();


        View footer = getLayoutInflater().inflate(R.layout.footer_layout, null);
        ListView listView = getListView();
        listView.addFooterView(footer);
        showResults();
        }

    //Populate view
    private void showResults (){
        Cursor cursor = mydbhelper.getUserWord();
        startManagingCursor(cursor);
        String[] from = new String[] {dbadapter.KEY_USERWORD};
         int[] to = new int[] {R.id.textType};
         ItemAdapter adapter = new ItemAdapter(this, R.layout.edit_row, cursor,
                        from, to);
            adapter.notifyDataSetChanged();
            this.setListAdapter(adapter);
            editCount = adapter.getCount();

    }


            //footer button
            public void onClick(View footer){
                    final MediaPlayer editClickSound = MediaPlayer.create(this, R.raw.button50);
                    editClickSound.start();
                    startActivity(new Intent("wanted.pro.madlibs.OUTPUT"));

                }

//custom cursor adapter
class ItemAdapter extends SimpleCursorAdapter {
    private LayoutInflater mInflater;
    private Cursor cursor;


    public ItemAdapter(Context context, int layout, Cursor cursor, String[] from,
            int[] to) {
        super(context, layout, cursor, from, to);
        this.cursor = cursor;
        mInflater = LayoutInflater.from(context);

    }


    static class ViewHolder {
        protected TextView text;
        protected EditText edittext;

    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {


        ViewHolder holder;
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.edit_row, null);


             holder = new ViewHolder();
            holder.text = (TextView) convertView.findViewById(R.id.textType);
            holder.edittext = (EditText) convertView.findViewById(R.id.editText);



            convertView.setTag(holder);

        } else {
            holder = (ViewHolder) convertView.getTag();

        }
        cursor.moveToPosition(position);
        int label_index = cursor.getColumnIndex("userword"); 
        String label = cursor.getString(label_index);

        holder.text.setText(label);

        return convertView;

    }

}

改成

class ItemAdapter extends SimpleCursorAdapter {
    private LayoutInflater mInflater;
    private Cursor cursor;
    Map<Integer, String> inputValues = new HashMap<Integer, String>();
    public View getView(final int position, View convertView, ViewGroup parent) {
        ....

        ViewHolder holder;
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.edit_row, null);


             holder = new ViewHolder();
            holder.text = (TextView) convertView.findViewById(R.id.textType);
            holder.edittext = (EditText) convertView.findViewById(R.id.editText);


            convertView.setTag(holder);

        } else {
            holder = (ViewHolder) convertView.getTag();

        }
        cursor.moveToPosition(position);
        int label_index = cursor.getColumnIndex("userword"); 
        String label = cursor.getString(label_index);

        holder.text.setText(label);
        String oldText =  inputValues.get(position);
        holder.edittext.setText(oldText == null ? "" : oldText); 
        holder.edittext.addTextChangedListener(new TextWatcher(){
            public void afterTextChanged(Editable editable) {
                inputValues.put(position, editable.toString());
            }

但在所有edittext都有数据之后它正在回收.尝试使用 holder.edittext.setText(oldText) 但效果相同.

but it is recycling after all edittext have data. Tried using holder.edittext.setText(oldText) but same effect.

推荐答案

首先,你真的不想阻止列表视图回收它的视图.视图回收是一个巨大的优化.有关列表的许多非常好的信息,请参阅 google IO 演讲:http://www.youtube.com/watch?v=wDBM6wVEO70

First of all, you really don't want to prevent a list view from recycling its views. View recycling is a huge optimization. For a lot of really good info on lists, see the google IO talk: http://www.youtube.com/watch?v=wDBM6wVEO70

话虽如此,您已经正确地确定了您的问题:您的 EditTexts 比您列表中的项目少得多.当您滚动浏览列表时,这些 EditTexts 会被回收,因此您会一遍又一遍地看到相同的输入.

That being said, you've correctly identified your problem: You have far fewer EditTexts than you do items in your list. As the you scroll through the list those EditTexts are recycled so you see the same input over and over again.

基本上,您需要做的是将 EditTexts 的输入保存在某些数据结构中(如果他们只编辑几个值,则为 HashMap,如果他们将更改大部分值,则可能是 List,两者都可以)映射输入的位置.您可以通过将 textChangedListener 添加到 getView 中的编辑文本来做到这一点:

Basically what you need to do is save the input for your EditTexts in some datastructure (a HashMap if they will only edit a few values, maybe a List if they will be changing most of the values, either would work) that maps the position to the input. You can do this by adding a textChangedListener to your edit texts in getView:

@Override
public View getView(final int position, View convertView, ViewGroup parent){
    ...
    cursor.moveToPosition(position);
    int label_index = cursor.getColumnIndex("userword");
    String label = cursor.getString(label_index);

    holder.text.setText(label);

    //clear whatever text was there from some other position
    //and set it to whatever text the user edited for the current 
    //position if available
    String oldText = yourMapOfPositionsToValues.get(position);
    holder.setText(oldText == null ? "" : oldText); 

    //every time the user adds/removes a character from the edit text, save 
    //the current value of the edit text to retrieve later
    holder.edittext.addTextChangedListener(new TextWatcher(){
        @Override
        public void afterTextChanged(Editable editable) {
            yourMapOfPositionsToValues.put(position, editable.toString());
        }
        ....
    };

    return convertView;
}

每当您的用户完成编辑后,您就可以遍历您的数据结构并对这些值执行任何操作.

Whenever your user is done editing, you can run through your datastructure and do whatever with those values.

我将 onTextChanged 更改为 afterTextChanged,因为我以前使用过它并且我知道它有效.请记住,每次 LETTER 更改时都会调用 afterTextChanged,而不仅仅是在用户输入完一个单词之后.如果用户键入dog" afterTextChanged 将被调用 3 次,首先是 'd',然后是 'do',然后是 'dog'.

I changed onTextChanged to afterTextChanged because I've used that before and I know it works. Keep in mind that afterTextChanged is called every time a LETTER changes, not just after the user finishes typing a word. If the user types "dog" afterTextChanged will be called three times, first with 'd', then with 'do', then with 'dog'.

HashMap 很简单:Map yourMapOfPositionsToValues = new HashMap();

A HashMap is simple: Map yourMapOfPositionsToValues = new HashMap();

添加或更新项目:yourMap.put(position, someText);获取项目:yourMap.get(position);

to add or update an item: yourMap.put(position, someText); to fetch an item: yourMap.get(position);

如果哈希图没有意义,请花一些时间研究它们.它们是非常重要的数据结构.

if hashmaps don't make sense, spend some time researching them. They are an incredibly important data structure.

您的 TextWatcher 实现不正确.您的数据结构不应属于单个视图,而应属于活动或适配器.在您看来,职位并不稳定,因为您的 List 归每个视图所有.位置本身是稳定的,除非基础数据发生变化,否则光标每次都会为相同的位置返回相同的数据.但是,编辑文本用于多个不同的位置.

Your TextWatcher implementation is incorrect. Your data structure should not belong to a single view, but rather the activity or your adapter. It appears to you that positions aren't stable because your List is owned by each view. The positions themselves are stable in that unless the underlying data changes the cursor will return the same data every time for the same position. However, the edit text is used for multiple different positions.

创建一个哈希图作为我在上面在适配器的构造函数中演示的实例变量.然后正好加上我原来写的TextWatcher,不需要命名类,匿名更简单.您的代码应该可以工作.

Create a hashmap as an instance variable I demonstrated above in the constructor of your adapter. Then add exactly the TextWatcher I wrote originally, no need for a named class, anonymous is simpler. Your code should work.

这篇关于ListView 中的 EditText 没有它回收输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆