1

我在复合组件中有 2 个 TextView 和一个 ImageView(扩展 LinearLayout)。

我希望整个组件都是可点击的,而不是单个包含的视图。

我在这个复合组件上设置的 onClick 监听器没有被调用,即使有视觉反馈表明该组件获得了触摸事件。

有任何想法吗 ?

更新:我的复合组件的代码:

public class HomeButton extends LinearLayout {
    TextView title;
    TextView subtitle;
    ImageView icon;

    public HomeButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray a = context.obtainStyledAttributes(attrs,
                R.styleable.HomeButton, 0, 0);
        String titleText = a.getString(R.styleable.HomeButton_title);
        String subtitleText = a
                .getString(R.styleable.HomeButton_subtitle);
        int iconResId = a.getResourceId(R.styleable.HomeButton_icon, 0);
        a.recycle();

        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(R.layout.home_button, this, true);

        title = (TextView) findViewById(R.id.home_button_title);
        title.setText(titleText);

        subtitle = (TextView) findViewById(R.id.home_button_subtitle);
        subtitle.setText(subtitleText);
        icon = (ImageView) findViewById(R.id.home_button_icon);
        icon.setImageResource(iconResId);
    }

    public void setTitle(String title) {
        this.title.setText(title);
    }

    public void setSubtitle(String subtitle) {
        this.subtitle
                .setVisibility(subtitle == null ? View.GONE : View.VISIBLE);
        this.subtitle.setText(subtitle);
    }

}

请参阅下面我自己的答案(我现在也在这里发布,因为我没有足够的代表来立即回答我自己的问题;))

解决办法,自己找的

问题是由于我为复合组件定义 XML 布局的方式。根是一个线性布局。

在 HomeButton 构造函数中扩展布局时,视图层次结构不是从 XML 中定义的 LinearLayout 开始,它有一个额外的根节点(我猜来自 HomeButton 类本身),XML 中定义的 LinearLayout 是第一个子节点这个根节点。

在 HomeButton 上设置 onClick 侦听器很好,但在这种情况下不需要这样做,因为 onClick 事件会被第一个子节点消耗......

从那里开始可能的解决方案:

  1. 删除根 LinearLayout 并使用合并标签
  2. 覆盖 setOnClickListener 以转发到第一个孩子
  3. 在第一个孩子上调用 setClickable(false)。

我选择使用第三种解决方案(但我已经测试过所有的工作),因为使用合并标签不允许按照我想要的方式设置样式。

public HomeButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray a = context.obtainStyledAttributes(attrs,
                R.styleable.HomeButton, 0, 0);
        String titleText = a.getString(R.styleable.HomeButton_title);
        String subtitleText = a
                .getString(R.styleable.HomeButton_subtitle);
        int iconResId = a.getResourceId(R.styleable.HomeButton_icon, 0);
        a.recycle();

        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(R.layout.home_button, this, true);

        title = (TextView) findViewById(R.id.home_button_title);
        title.setText(titleText);

        subtitle = (TextView) findViewById(R.id.home_button_subtitle);
        subtitle.setText(subtitleText);
        icon = (ImageView) findViewById(R.id.home_button_icon);
        icon.setImageResource(iconResId);

            // This made it work
            getChildAt(0).setClickable(false);
    }

解决方案 2 需要注意的一件事:如果您的 onClick 侦听器检查生成事件的视图的 id,您将不会获得您在 XML 中定义的 id(因为实际生成事件的视图是第一个子视图,而不是 HomeButton 视图),但您可以作弊并将 HomeButton 视图的 id 分配给第一个孩子...

4

3 回答 3

1

使用属性将布局设置为可点击

android:clickable=true

在您的 xml 中,或

setClickable(true)

以编程方式设置它。

您可能还想查看descendantFocusability以确定对其子级的点击将如何工作。

例如:

android:descendantFocusability="blocksDescendants"

为您提供:“ViewGroup 将阻止其后代接收焦点。”

于 2013-08-08T10:32:06.577 回答
1

解决办法,自己找的

问题是由于我为复合组件定义 XML 布局的方式。根是一个线性布局。

在 HomeButton 构造函数中扩展布局时,视图层次结构不是从 XML 中定义的 LinearLayout 开始,它有一个额外的根节点(我猜来自 HomeButton 类本身),XML 中定义的 LinearLayout 是第一个子节点这个根节点。

在 HomeButton 上设置 onClick 侦听器很好,但在这种情况下不需要这样做,因为 onClick 事件会被第一个子节点消耗......

从那里开始可能的解决方案:

  1. 删除根 LinearLayout 并使用合并标签
  2. 覆盖 setOnClickListener 以转发到第一个孩子
  3. 在第一个孩子上调用 setClickable(false)。

我选择使用第三种解决方案(但我已经测试过所有的工作),因为使用合并标签不允许按照我想要的方式设置样式。

public HomeButton(Context context, AttributeSet attrs) {
    super(context, attrs);
    TypedArray a = context.obtainStyledAttributes(attrs,
            R.styleable.HomeButton, 0, 0);
    String titleText = a.getString(R.styleable.HomeButton_title);
    String subtitleText = a
            .getString(R.styleable.HomeButton_subtitle);
    int iconResId = a.getResourceId(R.styleable.HomeButton_icon, 0);
    a.recycle();

    LayoutInflater inflater = (LayoutInflater) context
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    inflater.inflate(R.layout.home_button, this, true);

    title = (TextView) findViewById(R.id.home_button_title);
    title.setText(titleText);

    subtitle = (TextView) findViewById(R.id.home_button_subtitle);
    subtitle.setText(subtitleText);
    icon = (ImageView) findViewById(R.id.home_button_icon);
    icon.setImageResource(iconResId);

    // This made it work
    getChildAt(0).setClickable(false);
}

解决方案 2 需要注意的一件事:如果您的 onClick 侦听器检查生成事件的视图的 id,您将不会获得您在 XML 中定义的 id(因为实际生成事件的视图是第一个子视图,而不是 HomeButton 视图),但您可以作弊并将 HomeButton 视图的 id 分配给第一个孩子...

于 2013-08-09T06:20:21.547 回答
-2

在您的活动中,请检查以下内容。

  1. On Click 方法是否被调用。
  2. 如果 1 成功,请检查您在点击方法中使用的相应 View ID 是否正确。
于 2013-08-08T10:42:48.717 回答