RecyclerView inside of NestedScrollView fires all onBindViewHolder at once - android

I want to have scrollable screen with RecyclerView as one of its children, hierarchy would look like that:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
...
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
.../>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
.../>
<FrameLayout
.../>
<android.support.v7.widget.RecyclerView
android:id="#+id/list_contacts"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:nestedScrollingEnabled="false"/>
<FrameLayout
.../>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
</LinearLayout>
Note that all the items of RecyclerView should be visible and be siblings of ImageView, FrameLayout etc.
In the current solution, there is one significant issue, onBindViewHolder is called for all items at once, but I want them to be bind when they appear on the screen, like in standard RecyclerView. I was doing some experiments with
android:fillViewport="true"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
but it failed after all.
I know one of the solutions is implementing heterogeneous recyclerView, but I would like to avoid it. Any ideas?

Probably it happens because in this case, recyclerview cant know the height of itself.
Can you try:
layoutManager.isAutoMeasureEnabled=true

Related

Scrolling ImageView along with Recylcer View

So,
I have a layout.xml file which contains a Recycler View. Now, what I want is, I added two image Views on top of this Recycler View but I want those ImageViews to scroll with the RecyclerView as well.
I just wanted to ask, is this possible to do? And if yes, how can I achieve this?
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/content_parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<include
android:id="#+id/header_bar"
layout="#layout/section_header" />
<ImageView-1>
<ImageView-2>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/category_grid"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingHorizontal="#dimen/category_grid_edge_space"
android:paddingTop="#dimen/category_grid_padding_top"
android:scrollbarSize="#dimen/grid_padding"
android:scrollbarStyle="outsideOverlay"
android:scrollbarThumbVertical="?android:attr/textColorSecondary"
android:scrollbars="vertical"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Put your RecycleView in NestedScrollView
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<include
layout="#layout/your_header"/>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/category_grid"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
also don't forget to disabled NestedScrolling for RecyclerView
myRecyclerView.setNestedScrollingEnabled(false);
OR
Add those views as a header. Here is a good guide on how to add a custom item view: https://medium.com/androiddevelopers/get-ahead-using-headers-in-recyclerview-2909a69b19
https://github.com/masudias/RecyclerView-with-Header-and-Footer
You can use header and footer i

How make put ViewPager inside ScrollView and scroll all view as one part?

I have an activity that have viewpager inside scrollview like the follwoing
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!--someViews-->
</LinearLayout>
<!--then viewPager-->
<androidx.viewpager.widget.ViewPager
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</ScrollView>
Then the view pager holds some fragments which have a tall view too.
The problem is the scroll view not scrolling because of the view is not need to scroll but the view inside the viewpager fragment's not scrolling
so, Is it possible to make the whole view including the inside view pager scroll as one view?
What I am saying that I don't need to scroll the viewpager fragment as separated part I need to scroll it as part of activity view.
Thanks
I believe the setup you are looking for would work inside a CoordinatorLayout using the NestedScrollView widget like so:
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/app_name"
android:textAppearance="#style/Base.TextAppearance.AppCompat.Display1" />
<TextView
android:id="#+id/subTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/subtitle"
android:textAppearance="#style/Base.TextAppearance.AppCompat.Body1" />
<androidx.viewpager.widget.ViewPager
android:id="#+id/viewPager"
android:layout_width="match_parent"
android:layout_height="300dp" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
I have just tested this with a sample project with a single text view in a Fragment and I was able to both scroll the view and swipe through the pages.
Please note though: I did have to provide a specific height for the ViewPager in order for it to display.

Recyclerview in fragment which is inside nestedscrollview scrolling issue

In activity, I have TabLayout & FrameLayout for loading fragment. fragment contains RecyclerView. it works fine for first time only. but when I change tab and back to previous tab the RecyclerView not scrolling full.
Main Activity
<android.support.v4.widget.NestedScrollView
android:fillViewport="true"
android:layout_height="match_parent"
android:layout_width="match_parent">
<LinearLayout
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical">
<android.support.design.widget.TabLayout
android:id="#+id/tabMain"
android:layout_height="wrap_content"
android:layout_width="match_parent" />
<FrameLayout
android:id="#+id/containerMain"
android:layout_height="match_parent"
android:layout_width="match_parent" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
Fragment
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="#+id/rvMedia"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:nestedScrollingEnabled="false" />
</LinearLayout>
The recyclerView has a smooth scrolling by itself but when we need to put recyclerView within any scrollView it will not work like the below:
Layout XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</ScrollView>
</LinearLayout>
The solution for this is we need to used nestedScrollView instead of scrollview like the below
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v4.widget.NestedScrollView
android:id="#+id/nestedScrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:overScrollMode="never">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
</LinearLayout>
The problem occurs when we use nestedScrollView and put recyclerView inside nestedScrollView is, it scrolls in various speed depending on gesture. The scrolling feature will not be smooth.
So to fix this issue all you have to do after setting your adapter is to add this line ViewCompat.setNestedScrollingEnabled(recyclerView, false);
This is not a good solution. Placing a RecyclerView inside a NestedScrollView, causes ALL elements of the RecyclerView’s adapter to be rendered, ths using alot of memory. This can be so slow in most devices with less memory.
This approach might also lead to disabling need scrolling, which will disable views recycling thus all items will be initialized at once.e.g. In a list with 1000 items. This will make the application lag. You can avoid it if you use pagination where you load a fixed number of items when the user scrolls down on the list.
Read more about pagination.
Pagination with RecyclerView – Etienne Lawlor – Medium
Android RecyclerView Pagination with Paging Library using MVVM ...
Paging library overview | Android Developers

How to design complex UI in android

How can I have a ViewPager above a RecyclerView, or have several RecyclerViews in a ScrollView? I designed the following layout, but it has some problems when scrolling.
What is the problem and how can I solve it?
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#dcdcdc"
android:fillViewport="true"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context=".ActivityMain"
tools:showIn="#layout/app_bar_main">
<LinearLayout
android:id="#+id/header"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="200dip"
/>
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
</ScrollView>
I have tried compile 'com.bartoszlipinski:recyclerviewheader2:2.0.1' with
<com.bartoszlipinski.recyclerviewheader2.RecyclerViewHeader
android:id="#+id/header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|top">
1- firstly it supports 11 sdk or greater,
2- secondly ViewPager wont work in header RecyclerView.
and i have tried RecyclerView layout_width="wrap_content" but it is just supported in sdk21 .
How can I solve the RecyclerView scrolling ?
Try losing the top ScrollView and using a ListView instead of RecyclerView.
ScrollView is unnecessary here and you need a hack for ViewPager to work with RecyclerView as it consumes all touch events. It would be simpler if you could get away with a ListView.
You can take your view pager to app bar in collapssing toolbar layout and it will be ok

On Activity started layout jumps to RecyclerView's top

When the activity is opened, it shows the top of the RecyclerView layout instead of the top of the activity layout.
Activity layout .xml file:
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="20dp"
android:paddingTop="20dp">
...
<RelativeLayout/>
<View />
<LinearLayout/>
...
<android.support.v7.widget.RecyclerView
android:id="#+id/venue_place_info_gallery_recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"/>
</LinearLayout>
</ScrollView>
Activity onCreate:
RecyclerView galleryRecyclerView = (RecyclerView) findViewById(R.id.venue_place_info_gallery_recycler_view);
galleryRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(gridLayoutColumns, StaggeredGridLayoutManager.VERTICAL));
VenueGalleryAdapter venueGalleryAdapter = new VenueGalleryAdapter(VenuePlaceInfoActivity.this, images);
galleryRecyclerView.setAdapter(venueGalleryAdapter);
The adapter is very simple. It receives the images as an argument in the constructor and the data cannot be changed later on.
I've tried to apply all kinds of settings to the RecyclerView layout, but it works the same with or without them. For example:
galleryRecyclerView.setNestedScrollingEnabled(false);
galleryRecyclerView.setHasFixedSize(true);
galleryRecyclerView.setLayoutFrozen(true);
galleryRecyclerView.setPreserveFocusAfterLayout(false);
UPDATE:
I have found more info on the subject in the answer of another question. It's all because of the ScrollView and RecyclerView not being capable to live together even if you set setNestedScrollingEnabled to true. But it still doesn't give me the resolution of my problem. I need to have some stuff above the gallery RecyclerView and I want to scroll down through all the images (not putting them in a container).
If you want your layout to look good, I would use a CoordinatorLayout with an AppBarLayout as the first element inside it, and the RecyclerView as the second. Inside the AppBarLayout, you should put whatever it is that you would like to have above the RecyclerView. Something similar to this:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#color/white">
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="0dp">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|enterAlways"
app:titleEnabled="false">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="vertical"
android:paddingTop="20dp"
app:layout_collapseMode="parallax">
<!-- stuff you want above your recyclerview -->
</LinearLayout>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
app:layout_behavior="#string/appbar_scrolling_view_behavior"/>
</android.support.design.widget.CoordinatorLayout>
</LinearLayout>
Someone does something similar here, just instead of using a toolbar in the appbarlayout, you may use whatever view layouts you'd like. AppBarLayout is an extended Vertical LinearLayout: http://www.basagee.tk/handling-scrolls-with-coordinatorlayout/
just add the following tag on your activity/fragment root layout and you are good to go.
android:descendantFocusability="blocksDescendants"

Categories

Resources