0

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);
        }
    }
}
Staffan
  • 939
  • 1
  • 8
  • 9

2 Answers2

1

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 e.g. 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

Community
  • 1
  • 1
Dion
  • 159
  • 3
  • Thank you, it too me some time to get back to you, but this is a great, clear and exhaustive answer. I made a small test and android:clickable worked exactly as you described. – Staffan Sep 30 '14 at 14:36
0

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.

mango
  • 5,577
  • 4
  • 29
  • 41
  • No, as I wrote, it's in a child view, not the group. I've tried setting it to non-focusable both in xml and in code, but this has no effect (Note that just replacing "mybutton" with a CheckBox or a ToggleButton *does* work, it's just that you can't center the button graphic in those) – Staffan Nov 19 '12 at 14:42