setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { // ignore all touch events return true; } }); This will ignore all touch events happening on the relative layout (and all of its children) which includes simple touch down then release events (called clicks).
clickable - Defines whether this view reacts to click events. Must be a boolean value, either "true" or "false".
When you say click do you actually mean touch? Touch events are done element by element. They're first sent to the top level, which says if it handled it and if it didn't it goes onto each children of the view.
When a touch event is created, the onTouch
method of view in the chain is called, if any of these return true (true meaning "I handled this!") it stops going down to the children.
To make your relativelayout block touches and clicks for all of its children you simply need to set the onTouchListener, like this:
YOUR_RELATIVE_LAYOUT.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// ignore all touch events
return true;
}
});
This will ignore all touch events happening on the relative layout (and all of its children) which includes simple touch down then release events (called clicks).
I found an alternative way to achieve this. You may create a blocking LinearLayout on top all its sibling views in the RelativeLayout like below:
<RelativeLayout
android:id="@+id/rl_parent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- the children views begins -->
...
<!-- the children views ends -->
<LinearLayout
android:id="@+id/ll_mask"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent"
android:clickable="true"
android:orientation="horizontal"
android:visibility="visible"/>
</RelativeLayout>
Later you may toggle the LinearLayout's visibility to GONE to allow the children views to be clickable again:
mMask.setVisibility(View.VISIBLE); // blocks children
mMask.setVisibility(View.GONE); // children clickable
You can use following function to find all the child view and cancel click.
public void setClickable(View view) {
if (view != null) {
view.setClickable(false);
if (view instanceof ViewGroup) {
ViewGroup vg = ((ViewGroup) view);
for (int i = 0; i < vg.getChildCount(); i++) {
setClickable(vg.getChildAt(i));
}
}
}
}
A very simple and full-proof way to do it is to create a sub class and override onInterceptTouchEvent
:
public class MyRelativeLayout extends RelativeLayout {
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// true if you do not want the children to be clickable.
return mShouldInterceptAllTouch;
}
}
No need to call any of the children's methods.
You can still call setOnClickListener
on your myRelativeLayout
object. Also, you can use the class in XMLs as if you were using a RelativeLayout
An easy Kotlin extension solution to disable/enable a view and all of it's children:
fun View.isUserInteractionEnabled(enabled: Boolean) {
isEnabled = enabled
if (this is ViewGroup && this.childCount > 0) {
this.children.forEach {
it.isUserInteractionEnabled(enabled)
}
}
}
and call it with:
view.isUserInteractionEnabled(false)
If you want the children of a ViewGroup
to be unresponsive to touch events, but you want the ViewGroup
itself to respond to clicks, for example, you can create your own ViewGroup
subclass, override onInterceptTouchEvent()
, and always return true
. This will intercept all touch events before children see them, while allowing your custom ViewGroup
to remain responsive to touch events.
So, instead of RelativeLayout
, you could use your own subclass:
public class ControlFreakRelativeLayout extends RelativeLayout {
private boolean mWithholdTouchEventsFromChildren;
// Constructors omitted for sake of brevity
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mWithholdTouchEventsFromChildren || super.onInterceptTouchEvent(ev);
}
public void setWithholdTouchEventsFromChildren(boolean withholdTouchEventsFromChildren) {
mWithholdTouchEventsFromChildren = withholdTouchEventsFromChildren;
}
}
Problem : same as original question, but different use case. i want to progressBar widget which in container with transparent background colors. i want to disable all clicks on other items which comes under my transparent background color .
solution : just set your container clickable in my case Relative layout, it can any other layout too, keep your layout clickable true, until you want according to condition in my case till api call completed. after it simply set your parent clickable false.
android xml
<RelativeLayout
android:id="@+id/rl_parent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- the children views begins -->
...
<!-- the children views ends -->
</RelativeLayout>
Java:
rl_parent.setClickable(true); // when to disable all clicks of children view
rl_parent.setClickable(false); // when to enable all clicks of children view
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With