无法从 Listview 的 EditText 中获取值?
Posted
技术标签:
【中文标题】无法从 Listview 的 EditText 中获取值?【英文标题】:Can't get values from Listview's EditText? 【发布时间】:2017-01-03 03:33:40 【问题描述】:我正在尝试从我的 Listview 中的 EditText 获取数据。我看到了很多类似的问题并得到了solution。但它在我的实现中引发了 NPE。
所以请指导我解决这个问题。
适配器
public class Coscho_adapter extends BaseAdapter
Context con;
ArrayList<HashMap<String, String>> list;
LayoutInflater mInflater;
EditText marks;
TextView studname, acname;
public Coscho_adapter(Context co, ArrayList<HashMap<String, String>> list1)
list = list1;
con = co;
mInflater = (LayoutInflater) con.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
@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(final int position, View convertView, ViewGroup parent)
ViewHolder holder;
if(convertView==null)
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.sc_item,null,false);
holder.marks = (EditText) convertView.findViewById(R.id.marks);
holder.studname = (TextView) convertView.findViewById(R.id.stu_name);
holder.acname = (TextView) convertView.findViewById(R.id.act_name);
convertView.setTag(holder);
else
holder = (ViewHolder) convertView.getTag();
int sno = position + 1;
holder.studname.setText(sno + ". " + list.get(position).get("DESCRIPTOR"));
holder.acname.setVisibility(View.GONE);
holder.marks.setText(list.get(position).get("STUDENT_MARK"), TextView.BufferType.EDITABLE);
int maxLength = 1;
holder.marks.setFilters(new InputFilter[] new InputFilter.LengthFilter(maxLength), new InputFilterMinMax("0", "5"));
desc_ids.add(list.get(position).get("DESCRIPTOR_ID"));
return convertView;
class ViewHolder
EditText marks;
TextView studname, acname;
点击
@Override
public boolean onOptionsItemSelected(MenuItem item)
if(item.getItemId()==R.id.add)
View v;
ArrayList<String> scho = new ArrayList<String>();
EditText et;
if (co_adapter.getCount() != 0)
for (int i = 0; i < co_adapter.getCount(); i++)
v = mListView.getChildAt(i);
et = (EditText) v.findViewById(R.id.marks);
if (et != null)
scho.add(et.getText().toString());
Log.e("SCH", et.getText().toString());
return super.onOptionsItemSelected(item);
使用 TextWatcher 更新
现在我可以将编辑文本的值存储在一个数组中。但是当列表视图滚动时。这些值将更改为初始值。
public class Coscho_adapter extends BaseAdapter
Context con;
LayoutInflater mInflater;
public Scholastic_adapter(Context context, ArrayList<HashMap<String, String>> list1)
sadap_list = list1;
con = context;
mInflater = LayoutInflater.from(context);
@Override
public int getCount()
return sadap_list.size();
@Override
public Object getItem(int position)
return null;
@Override
public long getItemId(int position)
return position;
@Override
public View getView(final int position, View convertView, ViewGroup parent)
ViewHolder holder;
if(convertView==null)
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.sc_item,null,false);
holder.marks = (EditText) convertView.findViewById(R.id.marks);
holder.studname = (TextView) convertView.findViewById(R.id.stu_name);
holder.acname = (TextView) convertView.findViewById(R.id.act_name);
convertView.setTag(holder);
else
holder = (ViewHolder) convertView.getTag();
for (int i = 0; i < arrScMarks.length; i++)
Log.e("Array > ", i +"> "+ arrScMarks[i]);
int sno = position + 1;
holder.ref = position;
holder.studname.setText(sno + ". " + sadap_list.get(holder.ref).get("FIRST_NAME"));
holder.acname.setText(sadap_list.get(holder.ref).get("ACTIVITY_NAME"));
holder.marks.setText(arrScMarks[holder.ref]);
holder.marks.addTextChangedListener(new GenericTextWatcher(holder.ref));
return convertView;
class ViewHolder
EditText marks;
TextView studname, acname;
int ref;
TextWatcher
private class GenericTextWatcher implements TextWatcher
int position;
private GenericTextWatcher(int pos)
this.position = pos;
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2)
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2)
public void afterTextChanged(Editable editable)
String text = editable.toString();
arrScMarks[position] = text;
Log.e("Watcher > ", position +"> "+ arrScMarks[position] );
LOGCAT
输入数据
09-01 05:37:59.658 2466-2466/app E/Watcher >: 1>
09-01 05:38:00.638 2466-2466/app E/Watcher >: 1> 1
09-01 05:38:02.518 2466-2466/app E/Watcher >: 2>
09-01 05:38:02.798 2466-2466/app E/Watcher >: 2> 2
09-01 05:38:04.478 2466-2466/app E/Watcher >: 3>
09-01 05:38:05.318 2466-2466/app E/Watcher >: 3> 3
09-01 05:38:06.878 2466-2466/app E/Watcher >: 4>
09-01 05:38:07.758 2466-2466/app E/Watcher >: 4> 4
09-01 05:38:09.928 2466-2466/app E/Watcher >: 5>
09-01 05:38:10.278 2466-2466/app E/Watcher >: 5> 5
滚动时
09-01 05:48:49.188 16362-16362/app E/Watcher >: 0> 0
09-01 05:48:49.538 16362-16362/app E/Watcher >: 1> 0
09-01 05:48:49.708 16362-16362/app E/Watcher >: 2> 0
09-01 05:48:49.888 16362-16362/app E/Watcher >: 3> 0
09-01 05:48:50.268 16362-16362/app E/Watcher >: 4> 0
09-01 05:48:50.538 16362-16362/app E/Watcher >: 5> 0
09-01 05:48:50.558 16362-16362/app E/Watcher >: 6> 0
09-01 05:48:50.868 16362-16362/app E/Watcher >: 8> 0
09-01 05:48:52.708 16362-16362/app E/Watcher >: 9> 0
09-01 05:48:52.768 16362-16362/app E/Watcher >: 0> 0
09-01 05:48:52.768 16362-16362/app E/Watcher >: 10> 0
09-01 05:49:20.648 16362-16362/app E/Watcher >: 9> 0
09-01 05:49:20.648 16362-16362/app E/Watcher >: 18> 0
09-01 05:49:20.738 16362-16362/app E/Watcher >: 8> 0
09-01 05:49:20.738 16362-16362/app E/Watcher >: 17> 0
09-01 05:49:20.818 16362-16362/app E/Watcher >: 7> 0
09-01 05:49:20.888 16362-16362/app E/Watcher >: 5> 0
09-01 05:49:20.888 16362-16362/app E/Watcher >: 15> 0
09-01 05:49:20.898 16362-16362/app E/Watcher >: 4> 0
09-01 05:49:20.898 16362-16362/app E/Watcher >: 14> 0
09-01 05:49:20.968 16362-16362/app E/Watcher >: 3> 0
09-01 05:49:20.968 16362-16362/app E/Watcher >: 13> 0
09-01 05:49:21.068 16362-16362/app E/Watcher >: 6> 0
09-01 05:49:21.068 16362-16362/app E/Watcher >: 16> 0
09-01 05:49:22.008 16362-16362/app E/Watcher >: 1> 0
09-01 05:49:22.008 16362-16362/app E/Watcher >: 11> 0
09-01 05:49:22.058 16362-16362/app E/Watcher >: 0> 0
09-01 05:49:22.058 16362-16362/app E/Watcher >: 10> 0
09-01 05:49:22.058 16362-16362/app E/Watcher >: 10> 0
09-01 05:49:22.098 16362-16362/app E/Watcher >: 9> 0
09-01 05:49:22.098 16362-16362/app E/Watcher >: 18> 0
09-01 05:49:22.108 16362-16362/app E/Watcher >: 9> 0
滚动后重新输入值时
09-01 05:56:32.288 16362-16362/app E/Watcher >: 1>
09-01 05:56:32.288 16362-16362/app E/Watcher >: 10>
09-01 05:56:32.288 16362-16362/app E/Watcher >: 10>
09-01 05:56:32.288 16362-16362/app E/Watcher >: 1>
09-01 05:56:33.438 16362-16362/app E/Watcher >: 1> 1
09-01 05:56:33.438 16362-16362/app E/Watcher >: 10> 1
09-01 05:56:33.438 16362-16362/app E/Watcher >: 10> 1
09-01 05:56:33.438 16362-16362/app E/Watcher >: 1> 1
09-01 05:56:34.918 16362-16362/app E/Watcher >: 11>
09-01 05:56:34.918 16362-16362/app E/Watcher >: 2>
09-01 05:56:36.248 16362-16362/app E/Watcher >: 11> 2
09-01 05:56:36.248 16362-16362/app E/Watcher >: 2> 2
09-01 05:56:37.918 16362-16362/app E/Watcher >: 3>
09-01 05:56:37.918 16362-16362/app E/Watcher >: 12>
09-01 05:56:37.918 16362-16362/app E/Watcher >: 3>
09-01 05:56:39.008 16362-16362/app E/Watcher >: 3> 3
09-01 05:56:39.008 16362-16362/app E/Watcher >: 12> 3
09-01 05:56:39.008 16362-16362/app E/Watcher >: 3> 3
【问题讨论】:
从堆栈跟踪中可以清楚地看出,从mListView.getChildAt(i)
返回的视图为空
参考android - listview get item view by position
请在下面查看我的答案
我认为getItemId
的方法是错误的。你也可以发布errorlog
。
@Soham 请检查 Logcat。
【参考方案1】:
我首先尝试的方法是将 TextChangedListener 添加到 holder.marks,或者您可以添加一个按钮来保存输入到 EditText 中的新值。
当文本更改时,我会更改列表中的值。如果没有这个,当列表滚动为这一行时,您将失去数据用户:
holder.marks.setText(list.get(position).get("STUDENT_MARK"), TextView.BufferType.EDITABLE);
将重写原来在列表中的学生标记。
编辑:我将我找到的适配器代码放在链接中,以防将来不可用。
private class MyListAdapter extends BaseAdapter
@Override
public int getCount()
// TODO Auto-generated method stub
if(arrText != null && arrText.length != 0)
return arrText.length;
return 0;
@Override
public Object getItem(int position)
// TODO Auto-generated method stub
return arrText[position];
@Override
public long getItemId(int position)
// TODO Auto-generated method stub
return position;
@Override
public View getView(int position, View convertView, ViewGroup parent)
//ViewHolder holder = null;
final ViewHolder holder;
if (convertView == null)
holder = new ViewHolder();
LayoutInflater inflater = ListviewActivity.this.getLayoutInflater();
convertView = inflater.inflate(R.layout.lyt_listview_list, null);
holder.textView1 = (TextView) convertView.findViewById(R.id.textView1);
holder.editText1 = (EditText) convertView.findViewById(R.id.editText1);
convertView.setTag(holder);
else
holder = (ViewHolder) convertView.getTag();
holder.ref = position;
holder.textView1.setText(arrText[position]);
holder.editText1.setText(arrTemp[position]);
holder.editText1.addTextChangedListener(new TextWatcher()
@Override
public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3)
// TODO Auto-generated method stub
@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3)
// TODO Auto-generated method stub
@Override
public void afterTextChanged(Editable arg0)
// TODO Auto-generated method stub
arrTemp[holder.ref] = arg0.toString();
);
return convertView;
private class ViewHolder
TextView textView1;
EditText editText1;
int ref;
新编辑:
删除您的 GenericTextWatcher 并改用它。当我使用您的 TextWatcher 实现时它不起作用,我像这样更改了它,这对我有用。
holder.getEditText().addTextChangedListener(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)
String text = editable.toString();
ARR[holder.getPosition()] = text;
Log.e("Watcher > ", holder.getPosition()+"> "+ ARR[holder.getPosition()] );
);
【讨论】:
嗨。抱歉我不能早点回答。您的 EditText 标记是一个全局变量。它应该是一个私有的最终变量。另外,我可以给出的一条建议是我建议你应该使用 ViewHolder 模式。甚至 Android 开发人员都说我们应该使用该模式 :) 我无法将 EditText 变量更改为 final。给我看一些代码。我已经更新了代码。 好的,我有空闲时间尝试解决问题。 好的,我找到了一些东西。我测试了这个方法,它工作正常。 webplusandroid.com/… 我的方法看起来也差不多。我不知道我哪里出错了?【参考方案2】:您需要先从 edittext 中删除 TextWatcher,然后才能在其中设置文本
if (holder.marks.getTag() != null)
GenericTextWatcher oldWatcher = (GenericTextWatcher) holder.marks.getTag();
holder.marks.removeTextChangedListener(oldWatcher);
holder.marks.setText(arrScMarks[holder.ref]);
//then set new textwatcher to edittext with current position
GenericTextWatcher watcher;
watcher = new GenericTextWatcher(position);
holder.marks.addTextChangedListener(watcher);
holder.marks.setTag(watcher);
【讨论】:
【参考方案3】:您获得 NPE 的原因可能是因为您的 getItem 返回 null。
@Override
public Object getItem(int arg0)
return null;
您需要返回 Collection(Arraylist) 中的特定位置
@Override
public Object getItem(int arg0)
return list.get(arg0);
【讨论】:
【参考方案4】:替换这个:
if (et != null) // here you check if et,which is a textview if its null
scho.add(et.getText().toString());
Log.e("SCH", et.getText().toString());
有了这个:
if (et.getText().toString()) // check if the text is null
scho.add(et.getText().toString());
Log.e("SCH", et.getText().toString());
【讨论】:
他从 getChildAt(int) 得到 null,你的回答没有解决问题【参考方案5】:您正在使用的方法:
v = mListView.getChildAt(i);
属于 ViewGroup 超类,将仅返回 ListView 中当前可见的项目(因为它们被回收,没有理由将它们全部保存在内存中)。尝试在适配器的 getView() 方法中设置 OnClickListener:
public View getView(final int position, View convertView, ViewGroup parent)
...
convertView.setOnClickListener(new OnClickListener()
public void onClick(View v)
...
et = (EditText) v.findViewById(R.id.marks);
;
请注意,通常不需要为每个项目创建新的 OnClickListener 实例,并且会产生一些开销。您可以使用单个 OnClickListener 和标签来区分项目。
或者,您可以使用 ListView 的内置监听器:
https://developer.android.com/reference/android/widget/AdapterView.OnItemClickListener.html
【讨论】:
但我的 onclick 是 onOptionsItemSelected【参考方案6】:Listview 的getChildAt(i)
仅返回设备上可见项目的值,而不是适配器中膨胀的所有项目的值,因此您将获得设备屏幕上可见项目的所有视图,否则 null。所以尝试只获取可见项目视图并处理NullPointerException
,您可以进行检查:
View v = mListView.getChildAt(i);
if(v!=null)
// your code
【讨论】:
请看截图。该列表在 onclick 期间可见【参考方案7】:试试这个
@Override
public boolean onOptionsItemSelected(MenuItem item)
if(item.getItemId()==R.id.add)
ArrayList<String> scho = new ArrayList<String>();
EditText et;
if (mListView.getChildCount() > 0)
for (int i = 0; i < mListView.getChildCount(); i++)
// if your view statrts with relative layout then
RelativeLayout rl=(RelativeLayout)mListView.getChildAt(i);
// else
yourlayout lay =(yourlayout)mListView.getChildAt(i);
EditText et=(EditText)lay.getChildAt(your edit text positin in lay)
// main thing is we have to follow chain logic to find out the EditText position
System.out.println(et.getText().toString());
return super.onOptionsItemSelected(item);
【讨论】:
如果列表向下滚动很远,ListView 的视图将已经被回收并且值丢失。不过,这个解决方案适用于嵌套视图,我以前用过。以上是关于无法从 Listview 的 EditText 中获取值?的主要内容,如果未能解决你的问题,请参考以下文章
如何从具有多个视图的 ListView 中的 EditText 获取文本?
android - 在更改 EditText 值时无法更新列表视图