Подтвердить что ты не робот

Java.lang.UnsupportedOperationException: RecyclerView не поддерживает прокрутку до абсолютной позиции

Получение этой ошибки на Samsung GT-S7562 Android 4.0.4. Я не вызываю метод scrollTo через код. Он вызван внутренне. Пожалуйста, помогите

java.lang.UnsupportedOperationException: RecyclerView does not support scrolling to an absolute position.
            at android.support.v7.widget.RecyclerView.scrollTo(RecyclerView.java:941)
            at android.view.View.setScrollX(View.java:7010)
            at android.animation.PropertyValuesHolder.nCallIntMethod(Native Method)
            at android.animation.PropertyValuesHolder.access$200(PropertyValuesHolder.java:35)
            at android.animation.PropertyValuesHolder$IntPropertyValuesHolder.setAnimatedValue(PropertyValuesHolder.java:815)
            at android.animation.ObjectAnimator.animateValue(ObjectAnimator.java:476)
            at android.animation.ValueAnimator.animationFrame(ValueAnimator.java:1145)
            at android.animation.ValueAnimator.setCurrentPlayTime(ValueAnimator.java:551)
            at android.animation.LayoutTransition.startChangingAnimations(LayoutTransition.java:813)
            at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1805)
            at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2632)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:4517)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:993)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:760)
            at dalvik.system.NativeStart.main(Native Method)
4b9b3361

Ответ 1

Вы получите эту ошибку на некоторых Samsung, Sony,... Реализация ICS. Оба я основал, которые включают в себя странные управления внутренними представлениями. Одним из решений этого является расширение RecyclerView (или класс, генерирующий проблему) с вашим собственным классом и использование этого. В этом классе вы будете в основном "съедать" все возможные исключения для этих устройств. Это ужасно, это ужасно, но все, что я могу сделать, чтобы решить такие проблемы.

Для вашей конкретной проблемы с scrollTo....

package com.stackoverflow.customviews;

public class CustomRecyclerView extends RecyclerView{

  private static final String TAG = "CustomRecyclerView";

  public CustomRecyclerView(android.content.Context context) {
    super(context);
  }

  public CustomRecyclerView(android.content.Context context, android.util.AttributeSet attrs) {
      super(context, attrs);
  }

  public CustomRecyclerView(android.content.Context context, android.util.AttributeSet attrs, int defStyle) {
      super(context, attrs, defStyle);
  }

  @Override
  public void scrollTo(int x, int y) {
      Log.e(TAG, "CustomRecyclerView does not support scrolling to an absolute position.");
     // Either don't call super here or call just for some phones, or try catch it. From default implementation we have removed the Runtime Exception trown 
  }
}

Затем вы можете заменить в своем макете xml этот новый класс:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="wrap_content">

<com.stackoverflow.customviews.CustomRecyclerView
    android:id="@+id/my_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:overScrollMode="never"
    android:scrollbars="vertical" />

</FrameLayout>

Ответ 2

У меня была такая же проблема, для меня это было потому, что у меня был

android:animateLayoutChanges="true"

для моего родителя-ресайклера. Я удалил это, и он сработал.

Ответ 3

Чтобы программно выполнить прокрутку, вам необходимо использовать LayoutManager. Например, LinearLayoutManager имеет scrollToPositionWithOffset. GridLayoutManager расширяет LinearLayoutManager - поэтому вы также можете использовать это. Код работает для меня:

RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
if (layoutManager instanceof LinearLayoutManager) {
   LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager;
   linearLayoutManager.scrollToPositionWithOffset(0, newTopMargin - defaultMargin);
}

Ответ 4

У меня была такая же проблема с предупреждением из-за следующего в родительском ресайклере:

android:animateLayoutChanges="true"

Если вы хотите сохранить анимацию, просто поставьте переработчик внутри другого родителя, например framelayout. Он отлично работал у меня, и анимация также отлично работает.

Ответ 5

Как сказали другие в своих ответах android:animateLayoutChanges="true" в RecyclerView родительский макет, вызывают эту проблему, но решение проще, чем сказали другие.

Просто вам нужно поместить свой RecyclerView в новый Layout, у которого нет свойства android:animateLayoutChanges.

Например:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:animateLayoutChanges="true">

    ...

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintTop_toTopOf="parent">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recycler_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>

Ответ 6

Предупреждение появляется только в том случае, если RecyclerView находится внутри прямого родительского представления с атрибутом XML

android:animateLayoutChanges="true"

как @Aalap и @luis сказали (@luis даже дает одну идею, как оставить этот XML-attr с почти такой же иерархией раскладки).

Я хотел бы опубликовать немного опцию diff. Если у вас такая ситуация, возможно, вы хотите оживить некоторые изменения вида внутри родительского макета, но не внутри RecyclerView, иначе этот будет немного неправильным. Если вам нужны анимации RecyclerView, лучше сделать это внутри адаптера RecyclerView, а не XML.

Итак, в конце, если вам нужны анимации, когда что-то меняется вне RecyclerView, лучше поместите

android:animateLayoutChanges="true"

не в родительском представлении RecyclerView, а в родительском представлении на представление, которое вы хотите оживить.

Краткий пример:

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/top_parent_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<FrameLayout
  android:id="@+id/header_view"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:orientation="horizontal"
  android:gravity="center"
  android:clickable="true"
  android:animateLayoutChanges="true">
  <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
  <ImageView
    android:id="@+id/header_arrow_icon"
    android:layout_width="24dp"
    android:layout_height="24dp"
    android:layout_gravity="end|center_vertical"/>
</FrameLayout>
<android.support.v7.widget.RecyclerView
  android:id="@+id/recycler_view"
  android:layout_width="match_parent"
  android:layout_height="match_parent"/>

Это означает: Избегайте переноса RecyclerView с родительским представлением, у которого есть android: animateLayoutChanges = "true"