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 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.