Gifv player
This commit is contained in:
parent
990f364bf9
commit
90bd7baa94
|
@ -15,6 +15,7 @@ import org.joinmastodon.android.R;
|
|||
import org.joinmastodon.android.model.DisplayItemsParent;
|
||||
import org.joinmastodon.android.model.Status;
|
||||
import org.joinmastodon.android.ui.displayitems.FooterStatusDisplayItem;
|
||||
import org.joinmastodon.android.ui.displayitems.ImageStatusDisplayItem;
|
||||
import org.joinmastodon.android.ui.displayitems.PhotoStatusDisplayItem;
|
||||
import org.joinmastodon.android.ui.displayitems.StatusDisplayItem;
|
||||
import org.joinmastodon.android.ui.photoviewer.PhotoViewer;
|
||||
|
@ -122,18 +123,18 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
|||
public void openPhotoViewer(String parentID, Status _status, int attachmentIndex){
|
||||
final Status status=_status.reblog!=null ? _status.reblog : _status;
|
||||
currentPhotoViewer=new PhotoViewer(getActivity(), status.mediaAttachments, attachmentIndex, new PhotoViewer.Listener(){
|
||||
private PhotoStatusDisplayItem.Holder transitioningHolder;
|
||||
private ImageStatusDisplayItem.Holder transitioningHolder;
|
||||
|
||||
@Override
|
||||
public void setPhotoViewVisibility(int index, boolean visible){
|
||||
PhotoStatusDisplayItem.Holder holder=findPhotoViewHolder(index);
|
||||
ImageStatusDisplayItem.Holder holder=findPhotoViewHolder(index);
|
||||
if(holder!=null)
|
||||
holder.photo.setAlpha(visible ? 1f : 0f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startPhotoViewTransition(int index, @NonNull Rect outRect, @NonNull int[] outCornerRadius){
|
||||
PhotoStatusDisplayItem.Holder holder=findPhotoViewHolder(index);
|
||||
ImageStatusDisplayItem.Holder holder=findPhotoViewHolder(index);
|
||||
if(holder!=null){
|
||||
transitioningHolder=holder;
|
||||
View view=transitioningHolder.photo;
|
||||
|
@ -170,7 +171,7 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
|||
|
||||
@Override
|
||||
public Drawable getPhotoViewCurrentDrawable(int index){
|
||||
PhotoStatusDisplayItem.Holder holder=findPhotoViewHolder(index);
|
||||
ImageStatusDisplayItem.Holder holder=findPhotoViewHolder(index);
|
||||
if(holder!=null)
|
||||
return holder.photo.getDrawable();
|
||||
return null;
|
||||
|
@ -181,14 +182,14 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
|||
currentPhotoViewer=null;
|
||||
}
|
||||
|
||||
private PhotoStatusDisplayItem.Holder findPhotoViewHolder(int index){
|
||||
private ImageStatusDisplayItem.Holder findPhotoViewHolder(int index){
|
||||
int offset=0;
|
||||
for(StatusDisplayItem item:displayItems){
|
||||
if(item.parentID.equals(parentID)){
|
||||
if(item instanceof PhotoStatusDisplayItem){
|
||||
if(item instanceof ImageStatusDisplayItem){
|
||||
RecyclerView.ViewHolder holder=list.findViewHolderForAdapterPosition(getMainAdapterOffset()+offset+index);
|
||||
if(holder instanceof PhotoStatusDisplayItem.Holder){
|
||||
return (PhotoStatusDisplayItem.Holder) holder;
|
||||
if(holder instanceof ImageStatusDisplayItem.Holder){
|
||||
return (ImageStatusDisplayItem.Holder) holder;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -264,10 +265,10 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
|
|||
position-=getMainAdapterOffset();
|
||||
if(position>=0 && position<displayItems.size()){
|
||||
StatusDisplayItem item=displayItems.get(position);
|
||||
if(item instanceof PhotoStatusDisplayItem){
|
||||
int total=((PhotoStatusDisplayItem) item).totalPhotos;
|
||||
if(item instanceof ImageStatusDisplayItem){
|
||||
int total=((ImageStatusDisplayItem) item).totalPhotos;
|
||||
if(total>1){
|
||||
int index=((PhotoStatusDisplayItem) item).index;
|
||||
int index=((ImageStatusDisplayItem) item).index;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
package org.joinmastodon.android.ui.displayitems;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.graphics.Outline;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewOutlineProvider;
|
||||
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||
import org.joinmastodon.android.model.Attachment;
|
||||
import org.joinmastodon.android.model.Status;
|
||||
|
||||
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
|
||||
|
||||
public class GifVStatusDisplayItem extends ImageStatusDisplayItem{
|
||||
public GifVStatusDisplayItem(String parentID, Status status, Attachment photo, BaseStatusListFragment parentFragment, int index, int totalPhotos){
|
||||
super(parentID, parentFragment, photo, status, index, totalPhotos);
|
||||
request=new UrlImageLoaderRequest(photo.previewUrl, 1000, 1000);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType(){
|
||||
return Type.GIFV;
|
||||
}
|
||||
|
||||
public static class Holder extends ImageStatusDisplayItem.Holder<GifVStatusDisplayItem>{
|
||||
|
||||
public Holder(Activity activity, ViewGroup parent){
|
||||
super(activity, R.layout.display_item_gifv, parent);
|
||||
View play=findViewById(R.id.play_button);
|
||||
play.setOutlineProvider(new ViewOutlineProvider(){
|
||||
@Override
|
||||
public void getOutline(View view, Outline outline){
|
||||
outline.setOval(0, 0, view.getWidth(), view.getHeight());
|
||||
outline.setAlpha(.99f); // fixes shadow rendering
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
package org.joinmastodon.android.ui.displayitems;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Fragment;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||
import org.joinmastodon.android.model.Attachment;
|
||||
import org.joinmastodon.android.model.Status;
|
||||
import org.joinmastodon.android.ui.photoviewer.PhotoViewerHost;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
import me.grishka.appkit.imageloader.ImageLoaderViewHolder;
|
||||
import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
|
||||
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
|
||||
|
||||
public abstract class ImageStatusDisplayItem extends StatusDisplayItem{
|
||||
public final int index;
|
||||
public final int totalPhotos;
|
||||
protected Attachment attachment;
|
||||
protected ImageLoaderRequest request;
|
||||
protected Fragment parentFragment;
|
||||
protected Status status;
|
||||
|
||||
public ImageStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, Attachment photo, Status status, int index, int totalPhotos){
|
||||
super(parentID, parentFragment);
|
||||
this.attachment=photo;
|
||||
this.parentFragment=parentFragment;
|
||||
this.status=status;
|
||||
this.index=index;
|
||||
this.totalPhotos=totalPhotos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageCount(){
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageLoaderRequest getImageRequest(int index){
|
||||
return request;
|
||||
}
|
||||
|
||||
public static abstract class Holder<T extends ImageStatusDisplayItem> extends StatusDisplayItem.Holder<T> implements ImageLoaderViewHolder{
|
||||
public final ImageView photo;
|
||||
|
||||
public Holder(Activity activity, @LayoutRes int layout, ViewGroup parent){
|
||||
super(activity, layout, parent);
|
||||
photo=findViewById(R.id.photo);
|
||||
photo.setOnClickListener(this::onViewClick);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBind(ImageStatusDisplayItem item){
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImage(int index, Drawable drawable){
|
||||
photo.setImageDrawable(drawable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearImage(int index){
|
||||
photo.setImageDrawable(item.attachment.blurhashPlaceholder);
|
||||
}
|
||||
|
||||
private void onViewClick(View v){
|
||||
if(item.parentFragment instanceof PhotoViewerHost){
|
||||
Status contentStatus=item.status.reblog!=null ? item.status.reblog : item.status;
|
||||
((PhotoViewerHost) item.parentFragment).openPhotoViewer(item.parentID, item.status, contentStatus.mediaAttachments.indexOf(item.attachment));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,37 +1,19 @@
|
|||
package org.joinmastodon.android.ui.displayitems;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Fragment;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||
import org.joinmastodon.android.model.Attachment;
|
||||
import org.joinmastodon.android.model.Status;
|
||||
import org.joinmastodon.android.ui.photoviewer.PhotoViewerHost;
|
||||
|
||||
import me.grishka.appkit.imageloader.ImageLoaderViewHolder;
|
||||
import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
|
||||
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
|
||||
import me.grishka.appkit.utils.BindableViewHolder;
|
||||
|
||||
public class PhotoStatusDisplayItem extends StatusDisplayItem{
|
||||
private Attachment attachment;
|
||||
private ImageLoaderRequest request;
|
||||
private Fragment parentFragment;
|
||||
private Status status;
|
||||
public final int index, totalPhotos;
|
||||
public class PhotoStatusDisplayItem extends ImageStatusDisplayItem{
|
||||
public PhotoStatusDisplayItem(String parentID, Status status, Attachment photo, BaseStatusListFragment parentFragment, int index, int totalPhotos){
|
||||
super(parentID, parentFragment);
|
||||
this.status=status;
|
||||
this.attachment=photo;
|
||||
super(parentID, parentFragment, photo, status, index, totalPhotos);
|
||||
request=new UrlImageLoaderRequest(photo.url, 1000, 1000);
|
||||
this.parentFragment=parentFragment;
|
||||
this.index=index;
|
||||
this.totalPhotos=totalPhotos;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -39,44 +21,10 @@ public class PhotoStatusDisplayItem extends StatusDisplayItem{
|
|||
return Type.PHOTO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getImageCount(){
|
||||
return 1;
|
||||
}
|
||||
public static class Holder extends ImageStatusDisplayItem.Holder<PhotoStatusDisplayItem>{
|
||||
|
||||
@Override
|
||||
public ImageLoaderRequest getImageRequest(int index){
|
||||
return request;
|
||||
}
|
||||
|
||||
public static class Holder extends StatusDisplayItem.Holder<PhotoStatusDisplayItem> implements ImageLoaderViewHolder{
|
||||
public final ImageView photo;
|
||||
public Holder(Activity activity, ViewGroup parent){
|
||||
super(activity, R.layout.display_item_photo, parent);
|
||||
photo=findViewById(R.id.photo);
|
||||
photo.setOnClickListener(this::onViewClick);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBind(PhotoStatusDisplayItem item){
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImage(int index, Drawable drawable){
|
||||
photo.setImageDrawable(drawable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearImage(int index){
|
||||
photo.setImageDrawable(item.attachment.blurhashPlaceholder);
|
||||
}
|
||||
|
||||
private void onViewClick(View v){
|
||||
if(item.parentFragment instanceof PhotoViewerHost){
|
||||
Status contentStatus=item.status.reblog!=null ? item.status.reblog : item.status;
|
||||
((PhotoViewerHost) item.parentFragment).openPhotoViewer(item.parentID, item.status, contentStatus.mediaAttachments.indexOf(item.attachment));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ public abstract class StatusDisplayItem{
|
|||
case REBLOG_OR_REPLY_LINE -> new ReblogOrReplyLineStatusDisplayItem.Holder(activity, parent);
|
||||
case TEXT -> new TextStatusDisplayItem.Holder(activity, parent);
|
||||
case PHOTO -> new PhotoStatusDisplayItem.Holder(activity, parent);
|
||||
case GIFV -> new GifVStatusDisplayItem.Holder(activity, parent);
|
||||
case FOOTER -> new FooterStatusDisplayItem.Holder(activity, parent);
|
||||
default -> throw new UnsupportedOperationException();
|
||||
};
|
||||
|
@ -63,7 +64,7 @@ public abstract class StatusDisplayItem{
|
|||
int photoIndex=0;
|
||||
int totalPhotos=0;
|
||||
for(Attachment attachment:statusForContent.mediaAttachments){
|
||||
if(attachment.type==Attachment.Type.IMAGE){
|
||||
if(attachment.type==Attachment.Type.IMAGE || attachment.type==Attachment.Type.GIFV){
|
||||
totalPhotos++;
|
||||
}
|
||||
}
|
||||
|
@ -71,6 +72,9 @@ public abstract class StatusDisplayItem{
|
|||
if(attachment.type==Attachment.Type.IMAGE){
|
||||
items.add(new PhotoStatusDisplayItem(parentID, status, attachment, fragment, photoIndex, totalPhotos));
|
||||
photoIndex++;
|
||||
}else if(attachment.type==Attachment.Type.GIFV){
|
||||
items.add(new GifVStatusDisplayItem(parentID, status, attachment, fragment, photoIndex, totalPhotos));
|
||||
photoIndex++;
|
||||
}
|
||||
}
|
||||
items.add(new FooterStatusDisplayItem(parentID, fragment, statusForContent, accountID));
|
||||
|
|
|
@ -3,10 +3,16 @@ package org.joinmastodon.android.ui.photoviewer;
|
|||
import android.app.Activity;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.media.MediaPlayer;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
import android.view.Gravity;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.Surface;
|
||||
import android.view.TextureView;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
|
@ -16,6 +22,8 @@ import android.widget.ImageView;
|
|||
|
||||
import org.joinmastodon.android.model.Attachment;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
@ -28,6 +36,8 @@ import me.grishka.appkit.utils.BindableViewHolder;
|
|||
import me.grishka.appkit.utils.CubicBezierInterpolator;
|
||||
|
||||
public class PhotoViewer implements ZoomPanView.Listener{
|
||||
private static final String TAG="PhotoViewer";
|
||||
|
||||
private Activity activity;
|
||||
private List<Attachment> attachments;
|
||||
private int currentIndex;
|
||||
|
@ -37,6 +47,7 @@ public class PhotoViewer implements ZoomPanView.Listener{
|
|||
private FrameLayout windowView;
|
||||
private ViewPager2 pager;
|
||||
private ColorDrawable background=new ColorDrawable(0xff000000);
|
||||
private ArrayList<MediaPlayer> players=new ArrayList<>();
|
||||
|
||||
public PhotoViewer(Activity activity, List<Attachment> attachments, int index, Listener listener){
|
||||
this.activity=activity;
|
||||
|
@ -79,7 +90,7 @@ public class PhotoViewer implements ZoomPanView.Listener{
|
|||
int[] radius=new int[4];
|
||||
if(listener.startPhotoViewTransition(index, rect, radius)){
|
||||
RecyclerView rv=(RecyclerView) pager.getChildAt(0);
|
||||
PhotoViewHolder holder=(PhotoViewHolder) rv.findViewHolderForAdapterPosition(index);
|
||||
BaseHolder holder=(BaseHolder) rv.findViewHolderForAdapterPosition(index);
|
||||
holder.zoomPanView.animateIn(rect, radius);
|
||||
}
|
||||
|
||||
|
@ -121,7 +132,7 @@ public class PhotoViewer implements ZoomPanView.Listener{
|
|||
int[] radius=new int[4];
|
||||
if(listener.startPhotoViewTransition(index, rect, radius)){
|
||||
RecyclerView rv=(RecyclerView) pager.getChildAt(0);
|
||||
PhotoViewHolder holder=(PhotoViewHolder) rv.findViewHolderForAdapterPosition(index);
|
||||
BaseHolder holder=(BaseHolder) rv.findViewHolderForAdapterPosition(index);
|
||||
holder.zoomPanView.animateOut(rect, radius, velocityY);
|
||||
}else{
|
||||
windowView.animate()
|
||||
|
@ -140,6 +151,8 @@ public class PhotoViewer implements ZoomPanView.Listener{
|
|||
|
||||
@Override
|
||||
public void onDismissed(){
|
||||
for(MediaPlayer player:players)
|
||||
player.release();
|
||||
listener.setPhotoViewVisibility(pager.getCurrentItem(), true);
|
||||
wm.removeView(windowView);
|
||||
listener.photoViewerDismissed();
|
||||
|
@ -193,16 +206,20 @@ public class PhotoViewer implements ZoomPanView.Listener{
|
|||
void photoViewerDismissed();
|
||||
}
|
||||
|
||||
private class PhotoViewAdapter extends RecyclerView.Adapter<PhotoViewHolder>{
|
||||
private class PhotoViewAdapter extends RecyclerView.Adapter<BaseHolder>{
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public PhotoViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
|
||||
return new PhotoViewHolder();
|
||||
public BaseHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
|
||||
return switch(viewType){
|
||||
case 0 -> new PhotoViewHolder();
|
||||
case 1 -> new GifVViewHolder();
|
||||
default -> throw new IllegalStateException("Unexpected value: "+viewType);
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull PhotoViewHolder holder, int position){
|
||||
public void onBindViewHolder(@NonNull BaseHolder holder, int position){
|
||||
holder.bind(attachments.get(position));
|
||||
}
|
||||
|
||||
|
@ -210,27 +227,63 @@ public class PhotoViewer implements ZoomPanView.Listener{
|
|||
public int getItemCount(){
|
||||
return attachments.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position){
|
||||
Attachment att=attachments.get(position);
|
||||
return switch(att.type){
|
||||
case IMAGE -> 0;
|
||||
case GIFV -> 1;
|
||||
default -> throw new IllegalStateException("Unexpected value: "+att.type);
|
||||
};
|
||||
}
|
||||
|
||||
private class PhotoViewHolder extends BindableViewHolder<Attachment> implements ViewImageLoader.Target{
|
||||
public ImageView imageView;
|
||||
public ZoomPanView zoomPanView;
|
||||
@Override
|
||||
public void onViewDetachedFromWindow(@NonNull BaseHolder holder){
|
||||
super.onViewDetachedFromWindow(holder);
|
||||
if(holder instanceof GifVViewHolder){
|
||||
((GifVViewHolder) holder).reset();
|
||||
}
|
||||
}
|
||||
|
||||
public PhotoViewHolder(){
|
||||
@Override
|
||||
public void onViewAttachedToWindow(@NonNull BaseHolder holder){
|
||||
super.onViewAttachedToWindow(holder);
|
||||
if(holder instanceof GifVViewHolder){
|
||||
((GifVViewHolder) holder).prepareAndStartPlayer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private abstract class BaseHolder extends BindableViewHolder<Attachment>{
|
||||
public ZoomPanView zoomPanView;
|
||||
public BaseHolder(){
|
||||
super(new ZoomPanView(activity));
|
||||
zoomPanView=(ZoomPanView) itemView;
|
||||
zoomPanView.setListener(PhotoViewer.this);
|
||||
itemView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
imageView=new ImageView(activity);
|
||||
((FrameLayout)itemView).addView(imageView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.CENTER));
|
||||
zoomPanView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBind(Attachment item){
|
||||
zoomPanView.setScrollDirections(getAbsoluteAdapterPosition()>0, getAbsoluteAdapterPosition()<attachments.size()-1);
|
||||
}
|
||||
}
|
||||
|
||||
private class PhotoViewHolder extends BaseHolder implements ViewImageLoader.Target{
|
||||
public ImageView imageView;
|
||||
|
||||
public PhotoViewHolder(){
|
||||
imageView=new ImageView(activity);
|
||||
zoomPanView.addView(imageView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.CENTER));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBind(Attachment item){
|
||||
super.onBind(item);
|
||||
FrameLayout.LayoutParams params=(FrameLayout.LayoutParams) imageView.getLayoutParams();
|
||||
params.width=item.getWidth();
|
||||
params.height=item.getHeight();
|
||||
zoomPanView.setScrollDirections(getAbsoluteAdapterPosition()>0, getAbsoluteAdapterPosition()<attachments.size()-1);
|
||||
ViewImageLoader.load(this, listener.getPhotoViewCurrentDrawable(getAbsoluteAdapterPosition()), new UrlImageLoaderRequest(item.url), false);
|
||||
}
|
||||
|
||||
|
@ -244,4 +297,98 @@ public class PhotoViewer implements ZoomPanView.Listener{
|
|||
return imageView;
|
||||
}
|
||||
}
|
||||
|
||||
private class GifVViewHolder extends BaseHolder implements MediaPlayer.OnPreparedListener, MediaPlayer.OnErrorListener, TextureView.SurfaceTextureListener{
|
||||
public TextureView textureView;
|
||||
public FrameLayout wrap;
|
||||
public MediaPlayer player;
|
||||
private Surface surface;
|
||||
private boolean playerReady;
|
||||
|
||||
public GifVViewHolder(){
|
||||
textureView=new TextureView(activity);
|
||||
wrap=new FrameLayout(activity);
|
||||
zoomPanView.addView(wrap, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.CENTER));
|
||||
wrap.addView(textureView);
|
||||
|
||||
textureView.setSurfaceTextureListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBind(Attachment item){
|
||||
super.onBind(item);
|
||||
playerReady=false;
|
||||
FrameLayout.LayoutParams params=(FrameLayout.LayoutParams) wrap.getLayoutParams();
|
||||
params.width=item.getWidth();
|
||||
params.height=item.getHeight();
|
||||
wrap.setBackground(listener.getPhotoViewCurrentDrawable(getAbsoluteAdapterPosition()));
|
||||
if(itemView.isAttachedToWindow()){
|
||||
prepareAndStartPlayer();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepared(MediaPlayer mp){
|
||||
Log.d(TAG, "onPrepared() called with: mp = ["+mp+"]");
|
||||
playerReady=true;
|
||||
if(surface!=null)
|
||||
startPlayer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height){
|
||||
this.surface=new Surface(surface);
|
||||
if(playerReady)
|
||||
startPlayer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width, int height){
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface){
|
||||
this.surface=null;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface){
|
||||
|
||||
}
|
||||
|
||||
private void startPlayer(){
|
||||
player.setSurface(surface);
|
||||
player.setLooping(true);
|
||||
player.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onError(MediaPlayer mp, int what, int extra){
|
||||
Log.e(TAG, "gif player onError() called with: mp = ["+mp+"], what = ["+what+"], extra = ["+extra+"]");
|
||||
return false;
|
||||
}
|
||||
|
||||
public void prepareAndStartPlayer(){
|
||||
playerReady=false;
|
||||
player=new MediaPlayer();
|
||||
players.add(player);
|
||||
player.setOnPreparedListener(this);
|
||||
player.setOnErrorListener(this);
|
||||
try{
|
||||
player.setDataSource(activity, Uri.parse(item.url));
|
||||
player.prepareAsync();
|
||||
}catch(IOException x){
|
||||
Log.w(TAG, "Error initializing gif player", x);
|
||||
}
|
||||
}
|
||||
|
||||
public void reset(){
|
||||
playerReady=false;
|
||||
player.release();
|
||||
players.remove(player);
|
||||
player=null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="28dp"
|
||||
android:height="28dp"
|
||||
android:viewportWidth="28"
|
||||
android:viewportHeight="28">
|
||||
<path
|
||||
android:pathData="M21.875,4.084C23.9691,4.084 25.6667,5.7816 25.6667,7.8756V20.1287C25.6667,22.2227 23.9691,23.9203 21.875,23.9203H6.125C4.0309,23.9203 2.3333,22.2227 2.3333,20.1287V7.8756C2.3333,5.7816 4.0309,4.084 6.125,4.084H21.875ZM9.3504,10.3506C7.4531,10.3506 6.1379,11.9953 6.1379,13.9934C6.1379,15.9922 7.4534,17.6403 9.3504,17.6403C10.3861,17.6403 11.3373,17.1421 11.814,16.2241L11.9029,16.0349L11.9303,15.9537L11.9514,15.8666L11.9602,15.7698L11.9605,13.9956L11.9526,13.8878C11.9063,13.5753 11.6617,13.3274 11.3507,13.2761L11.2313,13.2664H10.0628L9.955,13.2743C9.6425,13.3206 9.3946,13.5652 9.3433,13.8761L9.3336,13.9956L9.3415,14.1033C9.3878,14.4159 9.6324,14.6638 9.9433,14.715L10.0628,14.7247L10.5012,14.7244V15.5808L10.494,15.5978C10.2738,15.9722 9.8504,16.182 9.3504,16.182C8.3402,16.182 7.5962,15.2499 7.5962,13.9934C7.5962,12.738 8.3392,11.8089 9.3504,11.8089C9.842,11.8089 10.1218,11.8629 10.4716,12.0308C10.8346,12.2052 11.2702,12.0522 11.4446,11.6892C11.6189,11.3262 11.4659,10.8906 11.1029,10.7162C10.5391,10.4455 10.0468,10.3506 9.3504,10.3506ZM14.7338,10.4929C14.3677,10.4929 14.0646,10.7627 14.0125,11.1144L14.0046,11.2221V16.7779L14.0125,16.8857C14.0646,17.2373 14.3677,17.5071 14.7338,17.5071C15.0999,17.5071 15.403,17.2373 15.455,16.8857L15.4629,16.7779V11.2221L15.455,11.1144C15.403,10.7627 15.0999,10.4929 14.7338,10.4929ZM20.5592,10.501L18.2289,10.4929C17.8628,10.4917 17.5588,10.7604 17.5055,11.1119L17.4972,11.2196V16.7592L17.5051,16.8669C17.5514,17.1794 17.796,17.4274 18.1069,17.4786L18.2264,17.4883L18.3341,17.4804C18.6467,17.4341 18.8946,17.1895 18.9458,16.8786L18.9555,16.7592L18.9549,15.4583L20.265,15.4588L20.3728,15.4509C20.6853,15.4046 20.9332,15.16 20.9844,14.8491L20.9942,14.7297L20.9863,14.6219C20.94,14.3094 20.6954,14.0615 20.3845,14.0102L20.265,14.0005L18.9549,13.9999V11.9524L20.5542,11.9593L20.6619,11.9518C21.0137,11.9009 21.2846,11.5988 21.2859,11.2327C21.2871,10.8666 21.0184,10.5626 20.6669,10.5093L20.5592,10.501L18.2289,10.4929L20.5592,10.501Z"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.8"/>
|
||||
<path
|
||||
android:pathData="M6.1379,13.9933C6.1379,11.9953 7.4531,10.3506 9.3504,10.3506C10.0468,10.3506 10.5391,10.4455 11.1029,10.7162C11.4659,10.8905 11.6189,11.3261 11.4446,11.6892C11.2702,12.0522 10.8346,12.2051 10.4716,12.0308C10.1218,11.8628 9.842,11.8089 9.3504,11.8089C8.3392,11.8089 7.5962,12.738 7.5962,13.9933C7.5962,15.2498 8.3402,16.182 9.3504,16.182C9.8504,16.182 10.2738,15.9721 10.494,15.5977L10.5012,15.5808V14.7244L10.0628,14.7247L9.9433,14.715C9.6324,14.6638 9.3878,14.4158 9.3415,14.1033L9.3336,13.9956L9.3433,13.8761C9.3946,13.5652 9.6425,13.3206 9.955,13.2743L10.0628,13.2664H11.2313L11.3507,13.2761C11.6616,13.3274 11.9063,13.5753 11.9526,13.8878L11.9605,13.9956L11.9602,15.7697L11.9514,15.8666L11.9303,15.9536L11.9029,16.0349L11.814,16.2241C11.3373,17.142 10.3861,17.6403 9.3504,17.6403C7.4533,17.6403 6.1379,15.9922 6.1379,13.9933ZM14.0125,11.1143C14.0646,10.7627 14.3677,10.4929 14.7338,10.4929C15.0999,10.4929 15.403,10.7627 15.455,11.1143L15.4629,11.2221V16.7779L15.455,16.8857C15.403,17.2373 15.0999,17.5071 14.7338,17.5071C14.3677,17.5071 14.0646,17.2373 14.0125,16.8857L14.0046,16.7779V11.2221L14.0125,11.1143ZM18.2289,10.4929L20.5592,10.501L20.6669,10.5092C21.0183,10.5625 21.2871,10.8666 21.2858,11.2326C21.2846,11.5987 21.0137,11.9009 20.6619,11.9518L20.5542,11.9593L18.9549,11.9524V13.9999L20.265,14.0005L20.3844,14.0102C20.6954,14.0614 20.94,14.3093 20.9863,14.6219L20.9942,14.7296L20.9844,14.8491C20.9332,15.16 20.6853,15.4046 20.3728,15.4509L20.265,15.4588L18.9549,15.4583L18.9555,16.7591L18.9458,16.8786C18.8946,17.1895 18.6467,17.4341 18.3341,17.4804L18.2264,17.4883L18.1069,17.4786C17.796,17.4273 17.5514,17.1794 17.5051,16.8669L17.4972,16.7591V11.2196L17.5055,11.1118C17.5588,10.7604 17.8628,10.4917 18.2289,10.4929Z"
|
||||
android:fillColor="#FCFCFD" />
|
||||
</vector>
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="20dp"
|
||||
android:height="20dp"
|
||||
android:viewportWidth="20"
|
||||
android:viewportHeight="20">
|
||||
<path
|
||||
android:pathData="M3,3.2739C3,1.567 4.8261,0.4817 6.3254,1.2975L18.687,8.0236C20.2531,8.8758 20.2531,11.1242 18.687,11.9764L6.3254,18.7025C4.8261,19.5183 3,18.433 3,16.7262V3.2739Z"
|
||||
android:fillColor="#F9FAFB"/>
|
||||
</vector>
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<shape android:shape="oval">
|
||||
<stroke android:color="@color/gray_50" android:width="4dp"/>
|
||||
<solid android:color="#80000000"/>
|
||||
<size android:width="52dp" android:height="52dp"/>
|
||||
</shape>
|
||||
</item>
|
||||
<item android:drawable="@drawable/ic_play" android:gravity="center"/>
|
||||
</layer-list>
|
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/photo"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="250dp"
|
||||
android:layout_gravity="center"
|
||||
android:scaleType="centerCrop"/>
|
||||
|
||||
<View
|
||||
android:id="@+id/play_button"
|
||||
android:layout_width="52dp"
|
||||
android:layout_height="52dp"
|
||||
android:layout_gravity="center"
|
||||
android:elevation="3dp"
|
||||
android:background="@drawable/play_button"/>
|
||||
|
||||
<View
|
||||
android:layout_width="28dp"
|
||||
android:layout_height="28dp"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_margin="8dp"
|
||||
android:background="@drawable/ic_gif"/>
|
||||
|
||||
</FrameLayout>
|
Loading…
Reference in New Issue