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;
}
}
Ответы
Ответ 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;
}
}
Ответ 3
возможно, вы можете попробовать это или увидеть справа раздел связанных должностей
EditText теряет содержимое при прокрутке в ListView
Ответ 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);
}
}