简体   繁体   English

(Expandable)ListView中的自定义CompoundButton是不可单击的(但CheckBox是可单击的)

[英]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. 我有一个即将完成的应用程序,该应用程序使用ExpandableListView,并且每个子行都有一个切换按钮。 I can use a CheckBox or a ToggleButton fine, but the underlying CompoundButton does not support horizontal centering of the button graphic (wtf?). 我可以很好地使用CheckBox或ToggleButton,但是底层的CompoundButton不支持按钮图形(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 . 我认为缺少的魔术是自定义控件的默认样式的属性的自动应用 ,特别是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 . 快速修复:小部件的构造函数中的setClickable(true) ,除非android:clickable已显式设置为false One could argue that a Button be clickable by default, or 有人可能会争辩说默认情况下Button是可单击的,或者

  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 : 对于2,请确保您在style_imagetoggle.xml中为自定义窗口小部件定义了默认样式,该样式具有“可点击”样式,例如Widget.CompoundButton为父级,或直接设置android:clickable = true

<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 注意:以下可能是为什么需要所有这些的原因: 问题12683:View类构造函数的defStyle参数出现问题

Is this issue specifically if your custom checkbox in your groupView rows? 如果您的groupView行中的自定义复选框是否特别是此问题? 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). 您的复选框必须设置为不可聚焦并且不能直接与groupview展开/折叠指示器相邻(尝试在它们之间放置textview或其他内容)。 For some reason, it's like they're fighting for dominance over what to express upon clicking. 出于某种原因,这就像是他们在争夺点击时要表达的内容的主导地位。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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