From beb97270a0c2f513e2d3b7822bd6f125386787ff Mon Sep 17 00:00:00 2001 From: tarsin Date: Sat, 5 Nov 2022 12:47:49 +0800 Subject: [PATCH] Initial support for predictive back gesture https://developer.android.com/guide/navigation/predictive-back-gesture --- app/src/main/AndroidManifest.xml | 1 + .../com/hippo/ehviewer/ui/SettingsActivity.kt | 2 +- .../ehviewer/ui/scene/GalleryListScene.java | 17 +++++ .../java/com/hippo/scene/SceneFragment.java | 1 + .../java/com/hippo/scene/StageActivity.java | 65 ++++++++++++++----- .../main/java/com/hippo/widget/FabLayout.java | 2 + 6 files changed, 72 insertions(+), 16 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 1d90bcafe..caa7e8839 100755 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -37,6 +37,7 @@ android:allowBackup="true" android:appCategory="image" android:dataExtractionRules="@xml/data_extraction_rules" + android:enableOnBackInvokedCallback="true" android:fullBackupContent="@xml/backup_scheme" android:hasFragileUserData="true" android:icon="@mipmap/ic_launcher" diff --git a/app/src/main/java/com/hippo/ehviewer/ui/SettingsActivity.kt b/app/src/main/java/com/hippo/ehviewer/ui/SettingsActivity.kt index 963d6d79a..9ecf40430 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/SettingsActivity.kt +++ b/app/src/main/java/com/hippo/ehviewer/ui/SettingsActivity.kt @@ -57,7 +57,7 @@ class SettingsActivity : EhActivity() { override fun onOptionsItemSelected(item: MenuItem): Boolean { if (item.itemId == android.R.id.home) { - onBackPressed() + onBackPressedDispatcher.onBackPressed() return true } return super.onOptionsItemSelected(item) diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java index 29ebe0534..172971ae1 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java @@ -91,6 +91,7 @@ import com.hippo.ehviewer.widget.SearchBar; import com.hippo.ehviewer.widget.SearchLayout; import com.hippo.scene.Announcer; import com.hippo.scene.SceneFragment; +import com.hippo.scene.StageActivity; import com.hippo.util.ExceptionUtils; import com.hippo.view.BringOutTransition; import com.hippo.view.ViewTransition; @@ -778,6 +779,21 @@ public final class GalleryListScene extends BaseScene return view; } + public boolean isBackpressCanPreviewLauncherStatus() { + if (null != mFabLayout && mFabLayout.isExpanded()) { + return false; + } + switch (mState) { + case STATE_NORMAL: + return getStackIndex() == 0; + case STATE_SIMPLE_SEARCH: + case STATE_SEARCH: + case STATE_SEARCH_SHOW_LIST: + return false; + } + return false; + } + @Override public void onBackPressed() { if (null != mFabLayout && mFabLayout.isExpanded()) { @@ -1184,6 +1200,7 @@ public final class GalleryListScene extends BaseScene break; } } + ((StageActivity)requireActivity()).updateBackPressCallBackStatus(); } @Override diff --git a/app/src/main/java/com/hippo/scene/SceneFragment.java b/app/src/main/java/com/hippo/scene/SceneFragment.java index fc4414bdc..ccf5e8da8 100644 --- a/app/src/main/java/com/hippo/scene/SceneFragment.java +++ b/app/src/main/java/com/hippo/scene/SceneFragment.java @@ -61,6 +61,7 @@ public class SceneFragment extends Fragment { FragmentActivity activity = getActivity(); if (activity instanceof StageActivity) { ((StageActivity) activity).startScene(announcer, horizontal); + ((StageActivity) activity).updateBackPressCallBackStatus(); } } diff --git a/app/src/main/java/com/hippo/scene/StageActivity.java b/app/src/main/java/com/hippo/scene/StageActivity.java index c2c7813e2..f26c7f1f7 100644 --- a/app/src/main/java/com/hippo/scene/StageActivity.java +++ b/app/src/main/java/com/hippo/scene/StageActivity.java @@ -23,6 +23,7 @@ import android.os.Bundle; import android.util.Log; import android.view.View; +import androidx.activity.OnBackPressedCallback; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; @@ -31,6 +32,7 @@ import androidx.fragment.app.FragmentTransaction; import com.hippo.ehviewer.R; import com.hippo.ehviewer.ui.EhActivity; +import com.hippo.ehviewer.ui.scene.GalleryListScene; import com.hippo.yorozuya.AssertUtils; import com.hippo.yorozuya.IntIdGenerator; @@ -58,6 +60,8 @@ public abstract class StageActivity extends EhActivity { private final SceneViewComparator mSceneViewComparator = new SceneViewComparator(); private int mStageId = IntIdGenerator.INVALID_ID; + private OnBackPressedCallback callback; + public static void registerLaunchMode(Class clazz, @SceneFragment.LaunchMode int launchMode) { if (launchMode != SceneFragment.LAUNCH_MODE_STANDARD && launchMode != SceneFragment.LAUNCH_MODE_SINGLE_TOP && @@ -140,6 +144,8 @@ public abstract class StageActivity extends EhActivity { protected final void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); + callback = new BackPressCallBack(false); + getOnBackPressedDispatcher().addCallback(callback); if (savedInstanceState != null) { mStageId = savedInstanceState.getInt(KEY_STAGE_ID, IntIdGenerator.INVALID_ID); ArrayList list = savedInstanceState.getStringArrayList(KEY_SCENE_TAG_LIST); @@ -247,6 +253,7 @@ public abstract class StageActivity extends EhActivity { public void startScene(Announcer announcer) { startScene(announcer, false); + updateBackPressCallBackStatus(); } public void startScene(Announcer announcer, boolean horizontal) { @@ -461,6 +468,7 @@ public abstract class StageActivity extends EhActivity { // TODO Call onNewArguments when view created ? scene.onNewArguments(args); } + updateBackPressCallBackStatus(); } int getSceneIndex(SceneFragment scene) { @@ -477,6 +485,7 @@ public abstract class StageActivity extends EhActivity { public void finishScene(SceneFragment scene) { finishScene(scene.getTag()); + updateBackPressCallBackStatus(); } private void finishScene(String tag) { @@ -558,25 +567,51 @@ public abstract class StageActivity extends EhActivity { } else { fragmentManager.beginTransaction().detach(fragment).attach(fragment).commitAllowingStateLoss(); } + updateBackPressCallBackStatus(); } - @Override - public void onBackPressed() { - int size = mSceneTagList.size(); - String tag = mSceneTagList.get(size - 1); - SceneFragment scene; - Fragment fragment = getSupportFragmentManager().findFragmentByTag(tag); - if (fragment == null) { - Log.e(TAG, "onBackPressed: Can't find scene by tag: " + tag); - return; - } - if (!(fragment instanceof SceneFragment)) { - Log.e(TAG, "onBackPressed: The fragment is not SceneFragment"); - return; + private boolean shouldEnableBackPressCallBack() { + if (mSceneTagList.size() > 1) + return true; + if (mSceneTagList.size() == 0) + return false; + String tag = mSceneTagList.get(0); + GalleryListScene fragment = (GalleryListScene) getSupportFragmentManager().findFragmentByTag(tag); + if (fragment == null) + return false; + return !fragment.isBackpressCanPreviewLauncherStatus(); + } + + public void updateBackPressCallBackStatus() { + var isEnabled = callback.isEnabled(); + var shouldEnable = shouldEnableBackPressCallBack(); + if (isEnabled != shouldEnable) + callback.setEnabled(shouldEnable); + } + + class BackPressCallBack extends OnBackPressedCallback { + public BackPressCallBack(boolean enabled) { + super(enabled); } - scene = (SceneFragment) fragment; - scene.onBackPressed(); + @Override + public void handleOnBackPressed() { + int size = mSceneTagList.size(); + String tag = mSceneTagList.get(size - 1); + SceneFragment scene; + Fragment fragment = getSupportFragmentManager().findFragmentByTag(tag); + if (fragment == null) { + Log.e(TAG, "onBackPressed: Can't find scene by tag: " + tag); + return; + } + if (!(fragment instanceof SceneFragment)) { + Log.e(TAG, "onBackPressed: The fragment is not SceneFragment"); + return; + } + + scene = (SceneFragment) fragment; + scene.onBackPressed(); + } } @Override diff --git a/app/src/main/java/com/hippo/widget/FabLayout.java b/app/src/main/java/com/hippo/widget/FabLayout.java index 35c52173c..0acd34f21 100644 --- a/app/src/main/java/com/hippo/widget/FabLayout.java +++ b/app/src/main/java/com/hippo/widget/FabLayout.java @@ -29,6 +29,7 @@ import androidx.annotation.NonNull; import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.hippo.ehviewer.R; +import com.hippo.scene.StageActivity; import com.hippo.yorozuya.AnimationUtils; import com.hippo.yorozuya.SimpleAnimatorListener; @@ -298,6 +299,7 @@ public class FabLayout extends ViewGroup implements View.OnClickListener { mOnExpandListener.onExpand(expanded); } } + ((StageActivity)getContext()).updateBackPressCallBackStatus(); }