What is the difference between ScrollView and NestedScrollView? Both of them, extend FrameLayout. I want to know in depth pros and cons of both of them.
NestedScrollView as the name suggests is used when there is a need for a scrolling view inside another scrolling view. Normally this would be difficult to accomplish since the system would be unable to decide which view to scroll.
This is where NestedScrollView comes in.
In addition to the nested scrolling NestedScrollView added one major functionality, which could even make it interesting outside of nested contexts: It has build in support for OnScrollChangeListener. Adding a OnScrollChangeListener to the original ScrollView below API 23 required subclassing ScrollView or messing around with the ViewTreeObserver of the ScrollView which often means even more work than subclassing. With NestedScrollView it can be done using the build-in setter.
Other than the advantages listed in the answers given, one more advantage of NestedScrollView over ScrollView is its compatibility with CoordinatorLayout. The ScrollView does not cooperate with the CoordinatorLayout. You have to use NestedScrollView to get "scroll off-screen" behaviour for the toolbar.
Toolbar will not collapse with Scrollview as child of CoordinatorLayout
NestedScrollView
NestedScrollView is just like ScrollView, but it supports acting as
both a nested scrolling parent and child on both new and old versions
of Android. Nested scrolling is enabled by default.
https://developer.android.com/reference/android/support/v4/widget/NestedScrollView.html
ScrollView
Layout container for a view hierarchy that can be scrolled by the
user, allowing it to be larger than the physical display. A
ScrollView is a FrameLayout, meaning you should place one child in it
containing the entire contents to scroll; this child may itself be a
layout manager with a complex hierarchy of objects
https://developer.android.com/reference/android/widget/ScrollView.html
NestedScrollView is just like ScrollView, but in NestedScrollView we can put other scrolling views as child of it, e.g. RecyclerView.
But if we put RecyclerView inside NestedScrollView, RecyclerView's smooth scrolling is disturbed. So to bring back smooth scrolling there's trick:
ViewCompat.setNestedScrollingEnabled(recyclerView, false);
put above line after setting adapter for recyclerView.
I think one Benefit of using Nested Scroll view is that the cooridinator layout
only listens for nested scroll events. So if for ex. you want the toolbar to scroll down when you scroll you content of activity, it will only scroll down when you are using nested scroll view in your layout. If you use a normal scroll view in your layout, the toolbar wont scroll when the user scrolls the content.
<androidx.core.widget.NestedScrollView android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
// your Layout xml code
</androidx.core.widget.NestedScrollView>
Related
If a layout is defining a ScrollView as a parent view and one of the children is a LinearLayout (vertical orientation with some children) is there a problem with this definition? Because I have seen sometimes that the linear layout is wrapped in another NestedScrollView so I was wondering what problem does that solve
If you directly wrap a ScrollView in a NestedScrollView, and that is the only child of the NestedScrollView, that is redundant and unnecessary. If there are other children of the NestedScrollView, that may be correct, but then you probably would want both to be NestedScrollViews, in order to get consistent behavior across Android versions.
How to properly scroll to a position in nestedscrollview which is inside a coordinate layout? When I use scrollTo(), it seems like the view inside AppBarLayout is loosing the ability to scroll down when I scroll to the end of NestedScrollView and coming back to top. What I need to know is how to programtically scroll to a position in nestedscrollview without causing problem with the normal behavior of collapsing layout.
Issue is similar to what is mentioned in this post:
The Coordinator layout doesn't Scroll up for a specific position
There is a Gif attached along with the above question:
https://i.stack.imgur.com/uSGfX.gif
I have tried the solution in above link, but it is not working.
In my application i have CoordinatorLayout with nested custom view, which has custom MoveUpwardBehavior. When Snackbar appears, I want this view to be pushed over it and it works.
The problem is, that CoordinatorLayout is nested in RelativeLayout which has flag animateLayoutChanges=true. When RelativeLayout animates its views, CoordinatorLayout shrinks a bit (vertically). It causes, that mentioned custom view also moves, but i want to make it stick to its position. Any thoughts, how I can accomplish it?
You need to set CoordinatorLayout to be top-level layout instead of wrapping it inside another parent. The animation and displacement of the views during layout animation is totally normal. You may want to tweak your MoveUpwardBehavior to get the target view to keep the intended behavior, in case that your custom view is not direct descendant of CoordinatorLayout.
I have a problem with a View hierarchy in the app I am working on right now.
One of the screens looks like this:
<CoordinatorLayout>
<AppBarLayout>
<Toolbar/>
</AppBarLayout>
<RecyclerView>
... items, some of which are horizontal Recyclers...
</RecyclerView>
</CoordinatorLayout>
The whole idea is to have the Toolbar parallax nicely when scrolling down the RecyclerView content.
The whole thing works rather nicely, but there is a problem with the mentioned parallax behavior (which is done with a custom AppBarLayout.ScrollingViewBehavior implementation).
There are two cases, depending on what item user focuses when scrolling:
If a normal child is focused, the whole thing works as expected - Toolbar parallaxes in and out.
If a Recycler-based child is focused, the content RecyclerView will scroll as expected, but the parallax behavior will not fire, leaving the layout in a weird mid-state.
Any idea why this is happening and how to get the correct behavior, aka the events being passed all the way up to the CoordinatorLayout?
For each of your sub-recyclerView's, you need to call
setNestedScrollingEnabled(false)
on that RecyclerView (you can do this from whatever viewholder you are using for your main recyclerview to create the sub ones). This is a currently known bug in nested scrolling. If I were to guess, I would say that it probably has something to do with the fact that nested scrolling layouts are not supposed to send nested scrolling notifiers to parents if they are scrolled in directions in which they do not have a scrolling axis, if that makes any sense.
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.