Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shouldn't there be an option for Fragments to retain click events within their view hierarchy?

After seeing a couple questions here on SO regarding Fragments "passing" their click events down to clickable Views in underlying Fragments, I recalled that I once encountered this problem. What is actually happening is that if a user clicks on a blank area of the top most Fragment, since its ViewGroup is not clickable, the event will be handled by the clickable View (i.e. Button) that is conveniently placed just below the user's finger. I fixed it by making the top Fragment's ViewGroup clickable. Back then I didn't give it much thought, but this solution seems a bit "hacky".

I understand that it is normal behavior for a View that is non clickable by default to not intercept click events, but one would think that given that one big use for Fragments is to display the view hierarchy (a task done by the Activity only before) that it will resemble an Activity in this sense. When one Activity fires the Intent to create a new Activity, and then this Activity is on the screen, no click events are delivered to the underlying Activity. I realize that an Activity can contain many Fragments that may not fill the whole screen or even have no xml, but sometimes click events are only meant to be retained by the top most Fragment.

With all that said, here come the questions:

1) Is setting the ViewGroup on the top most Fragment to be clickable the best way to solve this?

2) Does this feature exist and I am not aware of it? And if not, should it?

like image 702
Emmanuel Avatar asked Jan 15 '14 17:01

Emmanuel


People also ask

Why we use fragments instead of activities?

Like activities, they have a specific lifecycle, unlike activities, they are not top-level application components. Advantages of fragments include code reuse and modularity (e.g., using the same list view in many activities), including the ability to build multi-pane interfaces (mostly useful on tablets).

When should Fragments be used?

January 5, 2021. According to the Android documentation, a fragment is a part of applications user interface that is bound to an activity. Fragments have their lifecycle and layouts or UI components. Fragments help enrich your UI design, pass data between different screens, and adapt to different device configurations.

What are retained fragments?

A Fragment represents a reusable portion of your app's User Interface. Retained Fragment consists of the configuration change that causes the underlying Activity to be destroyed. The term "retained" refers to the fragment that will not be destroyed on configuration changes.

Can a fragment without a layout can be attached to an activity?

A fragment is not required to be a part of the Activity layout ; you may also use a fragment without its own UI as an invisible worker for the Activity but it needs to be attached to an Activity in order to appear on the screen. Save this answer.


1 Answers

Is setting the ViewGroup on the top most Fragment the best way to solve this?

Assuming that your UI is akin to the UI from the question you linked to, the UI is written improperly.

My take on the UI from that question is that the developer has two fragments, A and B, each of which fill the screen. A is there initially, with the three buttons at the bottom. The developer then calls add() to display B, where B has an opaque black background.

This is dumb on a few levels. Not only do you run into this touch event propagation issue, but you have overdraw problems, because Android is going to render the buttons, then render the black background on top of them.

The right answer here is to have B replace() A.

(I realize that the developer actually does not have a fragment A, but has those widgets in the activity, which adds another level of sketchiness to that UI)

More generally, I would not have fragments, or anything else, higher on the Z axis with the intent to hide underlying widgets. So, for example, having a full-screen VideoView, with a pop-up MediaController higher on the Z axis is fine, because touch events destined for the controller would be picked up by the controller, yet the user can still tap on portions of the VideoView not blocked by the controller. Conversely, I would not implement a tabbed Web browser by having one WebView overlay another WebView on the Z axis -- either there would only be one WebView, or there would only be one visible WebView (with the other removed from the view hierarchy or marked as View.GONE).

When one Activity fires the Intent to create a new Activity, and then this Activity is on the screen, no click events are delivered to the underlying Activity.

That is because there is no "underlying activity" in terms of the view hierarchy. More technically, each activity is in its own Window, and so even if the top-most Window does not fill the screen (e.g., dialog-themed activity), the "underlying activity" is visible but cannot receive touch events.

I realize that an Activity can contain many Fragments that may not fill the whole screen or even have no xml, but sometimes click events are only meant to be retained by the top most Fragment.

Then there should not be anything underneath "the top most Fragment", IMHO. Use replace(), not add(), when doing this sort of UI switch. Or, use a DialogFragment, if you want to temporarily have something modal take over foreground input (as a dialog gets its own Window, if I understand correctly). Do not just paint a solid background and pretend that other widgets, now painted over, do not exist.

Does this feature exist and I am not aware of it?

No, because fragments are not ViewGroups and therefore are not involved in managing the routing of touch events.

And if not, should it?

IMHO, no, though you're welcome to file an issue for it.

like image 50
CommonsWare Avatar answered Dec 16 '22 06:12

CommonsWare