从列表中删除项目后,扩展项目的位置不会在 ExpandableListView 上刷新 - Android?
After deleting an item from list, expanded item's position does not refresh on ExpandableListView - Android?
我有问题。我有一个 ExpandableListView
和一个从 BaseExpandableListAdapter
扩展而来的自定义适配器。我有一个 ArrayList
,其中包含我的组和组的子项。
问题是:
1)展开第3组
2) 从ArrayList 中删除第一项并notifyDataSetInvalidated
, notifyDataSetChanged
3) getGroupView
要求正确,我可以设置我需要的。
4) 但旧位置 (3) 要求 getChildView
。删除第一项时,索引会更改。但是 ListView
试图获取旧位置的子视图。
这是我的理解。哪里有问题?
这是我的适配器:
public class DashboardAdapter extends BaseExpandableListAdapter implements View.OnClickListener {
private static final String TAG = DashboardAdapter.class.getSimpleName();
private static final int groupTypeCount = GroupType.values().length;
private final Activity activity;
private final ExpandableListView exListView;
private final List<Object> dashboard = new ArrayList<>();
private String lastExpandedProductIban = null;
public DashboardAdapter(final Activity activity, ExpandableListView expandableListView) {
this.activity = activity;
exListView = expandableListView;
}
public void setDashboard(final List<Object> dashboard) {
if (Verify.notNull(dashboard)) {
this.dashboard.clear();
this.dashboard.addAll(dashboard);
}
@Override
public int getGroupTypeCount() {
return groupTypeCount;
}
@Override
public int getGroupType(int groupPosition) {
final Object group = getGroup(groupPosition);
if (group instanceof Dashboard.Products.Accordion)
return GroupType.PRODUCT_ACCORDION.ordinal();
return -1;
}
@Override
public int getGroupCount() {
return dashboard.size();
}
@Override
public int getChildrenCount(int groupPosition) {
if (getGroupType(groupPosition) == GroupType.PRODUCT_ACCORDION.ordinal())
return ((Dashboard.Products.Accordion) getGroup(groupPosition)).actions.size();
return 0;
}
@Override
public Object getGroup(int groupPosition) {
if (groupPosition >= 0 && groupPosition < dashboard.size())
return dashboard.get(groupPosition);
return null;
}
@Override
public Object getChild(int groupPosition, int childPosition) {
if (getGroupType(groupPosition) == GroupType.PRODUCT_ACCORDION.ordinal()) {
final Dashboard.Products.Accordion group = (Dashboard.Products.Accordion) getGroup(groupPosition);
if (group != null && childPosition >= 0 && childPosition < group.actions.size())
return group.actions.get(childPosition);
}
return null;
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public boolean hasStableIds() {
return true;
}
@Override
public View getGroupView(final int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
// initialise all possible ViewHolders
ViewHolderAccordion viewHolderAccordion = null;
// get GroupType of the current View
final GroupType groupType = GroupType.valueOf(getGroupType(groupPosition));
// Inflate the layout if convertView is null
if (convertView == null) {
LayoutInflater inflater = activity.getLayoutInflater();
switch (groupType) {
case PRODUCT_ACCORDION:
convertView = inflater.inflate(R.layout.item_dashboard_accordion, parent, false);
viewHolderAccordion = new ViewHolderAccordion(convertView);
break;
}
}
// reuse convertView if it isn't null
else {
switch (groupType) {
case PRODUCT_ACCORDION:
viewHolderAccordion = ((ViewHolderAccordion) convertView.getTag()).reset();
break;
}
}
if (viewHolderAccordion != null) {
final Dashboard.Products.Accordion accordion = (Dashboard.Products.Accordion) getGroup(groupPosition);
// set alternating background color
//if(dashboardGroups.accounts.indexOf(account) % 2 == 0)
//convertView.setBackgroundColor(activity.getResources().getColor(R.color.dashboard_account_alternate_color));
// populate view with content
if (accordion != null) {
setText(viewHolderAccordion.tvProductAccordionName, accordion.title);
setText(viewHolderAccordion.tvProductAccordionDetail, accordion.detail);
setText(viewHolderAccordion.tvProductAccordionBalance, accordion.balance);
boolean _isExpanded = getPositionFromIban(lastExpandedProductIban) == groupPosition;
accordion.isExpanded = _isExpanded;
viewHolderAccordion.groupExpander.setImageResource(_isExpanded ? R.drawable.expander_white_close : R.drawable.expander_open);
viewHolderAccordion.contentView.setActivated(_isExpanded ? true : false);
viewHolderAccordion.dashboard_product_accordion_divider.setVisibility(_isExpanded ? View.GONE : View.VISIBLE);
}
convertView.setTag(viewHolderAccordion);
}
return convertView;
}
private void deleteCell(final View view, final int groupPosition) {
final Animation.AnimationListener animationListener = new Animation.AnimationListener() {
@Override
public void onAnimationEnd(Animation arg0) {
dashboard.remove(groupPosition);
notifyDataSetInvalidated();
notifyDataSetChanged();
}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationStart(Animation animation) {
}
};
collapse(view, animationListener);
}
private void collapse(final View view, final Animation.AnimationListener al) {
final int initialHeight = view.getMeasuredHeight();
Animation anim = new Animation() {
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
if (interpolatedTime == 1) {
view.setVisibility(View.GONE);
} else {
view.getLayoutParams().height = initialHeight - (int) (initialHeight * interpolatedTime);
view.requestLayout();
}
}
@Override
public boolean willChangeBounds() {
return true;
}
};
if (al != null) {
anim.setAnimationListener(al);
}
anim.setDuration(200);
view.startAnimation(anim);
}
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
if (getGroupType(groupPosition) == GroupType.PRODUCT_ACCORDION.ordinal()) {
final Dashboard.Products.Accordion.Action action =
(Dashboard.Products.Accordion.Action) getChild(groupPosition, childPosition);
if (action != null) {
ViewHolderAccordionLink viewHolderAccordionLink;
if (convertView == null) {
LayoutInflater inflater = activity.getLayoutInflater();
convertView = inflater.inflate(R.layout.item_dashboard_accordion_link, parent, false);
viewHolderAccordionLink = new ViewHolderAccordionLink(convertView);
} else {
viewHolderAccordionLink = ((ViewHolderAccordionLink) convertView.getTag()).reset();
}
// populate view with content
if (viewHolderAccordionLink != null) {
if (Verify.notNull(action.icon)) {
viewHolderAccordionLink.ivAccordionLink.setVisibility(View.VISIBLE);
} else {
viewHolderAccordionLink.ivAccordionLink.setVisibility(View.GONE);
}
if (action.title != null) {
setText(viewHolderAccordionLink.tvAccordionLinkLabel, action.title);
}
convertView.setTag(viewHolderAccordionLink);
}
}
}
return convertView;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return getChildrenCount(groupPosition) > 0;
}
@Override
public boolean areAllItemsEnabled() {
return false;
}
@Override
public boolean isEmpty() {
return dashboard.size() == 0;
}
@Override
public void onGroupExpanded(int groupPosition) {
}
@Override
public void onGroupCollapsed(int groupPosition) {
}
private void setText(final TextView textView, final DashboardText text) {
if (text != null) {
textView.setVisibility(View.VISIBLE);
if (Verify.notNull(text.text)) {
textView.setText(Html.fromHtml(text.text));
}
switch (text.color) {
case BLACK:
textView.setTextColor(activity.getResources().getColorStateList(R.color.selector_dashboard_black));
break;
case ORANGE:
textView.setTextColor(activity.getResources().getColorStateList(R.color.selector_dashboard_orange));
break;
case RED:
textView.setTextColor(activity.getResources().getColorStateList(R.color.selector_dashboard_red));
break;
case GREEN:
textView.setTextColor(activity.getResources().getColorStateList(R.color.selector_dashboard_green));
break;
case GREY:
textView.setTextColor(activity.getResources().getColorStateList(R.color.selector_dashboard_grey));
break;
case WHITE:
textView.setTextColor(activity.getResources().getColor(R.color.white));
break;
}
} else {
textView.setVisibility(View.GONE);
}
}
public String getIbanAtPosition(int groupPosition) {
if (getGroupType(groupPosition) == GroupType.PRODUCT_ACCORDION.ordinal()) {
final Dashboard.Products.Accordion group = (Dashboard.Products.Accordion) getGroup(groupPosition);
if (group != null) {
return group.detail.text;
}
}
return null;
}
public int getPositionFromIban(String iban) {
if (dashboard != null) {
for (int groupPosition = 0; groupPosition < dashboard.size(); groupPosition++) {
if (getGroupType(groupPosition) == GroupType.PRODUCT_ACCORDION.ordinal()) {
Dashboard.Products.Accordion group = (Dashboard.Products.Accordion) getGroup(groupPosition);
if (group.detail.text.equalsIgnoreCase(iban))
return groupPosition;
}
}
}
return -1;
}
public void setLastExpandedProductIban(String lastExpandedProductIban) {
this.lastExpandedProductIban = lastExpandedProductIban;
}
private enum GroupType {
PERSONALIZATION, PRODUCT_ACCORDION;
// Converts from an ordinal value to the Groups
public static GroupType valueOf(final int index) {
final GroupType[] values = GroupType.values();
if (index < 0 || index >= values.length) {
return PERSONALIZATION;
}
return values[index];
}
}
class ViewHolderAccordion {
public View contentView;
public ImageView groupExpander;
public TextView tvProductAccordionName;
public TextView tvProductAccordionDetail;
public TextView tvProductAccordionBalance;
public View dashboard_product_accordion_divider;
public ViewHolderAccordion(View contentView) {
this.contentView = contentView;
groupExpander = (ImageView) contentView.findViewById(R.id.groupExpander);
tvProductAccordionName = (TextView) contentView.findViewById(R.id.tvProductAccordionName);
tvProductAccordionDetail = (TextView) contentView.findViewById(R.id.tvProductAccordionDetail);
tvProductAccordionBalance = (TextView) contentView.findViewById(R.id.tvProductAccordionBalance);
dashboard_product_accordion_divider = contentView.findViewById(R.id.dashboard_product_accordion_divider);
}
public ViewHolderAccordion reset() {
//contentView.setBackgroundColor(0xFFffffff);
tvProductAccordionName.setText("");
tvProductAccordionDetail.setText("");
tvProductAccordionDetail.setVisibility(View.VISIBLE);
tvProductAccordionBalance.setText("");
return this;
}
}}
我可以使用
解决这个问题
@Override
public long getGroupId(int groupPosition) {
return dashboard.get(groupPosition).hashCode();
}
而不是
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
我有问题。我有一个 ExpandableListView
和一个从 BaseExpandableListAdapter
扩展而来的自定义适配器。我有一个 ArrayList
,其中包含我的组和组的子项。
问题是:
1)展开第3组
2) 从ArrayList 中删除第一项并notifyDataSetInvalidated
, notifyDataSetChanged
3) getGroupView
要求正确,我可以设置我需要的。
4) 但旧位置 (3) 要求 getChildView
。删除第一项时,索引会更改。但是 ListView
试图获取旧位置的子视图。
这是我的理解。哪里有问题?
这是我的适配器:
public class DashboardAdapter extends BaseExpandableListAdapter implements View.OnClickListener {
private static final String TAG = DashboardAdapter.class.getSimpleName();
private static final int groupTypeCount = GroupType.values().length;
private final Activity activity;
private final ExpandableListView exListView;
private final List<Object> dashboard = new ArrayList<>();
private String lastExpandedProductIban = null;
public DashboardAdapter(final Activity activity, ExpandableListView expandableListView) {
this.activity = activity;
exListView = expandableListView;
}
public void setDashboard(final List<Object> dashboard) {
if (Verify.notNull(dashboard)) {
this.dashboard.clear();
this.dashboard.addAll(dashboard);
}
@Override
public int getGroupTypeCount() {
return groupTypeCount;
}
@Override
public int getGroupType(int groupPosition) {
final Object group = getGroup(groupPosition);
if (group instanceof Dashboard.Products.Accordion)
return GroupType.PRODUCT_ACCORDION.ordinal();
return -1;
}
@Override
public int getGroupCount() {
return dashboard.size();
}
@Override
public int getChildrenCount(int groupPosition) {
if (getGroupType(groupPosition) == GroupType.PRODUCT_ACCORDION.ordinal())
return ((Dashboard.Products.Accordion) getGroup(groupPosition)).actions.size();
return 0;
}
@Override
public Object getGroup(int groupPosition) {
if (groupPosition >= 0 && groupPosition < dashboard.size())
return dashboard.get(groupPosition);
return null;
}
@Override
public Object getChild(int groupPosition, int childPosition) {
if (getGroupType(groupPosition) == GroupType.PRODUCT_ACCORDION.ordinal()) {
final Dashboard.Products.Accordion group = (Dashboard.Products.Accordion) getGroup(groupPosition);
if (group != null && childPosition >= 0 && childPosition < group.actions.size())
return group.actions.get(childPosition);
}
return null;
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public boolean hasStableIds() {
return true;
}
@Override
public View getGroupView(final int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
// initialise all possible ViewHolders
ViewHolderAccordion viewHolderAccordion = null;
// get GroupType of the current View
final GroupType groupType = GroupType.valueOf(getGroupType(groupPosition));
// Inflate the layout if convertView is null
if (convertView == null) {
LayoutInflater inflater = activity.getLayoutInflater();
switch (groupType) {
case PRODUCT_ACCORDION:
convertView = inflater.inflate(R.layout.item_dashboard_accordion, parent, false);
viewHolderAccordion = new ViewHolderAccordion(convertView);
break;
}
}
// reuse convertView if it isn't null
else {
switch (groupType) {
case PRODUCT_ACCORDION:
viewHolderAccordion = ((ViewHolderAccordion) convertView.getTag()).reset();
break;
}
}
if (viewHolderAccordion != null) {
final Dashboard.Products.Accordion accordion = (Dashboard.Products.Accordion) getGroup(groupPosition);
// set alternating background color
//if(dashboardGroups.accounts.indexOf(account) % 2 == 0)
//convertView.setBackgroundColor(activity.getResources().getColor(R.color.dashboard_account_alternate_color));
// populate view with content
if (accordion != null) {
setText(viewHolderAccordion.tvProductAccordionName, accordion.title);
setText(viewHolderAccordion.tvProductAccordionDetail, accordion.detail);
setText(viewHolderAccordion.tvProductAccordionBalance, accordion.balance);
boolean _isExpanded = getPositionFromIban(lastExpandedProductIban) == groupPosition;
accordion.isExpanded = _isExpanded;
viewHolderAccordion.groupExpander.setImageResource(_isExpanded ? R.drawable.expander_white_close : R.drawable.expander_open);
viewHolderAccordion.contentView.setActivated(_isExpanded ? true : false);
viewHolderAccordion.dashboard_product_accordion_divider.setVisibility(_isExpanded ? View.GONE : View.VISIBLE);
}
convertView.setTag(viewHolderAccordion);
}
return convertView;
}
private void deleteCell(final View view, final int groupPosition) {
final Animation.AnimationListener animationListener = new Animation.AnimationListener() {
@Override
public void onAnimationEnd(Animation arg0) {
dashboard.remove(groupPosition);
notifyDataSetInvalidated();
notifyDataSetChanged();
}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationStart(Animation animation) {
}
};
collapse(view, animationListener);
}
private void collapse(final View view, final Animation.AnimationListener al) {
final int initialHeight = view.getMeasuredHeight();
Animation anim = new Animation() {
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
if (interpolatedTime == 1) {
view.setVisibility(View.GONE);
} else {
view.getLayoutParams().height = initialHeight - (int) (initialHeight * interpolatedTime);
view.requestLayout();
}
}
@Override
public boolean willChangeBounds() {
return true;
}
};
if (al != null) {
anim.setAnimationListener(al);
}
anim.setDuration(200);
view.startAnimation(anim);
}
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
if (getGroupType(groupPosition) == GroupType.PRODUCT_ACCORDION.ordinal()) {
final Dashboard.Products.Accordion.Action action =
(Dashboard.Products.Accordion.Action) getChild(groupPosition, childPosition);
if (action != null) {
ViewHolderAccordionLink viewHolderAccordionLink;
if (convertView == null) {
LayoutInflater inflater = activity.getLayoutInflater();
convertView = inflater.inflate(R.layout.item_dashboard_accordion_link, parent, false);
viewHolderAccordionLink = new ViewHolderAccordionLink(convertView);
} else {
viewHolderAccordionLink = ((ViewHolderAccordionLink) convertView.getTag()).reset();
}
// populate view with content
if (viewHolderAccordionLink != null) {
if (Verify.notNull(action.icon)) {
viewHolderAccordionLink.ivAccordionLink.setVisibility(View.VISIBLE);
} else {
viewHolderAccordionLink.ivAccordionLink.setVisibility(View.GONE);
}
if (action.title != null) {
setText(viewHolderAccordionLink.tvAccordionLinkLabel, action.title);
}
convertView.setTag(viewHolderAccordionLink);
}
}
}
return convertView;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return getChildrenCount(groupPosition) > 0;
}
@Override
public boolean areAllItemsEnabled() {
return false;
}
@Override
public boolean isEmpty() {
return dashboard.size() == 0;
}
@Override
public void onGroupExpanded(int groupPosition) {
}
@Override
public void onGroupCollapsed(int groupPosition) {
}
private void setText(final TextView textView, final DashboardText text) {
if (text != null) {
textView.setVisibility(View.VISIBLE);
if (Verify.notNull(text.text)) {
textView.setText(Html.fromHtml(text.text));
}
switch (text.color) {
case BLACK:
textView.setTextColor(activity.getResources().getColorStateList(R.color.selector_dashboard_black));
break;
case ORANGE:
textView.setTextColor(activity.getResources().getColorStateList(R.color.selector_dashboard_orange));
break;
case RED:
textView.setTextColor(activity.getResources().getColorStateList(R.color.selector_dashboard_red));
break;
case GREEN:
textView.setTextColor(activity.getResources().getColorStateList(R.color.selector_dashboard_green));
break;
case GREY:
textView.setTextColor(activity.getResources().getColorStateList(R.color.selector_dashboard_grey));
break;
case WHITE:
textView.setTextColor(activity.getResources().getColor(R.color.white));
break;
}
} else {
textView.setVisibility(View.GONE);
}
}
public String getIbanAtPosition(int groupPosition) {
if (getGroupType(groupPosition) == GroupType.PRODUCT_ACCORDION.ordinal()) {
final Dashboard.Products.Accordion group = (Dashboard.Products.Accordion) getGroup(groupPosition);
if (group != null) {
return group.detail.text;
}
}
return null;
}
public int getPositionFromIban(String iban) {
if (dashboard != null) {
for (int groupPosition = 0; groupPosition < dashboard.size(); groupPosition++) {
if (getGroupType(groupPosition) == GroupType.PRODUCT_ACCORDION.ordinal()) {
Dashboard.Products.Accordion group = (Dashboard.Products.Accordion) getGroup(groupPosition);
if (group.detail.text.equalsIgnoreCase(iban))
return groupPosition;
}
}
}
return -1;
}
public void setLastExpandedProductIban(String lastExpandedProductIban) {
this.lastExpandedProductIban = lastExpandedProductIban;
}
private enum GroupType {
PERSONALIZATION, PRODUCT_ACCORDION;
// Converts from an ordinal value to the Groups
public static GroupType valueOf(final int index) {
final GroupType[] values = GroupType.values();
if (index < 0 || index >= values.length) {
return PERSONALIZATION;
}
return values[index];
}
}
class ViewHolderAccordion {
public View contentView;
public ImageView groupExpander;
public TextView tvProductAccordionName;
public TextView tvProductAccordionDetail;
public TextView tvProductAccordionBalance;
public View dashboard_product_accordion_divider;
public ViewHolderAccordion(View contentView) {
this.contentView = contentView;
groupExpander = (ImageView) contentView.findViewById(R.id.groupExpander);
tvProductAccordionName = (TextView) contentView.findViewById(R.id.tvProductAccordionName);
tvProductAccordionDetail = (TextView) contentView.findViewById(R.id.tvProductAccordionDetail);
tvProductAccordionBalance = (TextView) contentView.findViewById(R.id.tvProductAccordionBalance);
dashboard_product_accordion_divider = contentView.findViewById(R.id.dashboard_product_accordion_divider);
}
public ViewHolderAccordion reset() {
//contentView.setBackgroundColor(0xFFffffff);
tvProductAccordionName.setText("");
tvProductAccordionDetail.setText("");
tvProductAccordionDetail.setVisibility(View.VISIBLE);
tvProductAccordionBalance.setText("");
return this;
}
}}
我可以使用
解决这个问题@Override
public long getGroupId(int groupPosition) {
return dashboard.get(groupPosition).hashCode();
}
而不是
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}