I have a ScrollView and views inside it.
I want to have special behaviour on one of the child views in the ScrollView. My question is, does the view itself know when it is scrolled? Is there a callback, like onScrollChanged or something that can notify my view that the scroll in the scrollView is changed?
The views should not know about the parent scrollview.
I tried using ViewTreeObsever, and registering a onScrollChangeListener callback, but for some reason I get no callback whatsoever when I scroll things.
There is the OnScrollListener which handles scroll events.
Related
I have nested ViewPagers and RecyclerViews as depicted in the image:
Requirements:
The first level ViewPager1 swipes from left to right. It uses FragmentStatePagerAdapter.
The first level RecyclerView1 scrolls vertically.
The second level ViewPager2 does not swipe - the swipe motion is controlled by a TabLayout. It uses a custom PagerAdapter that returns a View as a page.
The second level RecyclerView does not scroll - it simply wraps a list of dynamic items
What I have working so far:
The first level ViewPager1 and RecyclerView1 works as intended.
The ViewPager2 does not show because its height is defined as "wrap_content"
The ViewPager2/RecyclerView2 prevents RecyclerView1 to scroll up/down.
What I have tried:
Setting RecyclerView1.setNestedScrollingEnabled(false) stops it from passing the onTouch event to its children, but because the ViewPager2/RecyclerView2 wraps its content, it does not know what the size it needs to scroll.
Setting the ViewPager2 to a fixed height solves the scrolling problem. But because it is a fixed height, the content of RecyclerView2 is cut off.
Overriding OnMeasure as described here makes ViewPager2's content wrap, perfectly, but the scrolling no longer work again. I assume it is because OnMeasure is called "after" the View has already been attached?
So basically I need help on how to get the content to wrap but in such a way that RecyclerView 1 knows what the height is so that it can scroll.
EDIT
It turns out I was totally off base with point 3. The OnMeasure workaround DOES work as intended and the scrolling problem is NOT caused by recyclerView not knowing the height. It in fact does. The reason why it doesn't scroll is due to multiple nested scrollable view groups. I found this out by putting Log.i on onTouchEvent() and onInterceptTouchEvent() on all the scrollable view groups. Some surface of the views work, but if the surface has another scrollable child, it starts to cause problems.
Setting RecyclerView2.setNestedScrollingEnabled(false) fixed the vertical scrolling. However, now, the ViewPager2's touch behaviour is interfering with ViewPager1's
On closer inspection, ViewPager1 intercepts touch event when hitting non-scrollable surface, causing the ViewPager1 to call its onTouchEvent() to scroll left and right. However, if I start the touch event over a the ViewPager2's surface, ViewPager1 never intercept and it never handles the swipe left to right.
Unlike a RecyclerView, there is no simple method to disable nestedScrolling. So I tried disabling ViewPager2, but that didn't work and caused the inside views such as buttons not clickable.
I tried to return false in ViewPager2's OnTouchEvent so that it bubbles up the chain, but still, the ViewPager1's OnTouchEvent is never fired.
So I'm stuck again, how do I pass the touch event to the parent when the parent did not intercept the event when it should have. Again, I'm assuming, and again I might be off-base, that ViewPager1 might not intercept because ViewPager2 has requested a disallowInterceptTouchEvent() somewhere in its code? I just don't know where or how to begin to fix this problem.
I am using two (embedded) ScrollViews like suggested here, in order to create a '2D Scrollview'.
I add multiple childs to this view, and to some of them I set OnClickListener (I also tried with OnLongClickListener as well).
Functionally the result is what I have expected, although if I try to scroll (starting from a child, that has either of the listeners), the scrollview jumps/repositions to the ~opposite direction, I started the scroll to. So if I scroll like this e.g. upwards, the view jumps a big downwards so that I can scroll up at most to the original position.
I have been trying to play around with calling setFocusable(false) on the childs and setFocusable(true) on the ScrollView(s) (but also tried different permutations of it, as I am not sure about setFocusable()), but couldn't really get on top of it.. Any suggestions?
Just encase you are still wondering this is happening because when you start scrolling the other scroll view, ACTION_CANCEL is posted to the on touch method of the original ScrollView which causes a default scroll view to jump back to its original position.
I have a recycler view inside a ScrollView. I want to disable the recycler view scroll so that it listens to its parent layout, A ScrollView!
This should solve your RecyclerView nested scrolling.
mRecyclerView.setNestedScrollingEnabled(false);
RecyvlerView implements NestedScrollingChild
for instance if RecyclerView parent is a ScrollView or ListView or RecyclerView or any AbsListView
disable scrolling for the child RecyclerView.
Logically, it is not a good idea to put ListView inside a ScrollView. However, if you insist then:
You may either increase the ListView height based on the sum of its
rows height as mentioned here.
Or let the recycling in place but intercept the touch on ListView
to redirect scrolling to its parent ScrollView as mentioned
here.
Add this line in xml,
android:nestedScrollingEnabled="false"
I want to learn how to solve this problem. I want to have a Horizontal scrollview with the scroll blocked (the user should not be able to scroll it) and inside that horizontal scrollview i want to have another horizontal scroll view, and this scrollview must be able to be scrolled by the user (it haves more content that the width of the screen).
Is it possible to do it?
I tried using this on the parent horizontal scroll view:
((HorizontalScrollView) view).setHorizontalScrollBarEnabled(false);
((HorizontalScrollView) view).setEnabled(false);
((HorizontalScrollView) view).setFocusable(false);
((HorizontalScrollView) view).setFocusableInTouchMode(false);
and this on the child horizontal scroll view:
((HorizontalScrollView) view).requestFocus();
It is not working, the child appears to have a scroll bar, but it cannot be scrolled.
How can this be solved?
PD: I know that this is not a good practice, but I want to learn how to achieve this goal.
You should never use a
HorizontalScrollView with a ListView,
since ListView takes care of its own
scrolling. Most importantly, doing
this defeats all of the important
optimizations in ListView for dealing
with large lists, since it effectively
forces the ListView to display its
entire list of items to fill up the
infinite container supplied by
HorizontalScrollView.
http://developer.android.com/reference/android/widget/HorizontalScrollView.html
UPDATE:
Since you may be forced to use a two dimensional scrollview, you may consider using this:
http://blog.gorges.us/2010/06/android-two-dimensional-scrollview/
I haven't used this but it may be a reasonable approach.
you can do it. But you have to handle child layouts in scrollview i.e ScrollView can host only one direct child.
I have a custom ViewGroup and would like to add scrolling ability to it.
Is it possible to use a Scroller object and link it up with view group?
I have read somewhere that Scroller does not do any actual scrolling. That means it must be delegating the scrolling responsibility back to ViewGroup.
thanks
The ScrollView object is what allows for scrolling. Basically, most Views are able to be scrolled, but they have no way of propagating touch events to the View class. A ScrollView handles this for the user, so should be wrapped around a View whenever you would like to enable Scrolling for a that view.
Remember that a ScrollView can only have one child view, so if you need have multiple views in the same scrolling layout, you'll need to have them all inside one LinearLayout (or RelativeLayout, or whatever you decide).