Android nestedscrollview with recyclerview

Scrollable NestedScrollViews inside RecyclerView

Looks like nobody is talking about vertically scrollable items inside a vertically scrollable RecyclerView.

November 11th 2017: Updated the source to work properly with Android Studio 3 and API level 26.

In one of our apps most screens are composed of a small set of reusable UI components, glued together vertically using a RecyclerView . Our designer had a simple request for one of these screens: Add a fixed-height multi-line text input. Obviously that input must scroll vertically when the text becomes too long.

The functionality was very easy to implement on iOS since nested scrolling is well-supported since iOS 3 but it turned out to be incredibly difficult to achieve the same or even just a similar behavior on Android. With Support Library 22.1.0 support for nested scrolling was added a while ago, but even today RecyclerView only implements NestedScrollingChild and not NestedScrollingParent which is needed to support scrollable descendants.

When searching for information on how to make our NestedScrollView (which contains an EditText for text input) scroll properly inside a RecyclerView , we’ve found plenty of information on how to do it the other way round: a RecyclerView inside a NestedScrollView . Looks like that only few people ran into our issue before.

We’ve found one solution on StackOverflow, but its early use of parent?.requestDisallowInterceptTouchEvent(true) has a big downside: The NestedScrollView will steal all touches within that view from RecyclerView , which makes it impossible to scroll the RecyclerView from anywhere inside the NestedScrollView . So if the NestedScrollView isn’t currently scrollable (for example when it has only little content) or if it’s already scrolled to the end in the direction the user wants to scroll, nothing happens. That’s a horrible user experience!

Here it looks broken to the user:

Our Solution

After two days research and debugging of Android’s and RecyclerView ‘s touch handling it was clear that RecyclerView ‘s use of onInterceptTouchEvent makes it impossible for descendants to receive the touch movement events necessary for scrolling. Also we cannot properly implement NestedScrollingParent without changing the code of RecyclerView itself.

Читайте также:  Скан qr код android

The solution we came up with is to temporarily skip RecyclerView ‘s implementation of onInterceptTouchEvent as long as a NestedScrollChild is scrolling and is actually able to scroll in the direction the user is scrolling.

And here’s how it’s working:

The implementation is merely a workaround and we’d like to have a cleaner solution, but we’ve learned that workarounds are often necessary in Android development. Its SDKs have grown at a rapid pace since Android’s initial release in 2008 and they became incredibly complex.

The solution above works well in our case but may have unexpected side-effects for others. If you have improvements or thoughts to share then please let us know!

Источник

Nested RecyclerView In Android

A perfect guide to implement a recyclerview inside another recyclerview. Learn with MVVM

💥 Hello, In this article we are going to implement a nested recyclerview. We will learn how exactly nested recyclerview are made in real-time projects.

We can use a RecyclerView inside another RecyclerView. We refer to this as nested RecyclerView. Here are some pictures of nested recyclerview applications.

Prerequisites

  • Kotlin Language
  • Android RecyclerView
  • Hilt Dependency Injection
  • Retrofit
  • API_URL: https://game-of-thrones-quotes.herokuapp.com/v1/ houses

Why This Article? 🤔

Yeah, there are a lot of articles on this topic, but every article has its own way to represent data which is mainly static data. In this article we will build with API data.

Just Give me the Code,

iamnaran/template-recycler-view

A recycler view. Contribute to iamnaran/template-recycler-view development by creating an account on GitHub.

Let’s Get Started,

Step 1 — Setting up Model & API Data

An API that has a list of objects with the nested list of other objects. Take a look at the below API response. As we will integrate this public API into our application. Here, We have the Game Of Thrones API List which has a list of names of Houses and their nested Members list.

It’s important to understant data structure. I found many beginners developer were not able to understant API data structure which leads to bad development practice. So, Always understand model/data before you start your project.

Let’s SKIP our PEP talk and start coding Right! 👍

To generate KOTLIN model from JSON you can download this plugin ( JSON To Kotlin Class) in Android Studio. And, For JAVA look ( JSON To Java Class)

Now, Let’s create API Service to get responses from the above API URL. By breaking down our URL into BASE_URL & EndPoints.

Читайте также:  Андроид приставка для старого телевизора

Now, Let’s create our ViewModel to get this API Response

Here, HomeRepository acts as a repository class to get our response & PreferencesHelper acts as a helper class to store data in SharedPreference. You can see the project repository to understand it more clearly.

Step 2— User Interface Setup (XML)

Here, We will need three layouts,

  1. Activity UI, For Toolbar & Parent RecyclerView
  2. A Layout row Item for Parent RecyclerView — which consists of title & child recyclerview.
  3. A Layout row Item for Child RecyclerView.

Step 3— Setting up Adapter Classes

Several different classes work together to build our dynamic list. Here we have two recyclerview, which means we need two adapters. You define the adapter by extending RecyclerView.Adapter . You define the view holder by extending RecyclerView.ViewHolder . The layout manager arranges the individual elements in your list.

Remember Parent-Child Concept. Parent Adapter holds Child Adapter.

Let’s start with the child members adapter, where we will plot a list of members.

Now, Let’s work on our ParentHouseAdapter, It is main/parent recyclerview adapter from which we will call our child adapter.

Final Step — Integrate Adapter In View

We have our adapter ready, In our Activity, we will call our adapter after we get a response from our API.

Finally, The Output we get,

We are done here. We can always change our UI view with respect to our API.

Источник

karntrehan / DataFragment.kt

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters

import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import androidx.core.view.ViewCompat
import androidx.core.widget.NestedScrollView
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.fragment_data.nsvData
import kotlinx.android.synthetic.main.fragment_data.rvData
class DataFragment : Fragment () <
override fun onViewCreated (
view : View ,
savedInstanceState : Bundle ?
) <
super .onViewCreated(view, savedInstanceState)
enablePagination(
nestedScrollView = nsvData,
recyclerView = rvData,
nextPageFunction = viewModel::fetchNextData
)
>
private var paginatedRV : RecyclerView ? = null
private fun enablePagination (
nestedScrollView : NestedScrollView ,
recyclerView : RecyclerView ,
nextPageFunction : () -> Unit
) <
// Disable nested recyclerview from scrolling
ViewCompat .setNestedScrollingEnabled(recyclerView, false )
// Attach scroll listener to nested scrollview
nestedScrollView.viewTreeObserver?.addOnScrollChangedListener <
// If the paginated rv is not calculated already
if (paginatedRV == null ) <
// Get the parent holder
val holder = nestedScrollView.getChildAt( 0 ) as ViewGroup
// Loop through all children of parent holder
for (i in 0 until holder.childCount) <
// Pull the pagination recyclerview child
if (holder.getChildAt(i).id == recyclerView.id) <
paginatedRV = holder.getChildAt(i) as RecyclerView
break
>
>
>
paginatedRV?. let <
// Identify if recyclerview is scrolled to bottom
if (it.bottom — (nestedScrollView.height + nestedScrollView.scrollY) == 0 )
nextPageFunction()
>
>
>
>
Читайте также:  Комбинация для проверки аккумулятора андроид

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters

LinearLayout 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 = » @color/background_color «
android : orientation = » vertical «
tools : context = » com.karntrehan.DataFragment «
>
include layout = » @layout/toolbar »/>
androidx .core.widget.NestedScrollView
android : id = » @+id/nsvData «
android : layout_width = » match_parent «
android : layout_height = » wrap_content «
android : layout_marginLeft = » 8dp «
android : layout_marginRight = » 8dp «
tools : visibility = » visible «
>
LinearLayout
android : layout_width = » match_parent «
android : layout_height = » wrap_content «
android : orientation = » vertical «
>
Button
android : id = » @+id/btnViewed «
android : layout_width = » wrap_content «
android : layout_height = » 36dp «
android : layout_gravity = » end|right «
android : layout_marginTop = » 16dp «
android : background = » @color/white «
android : padding = » 8dp «
android : text = » @string/viewed «
android : textColor = » @color/recently_viewed_text_color «
android : textSize = » 12sp «
style = » @style/Button.Flat «
/>
TextView
android : id = » @+id/tvDataCount «
android : layout_height = » match_parent «
android : layout_marginBottom = » 8dp «
android : textColor = » @color/text_color_primary «
tools : text = » Showing 248 Events «
style = » @style/Text.Title.Regular «
/>
androidx .recyclerview.widget.RecyclerView
android : id = » @+id/rvData «
android : layout_width = » match_parent «
android : layout_height = » match_parent «
android : orientation = » vertical «
app : layoutManager = » androidx.recyclerview.widget.LinearLayoutManager «
tools : itemCount = » 3 «
tools : listitem = » @layout/item_data «
/>
ProgressBar
android : id = » @+id/pbLoading «
android : layout_width = » wrap_content «
android : layout_height = » wrap_content «
android : layout_gravity = » center «
android : layout_margin = » 8dp «
style = » ?android:attr/progressBarStyle «
/>
LinearLayout >
androidx .core.widget.NestedScrollView>
include
layout = » @layout/layout_empty «
android : id = » @+id/noData «
android : layout_width = » match_parent «
android : layout_height = » 0dp «
android : layout_weight = » 1 «
android : visibility = » gone «
tools : visibility = » gone «
/>
LinearLayout >

You can’t perform that action at this time.

You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.

Источник

Оцените статью