parent
bbedf46b21
commit
9823537474
|
@ -9,6 +9,7 @@ import android.app.Fragment;
|
|||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Outline;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
|
@ -47,9 +48,12 @@ import org.joinmastodon.android.api.session.AccountSessionManager;
|
|||
import org.joinmastodon.android.fragments.report.ReportReasonChoiceFragment;
|
||||
import org.joinmastodon.android.model.Account;
|
||||
import org.joinmastodon.android.model.AccountField;
|
||||
import org.joinmastodon.android.model.Attachment;
|
||||
import org.joinmastodon.android.model.Relationship;
|
||||
import org.joinmastodon.android.ui.SimpleViewHolder;
|
||||
import org.joinmastodon.android.ui.SingleImagePhotoViewerListener;
|
||||
import org.joinmastodon.android.ui.drawables.CoverOverlayGradientDrawable;
|
||||
import org.joinmastodon.android.ui.photoviewer.PhotoViewer;
|
||||
import org.joinmastodon.android.ui.tabs.TabLayout;
|
||||
import org.joinmastodon.android.ui.tabs.TabLayoutMediator;
|
||||
import org.joinmastodon.android.ui.text.CustomEmojiSpan;
|
||||
|
@ -121,6 +125,7 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
|||
private boolean refreshing;
|
||||
private View fab;
|
||||
private WindowInsets childInsets;
|
||||
private PhotoViewer currentPhotoViewer;
|
||||
|
||||
public ProfileFragment(){
|
||||
super(R.layout.loader_fragment_overlay_toolbar);
|
||||
|
@ -595,12 +600,10 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
|||
|
||||
private void onScrollChanged(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY){
|
||||
int topBarsH=getToolbar().getHeight()+statusBarHeight;
|
||||
if(scrollY>avatar.getTop()-topBarsH){
|
||||
float avaAlpha=Math.max(1f-((scrollY-(avatar.getTop()-topBarsH))/(float)V.dp(38)), 0f);
|
||||
avatar.setAlpha(avaAlpha);
|
||||
if(scrollY>avatarBorder.getTop()-topBarsH){
|
||||
float avaAlpha=Math.max(1f-((scrollY-(avatarBorder.getTop()-topBarsH))/(float)V.dp(38)), 0f);
|
||||
avatarBorder.setAlpha(avaAlpha);
|
||||
}else{
|
||||
avatar.setAlpha(1f);
|
||||
avatarBorder.setAlpha(1f);
|
||||
}
|
||||
if(scrollY>cover.getHeight()-topBarsH){
|
||||
|
@ -622,6 +625,9 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
|||
toolbarTitleView.setTranslationY(titleTransY);
|
||||
toolbarSubtitleView.setTranslationY(titleTransY);
|
||||
}
|
||||
if(currentPhotoViewer!=null){
|
||||
currentPhotoViewer.offsetView(0, oldScrollY-scrollY);
|
||||
}
|
||||
}
|
||||
|
||||
private Fragment getFragmentForPage(int page){
|
||||
|
@ -804,15 +810,38 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
|||
return false;
|
||||
}
|
||||
|
||||
private List<Attachment> createFakeAttachments(String url, Drawable drawable){
|
||||
Attachment att=new Attachment();
|
||||
att.type=Attachment.Type.IMAGE;
|
||||
att.url=url;
|
||||
att.meta=new Attachment.Metadata();
|
||||
att.meta.width=drawable.getIntrinsicWidth();
|
||||
att.meta.height=drawable.getIntrinsicHeight();
|
||||
return Collections.singletonList(att);
|
||||
}
|
||||
|
||||
private void onAvatarClick(View v){
|
||||
if(isInEditMode){
|
||||
startImagePicker(AVATAR_RESULT);
|
||||
}else{
|
||||
Drawable ava=avatar.getDrawable();
|
||||
if(ava==null)
|
||||
return;
|
||||
int radius=V.dp(25);
|
||||
currentPhotoViewer=new PhotoViewer(getActivity(), createFakeAttachments(account.avatar, ava), 0,
|
||||
new SingleImagePhotoViewerListener(avatar, avatarBorder, new int[]{radius, radius, radius, radius}, this, ()->currentPhotoViewer=null, ()->ava, null, null));
|
||||
}
|
||||
}
|
||||
|
||||
private void onCoverClick(View v){
|
||||
if(isInEditMode){
|
||||
startImagePicker(COVER_RESULT);
|
||||
}else{
|
||||
Drawable drawable=cover.getDrawable();
|
||||
if(drawable==null || drawable instanceof ColorDrawable)
|
||||
return;
|
||||
currentPhotoViewer=new PhotoViewer(getActivity(), createFakeAttachments(account.header, drawable), 0,
|
||||
new SingleImagePhotoViewerListener(cover, cover, null, this, ()->currentPhotoViewer=null, ()->drawable, ()->avatarBorder.setTranslationZ(2), ()->avatarBorder.setTranslationZ(0)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
tools:visibility="visible"
|
||||
android:text="@string/follows_you"/>
|
||||
|
||||
<View
|
||||
<FrameLayout
|
||||
android:id="@+id/avatar_border"
|
||||
android:layout_width="102dp"
|
||||
android:layout_height="102dp"
|
||||
|
@ -60,19 +60,19 @@
|
|||
android:layout_alignParentStart="true"
|
||||
android:layout_marginTop="-40dp"
|
||||
android:layout_marginStart="14dp"
|
||||
android:background="@drawable/profile_ava_bg"/>
|
||||
android:outlineProvider="@null"
|
||||
android:background="@drawable/profile_ava_bg">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/avatar"
|
||||
android:layout_width="98dp"
|
||||
android:layout_height="98dp"
|
||||
android:layout_below="@id/cover"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="-38dp"
|
||||
android:scaleType="centerCrop"
|
||||
android:contentDescription="@string/profile_picture"
|
||||
tools:src="#0f0" />
|
||||
<ImageView
|
||||
android:id="@+id/avatar"
|
||||
android:layout_width="98dp"
|
||||
android:layout_height="98dp"
|
||||
android:layout_gravity="center"
|
||||
android:scaleType="centerCrop"
|
||||
android:contentDescription="@string/profile_picture"
|
||||
tools:src="#0f0" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/profile_counters"
|
||||
|
@ -196,10 +196,10 @@
|
|||
android:id="@+id/name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/avatar"
|
||||
android:layout_below="@id/avatar_border"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_toStartOf="@id/profile_action_btn_wrap"
|
||||
android:textAppearance="@style/m3_headline_small"
|
||||
android:textAlignment="viewStart"
|
||||
|
@ -232,10 +232,10 @@
|
|||
android:id="@+id/name_edit"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/avatar"
|
||||
android:layout_below="@id/avatar_border"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_toStartOf="@id/profile_action_btn_wrap"
|
||||
android:textAppearance="@style/m3_body_large"
|
||||
android:textSize="16sp"
|
||||
|
|
Loading…
Reference in New Issue