A visualização de reciclagem dentro do ScrollView não rola suavemente


179

Para o meu aplicativo, estou usando um RecyclerViewdentro de um local ScrollViewonde RecyclerViewtem uma altura com base em seu conteúdo usando esta biblioteca . A rolagem está funcionando, mas não está funcionando perfeitamente quando eu rolar a tela RecyclerView. Quando eu rolar sobre o ScrollViewpróprio, ele está rolando sem problemas.

O código que estou usando para definir RecyclerView:

LinearLayoutManager friendsLayoutManager = new LinearLayoutManager(getActivity().getApplicationContext(), android.support.v7.widget.LinearLayoutManager.VERTICAL, false);
mFriendsListView.setLayoutManager(friendsLayoutManager);
mFriendsListView.addItemDecoration(new DividerItemDecoration(getActivity().getApplicationContext(), null));

O RecyclerViewno ScrollView:

<android.support.v7.widget.RecyclerView
    android:layout_marginTop="10dp"
    android:layout_marginBottom="10dp"
    android:id="@+id/friendsList"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

esta solução funciona para mim: stackoverflow.com/a/32390370/7308789 obrigado
— Houssin Boulla

1
@tahaDev, o que exatamente não está funcionando no seu caso, elabore mais sobre isso. Além disso, parece que nenhuma solução fornecida funcionou no seu caso, não é?
— Pravin Divraniya

Use androidx.constraintlayout.widget.ConstraintLayouto que vai resolver seu problema sem qualquer implementações complexas
— Saswata

Respostas:


379

Tente fazer:

RecyclerView v = (RecyclerView) findViewById(...);
v.setNestedScrollingEnabled(false);

Como alternativa, você pode modificar seu layout usando a biblioteca de design de suporte. Eu acho que seu layout atual é algo como:

<ScrollView >
   <LinearLayout >

       <View > <!-- upper content -->
       <RecyclerView > <!-- with custom layoutmanager -->

   </LinearLayout >
</ScrollView >

Você pode modificar isso para:

<CoordinatorLayout >

    <AppBarLayout >
        <CollapsingToolbarLayout >
             <!-- with your content, and layout_scrollFlags="scroll" -->
        </CollapsingToolbarLayout >
    </AppBarLayout >

    <RecyclerView > <!-- with standard layoutManager -->

</CoordinatorLayout >

No entanto, esse é um caminho mais longo e, se você estiver de acordo com o gerenciador de layout linear personalizado, desative a rolagem aninhada na visualização do reciclador.

Editar (03/04/2016)

O v 23.2lançamento das bibliotecas de suporte agora inclui um recurso de "wrap wrap" de fábrica em todos os LayoutManagers padrão . Não testei, mas você provavelmente deve preferir à biblioteca que estava usando.

<ScrollView >
   <LinearLayout >

       <View > <!-- upper content -->
       <RecyclerView > <!-- with wrap_content -->

   </LinearLayout >
</ScrollView >

16
Para adicionar a esta resposta: setNestedScrollingEnabled(false)só funcionou quando troquei o ScrollViewfor a pelo NestedScrollViewcontrário.
— Richard Le Mesurier

11
Para mim, setNestedScrollingEnabled(false)me devolveu a rolagem suave com meu RecyclerViewinterior de um ScrollView- Obrigado! Mas ainda não entendo por que isso funciona ...? O que realmente significa definir a rolagem aninhada como falsa?
— Micro

33
Observe que android:nestedScrollingEnabled="false"funciona apenas para a API 21+, mas v.setNestedScrollingEnabled(false)é aceitável para <21.
— Eric B.

3
Para referência futura, se alguém estiver enfrentando RecyclerViewum problema wrap_content no interior ScrollViewque só acontece em dispositivos marshmallow / nougat (API 23, 24), verifique minha solução alternativa em stackoverflow.com/a/38995399/132121
— Hossain Khan

2
Uma desvantagem desta solução que estou enfrentando agora é que o RecyclerView não receberá eventos no onScrollListener. Que eu preciso porque eu quero buscar mais dados quando tenho apenas uma certa quantidade de itens no reciclador
— Daniel W.

82

Eu só precisava usar isso:

mMyRecyclerView.setNestedScrollingEnabled(false);

no meu onCreateView()método

Muito obrigado!


26

Você pode usar desta maneira:

Adicione esta linha ao seu arquivo xml do recyclerView:

android:nestedScrollingEnabled="false"

Ou no código java:

RecyclerView.setNestedScrollingEnabled(false);

Espero que isso tenha ajudado.


10
requer Api 21+
— Muhammad Riyaz

11

Você pode tentar com as duas formas com XML e programaticamente. Mas o problema que você pode enfrentar é (abaixo da API 21) fazê-lo com XML não funcionará. Portanto, é melhor configurá-lo programaticamente em sua Atividade / Fragmento.

Código XML:

<android.support.v7.widget.RecyclerView
      android:id="@+id/recycleView"
      android:layout_width="match_parent"
      android:visibility="gone"
      android:nestedScrollingEnabled="false"
      android:layout_height="wrap_content"
      android:layout_below="@+id/linearLayoutBottomText" /> 

Programaticamente:

 recycleView = (RecyclerView) findViewById(R.id.recycleView);
 recycleView.setNestedScrollingEnabled(false);

6

Usar a Visualização de rolagem aninhada em vez da Visualização de rolagem resolveu meu problema

<LinearLayout> <!--Main Layout -->
   <android.support.v4.widget.NestedScrollView>
     <LinearLayout > <!--Nested Scoll View enclosing Layout -->`

       <View > <!-- upper content --> 
       <RecyclerView >


     </LinearLayout > 
   </android.support.v4.widget.NestedScrollView>
</LinearLayout>

5

Eu tive problemas semelhantes (tentei criar um RecyclerViews aninhado, algo como o design do Google PlayStore). A melhor maneira de lidar com isso é subclassificando o filho RecyclerViews e substituindo os métodos 'onInterceptTouchEvent' e 'onTouchEvent'. Dessa forma, você obtém controle completo de como esses eventos se comportam e, eventualmente, rolam.


3

Substituir ScrollView por NestedScrollView resultou em rolagem suave para a parte inferior.


1

Se você estiver usando o VideoView ou widgets de peso pesado em suas visualizações de crianças, mantenha o RecyclerView com altura wrap_content dentro de um NestedScrollView com altura. A match_parent rolagem funcionará perfeitamente da maneira que você desejar.

PARA SUA INFORMAÇÃO,

<android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.v7.widget.RecyclerView
            android:layout_width="match_parent"
            android:nestedScrollingEnabled="false"
            android:layout_height="wrap_content"
            android:clipToPadding="false" />

</android.support.v4.widget.NestedScrollView>

Graças à Micro, esta foi a sua dica!

Karthik


1

Resumo de todas as respostas (Vantagens e Desvantagens)

Para uma única visão de reciclagem

você pode usá-lo dentro do layout do coordenador.

Vantagem - não carregará itens inteiros de reciclagem. Carregamento tão suave.

Desvantagem - você não pode carregar duas visualizações de reciclagem dentro do layout do Coordinator - produz problemas de rolagem

referência - https://stackoverflow.com/a/33143512/3879847

Para várias recylerview com linhas mínimas

você pode carregar dentro do NestedScrollView

Vantagem - rolará suavemente

Desvantagem - Carrega todas as linhas da visão de reciclagem para que sua atividade seja aberta com atraso

referência - https://stackoverflow.com/a/33143512/3879847

Para várias recylerview com linhas grandes (mais de 100)

Você deve ir com a reciclagem.

Vantagem - role sem problemas, carregue sem problemas

Desvantagem - Você precisa escrever mais código e lógica

Carregue cada recylerview dentro da recyclerview principal com a ajuda de vários participantes

ex:

MainRecyclerview

-ChildRecyclerview1 (ViewHolder1)

-ChildRecyclerview2 (ViewHolder2)

-ChildRecyclerview3 (ViewHolder3) 

-Any other layout   (ViewHolder4)

Referência para multi-viewHolder - https://stackoverflow.com/a/26245463/3879847


0

Código XML:

<android.support.v4.widget.NestedScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <android.support.v7.widget.RecyclerView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:clipToPadding="false" />

        </android.support.v4.widget.NestedScrollView>

no código java:

  recycleView = (RecyclerView) findViewById(R.id.recycleView);
     recycleView.setNestedScrollingEnabled(false);

0

Ou você pode simplesmente definir android:focusableInTouchMode="true"na sua visualização do reciclador


0
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent">

        <android.support.constraint.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent">

            <android.support.constraint.ConstraintLayout
                android:id="@+id/constraintlayout_main"
                android:layout_width="match_parent"
                android:layout_height="@dimen/layout_width_height_fortyfive"
                android:layout_marginLeft="@dimen/padding_margin_sixteen"
                android:layout_marginRight="@dimen/padding_margin_sixteen"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent">

                <TextView
                    android:id="@+id/textview_settings"
                    style="@style/textviewHeaderMain"
                    android:gravity="start"
                    android:text="@string/app_name"
                    app:layout_constraintLeft_toLeftOf="parent"
                    app:layout_constraintRight_toRightOf="parent" />

            </android.support.constraint.ConstraintLayout>

            <android.support.constraint.ConstraintLayout
                android:id="@+id/constraintlayout_recyclerview"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="@dimen/padding_margin_zero"
                android:layout_marginTop="@dimen/padding_margin_zero"
                android:layout_marginEnd="@dimen/padding_margin_zero"
                app:layout_constraintLeft_toLeftOf="parent"
                app:layout_constraintRight_toRightOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/constraintlayout_main">

                <android.support.v7.widget.RecyclerView
                    android:id="@+id/recyclerview_list"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:nestedScrollingEnabled="false"
                    app:layout_constraintLeft_toLeftOf="parent"
                    app:layout_constraintRight_toRightOf="parent" />

            </android.support.constraint.ConstraintLayout>

        </android.support.constraint.ConstraintLayout>

    </android.support.v4.widget.NestedScrollView>

</android.support.constraint.ConstraintLayout>

Este código está funcionando no ConstraintLayout android


0

Kotlin

Defina isNestedScrollingEnabledcomo falsepara cada RecyclerView que está sob a exibição de rolagem

val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
recyclerView.isNestedScrollingEnabled = false

Usando layout XML

<android.support.v7.widget.RecyclerView
    android:layout_marginTop="10dp"
    android:layout_marginBottom="10dp"
    android:id="@+id/friendsList"
    android:layout_width="match_parent"
    android:nestedScrollingEnabled="false"
    android:layout_height="wrap_content" />
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.