Apqu
Apqu

Reputation: 5031

Prevent Click-through of Android ImageVIew?

I have an ImageView overlay inside of a RelativeLayout and want to prevent any clicks from going through the ImageView to the Buttons etc that are behind it (thus in effect disabling the entire RelativeLayout).

Is the a simpler way of doing this then iterating the RelativeLayout views and setting them to disabled as I currently am doing using this code:

RelativeLayout rlTest = (RelativeLayout ) findViewById(R.id.rlTest);
for (int i = 0; i < rlTest.getChildCount(); i++) {
       View view = rlTest.getChildAt(i);
       view.setEnabled(true);
}

Upvotes: 30

Views: 32559

Answers (9)

Alan
Alan

Reputation: 362

In C#, I use an empty delegate:

view.Click += delegate {};

I haven't encountered any problems with it but it does prevent clicks from filtering through to underlying controls.

Upvotes: -1

RandomType
RandomType

Reputation: 57

you can also se the root click listener to null:

// Do not process clicks on other areas of this fragment
        binding.root.setOnClickListener(null)

This works 100%. It doesnt affect other listeners that are already set on the fragment's views.

Upvotes: 0

nilsi
nilsi

Reputation: 10761

You could use databindings and consume the clicks like this:

android:onClick="@{() -> true}"

Upvotes: 0

Markos Evlogimenos
Markos Evlogimenos

Reputation: 718

There is a much cleaner way

You can use:

android:onClick="preventClicks"

in XML and in your Activity

public void preventClicks(View view) {}

This works with fragments. Example inside this Activity has multiple fragments overlapping one another, just by adding the XML attribute in the background of your fragment it will still call the Activity.preventClicks and will prevent touches on fragments behind it

Upvotes: 17

user2154462
user2154462

Reputation:

Just add these two listeners:

    // Set an OnTouchListener to always return true for onTouch events so that a touch
    // sequence cannot pass through the item to the item below.
    view.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            v.onTouchEvent(event);
            return true;
        }
    });
    // Set an OnHoverListener to always return true for onHover events so that focus cannot
    // pass through the item to the item below.
    view.setOnHoverListener(new OnHoverListener() {
        @Override
        public boolean onHover(View v, MotionEvent event) {
            v.onHoverEvent(event);
            return true;
        }
    });

Upvotes: 2

Marchy
Marchy

Reputation: 3734

The following solution works in the general case:

_container.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        // NOTE: This prevents the touches from propagating through the view and incorrectly invoking the button behind it
        return true;
    }
});

It basically blocks any touches from propagating through the view by marking the touch event as handled. This works on both UI controls and layout containers (ie: LinearLayout, FrameLayout etc.).

The solution to set "clickable" as false did not work for me for layout containers either in code or in the view XML.

Upvotes: 10

Blackbelt
Blackbelt

Reputation: 157467

Simply call rlTest.setClickable(false). This will prevent the click to be propagate to the children

Upvotes: 23

Kirill Kulakov
Kirill Kulakov

Reputation: 10255

you can set the image to be

android:clickable="true"

Upvotes: 53

Parth Kapoor
Parth Kapoor

Reputation: 1504

I assume that you are using onClickListeners.

How about using onTouchListener instead of onClickListeners. By doing this you will have a control over how deep down in your hierarchy the touch even can be visible. For example, if you have toch listeners on a relative-layout(RL) and a image-view(IV)(contained in RL), and you assign touchListeners to both. Now if you return true from IV's touch event, the lower down member RL will not receive the touch event. However if you return false from from IV's touch event, the lower down member RL will receive the touch event.

Hope this helps!

Upvotes: 2

Related Questions