Add thumbnail shared element animation.

This commit is contained in:
Alex Hart
2023-02-09 14:38:48 -04:00
committed by Greyson Parrelli
parent 2c48d40375
commit d0de43a6b2
25 changed files with 484 additions and 252 deletions

View File

@@ -345,7 +345,7 @@ final class MediaGalleryAllAdapter extends StickyHeaderGridAdapter {
}
thumbnailView.setImageResource(glideRequests, slide, false, false);
thumbnailView.setOnClickListener(view -> itemClickListener.onMediaClicked(mediaRecord));
thumbnailView.setOnClickListener(view -> itemClickListener.onMediaClicked(thumbnailView, mediaRecord));
thumbnailView.setOnLongClickListener(view -> onLongClick());
}
@@ -411,7 +411,7 @@ final class MediaGalleryAllAdapter extends StickyHeaderGridAdapter {
line1.setText(fileName.orElse(fileTypeDescription));
line2.setText(getLine2(context, mediaRecord, slide));
itemView.setOnClickListener(view -> itemClickListener.onMediaClicked(mediaRecord));
itemView.setOnClickListener(view -> itemClickListener.onMediaClicked(getTransitionAnchor(), mediaRecord));
itemView.setOnLongClickListener(view -> onLongClick());
selectForMarque = () -> line1.setSelected(true);
handler = new Handler(Looper.getMainLooper());
@@ -459,6 +459,10 @@ final class MediaGalleryAllAdapter extends StickyHeaderGridAdapter {
return fileName.orElse(null);
}
protected @NonNull View getTransitionAnchor() {
return itemView;
}
private @NonNull String describe(@NonNull Recipient from, @NonNull Recipient thread) {
if (from == Recipient.UNKNOWN && thread == Recipient.UNKNOWN) {
return fileName.orElse(fileTypeDescription);
@@ -541,8 +545,8 @@ final class MediaGalleryAllAdapter extends StickyHeaderGridAdapter {
audioView.setAudio((AudioSlide) slide, new AudioViewCallbacksAdapter(audioItemListener, mmsId), true, true);
audioItemListener.registerPlaybackStateObserver(audioView.getPlaybackStateObserver());
audioView.setOnClickListener(view -> itemClickListener.onMediaClicked(mediaRecord));
itemView.setOnClickListener(view -> itemClickListener.onMediaClicked(mediaRecord));
audioView.setOnClickListener(view -> itemClickListener.onMediaClicked(audioView, mediaRecord));
itemView.setOnClickListener(view -> itemClickListener.onMediaClicked(audioView, mediaRecord));
}
@Override
@@ -584,10 +588,15 @@ final class MediaGalleryAllAdapter extends StickyHeaderGridAdapter {
super.bind(context, mediaRecord, slide);
this.slide = slide;
thumbnailView.setImageResource(glideRequests, slide, false, false);
thumbnailView.setOnClickListener(view -> itemClickListener.onMediaClicked(mediaRecord));
thumbnailView.setOnClickListener(view -> itemClickListener.onMediaClicked(thumbnailView, mediaRecord));
thumbnailView.setOnLongClickListener(view -> onLongClick());
}
@Override
protected @NonNull View getTransitionAnchor() {
return thumbnailView;
}
@Override
protected String getFileTypeDescription(@NonNull Context context, @NonNull Slide slide) {
if (slide.hasVideo()) return context.getString(R.string.MediaOverviewActivity_video);
@@ -648,7 +657,7 @@ final class MediaGalleryAllAdapter extends StickyHeaderGridAdapter {
}
interface ItemClickListener {
void onMediaClicked(@NonNull MediaTable.MediaRecord mediaRecord);
void onMediaClicked(@NonNull View view, @NonNull MediaTable.MediaRecord mediaRecord);
void onMediaLongClicked(MediaTable.MediaRecord mediaRecord);
}

View File

@@ -34,6 +34,7 @@ import androidx.viewpager.widget.ViewPager;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.transition.platform.MaterialContainerTransformSharedElementCallback;
import org.signal.libsignal.protocol.util.Pair;
import org.thoughtcrime.securesms.PassphraseRequiredActivity;
@@ -91,6 +92,7 @@ public final class MediaOverviewActivity extends PassphraseRequiredActivity {
@Override
protected void onCreate(Bundle bundle, boolean ready) {
setExitSharedElementCallback(new MaterialContainerTransformSharedElementCallback());
setContentView(R.layout.media_overview_activity);
initializeResources();

View File

@@ -1,11 +1,13 @@
package org.thoughtcrime.securesms.mediaoverview;
import android.app.ActivityOptions;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
import android.util.Size;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
@@ -27,6 +29,7 @@ import androidx.recyclerview.widget.RecyclerView;
import com.codewaves.stickyheadergrid.StickyHeaderGridLayoutManager;
import org.signal.core.util.DimensionUnit;
import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
@@ -38,6 +41,7 @@ import org.thoughtcrime.securesms.database.MediaTable;
import org.thoughtcrime.securesms.database.loaders.GroupedThreadMediaLoader;
import org.thoughtcrime.securesms.database.loaders.MediaLoader;
import org.thoughtcrime.securesms.mediapreview.MediaIntentFactory;
import org.thoughtcrime.securesms.mediapreview.MediaPreviewV2Activity;
import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.mms.PartAuthority;
import org.thoughtcrime.securesms.util.BottomOffsetDecoration;
@@ -196,11 +200,11 @@ public final class MediaOverviewPageFragment extends Fragment
}
@Override
public void onMediaClicked(@NonNull MediaTable.MediaRecord mediaRecord) {
public void onMediaClicked(@NonNull View view, @NonNull MediaTable.MediaRecord mediaRecord) {
if (actionMode != null) {
handleMediaMultiSelectClick(mediaRecord);
} else {
handleMediaPreviewClick(mediaRecord);
handleMediaPreviewClick(view, mediaRecord);
}
}
@@ -224,7 +228,7 @@ public final class MediaOverviewPageFragment extends Fragment
}
}
private void handleMediaPreviewClick(@NonNull MediaTable.MediaRecord mediaRecord) {
private void handleMediaPreviewClick(@NonNull View view, @NonNull MediaTable.MediaRecord mediaRecord) {
if (mediaRecord.getAttachment().getUri() == null) {
return;
}
@@ -249,8 +253,18 @@ public final class MediaOverviewPageFragment extends Fragment
threadId == MediaTable.ALL_THREADS,
true,
sorting,
attachment.isVideoGif());
context.startActivity(MediaIntentFactory.create(context, args));
attachment.isVideoGif(),
new MediaIntentFactory.SharedElementArgs(
attachment.getWidth(),
attachment.getHeight(),
DimensionUnit.DP.toDp(12),
DimensionUnit.DP.toDp(12),
DimensionUnit.DP.toDp(12),
DimensionUnit.DP.toDp(12)
));
view.setTransitionName(MediaPreviewV2Activity.SHARED_ELEMENT_TRANSITION_NAME);
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(requireActivity(), view, MediaPreviewV2Activity.SHARED_ELEMENT_TRANSITION_NAME);
context.startActivity(MediaIntentFactory.create(context, args), options.toBundle());
} else {
if (!MediaUtil.isAudio(attachment)) {
showFileExternally(context, mediaRecord);