简体   繁体   中英

Custom CompoundButton in (Expandable)ListView is not clickable (but a CheckBox is)

I have a nearly finished app that uses an ExpandableListView, and a single toggle button per each child row. I can use a CheckBox or a ToggleButton fine, but the underlying CompoundButton does not support horizontal centering of the button graphic (wtf?). So I built my own, but somehow using it instead renders it unclickable in the listview.

In a regular layout, the custom compoundbutton works perfectly.

Some magic incantation appears missing and I'm not quite sure what that would be. I'll thank you for any insights.

package net.shangtai.listener;

import android.widget.CompoundButton;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.Gravity;

class ImageToggle extends CompoundButton {
    private Drawable buttonDrawable;

    public ImageToggle(Context context) {
        super(context, null);
    }
    public ImageToggle(Context context, AttributeSet attrs) {
        super(context, attrs, 0);
    }
    public ImageToggle(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public void setButtonDrawable(Drawable d) {
        super.setButtonDrawable(d);
        buttonDrawable=d;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (buttonDrawable != null) {
            final int gravity = getGravity();
            final int height = buttonDrawable.getIntrinsicHeight();
            final int width = buttonDrawable.getIntrinsicWidth();

            int top=0;
            int bottom=0;
            int left=getWidth();
            int right=getHeight();

            switch (gravity) {
                case Gravity.TOP:
                    top=0;
                    bottom=height;
                    break;
                case Gravity.BOTTOM:
                    top=getHeight() - height;
                    bottom=0;
                    break;
                case Gravity.CENTER_VERTICAL:
                    top=(getHeight() - height)/2;
                    bottom=top+height;
                    break;
                case Gravity.LEFT:
                    left=0;
                    right=width;
                    break;
                case Gravity.RIGHT:
                    left=getWidth() - width;
                    right=0;
                    break;
                case Gravity.CENTER_HORIZONTAL:
                    left=(getWidth() - width)/2;
                    right=left+width;
                    break;
                case Gravity.CENTER:
                    left=(getWidth() - width)/2;
                    right=left+width;
                    top=(getHeight() - height)/2;
                    bottom=top+height;
                    break;
            }

            buttonDrawable.setBounds(left, top, right, bottom);
            buttonDrawable.draw(canvas);
        }
    }
}

I think the magic that is missing is the automatic application of attributes from a default style for your custom widget, specifically android:clickable=true . Perhaps surprisingly, Buttons are not clickable by default; this is set through styling.

Now, if this is your problem, here are two ways how to fix this:

  1. quick fix: setClickable(true) in your widget's constructor(s), perhaps unless android:clickable has been explicitly set to false . One could argue that a Button be clickable by default, or

  2. more elaborate: follow the procedure outlined in the accepted answer of How to: Define theme (style) item for custom widget

For 2, make sure you define a default style for your custom widget in eg style_imagetoggle.xml that has a 'clickable' style such as Widget.CompoundButton for parent, or sets android:clickable=true directly :

<resources>
    <!-- Default style attribute values, can be expanded upon in themes -->
    <style name="Widget.CompoundButton.ImageToggle" parent="@android:style/Widget.CompoundButton" />
</resources>

Note: the following may be why all this is necessary: Issue 12683: Problem with the defStyle parameter of the View class constructor

Is this issue specifically if your custom checkbox in your groupView rows? Your checkbox must be set to non-focusable AND it can't be directly adjacent to the groupview expand/collapse indicator (try putting a textview or something between them). For some reason, it's like they're fighting for dominance over what to express upon clicking.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM