Bug 1339520 - Keep existing TopPanel when cursor is swapped r=sebastian

By default RecyclerView assumes any item change *might* need animation. It then
creates a new copy of the item that has changed, and interpolates between the two
to "animate" the change. We don't need that for topsites (the RecyclerView's we use
inside each TopSitePanel already animate changes, the overall size doesn't change -
moreover ViewPager state gets lost if you create a new panel), so we override
this behaviour to retain the existing panel. This stops the previously visible
horrible flickering.

(Every time history changes, which can happen if sync is working, or even if a page
finishes loading in the background, the DB is changed, and a reload is triggered.
Prior to this commit, topsites would flicker horribly, and would reset back to the first
topsites page. After this commit the page is retained, and the visible topsites
are rearranged by the inner RecyclerView's animations. You can test this by pinning a
site on the first page, the pinned site will shift to the front, the other sites smoothly
move to the right.)

MozReview-Commit-ID: CnocNfdQ2FS

--HG--
extra : rebase_source : 3a4e1d86c786126aee1e08ab020b855056e4f921
This commit is contained in:
Andrzej Hunt 2017-02-16 18:42:46 -08:00
Родитель 9915444198
Коммит 89530eaabc
3 изменённых файлов: 33 добавлений и 0 удалений

Просмотреть файл

@ -51,6 +51,8 @@ public class ActivityStream extends FrameLayout {
rv.setAdapter(adapter); rv.setAdapter(adapter);
rv.setLayoutManager(new LinearLayoutManager(getContext())); rv.setLayoutManager(new LinearLayoutManager(getContext()));
rv.setHasFixedSize(true); rv.setHasFixedSize(true);
// Override item animations to avoid horrible topsites refreshing
rv.setItemAnimator(new StreamItemAnimator());
RecyclerViewClickSupport.addTo(rv) RecyclerViewClickSupport.addTo(rv)
.setOnItemClickListener(adapter); .setOnItemClickListener(adapter);

Просмотреть файл

@ -0,0 +1,30 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.home.activitystream;
import android.support.annotation.NonNull;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.RecyclerView;
import org.mozilla.gecko.home.activitystream.stream.TopPanel;
/**
* We need our own item animator override to avoid default RV-style animations for certain panels.
*/
public class StreamItemAnimator extends DefaultItemAnimator {
@Override
public boolean canReuseUpdatedViewHolder(@NonNull RecyclerView.ViewHolder viewHolder) {
if (viewHolder.getItemViewType() == TopPanel.LAYOUT_ID) {
// The top panel doesn't ever change in size. We really don't want to reload it
// because it has its own state (i.e. the ViewPager state gets lost, and we
// also flicker when creating a new ViewHolder). Therefore we should try to
// keep the existing TopPanel whenever possible.
return true;
}
return super.canReuseUpdatedViewHolder(viewHolder);
}
}

Просмотреть файл

@ -473,6 +473,7 @@ gbjar.sources += ['java/org/mozilla/gecko/' + x for x in [
'home/activitystream/stream/StreamItem.java', 'home/activitystream/stream/StreamItem.java',
'home/activitystream/stream/TopPanel.java', 'home/activitystream/stream/TopPanel.java',
'home/activitystream/stream/WelcomePanel.java', 'home/activitystream/stream/WelcomePanel.java',
'home/activitystream/StreamItemAnimator.java',
'home/activitystream/StreamRecyclerAdapter.java', 'home/activitystream/StreamRecyclerAdapter.java',
'home/activitystream/topsites/CirclePageIndicator.java', 'home/activitystream/topsites/CirclePageIndicator.java',
'home/activitystream/topsites/TopSitesCard.java', 'home/activitystream/topsites/TopSitesCard.java',