Java – Android button cannot be clicked

Android button cannot be clicked… here is a solution to the problem.

Android button cannot be clicked

I’m creating an application that uses a toolbar, such as a fragment at the top and a couple of buttons. These buttons are added programmatically.

The problem is that when I launch the application, the toolbar and buttons appear, but I can’t click the buttons. When the mouse hovers over the button (I use the emulator) or clicks, they don’t change at all and don’t notify my OnClickListener. However, the buttons and other components in the fragment below it work fine.

The Toolbar’s code:

public class ToolbarFragment extends Fragment implements 
View.OnClickListener{

public static final String LOG_KEY = "SM_TOOLBAR";

public static final String TO_ADD_FEED_KEY = "TO_ADD_FEED_KEY";
public static final String TO_ADD_PROFILE_KEY = "TO_ADD_PROFILE_KEY";
public static final String TO_ADD_FRIENDS_KEY = "TO_ADD_FRIENDS_KEY";

private Button feed;
private Button profile;
private Button friends;
private Button logout;

public ToolbarFragment() {
     Required empty public constructor
}

private Button addButton(int stringID, LinearLayout linearLayout) {
    Button button = new Button(getContext());
    button.setText(stringID);
    button.setOnClickListener(this);
    linearLayout.addView(button);
    return button;
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
     Inflate the layout for this fragment
    LinearLayout linearLayout = (LinearLayout)inflater.inflate(R.layout.fragment_toolbar, container, false);

Bundle arguments = getArguments();
    if (arguments.getBoolean(TO_ADD_FEED_KEY)) {
        Log.i(LOG_KEY, "Created feed key");
        feed = addButton(R.string.feed, linearLayout);
    }
    if (arguments.getBoolean(TO_ADD_PROFILE_KEY)) {
        Log.i(LOG_KEY, "Created profile Key");
        profile = addButton(R.string.profile, linearLayout);
    }
    if (arguments.getBoolean(TO_ADD_FRIENDS_KEY)) {
        Log.i(LOG_KEY, "Created friends key");
        friends = addButton(R.string.friends, linearLayout);
    }
    logout = addButton(R.string.logout, linearLayout);

return linearLayout;
}

@Override
public void onClick(View view) {
    Log.i(LOG_KEY, "A button was clicked.");
    if (getActivity() instanceof IToolbarCallback) {
        IToolbarCallback itc = (IToolbarCallback) getActivity();
        if (view.equals(feed)) {
            itc.feed();
        }
        if (view.equals(profile)) {
            itc.profile();
        }
        if (view.equals(friends)) {
            itc.friends();
        }
        if (view.equals(logout)) {
            itc.logout();
        }
    }
}

There’s no other code pertinent to this, besides the callback
interface.

public interface IToolbarCallback {

void feed();

void profile();

void logout();

void friends();

This is just used to let the host activity know what was clicked.
Finally, the XML:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="project3.csc214.project23.Fragments.Toolbar.ToolbarFragment"
android:orientation="horizontal">

I use a builder for the fragment, and here’s the code:

public class ToolbarBuilder {

private boolean addFeed;
private boolean addProfile;
private boolean addFriends;

private FragmentManager fragmentManager;
private int addToID;

public ToolbarBuilder(FragmentManager fragmentManager, int addToID) {
    this.fragmentManager = fragmentManager;
    this.addToID = addToID;
    addFeed = false;
    addProfile = false;
    addFriends = false;
}

public ToolbarBuilder addFeed() {
    addFeed = true;
    return this;
}

public ToolbarBuilder addProfile() {
    addProfile = true;
    return this;
}

public ToolbarBuilder addFriends() {
    addFriends = true;
    return this;
}

public void build() {
    Bundle bundle = new Bundle();
    bundle.putBoolean(ToolbarFragment.TO_ADD_FEED_KEY, addFeed);
    bundle.putBoolean(ToolbarFragment.TO_ADD_FRIENDS_KEY, addFriends);
    bundle.putBoolean(ToolbarFragment.TO_ADD_PROFILE_KEY, addProfile);
    ToolbarFragment toolbarFragment = new ToolbarFragment();
    toolbarFragment.setArguments(bundle);
    fragmentManager.beginTransaction().add(addToID, toolbarFragment).commit();
}

To clarify, as far as I know, these buttons do not receive any input. Not only did they not call onClick, they didn’t use react in any way at all. As far as I can tell, onClick is set up correctly, the button is just broken on some basic level.

The plot thickens. Using the exact same settings in other activities seems to work fine… As far as I know, nothing has changed.

Anyway, I decided to hardcode this activity so that I could continue to use other parts of the application. Thank you all for your consideration. If I figure out what’s going on, I’ll post again.

Solution

Instead of comparing Views to see if they are equal, compare IDs. Here:

@Override
public void onClick(View view) {
    Log.i(LOG_KEY, "A button was clicked.");
    if (getActivity() instanceof IToolbarCallback) {
        IToolbarCallback itc = (IToolbarCallback) getActivity();
        if (view.equals(feed)) {
            itc.feed();
        }
        if (view.equals(profile)) {
            itc.profile();
        }
        if (view.equals(friends)) {
            itc.friends();
        }
        if (view.equals(logout)) {
            itc.logout();
        }
    }
}

It should be:

@Override
public void onClick(View view) {
    Log.i(LOG_KEY, "A button was clicked.");
    if (getActivity() instanceof IToolbarCallback) {
        IToolbarCallback itc = (IToolbarCallback) getActivity();
        if (view.getId() == feed.getId()) {
            itc.feed();
        }
        if (view.getId() == profile.getId()) {
            itc.profile();
        }
        if (view.getId() == friends.getId()) {
            itc.friends();
        }
        if (view.getId() == logout.getId()) {
            itc.logout();
        }
    }
}

In addition, when you create the Views yourself, you need to provide IDs for them. If you’re using API level 17+, you can simply call generateViewId() on View and Android will create a unique ID for you.
So do this:

private Button addButton(int stringID, LinearLayout linearLayout) {
    Button button = new Button(getContext());
    button.setText(stringID);
    button.setOnClickListener(this);
    linearLayout.addView(button);
    button.generateViewId();
    return button;
}

Edit:
Aside from what I specified above, your code looks pretty good. One thing I’ll try is setting up the listener outside of your addButton method:

private Button addButton(int stringID, LinearLayout linearLayout) {
    Button button = new Button(getContext());
    button.setText(stringID);
    linearLayout.addView(button);
    button.generateViewId();
    return button;
}

if (arguments.getBoolean(TO_ADD_FEED_KEY)) {
        Log.i(LOG_KEY, "Created feed key");
        feed = addButton(R.string.feed, linearLayout);
        feed.setOnClickListener(this);
    }
    if (arguments.getBoolean(TO_ADD_PROFILE_KEY)) {
        Log.i(LOG_KEY, "Created profile Key");
        profile = addButton(R.string.profile, linearLayout);
        profile.setOnClickListener(this);
    }
    if (arguments.getBoolean(TO_ADD_FRIENDS_KEY)) {
        Log.i(LOG_KEY, "Created friends key");
        friends = addButton(R.string.friends, linearLayout);
        friends.setOnClickListener(this);
    }
    logout = addButton(R.string.logout, linearLayout);
    logout.setOnClickListener(this);

If that doesn’t work, try checking if any other View at the top of your button is intercepting click events.

Related Problems and Solutions