Android复合组件和onclick

时间:2013-08-08 10:28:33

标签: android custom-component

我在复合组件中有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布局。根是LinearLayout。

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

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

可能的解决方案:

  1. 删除根LinearLayout并使用合并标记
  2. 覆盖setOnClickListener以转发给第一个孩子
  3. 在第一个孩子身上调用setClickable(false)。
  4. 我选择使用第3种解决方案(但我已经测试了所有工作),因为使用合并标记不允许按照我想要的方式设置样式。

    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分配给第一个孩子......

3 个答案:

答案 0 :(得分:1)

使用属性

将布局设置为可点击
android:clickable=true
你的xml中的

setClickable(true)

以编程方式设置。

您可能还需要查看descendantFocusability以确定其子项的点击次数是如何工作的。

例如:

android:descendantFocusability="blocksDescendants"

给你:“ViewGroup将阻止其后代获得焦点。”

答案 1 :(得分:1)

解决方案,由我自己找到

问题是由于我定义了复合组件的XML布局。根是LinearLayout。

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

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

可能的解决方案:

  1. 删除根LinearLayout并使用合并标记
  2. 覆盖setOnClickListener以转发给第一个孩子
  3. 在第一个孩子身上调用setClickable(false)。
  4. 我选择使用第3种解决方案(但我已经测试了所有工作),因为使用合并标记不允许按照我想要的方式设置样式。

    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分配给第一个孩子......

答案 2 :(得分:-2)

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

  1. 是否调用On Click方法。
  2. 如果1成功,请检查您在点击方法中使用的相应视图ID是否正确。