列表视图中重复的布局参考
我的列表视图发生了一件非常奇怪的事情。我正在创建一个带有按钮和 editText 的 ListView。
它的设置是这样的:[Button] [EditText] [Button],按钮的作用就像一个“增量器”和“减量器”,每次点击都会以 1 个单位更新 EditText 的数值。 问题是,当我单击按钮时,几乎每次更改另一个列表视图元素的 editText 时(单击的项目的 editText 也会更改)。如果我单击这个错误更改项目的按钮,它也会更改第一个项目的 editText。它们基本上具有相同的按钮和 editText 引用,尽管它们具有带有数据的 textView,并且这些数据在它们之间是不同的。
为了实现这一点,我创建了自定义适配器:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
convertView = mInflater.inflate(R.layout.lastproduct_row, null);
holder = new ViewHolder();
holder.btnAddQtd = (Button) convertView.findViewById(R.lastproduct_row.btn_add_qtd);
holder.btnSubQtd = (Button) convertView.findViewById(R.lastproduct_row.btn_sub_qtd);
holder.etQuantidade = (EditText) convertView.findViewById(R.lastproduct_row.et_quantidade);
TextView tv;
holder.tvList = new TextView[PRODUCTROW_INT_KEY.length];
for(int i = 0; i < PRODUCTROW_INT_KEY.length; i++) {
tv = (TextView) convertView.findViewById(PRODUCTROW_INT_KEY[i]);
holder.tvList[i] = tv;
}
convertView.setTag(holder);
}
else {
holder = (ViewHolder) convertView.getTag();
}
HashMap<String, String> hm = productsList.get(position);
String key = hm.get(CODIGO_KEY);
for(int i = 0; i < PRODUCTROW_INT_KEY.length; i++) {
holder.tvList[i].setText(hm.get(PRODUCTROW_STR_KEY[i]));
}
holder.btnAddQtd.setTag(key+QTD_FLAG+ADD_ACTION);
holder.btnSubQtd.setTag(key+QTD_FLAG+SUB_ACTION);
holder.btnAddQtd.setOnClickListener(handle);
holder.btnSubQtd.setOnClickListener(handle);
if(novosEstoques.containsKey(key)) {
holder.etQuantidade.setText(MyParseFunctions.parseCentesimal(novosEstoques.get(key).getQuantidade()));
}
return convertView;
}
class ViewHolder {
private TextView []tvList;
private Button btnAddQtd, btnSubQtd;
private Button btnAddQtVol, btnSubQtVol;
private EditText etQuantidade, etQtVolume;
}
我向按钮添加了 onClick 侦听器,并使用我的 listView 元素 ID(与其他信息连接)设置它们的标签。然后在我的事件侦听器中,我只需获取按钮父视图(LinearLayout)并使用 getViewAt() 从中获取 EditText:
@Override
public void onClick(View v) {
String tag = (String) v.getTag();
if(tag.contains(QTD_FLAG)) {
String []info = ((String) v.getTag()).split(QTD_FLAG);
float qtd;
LinearLayout ll = (LinearLayout) v.getParent();
ll.setBackgroundColor(Color.rgb(0, 128, 30));
EditText et = (EditText) ll.getChildAt(2);
qtd = Float.parseFloat(et.getText().toString().replace(",", "."));
if(info[1].equals(ADD_ACTION)) {
qtd++;
}
else if(info[1].equals(SUB_ACTION)) {
if(qtd > 0)
qtd--;
}
Log.d("TESTE", "MODIFICAR KEY = "+info[0]);
et.setText(qtd+"");
}
}
在本例中我使用 setBackgroundColor 来确认 LinearLayout 实例在 lisView 中重复。当我单击某个按钮时,它会绘制在 2 个不同的列表视图项中。
任何人都可以指出我可以做什么?我发现有人有重复的 ListView 项目,我不知道这是否是我的情况,因为我的 ListView 中有 TextView,并且它们不相等,只有带有按钮和 editText 的 LinearLayout 部分是“共享”的。
我对 getView 方法做了一些更改,现在它可以工作了!似乎每次调用 getView 方法时,我都不能保证我的 editTexts 会被正确填充,而且我没有意识到这一点。因此,我进行的每次 getView 调用都会设置 editText 值,如果用户编辑 ET 值,我会将其存储在 HashMap 中以在 getView 中恢复,如果 HashMap 中没有给定 editText 的条目,则将其设置为默认值值(零):
...
if(convertView == null) {
holder = new ViewHolder();
holder.btnAddQtd = (Button) convertView.findViewById(R.lastproduct_row.btn_add_qtd);
holder.btnSubQtd = (Button) convertView.findViewById(R.lastproduct_row.btn_sub_qtd);
holder.etQuantidade = (EditText) convertView.findViewById(R.lastproduct_row.et_quantidade);
//Now it is easier to get etQuantidade reference in button
//click handle, I just have to do:
// public onClick(View v) {
// EditText etButtonAssociated = (EditText) v.getTag();
// ...
// }
holder.btnAddQtd.setTag(holder.etQuantidade);
holder.btnSubQtd.setTag(holder.etQuantidade);
holder.btnAddQtd.setOnClickListener(handle);
holder.btnSubQtd.setOnClickListener(handle);
...
}
else {
...
}
holder.etQuantidade.setTag(key);
if(novosEstoques.containsKey(key)) {
holder.etQuantidade.setText(MyParseFunctions.parseCentesimal(novosEstoques.get(key).getQuantidade()));
}
else {
holder.etQuantidade.setText("0");
}
return convertView;
There is an really weird thing happening with my listview. I am creating an ListView with buttons and an editText.
It's disposed like this: [Button] [EditText] [Button], The buttons works like an "incrementer" and "decrementer" updating the numerical value of EditText in 1 unit per click.
The problem is, when I click in an button, almost every time an editText of another list view element is changed (the editText of the clicked item is also changed). And if I click in a button of this erroneous changed item, it also changes the editText of the first one. They basically have the same reference of buttons and editText, although they have textViews with data, and this data is different between they.
To accomplish that I created and custom adapter:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null) {
convertView = mInflater.inflate(R.layout.lastproduct_row, null);
holder = new ViewHolder();
holder.btnAddQtd = (Button) convertView.findViewById(R.lastproduct_row.btn_add_qtd);
holder.btnSubQtd = (Button) convertView.findViewById(R.lastproduct_row.btn_sub_qtd);
holder.etQuantidade = (EditText) convertView.findViewById(R.lastproduct_row.et_quantidade);
TextView tv;
holder.tvList = new TextView[PRODUCTROW_INT_KEY.length];
for(int i = 0; i < PRODUCTROW_INT_KEY.length; i++) {
tv = (TextView) convertView.findViewById(PRODUCTROW_INT_KEY[i]);
holder.tvList[i] = tv;
}
convertView.setTag(holder);
}
else {
holder = (ViewHolder) convertView.getTag();
}
HashMap<String, String> hm = productsList.get(position);
String key = hm.get(CODIGO_KEY);
for(int i = 0; i < PRODUCTROW_INT_KEY.length; i++) {
holder.tvList[i].setText(hm.get(PRODUCTROW_STR_KEY[i]));
}
holder.btnAddQtd.setTag(key+QTD_FLAG+ADD_ACTION);
holder.btnSubQtd.setTag(key+QTD_FLAG+SUB_ACTION);
holder.btnAddQtd.setOnClickListener(handle);
holder.btnSubQtd.setOnClickListener(handle);
if(novosEstoques.containsKey(key)) {
holder.etQuantidade.setText(MyParseFunctions.parseCentesimal(novosEstoques.get(key).getQuantidade()));
}
return convertView;
}
class ViewHolder {
private TextView []tvList;
private Button btnAddQtd, btnSubQtd;
private Button btnAddQtVol, btnSubQtVol;
private EditText etQuantidade, etQtVolume;
}
I added onClick listenners to the buttons, setting their tags with my listView element ID (concatenated with another informations). Then in my event listener I just get the button parent View (an LinearLayout) and get the EditText from that using getViewAt():
@Override
public void onClick(View v) {
String tag = (String) v.getTag();
if(tag.contains(QTD_FLAG)) {
String []info = ((String) v.getTag()).split(QTD_FLAG);
float qtd;
LinearLayout ll = (LinearLayout) v.getParent();
ll.setBackgroundColor(Color.rgb(0, 128, 30));
EditText et = (EditText) ll.getChildAt(2);
qtd = Float.parseFloat(et.getText().toString().replace(",", "."));
if(info[1].equals(ADD_ACTION)) {
qtd++;
}
else if(info[1].equals(SUB_ACTION)) {
if(qtd > 0)
qtd--;
}
Log.d("TESTE", "MODIFICAR KEY = "+info[0]);
et.setText(qtd+"");
}
}
I'm using an setBackgroundColor in this example to confirm that the LinearLayout instance is duplicated in the lisView. When I click an Button, it's painted in 2 different list view item.
Anyone can point me what could be doing this? I have found people with an duplicated ListView item, I don know if that is my case, cause I have TextView's inside my ListView, and they are not equal, only the LinearLayout portion with buttons and editText is "shared".
I make some changes in my getView method and it's working now! It seems that every time the getView method is called i have not guarantee at all that my editTexts will be filled properly and I didn't realize that. So every getView call I make I set the editText value, if the user edit an ET value, I store it in a HashMap to restore in getView, if there is no entry in HashMap for the given editText, then I set it to the default value (zero):
...
if(convertView == null) {
holder = new ViewHolder();
holder.btnAddQtd = (Button) convertView.findViewById(R.lastproduct_row.btn_add_qtd);
holder.btnSubQtd = (Button) convertView.findViewById(R.lastproduct_row.btn_sub_qtd);
holder.etQuantidade = (EditText) convertView.findViewById(R.lastproduct_row.et_quantidade);
//Now it is easier to get etQuantidade reference in button
//click handle, I just have to do:
// public onClick(View v) {
// EditText etButtonAssociated = (EditText) v.getTag();
// ...
// }
holder.btnAddQtd.setTag(holder.etQuantidade);
holder.btnSubQtd.setTag(holder.etQuantidade);
holder.btnAddQtd.setOnClickListener(handle);
holder.btnSubQtd.setOnClickListener(handle);
...
}
else {
...
}
holder.etQuantidade.setTag(key);
if(novosEstoques.containsKey(key)) {
holder.etQuantidade.setText(MyParseFunctions.parseCentesimal(novosEstoques.get(key).getQuantidade()));
}
else {
holder.etQuantidade.setText("0");
}
return convertView;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
以色列,
在查看了您的代码后,我想知道您所做的实施决定。由于每个按钮都“绑定”到特定的
EditText
,您是否考虑过将这些Buttons
的Tag
设置为EditText?
Tag
可以是任何包括UI元素的Object
。这对于动态 UI 元素(例如运行时填充的列表)特别有用。由于这是在您的 Adapter 中处理的,因此您不必担心重复的 Parent 等。此外,您可以避免担心在
onClick()
中“查找”控件,因为您已经拥有它(它是标签)。我不确定您的项目到底需要什么,但这似乎是一个潜在可行的解决方案,除非您需要这些按钮来完成其他任务。注意事项
完成后,请确保删除标签对
EditText
的引用。否则,您将面临泄漏一些内存的风险。模糊逻辑
Israel,
After looking over your code, I was wondering about an implementation decision you have made. Since each Button is "bound" to a particular
EditText
, have you considered setting theTag
of thoseButtons
to theEditText
? TheTag
may be anyObject
including a UI element. This is especially useful for dynamic UI elements, such as a runtime populated list.Since this is handled in your
Adapter
you wouldn't have to worry about duplicate Parents and such. Additionally, you could avoid having to worry about "finding" the control in youronClick()
because you would have it (It's the tag). I'm not sure exactly what your project needs are, but this seems like a potentially viable solution, unless you need thoseButtons
to accomplish other tasks.Note of Caution
Just make sure that you erase the Tags' references to the
EditText
when you are done. Otherwise, you run the risk of leaking some memory.FuzzicalLogic