Подтвердить что ты не робот

EditText теряет содержимое при прокрутке в ListView?

У меня есть элемент списка с EditText, я не знаю, сколько будет элементов. У меня проблема, когда я ввожу какой-то текст в EditText, а затем прокручиваю вниз ListView, после того, как я снова прокручиваю вверх, в моем первом EditText нет текста, или есть какой-то текст из другого EditText из ListView.

Я пробовал TextWatcher и сохранял данные в массив, но проблема в том, что возвращаемая позиция обзора в ListView не всегда правильная, поэтому я потерял некоторые данные из массива.

Вот мой код:

public class EfficientAdapter extends BaseAdapter {

    private LayoutInflater mInflater;
    public String[] Current;
    ArrayList<String> MeterName, PreviousReading, Current_Reading;
    JSONArray getArray_Meter_Reading;

    public EfficientAdapter(Context context, JSONArray getArray_Meter_Reading) {
        mInflater = LayoutInflater.from(context);
        this.getArray_Meter_Reading = getArray_Meter_Reading;
        MeterName = new ArrayList<String>();
        PreviousReading = new ArrayList<String>();
        for (int i = 0; i < getArray_Meter_Reading.length(); i++) {
            try {
                String Meter_Name = getArray_Meter_Reading.getJSONObject(i)
                        .getString("MeterName").toString();
                String previous_Meter_Reading = getArray_Meter_Reading
                        .getJSONObject(i).getString("PrevMeterReading")
                        .toString();
                MeterName.add(Meter_Name);
                PreviousReading.add(previous_Meter_Reading);

                // Meter[i]=MeterName.get(i);
                // Previous[i]=PreviousReading.get(i);
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    public int getCount() {

        return getArray_Meter_Reading.length();
    }

    public Object getItem(int position) {
        // TODO Auto-generated method stub
        return position;
    }

    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return position;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        final ViewHolder holder;

        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.meter_reading_list, null);
            holder = new ViewHolder();
            holder.adp_MeterName = (TextView) convertView
                    .findViewById(R.id.txt_Meter_Name);
            holder.adp_Previous = (TextView) convertView
                    .findViewById(R.id.txt_Previous);
            holder.adp_Current = (EditText) convertView
                    .findViewById(R.id.ed_Current);

            holder.adp_Current.addTextChangedListener(new TextWatcher() {

                public void onTextChanged(CharSequence s, int start,
                        int before, int count) {

                }

                public void beforeTextChanged(CharSequence s, int start,
                        int count, int after) {
                    // TODO Auto-generated method stub

                }

                public void afterTextChanged(Editable s) {

                    Current[holder.ref] = s.toString();

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

        holder.ref = position;
        holder.adp_MeterName.setText(MeterName.get(position));
        holder.adp_Previous.setText(PreviousReading.get(position));
        // holder.adp_Current.setHint(MeterName.get(position));

        // holder.adp_Current.setText(PreviousReading.get(position));

        return convertView;
    }

    class ViewHolder {
        TextView adp_MeterName, adp_Previous;
        EditText adp_Current;
        int ref;

    }

}
4b9b3361

Ответ 1

попробуйте следующее:

public class EfficientAdapter extends BaseAdapter {

private LayoutInflater mInflater;
public String[] Current;
ArrayList<String> MeterName, PreviousReading, Current_Reading;
JSONArray getArray_Meter_Reading;
public static HashMap<Integer,String> myList=new HashMap<Integer,String>();

public EfficientAdapter(Context context, JSONArray getArray_Meter_Reading) {
    mInflater = LayoutInflater.from(context);
    this.getArray_Meter_Reading = getArray_Meter_Reading;
    MeterName = new ArrayList<String>();
    PreviousReading = new ArrayList<String>();

    for (int i = 0; i < getArray_Meter_Reading.length(); i++) {
        try {
            String Meter_Name = getArray_Meter_Reading.getJSONObject(i)
                    .getString("MeterName").toString();
            String previous_Meter_Reading = getArray_Meter_Reading
                    .getJSONObject(i).getString("PrevMeterReading")
                    .toString();
            MeterName.add(Meter_Name);
            PreviousReading.add(previous_Meter_Reading);

            // Meter[i]=MeterName.get(i);
            // Previous[i]=PreviousReading.get(i);
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    // initialize myList
    for(int i=0;i<JSON_ARRAY_LENGTH;i++)
    {
       myList.put(i,"");
    }
}

public int getCount() {

    return getArray_Meter_Reading.length();
}

public Object getItem(int position) {
    // TODO Auto-generated method stub
    return position;
}

public long getItemId(int position) {
    // TODO Auto-generated method stub
    return position;
}

public View getView(int position, View convertView, ViewGroup parent) {
    final ViewHolder holder;
    final int pos=position;
    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.meter_reading_list, null);
        holder = new ViewHolder();
        holder.adp_MeterName = (TextView) convertView
                .findViewById(R.id.txt_Meter_Name);
        holder.adp_Previous = (TextView) convertView
                .findViewById(R.id.txt_Previous);
        holder.adp_Current = (EditText) convertView
                .findViewById(R.id.ed_Current);


        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }
     holder.adp_Current.addTextChangedListener(new TextWatcher() {

            public void onTextChanged(CharSequence s, int start,
                    int before, int count) {

            }

            public void beforeTextChanged(CharSequence s, int start,
                    int count, int after) {
                // TODO Auto-generated method stub

            }

            public void afterTextChanged(Editable s) {

                Current[holder.ref] = s.toString();
                myList.put(pos,s.toString.trim());
            }
        });
    holder.ref = position;
    holder.adp_MeterName.setText(MeterName.get(position));
    holder.adp_Previous.setText(PreviousReading.get(position));
    // holder.adp_Current.setHint(MeterName.get(position));

    // holder.adp_Current.setText(PreviousReading.get(position));

    holder.adp_Current.setText(myList.get(position));

    return convertView;
}

class ViewHolder {
    TextView adp_MeterName, adp_Previous;
    EditText adp_Current;
    int ref;

}

}

Здесь я включил объект HashMap, который будет следить за тем, имеет ли значение EditText значение или нет. И когда вы прокручиваете список, он будет отображаться снова, вызвав метод getView вместе с текстом, связанным с каждым редактором.

В этом коде, когда вы сначала загружаете listview, все ваши edittext будут без text.once, вы вводите какой-то текст, это будет отмечено в myList.So, когда вы снова визуализируете список, ваш текст будет предотвращен.

Еще одна вещь, вы должны реализовать textwatcher вне if (convertView == null).. else.. block.That лучше практика!

Ответ 2

У меня была такая же проблема с проектом, над которым я работал. Все найденные мной решения также упоминались с использованием textChangeListener, однако из-за характера списка и с EditText в каждом представлении строк это было очень неэффективно. Я сделал отдельный подход, используя EditText.setOnFocusChangeListener().

Я привязал это к каждому EditText в методе getView. Причина, по которой это работает так хорошо, называется вызовом, когда пользователь переключается на другой edittext или свитки, поэтому текущая строка находится на экране, что приводит к потере фокуса EditText.

В onFocusChange (View v, boolean hasFocus) внутри слушателя я просто поставил:

if (!hasFocus) {
                EditText et = (EditText) v.findViewById(R.id.groupAmount);                  
                data.get(position).put("dueAmount", et.getText().toString().trim());
            }

В моем примере я сохраняю введенное значение в свои данные, используемые для заполнения представлений при каждом вызове getView, но это все равно должно показать, как получить доступ к данным, введенным пользователем. Просто убедитесь, что вы пытаетесь взять эти сохраненные данные и попробуйте заполнить editText в соответствующей позиции.

Надеюсь, что это поможет.

Проводка моего полного адаптера для справки

public class memberlistadapter extends BaseAdapter {
private LayoutInflater mInflater;
public ArrayList<Hashtable<String, String>> data;
ViewHolder viewHolder;
public static HashMap<Integer,String> myList=new HashMap<Integer,String>();

public memberlistadapter(Context context) {
    mInflater = LayoutInflater.from(context);
}

public memberlistadapter(Activity activity, ArrayList<Hashtable<String, String>> objects) {
    super();
    mInflater = activity.getLayoutInflater();
    //this.activity = activity;
    this.data = objects;
    Log.d("data", data.toString());
}

public void clear() {
    this.data.clear();
    viewHolder = null;
}

public void setData(ArrayList<Hashtable<String, String>> data) {
    this.data = data;
}

public int getCount() {
    return data.size();
}

public Object getItem(int item) {
    return data.get(item);
}

public long getItemId(int position) {
    return position;
}

public View getView(final int position, View convertView, ViewGroup parent) {
    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.member_amount_child, null);
        viewHolder = new ViewHolder();

        viewHolder.nameText = (TextView) convertView.findViewById(R.id.grp_amt_child);
        viewHolder.amountText = (EditText) convertView.findViewById(R.id.groupAmount);
        viewHolder.checkBox = (CheckBox) convertView.findViewById(R.id.memberCheckNotif);

        convertView.setTag(viewHolder);

    } else {
        viewHolder = (ViewHolder) convertView.getTag();
    }
    //Log.d("data at "+position, data.get(position).toString());
    String amt = data.get(position).get("dueAmount");
    String name = data.get(position).get("name");
    String check = data.get(position).get("reminder");

    viewHolder.nameText.setText(name);
    try {
    if (amt.length() > 0 && !amt.equalsIgnoreCase("0")) {
        viewHolder.amountText.setText(amt);
    } else {
        viewHolder.amountText.setText("");
    }
    } catch (Exception e) {
        viewHolder.amountText.setText("");
    }

    viewHolder.amountText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
        public void onFocusChange(View v, boolean hasFocus) {
            if (!hasFocus) {
                EditText et = (EditText) v.findViewById(R.id.groupAmount);
                data.get(position).put("dueAmount", et.getText().toString().trim());
            }
        }
    });

    try {
    if (check.equalsIgnoreCase("true")) {
        viewHolder.checkBox.setChecked(true);
    } else {
        viewHolder.checkBox.setChecked(false);
    }
    } catch (Exception e) {
        viewHolder.checkBox.setChecked(false);
    }
    viewHolder.checkBox.setOnClickListener(new View.OnClickListener() {

        public void onClick(View v) {
            if (((CheckBox) v).isChecked()) {
                data.get(position).put("reminder", "True");
            } else {
                data.get(position).put("reminder", "False");
            }
        }
    });
    if (position == 0) {
        viewHolder.checkBox.setVisibility(View.GONE);
        viewHolder.amountText.setVisibility(View.GONE);
        viewHolder.nameText.setVisibility(View.GONE);
    } else {
        viewHolder.checkBox.setVisibility(View.VISIBLE);
        viewHolder.amountText.setVisibility(View.VISIBLE);
        viewHolder.nameText.setVisibility(View.VISIBLE);
    }

    return convertView;
}

static class ViewHolder {
    TextView nameText;
    EditText amountText;
    CheckBox checkBox;
}
}

Ответ 4

Сначала объявите переменную-член String[] или List<String> (внутри класса вне getView()) для хранения входного текста из объекта EditText и запишите текст в addTextChangeListener(), который вы установили для объекта EditText.

Во-вторых, поместите свой setText() после (не внутри) addTextChangeListener().

    viewHolder.editText.removeTextChangedListener(viewHolder.textWatcher);

    viewHolder.textWatcher = new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        }

        @Override
        public void afterTextChanged(Editable editable) {
            mInputs[position] = editable.toString();            //record input

            viewHolder.editText.setSelection(viewHolder.editText.getText().length());       //set cursor to the end
        }
    };

    viewHolder.editText.addTextChangedListener(viewHolder.textWatcher);
    viewHolder.editText.setText(mInputs[position]);

private class ViewHolder {
    EditText editText;
    TextWatcher textWatcher;

    public ViewHolder(View itemView) {
        editText = itemView.findViewById(R.id.main_editText);
    }
}