Add basic animations to conversation list.

fork-5.53.8
Greyson Parrelli 2021-11-05 01:23:36 -04:00
rodzic b8dc541fc5
commit c4164b17a2
4 zmienionych plików z 36 dodań i 52 usunięć

Wyświetl plik

@ -0,0 +1,16 @@
package org.thoughtcrime.securesms.components.recyclerview;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.RecyclerView;
public class ConversationListItemAnimator extends DefaultItemAnimator {
public ConversationListItemAnimator() {
setSupportsChangeAnimations(false);
}
@Override public boolean animateRemove(RecyclerView.ViewHolder holder) {
return super.animateRemove(holder);
}
}

Wyświetl plik

@ -1,26 +0,0 @@
package org.thoughtcrime.securesms.components.recyclerview;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.RecyclerView;
public class DeleteItemAnimator extends DefaultItemAnimator {
public DeleteItemAnimator() {
setSupportsChangeAnimations(false);
}
@Override
public boolean animateAdd(RecyclerView.ViewHolder viewHolder) {
dispatchAddFinished(viewHolder);
return false;
}
@Override
public boolean animateMove(RecyclerView.ViewHolder viewHolder, int fromX, int fromY, int toX, int toY) {
dispatchMoveFinished(viewHolder);
return false;
}
}

Wyświetl plik

@ -57,8 +57,6 @@ class ConversationListAdapter extends ListAdapter<Conversation, RecyclerView.Vie
this.glideRequests = glideRequests; this.glideRequests = glideRequests;
this.onConversationClickListener = onConversationClickListener; this.onConversationClickListener = onConversationClickListener;
this.setHasStableIds(true);
} }
@Override @Override
@ -171,23 +169,6 @@ class ConversationListAdapter extends ListAdapter<Conversation, RecyclerView.Vie
return super.getItem(position); return super.getItem(position);
} }
@Override
public long getItemId(int position) {
Conversation item = getItem(position);
if (item == null) {
return 0;
}
switch (item.getType()) {
case THREAD: return item.getThreadRecord().getThreadId();
case PINNED_HEADER: return -1;
case UNPINNED_HEADER: return -2;
case ARCHIVED_FOOTER: return -3;
default: throw new AssertionError();
}
}
public void setPagingController(@Nullable PagingController pagingController) { public void setPagingController(@Nullable PagingController pagingController) {
this.pagingController = pagingController; this.pagingController = pagingController;
} }

Wyświetl plik

@ -26,6 +26,7 @@ import android.content.res.Resources;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
@ -89,7 +90,7 @@ import org.thoughtcrime.securesms.components.UnreadPaymentsView;
import org.thoughtcrime.securesms.components.menu.ActionItem; import org.thoughtcrime.securesms.components.menu.ActionItem;
import org.thoughtcrime.securesms.components.menu.SignalBottomActionBar; import org.thoughtcrime.securesms.components.menu.SignalBottomActionBar;
import org.thoughtcrime.securesms.components.menu.SignalContextMenu; import org.thoughtcrime.securesms.components.menu.SignalContextMenu;
import org.thoughtcrime.securesms.components.recyclerview.DeleteItemAnimator; import org.thoughtcrime.securesms.components.recyclerview.ConversationListItemAnimator;
import org.thoughtcrime.securesms.components.registration.PulsingFloatingActionButton; import org.thoughtcrime.securesms.components.registration.PulsingFloatingActionButton;
import org.thoughtcrime.securesms.components.reminder.DozeReminder; import org.thoughtcrime.securesms.components.reminder.DozeReminder;
import org.thoughtcrime.securesms.components.reminder.ExpiredBuildReminder; import org.thoughtcrime.securesms.components.reminder.ExpiredBuildReminder;
@ -270,7 +271,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode
cameraFab.show(); cameraFab.show();
list.setLayoutManager(new LinearLayoutManager(requireActivity())); list.setLayoutManager(new LinearLayoutManager(requireActivity()));
list.setItemAnimator(new DeleteItemAnimator()); list.setItemAnimator(new ConversationListItemAnimator());
list.addOnScrollListener(new ScrollListener()); list.addOnScrollListener(new ScrollListener());
snapToTopDataObserver = new SnapToTopDataObserver(list); snapToTopDataObserver = new SnapToTopDataObserver(list);
@ -638,7 +639,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode
viewModel.getSearchResult().observe(getViewLifecycleOwner(), this::onSearchResultChanged); viewModel.getSearchResult().observe(getViewLifecycleOwner(), this::onSearchResultChanged);
viewModel.getMegaphone().observe(getViewLifecycleOwner(), this::onMegaphoneChanged); viewModel.getMegaphone().observe(getViewLifecycleOwner(), this::onMegaphoneChanged);
viewModel.getConversationList().observe(getViewLifecycleOwner(), this::onSubmitList); viewModel.getConversationList().observe(getViewLifecycleOwner(), this::onConversationListChanged);
viewModel.hasNoConversations().observe(getViewLifecycleOwner(), this::updateEmptyState); viewModel.hasNoConversations().observe(getViewLifecycleOwner(), this::updateEmptyState);
viewModel.getPipeState().observe(getViewLifecycleOwner(), this::updateProxyStatus); viewModel.getPipeState().observe(getViewLifecycleOwner(), this::updateProxyStatus);
@ -655,6 +656,17 @@ public class ConversationListFragment extends MainFragment implements ActionMode
viewModel.getUnreadPaymentsLiveData().observe(getViewLifecycleOwner(), this::onUnreadPaymentsChanged); viewModel.getUnreadPaymentsLiveData().observe(getViewLifecycleOwner(), this::onUnreadPaymentsChanged);
} }
private void onConversationListChanged(@NonNull List<Conversation> conversations) {
LinearLayoutManager layoutManager = (LinearLayoutManager) list.getLayoutManager();
int firstVisibleItem = layoutManager != null ? layoutManager.findFirstCompletelyVisibleItemPosition() : -1;
defaultAdapter.submitList(conversations, () -> {
if (firstVisibleItem == 0) {
list.scrollToPosition(0);
}
});
}
private void onUnreadPaymentsChanged(@NonNull Optional<UnreadPayments> unreadPayments) { private void onUnreadPaymentsChanged(@NonNull Optional<UnreadPayments> unreadPayments) {
if (unreadPayments.isPresent()) { if (unreadPayments.isPresent()) {
paymentNotificationView.get().setListener(new PaymentNotificationListener(unreadPayments.get())); paymentNotificationView.get().setListener(new PaymentNotificationListener(unreadPayments.get()));
@ -1338,6 +1350,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode
private static final int ARCHIVE_SWIPE_START_COLOR = 0xFF28782A; private static final int ARCHIVE_SWIPE_START_COLOR = 0xFF28782A;
private static final int ARCHIVE_SWIPE_END_COLOR = 0xFF329635; private static final int ARCHIVE_SWIPE_END_COLOR = 0xFF329635;
private static final float MIN_ICON_SCALE = 0.75f;
ArchiveListenerCallback() { ArchiveListenerCallback() {
super(0, ItemTouchHelper.RIGHT); super(0, ItemTouchHelper.RIGHT);
@ -1392,11 +1405,11 @@ public class ConversationListFragment extends MainFragment implements ActionMode
float scale; float scale;
if (dX < scaleStartPoint) { if (dX < scaleStartPoint) {
scale = 0.5f; scale = MIN_ICON_SCALE;
} else if (dX > scaleEndPoint) { } else if (dX > scaleEndPoint) {
scale = 1f; scale = 1f;
} else { } else {
scale = Math.min(1f, 0.5f + ((dX - scaleStartPoint) / (scaleEndPoint - scaleStartPoint)) * (1f - 0.5f)); scale = Math.min(1f, MIN_ICON_SCALE + ((dX - scaleStartPoint) / (scaleEndPoint - scaleStartPoint)) * (1f - MIN_ICON_SCALE));
} }
if (dX > 0) { if (dX > 0) {