I have a ListView with video items. When user clicks the image of the Video it goes to a new screen and starts playing the video. If user clicks a button next to the video image then I display a BottomSheet from google design library. Because I want to apply a shadow when bottomSheet is expanded I have a View with a transparent dark overlay just above the ListView, which initially has visibility set to Gone and I change it to Visible when I expand BottomSheet.
The problem is that despite the shadow layer items below it can still get click events which is a behavior I want to prevent. Is there a solution for this ? Maybe an attribute for that view so when its visible won't let touch events happen ?
Hey if you want to disable the touch intercept capability of view by you self. If it is a button or Views like Linearlayout, RelativeLayout just use view.setClickable(false) once you hide the view. Otherwise views intecept touch events even ,if they are not visible(Given that none other views are intercepting touch event for that portion of screen).
Related
I have created an activity that will be used as a screen to display a custom-designed modal. The entire background of this activity will be a 30% black overlay view that should be tappable to dismiss the activity.
Here's a screen of the simple layout:
In onCreate, I added a setOnClickListener to the overlay:
overlayView.setOnClickListener {
println("tapped")
}
The overlay is receiving taps, which is desired, however the white 'modal' view is also receiving taps, which is not desired.
As you can see from the component tree in the above screenshot, I'm using a view (overlayView), and then above it, using a ConstraintLayout with a nested textView. I would think that since the white modal is above the overlayView, it would not be receiving taps from overlayView.
How can I structure / organize my component tree so that I can detect taps from just the overlayView, and not the white modal?
In general, touch events will go "through" views until they find one that actually handles the event. In this case, even though you're tapping on the modal view, the click event will go to the background overlay because the modal view doesn't do anything to intercept the event.
You can solve this by adding a do-nothing click listener to the modal view:
modalView.setOnClickListener { }
This causes the modal view to receive any click events on it and handle them, stopping them from going "through" to the background overlay view.
I was trying to make an area so when ToggleButton is on, you are able to toggle buttons within this area and if ToggleButon is off, you won't be able to toggle the buttons within this area.
For this specific area I used a FrameLayout, so I can stack two LinearLayout on top of each other. So when I hit the Edit-Button, the one on top which is half transparent disappears with setVisibility(View.GONE) and you are now allowed to click the buttons now.
PROBLEM: The buttons in this area are always clickable
I was able to toggle them separately with button.setClickable(true/false) but is there a solution so you just can't click through the LinearLayout that is on top (like "not-through-clickable")?
Link to an image of the Layout: https://i.imgur.com/eTyhCDc.png
Desired behavior:
Hit EDIT -> half transparent Layout on top of blue Layout disappears -> TESTOFF1 and TESTOFF2 are now clickable.
-> Hit DONE -> the half transparent Layout appears on top again and the buttons below it are not clickable anymore (without using .setClickable for every single button).
The view on top gets first crack at any touch events. If the top view doesn't handle the touch then the view below get a chance on down to the bottom view. The top layer is a LinearLayout so, but default, it doesn't handle touches, so it allows the touch events to percolate down to the buttons which are happy to respond.
One way to resolve this is to place a touch listener on the semi-transparent view that just returns true. Thus, the LinearLayout will consume the events and not let the buttons see them.
When the view is gone, the buttons become the top view so they will see the clicks.
If you want to know more about how touch events are handled, read this Stack Overflow answer for an excellent explanation.
editButton.setOnClickListener {
button1.isEnabled = !button1.isEnabled
button2.isEnabled = !button2.isEnabled
editButton.setText(
if (button1.isEnabled) {
R.string.done
} else {
R.string.edit
}
)
transparentView.isInvisible = button1.isEnabled
}
This example is using kotlin and the Android KTX libraries
Java version
editButton.setOnClickListener(new OnClickListener {
button1.setEnabled(!button1.isEnabled());
button2.setEnabled(!button2.isEnabled());
editButton.setText(button1.isEnabled() ? R.string.done : R.string.edit);
transparentView.setVisibility(button1.isEnabled() ? View.INVISIBLE : View.VISIBLE);
});
Here's my current situation: I can't click on the toolbar because there is a view that is overlapping it intercepting the touch responses. I'll expand: I'm making a music app. In the music app, there is a list of songs that is beneath the toolbar. However, once you click on a song, a panel opens up and slides up over the toolbar and continues into a transparent status bar. Pictures of this will be attached.
Now, obviously because this view is overlapping the toolbar I cannot actually use the toolbar for any touch events. But I need to. I cannot move the view below the toolbar because then my sliding up panel is limited to beneath the toolbar instead of overlapping it. If there is anyway to get around this, please let me know. I'd very much appreciate it.
So, in my current situation, I thought maybe I'd be able to touch the portion of the view that covers the toolbar and send that data to the view that contains the toolbar so I can detect touches on the toolbar. However, I cannot figure out how to do this, or even if it is possible.
My question is: How can I detect touches in the view beneath another view?
Here are the pictures:
Here is the list of songs:
And here is when the song panel is opened(I'm using an image of a tiger for any song that doesn't have art at the moment):
Thanks!
wtf?
You want that your user can touch on the toolbar which is not visible at the moment because its overlapped by another view? What kind of user would expect such a user experience?
I mean:
How does the user even know that he can click on a not visible element ^^
If the user magically knows somehow that he can click, how does he know where exactly he has to click. For example, he could also click on one of the toolbar menu items, but if he clicks a few pixel more left, then he would click on toolbar item 1 instead of toolbar item 2.
However, you have three possibilities:
You can make the overlapping view not clickable by overlappingView.setClickable(false);.
You could add a transparent view with an OnClickListener that has the same width and height as the toolbar over the overlapping view. In the OnClickListener you could simply invoke the desired method like onOptionsItemSelected() (fake the required parameters) or use an EventBus for communication.
Similar to the 2. option add a transparent view, but instead of setting a OnClickListener set a OnTouchListener by extending from View) and forward the MotionEvent to the Toolbar by calling toolbar.onTouchEvent(motionEvent);
If you really want to detect touch events of a view beneath another view you could set onTouchEvent of the foreground view to false. However, I advise you to rethink the layout in order to put the Toolbar on top so the users can see it otherwise they don't know what they are clicking on.
I have a SlidingDrawer that pops up from the bottom of the screen and fills the screen about 80%. Even though the SlidingDrawer view is in focus, it is still possible to click on items, buttons and other elements in the view that is behind the SlidingDrawer. When SlidingDrawer is active/pulled up/in focus, I want to disable the entire view behind it so it will not be able to recieve clicks and touches. Is there a good way to disable an entire view? I have tried setEnable(false) and setClickable(false) but neither of them work.
Grab the LinearLayout that holds the contents and add a click listener. Have the click listener respond to clicks (throw away, whatever) - and this then stops it propagating to the view below the sliding drawer - it works for me - and it doesn't block the other items in the drawer.
Other way is to put SlidingDrawer in the RelativeLayout, instead of LinearLayout. And set mySlidingDrawer.bringToFront() in opening method.
I am using a CustomSlider in my app, and I have set it to be invisible.
When the user drags it or touches it (from top to bottom), my application needs to make the slider visible. Is this possible? How would I achieve it?
I needed to do this with an ImageView and still get touch events. The solution was to setAlpha(0.0f) to hide the image and still get events.
The touch event will be detected on the visible Views of your activity. While a View instance is hidden / invisible, you cannot interact with it.
You need a motion handler on the parent view / visible view to determine whether you need to show the slider (in case the motion is vertical) or not.