From 8bce03fad3d5bcc29ec8e3a19ce99789e71de9e5 Mon Sep 17 00:00:00 2001 From: FineFindus <63370021+FineFindus@users.noreply.github.com> Date: Tue, 17 Jan 2023 22:05:39 +0100 Subject: [PATCH 1/6] feat(composeButton): hide fab on scroll --- .../fragments/BaseStatusListFragment.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/BaseStatusListFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/BaseStatusListFragment.java index 00e577c4c..9ebc561bd 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/BaseStatusListFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/BaseStatusListFragment.java @@ -13,9 +13,12 @@ import android.text.Layout; import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; +import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.WindowInsets; +import android.view.animation.TranslateAnimation; +import android.widget.ImageButton; import android.widget.Toolbar; import org.joinmastodon.android.E; @@ -71,6 +74,8 @@ public abstract class BaseStatusListFragment exten protected DisplayItemsAdapter adapter; protected String accountID; protected PhotoViewer currentPhotoViewer; + protected ImageButton fab; + protected boolean isScrollingUp = false; protected HashMap knownAccounts=new HashMap<>(); protected HashMap relationships=new HashMap<>(); protected Rect tmpRect=new Rect(); @@ -273,11 +278,42 @@ public abstract class BaseStatusListFragment exten @Override public void onViewCreated(View view, Bundle savedInstanceState){ super.onViewCreated(view, savedInstanceState); + fab=view.findViewById(R.id.fab); list.addOnScrollListener(new RecyclerView.OnScrollListener(){ @Override public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy){ if(currentPhotoViewer!=null) currentPhotoViewer.offsetView(-dx, -dy); + + if (fab!=null) { + if (dy > 0 ) { + if (isScrollingUp) { + fab.setVisibility(View.INVISIBLE); + TranslateAnimation animate = new TranslateAnimation( + 0, + 0, + 0, + fab.getHeight() * 2); + animate.setDuration(300); + animate.setFillAfter(true); + fab.startAnimation(animate); + isScrollingUp = false; + } + } else { + if (!isScrollingUp) { + fab.setVisibility(View.VISIBLE); + TranslateAnimation animate = new TranslateAnimation( + 0, + 0, + fab.getHeight() * 2, + 0); + animate.setDuration(300); + animate.setFillAfter(true); + fab.startAnimation(animate); + isScrollingUp = true; + } + } + } } }); list.addItemDecoration(new StatusListItemDecoration()); From cc4483dea1ddf43ccd9bc1cf503a99445ed8f9a1 Mon Sep 17 00:00:00 2001 From: FineFindus <63370021+FineFindus@users.noreply.github.com> Date: Thu, 19 Jan 2023 19:31:52 +0100 Subject: [PATCH 2/6] feat(composeButton): hide when scrolling in profile fragment --- .../android/fragments/AccountTimelineFragment.java | 5 +++++ .../android/fragments/ProfileFragment.java | 11 ++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/AccountTimelineFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/AccountTimelineFragment.java index 2415649e4..786bf6ca4 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/AccountTimelineFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/AccountTimelineFragment.java @@ -3,6 +3,10 @@ package org.joinmastodon.android.fragments; import android.app.Activity; import android.os.Bundle; import android.view.View; +import android.view.animation.TranslateAnimation; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; import org.joinmastodon.android.R; import org.joinmastodon.android.api.requests.accounts.GetAccountStatuses; @@ -67,6 +71,7 @@ public class AccountTimelineFragment extends StatusListFragment{ @Override public void onViewCreated(View view, Bundle savedInstanceState){ super.onViewCreated(view, savedInstanceState); + fab = ((ProfileFragment) getParentFragment()).getFab(); } @Override diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java index 6386a9e3b..a1f36ac80 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java @@ -24,19 +24,23 @@ import android.os.Vibrator; import android.text.SpannableStringBuilder; import android.text.TextUtils; import android.text.style.ImageSpan; +import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.ViewOutlineProvider; import android.view.ViewTreeObserver; import android.view.WindowInsets; +import android.view.animation.TranslateAnimation; import android.widget.Button; import android.widget.EditText; import android.widget.FrameLayout; +import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ProgressBar; @@ -134,10 +138,11 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList private Uri editNewAvatar, editNewCover; private String profileAccountID; private boolean refreshing; - private View fab; + private ImageButton fab; private WindowInsets childInsets; private PhotoViewer currentPhotoViewer; private boolean editModeLoading; + private boolean isScrollingUp = false; public ProfileFragment(){ super(R.layout.loader_fragment_overlay_toolbar); @@ -691,6 +696,10 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList if (getActivity() != null) notifyButton.setContentDescription(getString(relationship.notifying ? R.string.sk_user_post_notifications_on : R.string.sk_user_post_notifications_off, '@'+account.username)); } + public ImageButton getFab() { + return fab; + } + private void onScrollChanged(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY){ int topBarsH=getToolbar().getHeight()+statusBarHeight; if(scrollY>avatarBorder.getTop()-topBarsH){ From 327426e443df2886f7b0a2570c2bcc4dce56e9aa Mon Sep 17 00:00:00 2001 From: FineFindus <63370021+FineFindus@users.noreply.github.com> Date: Wed, 25 Jan 2023 22:09:10 +0100 Subject: [PATCH 3/6] refactor(compose-fab): show fab after small scroll distance --- .../fragments/AccountTimelineFragment.java | 2 +- .../fragments/BaseStatusListFragment.java | 34 +++++++++---------- .../android/fragments/ProfileFragment.java | 23 +++++++++++++ .../ui/views/NestedRecyclerScrollView.java | 17 ++++++++++ 4 files changed, 58 insertions(+), 18 deletions(-) diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/AccountTimelineFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/AccountTimelineFragment.java index 786bf6ca4..b330ff4cc 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/AccountTimelineFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/AccountTimelineFragment.java @@ -71,7 +71,7 @@ public class AccountTimelineFragment extends StatusListFragment{ @Override public void onViewCreated(View view, Bundle savedInstanceState){ super.onViewCreated(view, savedInstanceState); - fab = ((ProfileFragment) getParentFragment()).getFab(); +// fab = ((ProfileFragment) getParentFragment()).getFab(); } @Override diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/BaseStatusListFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/BaseStatusListFragment.java index 9ebc561bd..e60b163f3 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/BaseStatusListFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/BaseStatusListFragment.java @@ -75,7 +75,7 @@ public abstract class BaseStatusListFragment exten protected String accountID; protected PhotoViewer currentPhotoViewer; protected ImageButton fab; - protected boolean isScrollingUp = false; + protected int scrollDiff = 0; protected HashMap knownAccounts=new HashMap<>(); protected HashMap relationships=new HashMap<>(); protected Rect tmpRect=new Rect(); @@ -286,21 +286,19 @@ public abstract class BaseStatusListFragment exten currentPhotoViewer.offsetView(-dx, -dy); if (fab!=null) { - if (dy > 0 ) { - if (isScrollingUp) { - fab.setVisibility(View.INVISIBLE); - TranslateAnimation animate = new TranslateAnimation( - 0, - 0, - 0, - fab.getHeight() * 2); - animate.setDuration(300); - animate.setFillAfter(true); - fab.startAnimation(animate); - isScrollingUp = false; - } - } else { - if (!isScrollingUp) { + if (dy > 0 && fab.getVisibility() == View.VISIBLE) { + TranslateAnimation animate = new TranslateAnimation( + 0, + 0, + 0, + fab.getHeight() * 2); + animate.setDuration(300); + animate.setFillAfter(true); + fab.startAnimation(animate); + fab.setVisibility(View.INVISIBLE); + scrollDiff = 0; + } else if (dy < 0 && fab.getVisibility() != View.VISIBLE) { + if (scrollDiff > 400) { fab.setVisibility(View.VISIBLE); TranslateAnimation animate = new TranslateAnimation( 0, @@ -310,7 +308,9 @@ public abstract class BaseStatusListFragment exten animate.setDuration(300); animate.setFillAfter(true); fab.startAnimation(animate); - isScrollingUp = true; + scrollDiff = 0; + } else { + scrollDiff += Math.abs(dy); } } } diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java index a1f36ac80..9da50f492 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java @@ -400,6 +400,29 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList }); scrollView.setOnScrollChangeListener(this::onScrollChanged); + scrollView.setNestedScrollListener((target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed) -> { + if (dyConsumed > 0) { + fab.setVisibility(View.INVISIBLE); + TranslateAnimation animate = new TranslateAnimation( + 0, + 0, + 0, + fab.getHeight() * 2); + animate.setDuration(300); + animate.setFillAfter(true); + fab.startAnimation(animate); + } else { + fab.setVisibility(View.VISIBLE); + TranslateAnimation animate = new TranslateAnimation( + 0, + 0, + fab.getHeight() * 2, + 0); + animate.setDuration(300); + animate.setFillAfter(true); + fab.startAnimation(animate); + } + }); titleTransY=getToolbar().getLayoutParams().height; if(toolbarTitleView!=null){ toolbarTitleView.setTranslationY(titleTransY); diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/views/NestedRecyclerScrollView.java b/mastodon/src/main/java/org/joinmastodon/android/ui/views/NestedRecyclerScrollView.java index 8bad60d6e..9f7259539 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/views/NestedRecyclerScrollView.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/views/NestedRecyclerScrollView.java @@ -10,7 +10,12 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; public class NestedRecyclerScrollView extends CustomScrollView{ + + public interface NestedScrollListener{ + public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed); + } private Supplier scrollableChildSupplier; + private NestedScrollListener nestedScrollListener; public NestedRecyclerScrollView(Context context){ super(context); @@ -24,6 +29,18 @@ public class NestedRecyclerScrollView extends CustomScrollView{ super(context, attrs, defStyleAttr); } + @Override + public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) { + super.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed); + if (nestedScrollListener != null) { + nestedScrollListener.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed); + } + } + + public void setNestedScrollListener(NestedScrollListener listener) { + this.nestedScrollListener = listener; + } + @Override public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) { final RecyclerView rv = (RecyclerView) target; From e9cd29c59e089f63146be56f35949849c3d0160c Mon Sep 17 00:00:00 2001 From: FineFindus <63370021+FineFindus@users.noreply.github.com> Date: Thu, 26 Jan 2023 16:12:54 +0100 Subject: [PATCH 4/6] refactor(compose-fab): code cleanup --- .../fragments/AccountTimelineFragment.java | 2 +- .../android/fragments/ProfileFragment.java | 23 ------------------- .../ui/views/NestedRecyclerScrollView.java | 17 -------------- 3 files changed, 1 insertion(+), 41 deletions(-) diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/AccountTimelineFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/AccountTimelineFragment.java index b330ff4cc..786bf6ca4 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/AccountTimelineFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/AccountTimelineFragment.java @@ -71,7 +71,7 @@ public class AccountTimelineFragment extends StatusListFragment{ @Override public void onViewCreated(View view, Bundle savedInstanceState){ super.onViewCreated(view, savedInstanceState); -// fab = ((ProfileFragment) getParentFragment()).getFab(); + fab = ((ProfileFragment) getParentFragment()).getFab(); } @Override diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java index 9da50f492..a1f36ac80 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java @@ -400,29 +400,6 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList }); scrollView.setOnScrollChangeListener(this::onScrollChanged); - scrollView.setNestedScrollListener((target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed) -> { - if (dyConsumed > 0) { - fab.setVisibility(View.INVISIBLE); - TranslateAnimation animate = new TranslateAnimation( - 0, - 0, - 0, - fab.getHeight() * 2); - animate.setDuration(300); - animate.setFillAfter(true); - fab.startAnimation(animate); - } else { - fab.setVisibility(View.VISIBLE); - TranslateAnimation animate = new TranslateAnimation( - 0, - 0, - fab.getHeight() * 2, - 0); - animate.setDuration(300); - animate.setFillAfter(true); - fab.startAnimation(animate); - } - }); titleTransY=getToolbar().getLayoutParams().height; if(toolbarTitleView!=null){ toolbarTitleView.setTranslationY(titleTransY); diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/views/NestedRecyclerScrollView.java b/mastodon/src/main/java/org/joinmastodon/android/ui/views/NestedRecyclerScrollView.java index 9f7259539..8bad60d6e 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/views/NestedRecyclerScrollView.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/views/NestedRecyclerScrollView.java @@ -10,12 +10,7 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; public class NestedRecyclerScrollView extends CustomScrollView{ - - public interface NestedScrollListener{ - public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed); - } private Supplier scrollableChildSupplier; - private NestedScrollListener nestedScrollListener; public NestedRecyclerScrollView(Context context){ super(context); @@ -29,18 +24,6 @@ public class NestedRecyclerScrollView extends CustomScrollView{ super(context, attrs, defStyleAttr); } - @Override - public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) { - super.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed); - if (nestedScrollListener != null) { - nestedScrollListener.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed); - } - } - - public void setNestedScrollListener(NestedScrollListener listener) { - this.nestedScrollListener = listener; - } - @Override public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) { final RecyclerView rv = (RecyclerView) target; From e7e3d94add2e30a3e2fa5e51c2a782c87c9f6497 Mon Sep 17 00:00:00 2001 From: FineFindus <63370021+FineFindus@users.noreply.github.com> Date: Sun, 29 Jan 2023 21:31:15 +0100 Subject: [PATCH 5/6] feat(composeButton): hide when scrolling in profile --- .../android/fragments/ProfileFragment.java | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java index a1f36ac80..a76d0a4da 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/ProfileFragment.java @@ -142,7 +142,7 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList private WindowInsets childInsets; private PhotoViewer currentPhotoViewer; private boolean editModeLoading; - private boolean isScrollingUp = false; + protected int scrollDiff = 0; public ProfileFragment(){ super(R.layout.loader_fragment_overlay_toolbar); @@ -730,6 +730,36 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList if(currentPhotoViewer!=null){ currentPhotoViewer.offsetView(0, oldScrollY-scrollY); } + + int dy = scrollY - oldScrollY; + + if (dy > 0 && fab.getVisibility() == View.VISIBLE) { + TranslateAnimation animate = new TranslateAnimation( + 0, + 0, + 0, + fab.getHeight() * 2); + animate.setDuration(300); + animate.setFillAfter(true); + fab.startAnimation(animate); + fab.setVisibility(View.INVISIBLE); + scrollDiff = 0; + } else if (dy < 0 && fab.getVisibility() != View.VISIBLE) { + if (scrollDiff > 400) { + fab.setVisibility(View.VISIBLE); + TranslateAnimation animate = new TranslateAnimation( + 0, + 0, + fab.getHeight() * 2, + 0); + animate.setDuration(300); + animate.setFillAfter(true); + fab.startAnimation(animate); + scrollDiff = 0; + } else { + scrollDiff += Math.abs(dy); + } + } } private Fragment getFragmentForPage(int page){ From 363ceed2adea812a76d73bb4feef7687ca726cfe Mon Sep 17 00:00:00 2001 From: FineFindus <63370021+FineFindus@users.noreply.github.com> Date: Wed, 8 Feb 2023 20:52:20 +0100 Subject: [PATCH 6/6] fix: duplicate fab var --- .../joinmastodon/android/fragments/BaseStatusListFragment.java | 1 - 1 file changed, 1 deletion(-) diff --git a/mastodon/src/main/java/org/joinmastodon/android/fragments/BaseStatusListFragment.java b/mastodon/src/main/java/org/joinmastodon/android/fragments/BaseStatusListFragment.java index 1b879b2a5..374f4b0b8 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/fragments/BaseStatusListFragment.java +++ b/mastodon/src/main/java/org/joinmastodon/android/fragments/BaseStatusListFragment.java @@ -83,7 +83,6 @@ public abstract class BaseStatusListFragment exten protected HashMap knownAccounts=new HashMap<>(); protected HashMap relationships=new HashMap<>(); protected Rect tmpRect=new Rect(); - protected ImageButton fab; public BaseStatusListFragment(){ super(20);