New sensitive media design

This commit is contained in:
Grishka
2023-03-24 00:33:02 +03:00
parent 4492e940e5
commit e873dd7d0a
14 changed files with 180 additions and 137 deletions

View File

@@ -5,8 +5,11 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
@@ -19,9 +22,11 @@ import org.joinmastodon.android.fragments.BaseStatusListFragment;
import org.joinmastodon.android.model.Attachment;
import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.ui.PhotoLayoutHelper;
import org.joinmastodon.android.ui.drawables.SpoilerStripesDrawable;
import org.joinmastodon.android.ui.photoviewer.PhotoViewerHost;
import org.joinmastodon.android.ui.utils.MediaAttachmentViewController;
import org.joinmastodon.android.ui.views.FrameLayoutThatOnlyMeasuresFirstChild;
import org.joinmastodon.android.ui.views.MaxWidthFrameLayout;
import org.joinmastodon.android.ui.views.MediaGridLayout;
import org.joinmastodon.android.utils.TypedObjectPool;
@@ -42,6 +47,7 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
private final List<Attachment> attachments;
private final ArrayList<ImageLoaderRequest> requests=new ArrayList<>();
public final Status status;
public boolean sensitiveRevealed;
public MediaGridStatusDisplayItem(String parentID, BaseStatusListFragment<?> parentFragment, PhotoLayoutHelper.TiledLayoutResult tiledLayout, List<Attachment> attachments, Status status){
super(parentID, parentFragment);
@@ -49,6 +55,7 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
this.viewPool=parentFragment.getAttachmentViewsPool();
this.attachments=attachments;
this.status=status;
sensitiveRevealed=!status.sensitive;
for(Attachment att:attachments){
requests.add(new UrlImageLoaderRequest(switch(att.type){
case IMAGE -> att.url;
@@ -85,12 +92,18 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
private final View.OnClickListener clickListener=this::onViewClick, altTextClickListener=this::onAltTextClick;
private final ArrayList<MediaAttachmentViewController> controllers=new ArrayList<>();
private final MaxWidthFrameLayout overlays;
private final FrameLayout altTextWrapper;
private final TextView altTextButton;
private final View altTextScroller;
private final ImageButton altTextClose;
private final TextView altText;
private final View sensitiveOverlay;
private final LayerDrawable sensitiveOverlayBG;
private static final ColorDrawable drawableForWhenThereIsNoBlurhash=new ColorDrawable(0xffffffff);
private final TextView hideSensitiveButton;
private int altTextIndex=-1;
private Animator altTextAnimator;
@@ -100,15 +113,34 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
layout=new MediaGridLayout(activity);
wrapper.addView(layout);
wrapper.setPadding(0, 0, 0, V.dp(8));
wrapper.setClipToPadding(false);
activity.getLayoutInflater().inflate(R.layout.overlay_image_alt_text, wrapper);
overlays=new MaxWidthFrameLayout(activity);
overlays.setMaxWidth(V.dp(MediaGridLayout.MAX_WIDTH));
wrapper.addView(overlays, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, Gravity.CENTER_HORIZONTAL));
activity.getLayoutInflater().inflate(R.layout.overlay_image_alt_text, overlays);
altTextWrapper=findViewById(R.id.alt_text_wrapper);
altTextButton=findViewById(R.id.alt_button);
altTextScroller=findViewById(R.id.alt_text_scroller);
altTextClose=findViewById(R.id.alt_text_close);
altText=findViewById(R.id.alt_text);
altTextClose.setOnClickListener(this::onAltTextCloseClick);
wrapper.setClipToPadding(false);
hideSensitiveButton=(TextView) activity.getLayoutInflater().inflate(R.layout.alt_text_badge, overlays, false);
hideSensitiveButton.setText(R.string.hide);
FrameLayout.LayoutParams lp;
overlays.addView(hideSensitiveButton, lp=new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, V.dp(24), Gravity.END | Gravity.BOTTOM));
int margin=V.dp(8);
lp.setMargins(margin, margin, margin, margin);
activity.getLayoutInflater().inflate(R.layout.overlay_image_sensitive, overlays);
sensitiveOverlay=findViewById(R.id.sensitive_overlay);
sensitiveOverlayBG=(LayerDrawable) sensitiveOverlay.getBackground();
sensitiveOverlayBG.setDrawableByLayerId(R.id.left_drawable, new SpoilerStripesDrawable(false));
sensitiveOverlayBG.setDrawableByLayerId(R.id.right_drawable, new SpoilerStripesDrawable(true));
sensitiveOverlay.setOnClickListener(v->revealSensitive());
hideSensitiveButton.setOnClickListener(v->hideSensitive());
}
@Override
@@ -148,6 +180,16 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
}
altTextWrapper.setVisibility(View.GONE);
altTextIndex=-1;
if(!item.sensitiveRevealed){
sensitiveOverlay.setVisibility(View.VISIBLE);
layout.setVisibility(View.INVISIBLE);
updateBlurhashInSensitiveOverlay();
}else{
sensitiveOverlay.setVisibility(View.GONE);
layout.setVisibility(View.VISIBLE);
}
hideSensitiveButton.setVisibility(item.status.sensitive ? View.VISIBLE : View.GONE);
}
@Override
@@ -182,7 +224,7 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
int[] loc={0, 0};
v.getLocationInWindow(loc);
int btnL=loc[0], btnT=loc[1];
wrapper.getLocationInWindow(loc);
overlays.getLocationInWindow(loc);
btnL-=loc[0];
btnT-=loc[1];
@@ -240,7 +282,7 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
int[] loc={0, 0};
btn.getLocationInWindow(loc);
int btnL=loc[0], btnT=loc[1];
wrapper.getLocationInWindow(loc);
overlays.getLocationInWindow(loc);
btnL-=loc[0];
btnT-=loc[1];
@@ -276,12 +318,6 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
set.start();
}
public void setRevealed(boolean revealed){
for(MediaAttachmentViewController c:controllers){
c.setRevealed(revealed);
}
}
public MediaAttachmentViewController getViewController(int index){
return controllers.get(index);
}
@@ -290,5 +326,25 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
layout.setClipChildren(clip);
wrapper.setClipChildren(clip);
}
private void updateBlurhashInSensitiveOverlay(){
Drawable d=item.attachments.get(0).blurhashPlaceholder;
sensitiveOverlayBG.setDrawableByLayerId(R.id.blurhash, d==null ? drawableForWhenThereIsNoBlurhash : d.mutate());
}
private void revealSensitive(){
if(item.sensitiveRevealed)
return;
item.sensitiveRevealed=true;
V.setVisibilityAnimated(sensitiveOverlay, View.GONE);
layout.setVisibility(View.VISIBLE);
}
private void hideSensitive(){
if(!item.sensitiveRevealed)
return;
item.sensitiveRevealed=false;
V.setVisibilityAnimated(sensitiveOverlay, View.VISIBLE, ()->layout.setVisibility(View.INVISIBLE));
}
}
}

View File

@@ -11,6 +11,7 @@ import org.joinmastodon.android.MastodonApp;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import me.grishka.appkit.utils.V;
public class SpoilerStripesDrawable extends Drawable{
private Paint paint=new Paint(Paint.ANTI_ALIAS_FLAG);
@@ -33,6 +34,8 @@ public class SpoilerStripesDrawable extends Drawable{
canvas.translate(bounds.left, bounds.top);
canvas.clipRect(0, 0, bounds.width(), bounds.height());
float scale=MastodonApp.context.getResources().getDisplayMetrics().density;
if(bounds.width()>V.dp(10))
scale*=2;
canvas.scale(scale, scale, 0, 0);
float height=bounds.height()/scale;

View File

@@ -50,4 +50,10 @@ public class BlurHashDrawable extends Drawable{
public int getIntrinsicHeight(){
return height;
}
@NonNull
@Override
public Drawable mutate(){
return new BlurHashDrawable(bitmap, width, height);
}
}

View File

@@ -52,7 +52,7 @@ public class MediaAttachmentViewController{
this.status=status;
crossfadeDrawable.setSize(attachment.getWidth(), attachment.getHeight());
crossfadeDrawable.setBlurhashDrawable(attachment.blurhashPlaceholder);
crossfadeDrawable.setCrossfadeAlpha(status.spoilerRevealed ? 0f : 1f);
crossfadeDrawable.setCrossfadeAlpha(0f);
photo.setImageDrawable(null);
photo.setImageDrawable(crossfadeDrawable);
photo.setContentDescription(TextUtils.isEmpty(attachment.description) ? context.getString(R.string.media_no_description) : attachment.description);
@@ -67,7 +67,7 @@ public class MediaAttachmentViewController{
public void setImage(Drawable drawable){
crossfadeDrawable.setImageDrawable(drawable);
if(didClear && status.spoilerRevealed)
if(didClear)
crossfadeDrawable.animateAlpha(0f);
}
@@ -76,8 +76,4 @@ public class MediaAttachmentViewController{
crossfadeDrawable.setImageDrawable(null);
didClear=true;
}
public void setRevealed(boolean revealed){
crossfadeDrawable.animateAlpha(revealed ? 0f : 1f);
}
}