【问题标题】:Android custom view with button not clickable带有按钮不可点击的Android自定义视图
【发布时间】:2015-10-20 08:07:34
【问题描述】:

我创建了一个自定义的RelativeLayout 视图,我用merge 标签进行了扩展。
在这个自定义视图中,我有一个按钮,我希望它做一些事情。
我尝试了很多东西,但按钮就是拒绝点击。

奇怪的是,我可以很好地找到视图并更改它们的可见性。

是否可以通过这种方式单击按钮,还是应该以其他方式完成?

我尝试过的事情:

  • onClickListener 的匿名内部类
  • onClick 的 XML 属性
  • 查看onClickonClickListener(this)
  • 用代码检查是否可以点击(返回true)
  • 在 XML 和代码中添加了 clickable(true)
  • 来自构造函数而不是 getContext() 的私有上下文
  • 将逻辑从 init() 移动到 onFinishInflate()
  • 使用 inflater 的视图来查找视图
  • inflate() 切换到LayoutInflater

膨胀的自定义视图:

<?xml version="1.0" encoding="utf-8"?>
<merge
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/internet_view_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="@string/internet_offline"/>

    <custom.IconView
        android:id="@+id/internet_view_icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="ICON"
        android:visibility="invisible"
        android:layout_below="@+id/internet_view_text"/>

    <Button
        android:id="@+id/internet_view_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="BUTTON"
        android:clickable="true"
        android:layout_below="@+id/internet_view_text"/>
</merge>

父视图的相关部分:

<custom.NoInternetView
    android:id="@+id/webview_no_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:visibility="invisible"
    app:automaticReconnect="false"/>

类文件:

public class NoInternetView extends RelativeLayout implements View.OnClickListener {

    private static final String TAG = NoInternetView.class.getSimpleName();

    private static ConnectivityChangeListener listener;
    private static boolean automaticReconnect;
    private Context mContext;
    private View view;

    private Button button;

    public NoInternetView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.NoInternetView, defStyleAttr, 0);
        automaticReconnect = a.getBoolean(R.styleable.NoInternetView_automaticReconnect, false);
        a.recycle();
        init();
    }

    public NoInternetView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public NoInternetView(Context context) {
        this(context, null);
    }

    @Override
    protected void onFinishInflate() {
        Log.d(TAG, "onFinishInflate");
        super.onFinishInflate();

        button = (Button) view.findViewById(R.id.internet_view_button);
        button.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d(TAG, "Clicked on some Button");
                if (listener != null && NetworkHelper.hasAccess(getContext())) {
                    listener.connected();
                }
            }
        });
        button.setClickable(true);

        boolean clicked = button.callOnClick();
        Log.d(TAG, "clicked: "+clicked);

        TextView text = (TextView) view.findViewById(R.id.internet_view_icon);
        text.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d(TAG, "Clicked on some TextView");
                if (listener != null && NetworkHelper.hasAccess(getContext())) {
                    listener.connected();
                }
            }
        });

        //check if the attribute 'automaticReconnect' is set to true
        //if so, show an icon instead of a button
        if (automaticReconnect){
            button.setVisibility(INVISIBLE);
            view.findViewById(R.id.internet_view_icon).setVisibility(VISIBLE);
        }

    }

    public void init(){
        Log.d(TAG, "init");
        view = LayoutInflater.from(mContext).inflate(R.layout.no_internet_view, this, false);
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        Log.d(TAG, "something happened?");
        return super.dispatchKeyEvent(event);
    }

    @Override
    public void onClick(View v) {
        Log.d(TAG, "Clicked on Button(TextView)");
        if (listener != null && NetworkHelper.hasAccess(getContext())){
            listener.connected();
        }
    }

【问题讨论】:

  • 为什么在这里使用合并标签?您在此处使用的布局仅用于 CustomView 中的膨胀,此处不需要合并。如果您将合并替换为布局类型,它是否有效。
  • @Henry 我使用了合并标签,因为我阅读了这个link,当您不使用合并标签时,它会在层次结构中显示一个额外的布局。此外,当我将合并更改为 RelativeLayout 时,我的 TextView 和 Button 不可见。
  • 给我几个小时。我会调试它并告诉你。
  • 我使用了 标签,但在充气时出现异常。请参考此内容以了解为什么不使用 stackoverflow.com/questions/14039162/…
  • 我没有收到任何合并错误消息。

标签: android android-layout android-custom-view android-button android-inflate


【解决方案1】:

所以我让它工作了。以下是我为使其发挥作用所做的事情。

  1. merge 标记替换为RelativeLayout,因为您正在扩展布局以显示在视图中。更多信息在这里:Android xml merge layout error on inflate

  2. 您已设置android:visibility="invisible",将其更改为android:visibility="visible"(这只是为了让视图可见,您可以稍后以编程方式更改它)

  3. 将以下行添加到 NoInternetView 的 init() 方法中。您正在用所有视图膨胀布局,但只有当您添加此视图时,您才能看到它。

    public void init(){
           Log.d(TAG, "init");
           view = LayoutInflater.from(mContext).inflate(R.layout.no_internet_view, this, false);
           this.addView(view);}
    

完成此操作后,该按钮将可见,并且单击该按钮将是可单击的。您可以使用匿名onClickListener 或使视图实现onClickListener 并覆盖onClick() 方法。一切正常。

【讨论】:

  • this.addView(view) 将导致循环并最终导致内存不足异常。
  • 不完全是。您已经创建了一个 CustomView,它是一个 RelativeLayout。你需要在屏幕上显示一些东西,所以你在 CustomView 中夸大了布局。问题是,仅仅膨胀是不够的。您需要将该膨胀视图添加到 CustomView。我认为您在其他地方做错了什么。在进行所有这些修改后,我运行了您的代码。对我来说很好。
  • 将此布局加载到片段布局有什么不同吗?
  • 不,应该没什么区别。
  • 我没有看到日志“onFinishInflate”,最后一个日志是“Init”。不知何故,这导致了一个循环。我当前的布局如下所示:Activity -> 片段 -> 自定义布局
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-10
  • 1970-01-01
  • 2014-08-30
相关资源
最近更新 更多