parent
c618feabe9
commit
8e60d107fe
|
@ -1,7 +1,18 @@
|
||||||
package org.joinmastodon.android.ui.displayitems;
|
package org.joinmastodon.android.ui.displayitems;
|
||||||
|
|
||||||
|
import android.animation.Animator;
|
||||||
|
import android.animation.AnimatorListenerAdapter;
|
||||||
|
import android.animation.AnimatorSet;
|
||||||
|
import android.animation.ObjectAnimator;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.view.ViewTreeObserver;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
import android.widget.ImageButton;
|
||||||
|
import android.widget.ScrollView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.joinmastodon.android.R;
|
import org.joinmastodon.android.R;
|
||||||
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||||
|
@ -10,6 +21,7 @@ import org.joinmastodon.android.model.Status;
|
||||||
import org.joinmastodon.android.ui.PhotoLayoutHelper;
|
import org.joinmastodon.android.ui.PhotoLayoutHelper;
|
||||||
|
|
||||||
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
|
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
|
||||||
|
import me.grishka.appkit.utils.CubicBezierInterpolator;
|
||||||
|
|
||||||
public class PhotoStatusDisplayItem extends ImageStatusDisplayItem{
|
public class PhotoStatusDisplayItem extends ImageStatusDisplayItem{
|
||||||
public PhotoStatusDisplayItem(String parentID, Status status, Attachment photo, BaseStatusListFragment parentFragment, int index, int totalPhotos, PhotoLayoutHelper.TiledLayoutResult tiledLayout, PhotoLayoutHelper.TiledLayoutResult.Tile thisTile){
|
public PhotoStatusDisplayItem(String parentID, Status status, Attachment photo, BaseStatusListFragment parentFragment, int index, int totalPhotos, PhotoLayoutHelper.TiledLayoutResult tiledLayout, PhotoLayoutHelper.TiledLayoutResult.Tile thisTile){
|
||||||
|
@ -23,9 +35,109 @@ public class PhotoStatusDisplayItem extends ImageStatusDisplayItem{
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Holder extends ImageStatusDisplayItem.Holder<PhotoStatusDisplayItem>{
|
public static class Holder extends ImageStatusDisplayItem.Holder<PhotoStatusDisplayItem>{
|
||||||
|
private final FrameLayout altTextWrapper;
|
||||||
|
private final TextView altTextButton;
|
||||||
|
private final View altTextScroller;
|
||||||
|
private final ImageButton altTextClose;
|
||||||
|
private final TextView altText;
|
||||||
|
|
||||||
|
private boolean altTextShown;
|
||||||
|
private AnimatorSet currentAnim;
|
||||||
|
|
||||||
public Holder(Activity activity, ViewGroup parent){
|
public Holder(Activity activity, ViewGroup parent){
|
||||||
super(activity, R.layout.display_item_photo, parent);
|
super(activity, R.layout.display_item_photo, parent);
|
||||||
|
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);
|
||||||
|
|
||||||
|
altTextButton.setOnClickListener(this::onShowHideClick);
|
||||||
|
altTextClose.setOnClickListener(this::onShowHideClick);
|
||||||
|
// altTextScroller.setNestedScrollingEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBind(ImageStatusDisplayItem item){
|
||||||
|
super.onBind(item);
|
||||||
|
altTextShown=false;
|
||||||
|
if(currentAnim!=null)
|
||||||
|
currentAnim.cancel();
|
||||||
|
altTextScroller.setVisibility(View.GONE);
|
||||||
|
altTextClose.setVisibility(View.GONE);
|
||||||
|
altTextButton.setVisibility(View.VISIBLE);
|
||||||
|
if(TextUtils.isEmpty(item.attachment.description)){
|
||||||
|
altTextWrapper.setVisibility(View.GONE);
|
||||||
|
}else{
|
||||||
|
altTextWrapper.setVisibility(View.VISIBLE);
|
||||||
|
altText.setText(item.attachment.description);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onShowHideClick(View v){
|
||||||
|
boolean show=v.getId()==R.id.alt_button;
|
||||||
|
|
||||||
|
if(altTextShown==show)
|
||||||
|
return;
|
||||||
|
if(currentAnim!=null)
|
||||||
|
currentAnim.cancel();
|
||||||
|
|
||||||
|
altTextShown=show;
|
||||||
|
if(show){
|
||||||
|
altTextScroller.setVisibility(View.VISIBLE);
|
||||||
|
altTextClose.setVisibility(View.VISIBLE);
|
||||||
|
}else{
|
||||||
|
altTextButton.setVisibility(View.VISIBLE);
|
||||||
|
// Hide these views temporarily so FrameLayout measures correctly
|
||||||
|
altTextScroller.setVisibility(View.GONE);
|
||||||
|
altTextClose.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is the current size...
|
||||||
|
int prevLeft=altTextWrapper.getLeft();
|
||||||
|
int prevRight=altTextWrapper.getRight();
|
||||||
|
int prevTop=altTextWrapper.getTop();
|
||||||
|
altTextWrapper.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener(){
|
||||||
|
@Override
|
||||||
|
public boolean onPreDraw(){
|
||||||
|
altTextWrapper.getViewTreeObserver().removeOnPreDrawListener(this);
|
||||||
|
|
||||||
|
// ...and this is after the layout pass, right now the FrameLayout has its final size, but we animate that change
|
||||||
|
if(!show){
|
||||||
|
// Show these views again so they're visible for the duration of the animation.
|
||||||
|
// No one would notice they were missing during measure/layout.
|
||||||
|
altTextScroller.setVisibility(View.VISIBLE);
|
||||||
|
altTextClose.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
AnimatorSet set=new AnimatorSet();
|
||||||
|
set.playTogether(
|
||||||
|
ObjectAnimator.ofInt(altTextWrapper, "left", prevLeft, altTextWrapper.getLeft()),
|
||||||
|
ObjectAnimator.ofInt(altTextWrapper, "right", prevRight, altTextWrapper.getRight()),
|
||||||
|
ObjectAnimator.ofInt(altTextWrapper, "top", prevTop, altTextWrapper.getTop()),
|
||||||
|
ObjectAnimator.ofFloat(altTextButton, View.ALPHA, show ? 1f : 0f, show ? 0f : 1f),
|
||||||
|
ObjectAnimator.ofFloat(altTextScroller, View.ALPHA, show ? 0f : 1f, show ? 1f : 0f),
|
||||||
|
ObjectAnimator.ofFloat(altTextClose, View.ALPHA, show ? 0f : 1f, show ? 1f : 0f)
|
||||||
|
);
|
||||||
|
set.setDuration(300);
|
||||||
|
set.setInterpolator(CubicBezierInterpolator.DEFAULT);
|
||||||
|
set.addListener(new AnimatorListenerAdapter(){
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation){
|
||||||
|
if(show){
|
||||||
|
altTextButton.setVisibility(View.GONE);
|
||||||
|
}else{
|
||||||
|
altTextScroller.setVisibility(View.GONE);
|
||||||
|
altTextClose.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
currentAnim=null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
set.start();
|
||||||
|
currentAnim=set;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
package org.joinmastodon.android.ui.views;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.ViewConfiguration;
|
||||||
|
import android.widget.ScrollView;
|
||||||
|
|
||||||
|
public class NestableScrollView extends ScrollView{
|
||||||
|
private float downY, touchslop;
|
||||||
|
private boolean didDisallow;
|
||||||
|
|
||||||
|
public NestableScrollView(Context context){
|
||||||
|
super(context);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public NestableScrollView(Context context, AttributeSet attrs){
|
||||||
|
super(context, attrs);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public NestableScrollView(Context context, AttributeSet attrs, int defStyleAttr){
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public NestableScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes){
|
||||||
|
super(context, attrs, defStyleAttr, defStyleRes);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init(){
|
||||||
|
touchslop=ViewConfiguration.get(getContext()).getScaledTouchSlop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onTouchEvent(MotionEvent ev){
|
||||||
|
Log.d("111", "onTouchEvent: "+ev);
|
||||||
|
if(ev.getAction()==MotionEvent.ACTION_DOWN){
|
||||||
|
if(canScrollVertically(-1) || canScrollVertically(1)){
|
||||||
|
getParent().requestDisallowInterceptTouchEvent(true);
|
||||||
|
didDisallow=true;
|
||||||
|
}else{
|
||||||
|
didDisallow=false;
|
||||||
|
}
|
||||||
|
downY=ev.getY();
|
||||||
|
}else if(didDisallow && ev.getAction()==MotionEvent.ACTION_MOVE){
|
||||||
|
if(Math.abs(downY-ev.getY())>=touchslop){
|
||||||
|
if(!canScrollVertically((int)(downY-ev.getY()))){
|
||||||
|
didDisallow=false;
|
||||||
|
getParent().requestDisallowInterceptTouchEvent(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.onTouchEvent(ev);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<solid android:color="#D9000000"/>
|
||||||
|
<corners android:radius="4dp"/>
|
||||||
|
</shape>
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector android:height="24dp" android:tint="#000000"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
|
||||||
|
</vector>
|
|
@ -1,5 +1,6 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<org.joinmastodon.android.ui.views.ImageAttachmentFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<org.joinmastodon.android.ui.views.ImageAttachmentFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
@ -10,4 +11,62 @@
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:scaleType="centerCrop"/>
|
android:scaleType="centerCrop"/>
|
||||||
|
|
||||||
|
<!-- This is hidden from screenreaders because that same alt text is set as content description on the ImageView -->
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/alt_text_wrapper"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="start|bottom"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginBottom="8dp"
|
||||||
|
android:importantForAccessibility="noHideDescendants"
|
||||||
|
android:background="@drawable/bg_image_alt_overlay">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/alt_button"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="22dp"
|
||||||
|
android:textAppearance="@style/m3_label_large"
|
||||||
|
android:textColor="#FFF"
|
||||||
|
android:gravity="center"
|
||||||
|
android:includeFontPadding="false"
|
||||||
|
android:text="ALT"/>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/alt_text_close"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_gravity="end|top"
|
||||||
|
android:src="@drawable/ic_baseline_close_24"
|
||||||
|
android:tint="#FFF"
|
||||||
|
android:background="?android:selectableItemBackgroundBorderless"/>
|
||||||
|
|
||||||
|
<org.joinmastodon.android.ui.views.NestableScrollView
|
||||||
|
android:id="@+id/alt_text_scroller"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="40dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/alt_text"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
android:textAppearance="@style/m3_body_medium"
|
||||||
|
android:textColor="#FFF"
|
||||||
|
tools:text="Alt text goes here"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</org.joinmastodon.android.ui.views.NestableScrollView>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
</org.joinmastodon.android.ui.views.ImageAttachmentFrameLayout>
|
</org.joinmastodon.android.ui.views.ImageAttachmentFrameLayout>
|
Loading…
Reference in New Issue