0

I've created a custom RelativeLayout view which I inflate with merge tags.
In this custom view I have a button which I want it to do something.
I've tried many things but the button simply refuses to be clicked.

The strange part is, I can find the views and change their visibility just fine.

Is it possible to click a button this way, or should it be done in a different way?

The things I've tried:

  • Anonymous innerclass for onClickListener
  • XML attribute for onClick
  • View onClick with onClickListener(this)
  • Check if it's clickable with code (it returns true)
  • Added clickable(true) to both XML and code.
  • Private context from constructor instead of getContext()
  • Moved logic from init() to onFinishInflate()
  • Used the view from inflater to find views
  • Switch from inflate() to LayoutInflater

Inflated custom view:

<?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>

Relevant part of the parent view:

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

The class file:

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();
        }
    }
Lars Celie
  • 622
  • 5
  • 17
  • 1
    Why do you use a merge tag here ? The layout you are using here is just for inflation in the CustomView, merge is not needed here. Is it working if you replace merge with a Layout type. – Henry Oct 20 '15 at 08:52
  • @Henry I used the merge tag because I read this [link](http://trickyandroid.com/protip-inflating-layout-for-your-custom-view/) that shows an extra layout in the hierarchy when you don't use merge tags. Also when I change merge to RelativeLayout, my TextView and Button is not visible. – Lars Celie Oct 20 '15 at 08:59
  • Give me a couple of hours. I will debug it and let you know. – Henry Oct 20 '15 at 09:37
  • I used tag and I got an exception while inflating. Kindly refer this to understand why to not use : http://stackoverflow.com/questions/14039162/android-xml-merge-layout-error-on-inflate – Henry Oct 20 '15 at 10:13
  • I didn't got any error message with merge though. – Lars Celie Oct 20 '15 at 12:00

1 Answers1

0

So I got it to work. Here are the things I did to make it work.

  1. Replace the merge tag with RelativeLayout, because you are inflating the layout to show inside a view. More info here: Android xml merge layout error on inflate

  2. You have set android:visibility="invisible", change that to android:visibility="visible" (This is just to get the view visible, you can later change it programatically)

  3. Add the below line to the init() method of your NoInternetView. You are inflating the layout with all the views, but only when you add this view, you will be able to see it.

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

Once you are done with this, the button will be visible and clicking on the button will be clickable. You can either use anonymous onClickListener or make the view implement the onClickListener and override the onClick() method. Anything works.

Community
  • 1
  • 1
Henry
  • 17,490
  • 7
  • 63
  • 98
  • this.addView(view) will cause a loop and eventually an Out of Memory exception. – Lars Celie Oct 20 '15 at 11:07
  • Not exactly. You have create a CustomView, that's a RelativeLayout. You need to show something on the screen, so you are inflating the layout in the CustomView. The problem is, inflating alone is not sufficient. You need to add that inflated view to the CustomView. I think you are doing some thing wrong somewhere else. I ran your code after making all these modification. Works fine for me. – Henry Oct 20 '15 at 11:50
  • Does it make any difference that this layout is loaded onto a fragment layout? – Lars Celie Oct 20 '15 at 12:02
  • No it shouldn't make any difference. – Henry Oct 20 '15 at 12:06
  • i don't see a log 'onFinishInflate' and the last log is 'Init'. Somehow this is causing a loop. My current layout looks like this: Activity -> fragment -> custom layout – Lars Celie Oct 20 '15 at 12:12
  • In that case, I need to look at the complete code to see what's wrong. – Henry Oct 20 '15 at 12:22
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/92859/discussion-between-xeforine-and-henry). – Lars Celie Oct 20 '15 at 12:24