Два RecyclerView десинхронизируются во время прокрутки программы

У меня есть два RecyclerViews на моем экране. А мне нужно прокручивать оба одновременно на одинаковое расстояние программно. Но если я делаю это быстро - RecyclerViews рассинхронизируется.

В этом исходном коде вы должны быстро нажать кнопку в правом верхнем углу и увидеть результат.

введите здесь описание изображения

Это Activity, где создан прослушиватель кнопок для прокрутки списков:

public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView1;
private RecyclerView recyclerView2;
private Adapter adapter1;
private Adapter adapter2;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    recyclerView1 = findViewById(R.id.recycler_view1);
    recyclerView2 = findViewById(R.id.recycler_view2);

    adapter1 = new Adapter();
    recyclerView1.setLayoutManager(new LinearLayoutManager(this));
    recyclerView1.setAdapter(adapter1);

    adapter2 = new Adapter();
    recyclerView2.setLayoutManager(new LinearLayoutManager(this));
    recyclerView2.setAdapter(adapter2);

    findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            recyclerView1.smoothScrollBy(0, 400);
            recyclerView2.smoothScrollBy(0, 400);
        }
    });
}
}

Адаптер для списков:

public class Adapter extends RecyclerView.Adapter<Adapter.Holder>{

private boolean changeHeight = false;

@Override
public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
    return new Holder(view);
}

@Override
public void onBindViewHolder(Holder holder, int position) {
    holder.setContent(String.valueOf(position), position % 2 == 0 ? R.color.colorPrimary : R.color.colorAccent);
    if (changeHeight && position == 3) holder.changeHeight();
}

@Override
public int getItemCount() {
    return 100;
}

class Holder extends RecyclerView.ViewHolder {

    private View view;
    private TextView textView;

    public Holder(View itemView) {
        super(itemView);
        view = itemView;
        textView = itemView.findViewById(R.id.text_view);
    }

    public void setContent(String text, int colorRes) {
        textView.setText(text);
        textView.setBackgroundResource(colorRes);
    }

    public void changeHeight() {
        ViewGroup.LayoutParams params = view.getLayoutParams();
        params.height = view.getHeight() * 2;
        view.setLayoutParams(params);
    }
}
}

Это макет activity_main.xml для Activity

<?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.support.v7.widget.RecyclerView
    android:id="@+id/recycler_view1"
    android:layout_width="0dp"
    android:layout_weight="0.5"
    android:layout_height="match_parent"/>

<android.support.v7.widget.RecyclerView
    android:id="@+id/recycler_view2"
    android:layout_width="0dp"
    android:layout_weight="0.5"
    android:layout_height="match_parent"/>

<Button
    android:id="@+id/button"
    android:layout_width="100dp"
    android:layout_height="100dp"/>

</LinearLayout>

Элемент для RecyclerView item.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="100dp">

<TextView
    android:id="@+id/text_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"/>

</RelativeLayout>

person Pablo    schedule 15.02.2018    source источник
comment
Вам нужно, чтобы переработчики всегда имели одинаковую прокрутку или только после нажатия кнопки? Должна ли пользовательская сенсорная прокрутка быть отключена?   -  person Pawel    schedule 15.02.2018
comment
@Pawel Для упрощения сенсорной прокрутки пользователя отключена. Таким образом, даже после нажатия кнопки списки должны быть синхронизированы.   -  person Pablo    schedule 15.02.2018
comment
Использование вертикального GridLayoutManager с двумя столбцами не удовлетворяет вашим требованиям?   -  person Pawel    schedule 15.02.2018
comment
При SmoothScrolling, если вы вызываете во время выполнения анимации, есть шанс, что предыдущий не остановился в том же состоянии, что и другой, поэтому это вызывает рассинхронизацию, вам нужно дождаться завершения прокрутки, прежде чем вызывать его снова   -  person Marcos Vasconcelos    schedule 15.02.2018
comment
@Pawel Нет. У меня более сложный случай, но это простой пример.   -  person Pablo    schedule 15.02.2018


Ответы (1)


Грубое решение копирует прокрутку первого ресайклера во второй:

    recyclerView1.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            recyclerView2.scrollBy(dx, dy);
        }
    });

Затем перейдите к smoothScroll только recyclerView1.

person Pawel    schedule 15.02.2018