expandableListView 子项之间的干扰
Interference between expandableListView children
我在实现 expandableListView 时遇到了一些问题。我已经实现了我的 ExpandableListAdapter
public class ExpandableListAdapter 扩展了 BaseExpandableListAdapter {
private static final int SUM = 1;
private static final int SUB = 2;
private Context context;
private List<String> listDataHeader; //Header titles
private HashMap<String, List<Article>> listDataChild;
private HashMap<Integer, Bitmap> productImagesHashMap;
public ExpandableListAdapter (Context context, List<String> listDataHeader, HashMap<String, List<Article>> listDataChild, HashMap<Integer, Bitmap> productImagesHashMap) {
this.context = context;
this.listDataHeader = listDataHeader;
this.listDataChild = listDataChild;
this.productImagesHashMap = productImagesHashMap;
}
@Override
public int getGroupCount() {
return this.listDataHeader.size();
}
@Override
public int getChildrenCount(int groupPosition) {
return this.listDataChild.get(this.listDataHeader.get(groupPosition)).size();
}
@Override
public Object getGroup(int groupPosition) {
return this.listDataHeader.get(groupPosition);
}
@Override
public Object getChild(int groupPosition, int childPosition) {
return this.listDataChild.get(this.listDataHeader.get(groupPosition)).get(childPosition);
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
String headerTitle = (String) getGroup(groupPosition);
if (convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.user_expand_listview_header, null);
}
TextView listHeaderTextView = (TextView) convertView.findViewById(R.id.list_header);
listHeaderTextView.setTypeface(null, Typeface.BOLD);
listHeaderTextView.setText(headerTitle);
return convertView;
}
@Override
public View getChildView(final int groupPosition, final int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
final Article childValues = (Article) getChild(groupPosition, childPosition);
if (convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.product_row, null);
}
Integer articleId = childValues.getId();
final TextView articleIdTextView = (TextView) convertView.findViewById(R.id.product_id);
ImageView productImageTextView = (ImageView) convertView.findViewById(R.id.product_image);
TextView productNameTextView = (TextView) convertView.findViewById(R.id.product_name);
TextView productDescriptionTextView = (TextView) convertView.findViewById(R.id.product_description);
final TextView productPriceTextView = (TextView) convertView.findViewById(R.id.product_price);
articleIdTextView.setText(articleId.toString());
productImageTextView.setImageBitmap(productImagesHashMap.get(articleId));
productNameTextView.setText(childValues.getNome());
productDescriptionTextView.setText(childValues.getDescrizione());
productPriceTextView.setText(childValues.getPrezzo());
ImageButton addButton = (ImageButton) convertView.findViewById(R.id.add_btn);
final TextView articleQty =(TextView) convertView.findViewById(R.id.product_qnty);
ImageButton removeButton = (ImageButton) convertView.findViewById(R.id.remove_btn);
addButton.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View view) {
if (context instanceof UserActivity) {
((UserActivity) context).updateTotal(
Integer.parseInt(articleIdTextView.getText().toString()),
productPriceTextView.getText().toString(),
SUM);
articleQty.setText(updateProductQty(articleQty, SUM));
}
}
});
removeButton.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View view) {
if (context instanceof UserActivity) {
((UserActivity) context).updateTotal(
Integer.parseInt(articleIdTextView.getText().toString()),
productPriceTextView.getText().toString(),
SUB);
articleQty.setText(updateProductQty(articleQty, SUB));
}
}
});
return convertView;
}
@Override
public boolean isChildSelectable(int i, int i1) {
return true;
}
private String updateProductQty(TextView productQty, int operation) {
Integer qty = Integer.parseInt(productQty.getText().toString());
switch (operation) {
case 1: //SUM
qty += 1;
break;
case 2: //SUB
if (qty > 0)
qty -= 1;
break;
}
return qty.toString();
}
}
有一些产品是从数据库中读取并按类型(实际上是笔、笔记本和纸)插入到 ExpandableListView 中的。然后有两个按钮允许 select 用户想要购买多少,数量由 TextView 跟踪。现在,当我用普通的 ListView 实现它时,一切正常,但是使用 ExpandableListView 时,子级的 TextView 数量之间存在干扰。
例如ExpandableListView的实际组成是:
笔
-- 黑笔
-- 蓝笔
-- 红笔
笔记本
-- 黑色笔记本
-- 蓝色笔记本
-- 红色笔记本
论文
-- A4纸
如果用户添加黑色笔记本,也会添加蓝色笔
如果用户添加了蓝色笔记本,也会添加黑色笔
如果用户添加红色笔记本,也会添加蓝色笔
为什么会有这些干扰?
您没有正确跟踪数量更新。
因为 ExpandableListView
——像 ListView
——回收它的视图,你得到这个行为:
- 用户按下黑色笔记本的添加按钮。
- 用户 scrolls/expands/collapses 列表。
- 蓝色笔的视图是通过回收黑色笔记本的视图创建的。
- 蓝色笔的视图显示黑色笔记本中的数量。
这是你需要做的:
- 将数量 属性 添加到
Article
class
- 创建子视图时,使用
Article
对象中包含的数量填充 articleQty
TextView
。
- 当用户按下 Add/Remove 按钮时,更新
Article
对象中的数量并调用 notifyDataSetChanged()
.
规则是:视图从模型填充,模型从侦听器更新。不要使用侦听器来更新视图,调用 notifyDataSetcChanged()
会解决这个问题。
我在实现 expandableListView 时遇到了一些问题。我已经实现了我的 ExpandableListAdapter
public class ExpandableListAdapter 扩展了 BaseExpandableListAdapter {
private static final int SUM = 1;
private static final int SUB = 2;
private Context context;
private List<String> listDataHeader; //Header titles
private HashMap<String, List<Article>> listDataChild;
private HashMap<Integer, Bitmap> productImagesHashMap;
public ExpandableListAdapter (Context context, List<String> listDataHeader, HashMap<String, List<Article>> listDataChild, HashMap<Integer, Bitmap> productImagesHashMap) {
this.context = context;
this.listDataHeader = listDataHeader;
this.listDataChild = listDataChild;
this.productImagesHashMap = productImagesHashMap;
}
@Override
public int getGroupCount() {
return this.listDataHeader.size();
}
@Override
public int getChildrenCount(int groupPosition) {
return this.listDataChild.get(this.listDataHeader.get(groupPosition)).size();
}
@Override
public Object getGroup(int groupPosition) {
return this.listDataHeader.get(groupPosition);
}
@Override
public Object getChild(int groupPosition, int childPosition) {
return this.listDataChild.get(this.listDataHeader.get(groupPosition)).get(childPosition);
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public boolean hasStableIds() {
return false;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
String headerTitle = (String) getGroup(groupPosition);
if (convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.user_expand_listview_header, null);
}
TextView listHeaderTextView = (TextView) convertView.findViewById(R.id.list_header);
listHeaderTextView.setTypeface(null, Typeface.BOLD);
listHeaderTextView.setText(headerTitle);
return convertView;
}
@Override
public View getChildView(final int groupPosition, final int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
final Article childValues = (Article) getChild(groupPosition, childPosition);
if (convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.product_row, null);
}
Integer articleId = childValues.getId();
final TextView articleIdTextView = (TextView) convertView.findViewById(R.id.product_id);
ImageView productImageTextView = (ImageView) convertView.findViewById(R.id.product_image);
TextView productNameTextView = (TextView) convertView.findViewById(R.id.product_name);
TextView productDescriptionTextView = (TextView) convertView.findViewById(R.id.product_description);
final TextView productPriceTextView = (TextView) convertView.findViewById(R.id.product_price);
articleIdTextView.setText(articleId.toString());
productImageTextView.setImageBitmap(productImagesHashMap.get(articleId));
productNameTextView.setText(childValues.getNome());
productDescriptionTextView.setText(childValues.getDescrizione());
productPriceTextView.setText(childValues.getPrezzo());
ImageButton addButton = (ImageButton) convertView.findViewById(R.id.add_btn);
final TextView articleQty =(TextView) convertView.findViewById(R.id.product_qnty);
ImageButton removeButton = (ImageButton) convertView.findViewById(R.id.remove_btn);
addButton.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View view) {
if (context instanceof UserActivity) {
((UserActivity) context).updateTotal(
Integer.parseInt(articleIdTextView.getText().toString()),
productPriceTextView.getText().toString(),
SUM);
articleQty.setText(updateProductQty(articleQty, SUM));
}
}
});
removeButton.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View view) {
if (context instanceof UserActivity) {
((UserActivity) context).updateTotal(
Integer.parseInt(articleIdTextView.getText().toString()),
productPriceTextView.getText().toString(),
SUB);
articleQty.setText(updateProductQty(articleQty, SUB));
}
}
});
return convertView;
}
@Override
public boolean isChildSelectable(int i, int i1) {
return true;
}
private String updateProductQty(TextView productQty, int operation) {
Integer qty = Integer.parseInt(productQty.getText().toString());
switch (operation) {
case 1: //SUM
qty += 1;
break;
case 2: //SUB
if (qty > 0)
qty -= 1;
break;
}
return qty.toString();
}
}
有一些产品是从数据库中读取并按类型(实际上是笔、笔记本和纸)插入到 ExpandableListView 中的。然后有两个按钮允许 select 用户想要购买多少,数量由 TextView 跟踪。现在,当我用普通的 ListView 实现它时,一切正常,但是使用 ExpandableListView 时,子级的 TextView 数量之间存在干扰。
例如ExpandableListView的实际组成是:
笔
-- 黑笔
-- 蓝笔
-- 红笔
笔记本
-- 黑色笔记本
-- 蓝色笔记本
-- 红色笔记本
论文
-- A4纸
如果用户添加黑色笔记本,也会添加蓝色笔
如果用户添加了蓝色笔记本,也会添加黑色笔
如果用户添加红色笔记本,也会添加蓝色笔
为什么会有这些干扰?
您没有正确跟踪数量更新。
因为 ExpandableListView
——像 ListView
——回收它的视图,你得到这个行为:
- 用户按下黑色笔记本的添加按钮。
- 用户 scrolls/expands/collapses 列表。
- 蓝色笔的视图是通过回收黑色笔记本的视图创建的。
- 蓝色笔的视图显示黑色笔记本中的数量。
这是你需要做的:
- 将数量 属性 添加到
Article
class - 创建子视图时,使用
Article
对象中包含的数量填充articleQty
TextView
。 - 当用户按下 Add/Remove 按钮时,更新
Article
对象中的数量并调用notifyDataSetChanged()
.
规则是:视图从模型填充,模型从侦听器更新。不要使用侦听器来更新视图,调用 notifyDataSetcChanged()
会解决这个问题。