@@ -0,0 +1,87 @@
|
||||
package org.joinmastodon.android.ui;
|
||||
|
||||
import android.app.Fragment;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.View;
|
||||
|
||||
import org.joinmastodon.android.ui.photoviewer.PhotoViewer;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
public class SingleImagePhotoViewerListener implements PhotoViewer.Listener{
|
||||
private final View sourceView, transformView;
|
||||
private final int[] cornerRadius;
|
||||
private final Runnable onDismissed;
|
||||
private final Fragment parentFragment;
|
||||
private final Supplier<Drawable> currentDrawableSupplier;
|
||||
private final Runnable onStart, onEnd;
|
||||
|
||||
private float origAlpha;
|
||||
|
||||
public SingleImagePhotoViewerListener(View sourceView, View transformView, int[] cornerRadius, Fragment parentFragment, Runnable onDismissed, Supplier<Drawable> currentDrawableSupplier, Runnable onStart, Runnable onEnd){
|
||||
this.sourceView=sourceView;
|
||||
this.transformView=transformView;
|
||||
this.cornerRadius=cornerRadius;
|
||||
this.onDismissed=onDismissed;
|
||||
this.parentFragment=parentFragment;
|
||||
this.currentDrawableSupplier=currentDrawableSupplier;
|
||||
this.onStart=onStart;
|
||||
this.onEnd=onEnd;
|
||||
if(cornerRadius!=null && cornerRadius.length!=4)
|
||||
throw new IllegalArgumentException("Corner radius must be null or have length of 4");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPhotoViewVisibility(int index, boolean visible){
|
||||
transformView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startPhotoViewTransition(int index, @NonNull Rect outRect, @NonNull int[] outCornerRadius){
|
||||
int[] loc={0, 0};
|
||||
sourceView.getLocationOnScreen(loc);
|
||||
outRect.set(loc[0], loc[1], loc[0]+sourceView.getWidth(), loc[1]+sourceView.getHeight());
|
||||
if(cornerRadius!=null)
|
||||
System.arraycopy(cornerRadius, 0, outCornerRadius, 0, 4);
|
||||
transformView.setTranslationZ(1);
|
||||
if(onStart!=null)
|
||||
onStart.run();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTransitioningViewTransform(float translateX, float translateY, float scale){
|
||||
transformView.setTranslationX(translateX);
|
||||
transformView.setTranslationY(translateY);
|
||||
transformView.setScaleX(scale);
|
||||
transformView.setScaleY(scale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endPhotoViewTransition(){
|
||||
setTransitioningViewTransform(0f, 0f, 1f);
|
||||
transformView.setTranslationZ(0);
|
||||
if(onEnd!=null)
|
||||
onEnd.run();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Drawable getPhotoViewCurrentDrawable(int index){
|
||||
return currentDrawableSupplier.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void photoViewerDismissed(){
|
||||
onDismissed.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissions(String[] permissions){
|
||||
parentFragment.requestPermissions(permissions, PhotoViewer.PERMISSION_REQUEST);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.util.AttributeSet;
|
||||
@@ -54,6 +55,9 @@ public class ZoomPanView extends FrameLayout implements ScaleGestureDetector.OnS
|
||||
private float lastFlingVelocityY;
|
||||
private float backgroundAlphaForTransition=1f;
|
||||
private boolean forceUpdateLayout;
|
||||
private int[] transitionCornerRadius;
|
||||
private Path transitionClipPath=new Path();
|
||||
private float[] tmpFloatArray=new float[8];
|
||||
|
||||
private static final String TAG="ZoomPanView";
|
||||
|
||||
@@ -148,10 +152,25 @@ public class ZoomPanView extends FrameLayout implements ScaleGestureDetector.OnS
|
||||
child.getMatrix().mapRect(tmpRect2);
|
||||
tmpRect2.offset(child.getLeft(), child.getTop());
|
||||
canvas.save();
|
||||
canvas.clipRect(interpolate(tmpRect2.left, tmpRect.left, cropAnimationValue),
|
||||
interpolate(tmpRect2.top, tmpRect.top, cropAnimationValue),
|
||||
interpolate(tmpRect2.right, tmpRect.right, cropAnimationValue),
|
||||
interpolate(tmpRect2.bottom, tmpRect.bottom, cropAnimationValue));
|
||||
if(transitionCornerRadius!=null){
|
||||
float radiusScale=child.getScaleX();
|
||||
tmpFloatArray[0]=tmpFloatArray[1]=(float)transitionCornerRadius[0]*radiusScale*(1f-cropAnimationValue);
|
||||
tmpFloatArray[2]=tmpFloatArray[3]=(float)transitionCornerRadius[1]*radiusScale*(1f-cropAnimationValue);
|
||||
tmpFloatArray[4]=tmpFloatArray[5]=(float)transitionCornerRadius[2]*radiusScale*(1f-cropAnimationValue);
|
||||
tmpFloatArray[6]=tmpFloatArray[7]=(float)transitionCornerRadius[3]*radiusScale*(1f-cropAnimationValue);
|
||||
transitionClipPath.rewind();
|
||||
transitionClipPath.addRoundRect(interpolate(tmpRect2.left, tmpRect.left, cropAnimationValue),
|
||||
interpolate(tmpRect2.top, tmpRect.top, cropAnimationValue),
|
||||
interpolate(tmpRect2.right, tmpRect.right, cropAnimationValue),
|
||||
interpolate(tmpRect2.bottom, tmpRect.bottom, cropAnimationValue),
|
||||
tmpFloatArray, Path.Direction.CW);
|
||||
canvas.clipPath(transitionClipPath);
|
||||
}else{
|
||||
canvas.clipRect(interpolate(tmpRect2.left, tmpRect.left, cropAnimationValue),
|
||||
interpolate(tmpRect2.top, tmpRect.top, cropAnimationValue),
|
||||
interpolate(tmpRect2.right, tmpRect.right, cropAnimationValue),
|
||||
interpolate(tmpRect2.bottom, tmpRect.bottom, cropAnimationValue));
|
||||
}
|
||||
boolean res=super.drawChild(canvas, child, drawingTime);
|
||||
canvas.restore();
|
||||
return res;
|
||||
@@ -189,6 +208,18 @@ public class ZoomPanView extends FrameLayout implements ScaleGestureDetector.OnS
|
||||
return initialScale;
|
||||
}
|
||||
|
||||
private void validateAndSetCornerRadius(int[] cornerRadius){
|
||||
transitionCornerRadius=null;
|
||||
if(cornerRadius!=null && cornerRadius.length==4){
|
||||
for(int corner:cornerRadius){
|
||||
if(corner>0){
|
||||
transitionCornerRadius=cornerRadius;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void animateIn(Rect rect, int[] cornerRadius){
|
||||
int[] loc={0, 0};
|
||||
getLocationOnScreen(loc);
|
||||
@@ -204,6 +235,7 @@ public class ZoomPanView extends FrameLayout implements ScaleGestureDetector.OnS
|
||||
animatingTransition=true;
|
||||
|
||||
matrix.getValues(matrixValues);
|
||||
validateAndSetCornerRadius(cornerRadius);
|
||||
|
||||
child.setAlpha(0f);
|
||||
setupAndStartTransitionAnim(new SpringAnimation(this, CROP_AND_FADE, 1f).setMinimumVisibleChange(DynamicAnimation.MIN_VISIBLE_CHANGE_SCALE));
|
||||
@@ -233,6 +265,7 @@ public class ZoomPanView extends FrameLayout implements ScaleGestureDetector.OnS
|
||||
animatingTransition=true;
|
||||
dismissAfterTransition=true;
|
||||
rawCropAndFadeValue=1f;
|
||||
validateAndSetCornerRadius(cornerRadius);
|
||||
|
||||
setupAndStartTransitionAnim(new SpringAnimation(this, CROP_AND_FADE, 0f).setMinimumVisibleChange(DynamicAnimation.MIN_VISIBLE_CHANGE_SCALE));
|
||||
setupAndStartTransitionAnim(new SpringAnimation(child, DynamicAnimation.SCALE_X, initialScale));
|
||||
|
||||
Reference in New Issue
Block a user