I'm trying to do a sort of infinite scroll. Each Fragment contains a scrolling WebView (or ScrollView), and when the user hits the bottom, I'd like to test for continued swiping to reveal the next Fragment below.
The user should not be able to go back, and I'm not interested in caching, so that rules out RecyclerView or ViewPager (modified to scroll vertically). I'm only concerned about managing the current Fragment, loading the next, and removing the last one once it's offscreen.
I want the next Fragment to follow the users touch, and I want the transition to abort if the user lets go below a certain threshold.
FragmentManager allows custom animations but they are non-interactive. I could perhaps write my own ViewGroup where I can manually animate a Fragment into position, and remove the previous Fragment manually, but I'm not sure if this is the best path forward.
Anyone have thoughts/tips on a good approach here?
I have two activities one with some data and the second one, semitrasparent with some buttons on it.
I want the second activity slide over the first one after the swipe gesture.
I've already read about ViewPager and it's not what I am looking for. I want the first activity still being visible over the semitrasparent second one.
I am looking for any suggestions how to do this.
Literally not possible.
The entire point of an Activity is that it fills the ENTIRE screen, and there are never 2 of them shown at the same time, ever.
So you can't swipe to "semi" open one with a slide animation.
To do that, you'll have to use 1 Activity, and multiple Fragments.
I have an Activity with two Fragments, where only one Fragment is shown at the same time. But the user can swipe between them.
The left Fragment is a MapFragment, and the user is able to scroll and zoom this as normal. But when the user starts a swipe touching the rightmost part of the screen, it will scroll to the other Fragment instead of scrolling the map.
In other words:
if (motionEvent.getX()<myFragment.getWidth()-SOME_VALUE) {
scroll the map
} else {
switch to the other Fragment
}
My question: What is a good value for the constant SOME_VALUE? Are there any system defined constants I can use?
Wild guess: SOME_VALUE should be a percentage of your screenwidth, for example 10%.
Most important is to test this on an actual device. I'm not sure if the user finds your described behaviour logical (I think I wouldn't).
I myself would probably choose a small menu bar at the top of the screen to be able to switch between the fragments. Then your swipe has become very simple without having to choose what to do depending on the position that started the swipe.
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?
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.
I've used ViewPager to let the user flip left and right to navigate among pages of a given activity.
Is it possible to programatically control the flow of pages of the ViewPager?
For exemple:
If the user didn't fill a given EditText on the current page, I don't want him to be able to navigate to the next one.
Another case: If the user is currently on page 1 and if hi filled a given EditText with a specific value and the user flip right to left, I want him to go straight to the 5th page instead of the 2nd one.
By "flipping" you mean dragging with a finger or just using the ViewPager for animation?
If it's the former, you'll have to dynamically edit the children of the ViewPager to get the effect you want. You can override onInterceptTouchEvent() to block touch events until a page is completed.
However, I recommend disabling finger-dragging in the ViewPager (perhaps using onInterceptTouchEvent()) and then using setCurrentItem(4, true) to show the animation and navigate to a specific page. The logic you need can be implemented using buttons which will call setCurrentItem(4, true). For example, you can have a "Next->" button that is grayed out unless the form is completely completed. That will be more intuitive then the first option anyway.
Edit: 4 is just whatever child index you want to switch to.