You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ExpandableListView子项ImageView资源切换及按钮点击处理问题求助

Hey there, let's dig into this issue you're facing with the ImageSwitcher in your ExpandableListView's child item. Looking at your code, I can spot a few key problems that are causing abnormal behavior when switching image resources. Let's break them down and fix them step by step.

Key Issues in Your Current Code

  • Incorrect ConvertView Reuse: Right now, you're inflating a new layout every time getChildView is called—even when convertView is not null. This completely bypasses the View reuse mechanism of ExpandableListView, leading to memory bloat and lost state when scrolling.
  • Duplicate Click Listener Binding: For groupPosition == 3, you're setting click listeners on btm and btm1 every time getChildView runs (when convertView exists). This means multiple listeners get attached to the same buttons, causing unexpected behavior like multiple image switches per click or state inconsistencies.
  • No State Persistence: You're not saving the current state of the ImageSwitcher (which image is active). When the view gets reused, it resets to the default state instead of retaining the user's selection.

Fixed Implementation with ViewHolder Pattern

Let's refactor the code using the ViewHolder pattern to handle view reuse properly, bind listeners once, and persist selection state.

First, create ViewHolder classes for each child layout type:

// Base ViewHolder to unify all types
private abstract class BaseViewHolder {}

// ViewHolder for groupPosition 3 (sort_by_date_child_layout)
private class DateSortViewHolder extends BaseViewHolder {
    ImageSwitcher bookedonImage;
    Button btm, btm1;
    // Track current selection state: 0 = default, 1 = ascending, 2 = descending
    int currentSortState = 0;

    DateSortViewHolder(View itemView) {
        bookedonImage = itemView.findViewById(R.id.booedOnImage);
        btm = itemView.findViewById(R.id.btm);
        btm1 = itemView.findViewById(R.id.btm1);

        // Initialize ImageSwitcher factory ONCE
        bookedonImage.setFactory(() -> {
            ImageView myView = new ImageView(mContext);
            myView.setScaleType(ImageView.ScaleType.FIT_CENTER);
            return myView;
        });

        // Bind click listeners ONCE here
        btm.setOnClickListener(v -> {
            currentSortState = 1;
            bookedonImage.setImageResource(R.drawable.ascending_active);
        });

        btm1.setOnClickListener(v -> {
            currentSortState = 2;
            bookedonImage.setImageResource(R.drawable.decending_active);
        });
    }

    // Restore the saved state when the view is reused
    void restoreState() {
        switch (currentSortState) {
            case 1:
                bookedonImage.setImageResource(R.drawable.ascending_active);
                break;
            case 2:
                bookedonImage.setImageResource(R.drawable.decending_active);
                break;
            default:
                // Set your default drawable here if needed
                bookedonImage.setImageResource(/* your default drawable ID */);
                break;
        }
    }
}

// Add ViewHolders for other group positions if you need to handle their views
private class BookingStatusViewHolder extends BaseViewHolder {
    BookingStatusViewHolder(View itemView) {
        // Initialize views for booking_status_child_layout here
    }
}

private class FilterByViewHolder extends BaseViewHolder {
    FilterByViewHolder(View itemView) {
        // Initialize views for filterby_child_layout here
    }
}

private class TransferStatusViewHolder extends BaseViewHolder {
    TransferStatusViewHolder(View itemView) {
        // Initialize views for transfer_status_child_layout here
    }
}

Then update the getChildView method to use these ViewHolders:

@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
    BaseViewHolder viewHolder;
    LayoutInflater infalInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    if (convertView == null) {
        // Inflate the correct layout based on groupPosition
        switch (groupPosition) {
            case 0:
                convertView = infalInflater.inflate(R.layout.booking_status_child_layout, parent, false);
                viewHolder = new BookingStatusViewHolder(convertView);
                break;
            case 1:
                convertView = infalInflater.inflate(R.layout.filterby_child_layout, parent, false);
                viewHolder = new FilterByViewHolder(convertView);
                break;
            case 2:
                convertView = infalInflater.inflate(R.layout.transfer_status_child_layout, parent, false);
                viewHolder = new TransferStatusViewHolder(convertView);
                break;
            case 3:
                convertView = infalInflater.inflate(R.layout.sort_by_date_child_layout, parent, false);
                viewHolder = new DateSortViewHolder(convertView);
                break;
            default:
                convertView = infalInflater.inflate(R.layout.booking_status_child_layout, parent, false);
                viewHolder = new BookingStatusViewHolder(convertView);
                break;
        }
        convertView.setTag(viewHolder);
    } else {
        // Reuse the existing ViewHolder
        viewHolder = (BaseViewHolder) convertView.getTag();
    }

    // Restore saved state for the date sort view
    if (groupPosition == 3) {
        ((DateSortViewHolder) viewHolder).restoreState();
    }

    // Add any other view population logic for other group positions here

    return convertView;
}

Additional Tips

  • State Persistence Across Config Changes: If you need to retain the sort state across screen rotations or other configuration changes, save currentSortState in a ViewModel or persist it in your adapter's data model.
  • Clean Up Unused Code: Remove redundant variables like childView, groupName, and unused view references to keep the code maintainable.
  • Correct Inflation: Using parent as the second parameter in inflate() ensures the layout uses the correct LayoutParams from the parent ExpandableListView.

内容的提问来源于stack exchange,提问作者singh.indolia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:50:59