From de767e960f3ef82911291f79642137643d9cbe11 Mon Sep 17 00:00:00 2001 From: JingYeoh Date: Wed, 1 Aug 2018 22:15:51 +0800 Subject: [PATCH] :construction: Add Activity swipe back support. --- .../jkb/fragment/rigger/rigger/IRigger.java | 2 +- .../rigger/rigger/_ActivityRigger.java | 2 +- .../rigger/rigger/_FragmentRigger.java | 2 +- .../jkb/fragment/rigger/rigger/_Rigger.java | 2 +- .../fragment/swiper/SwipeActivityManager.java | 53 ++++++++++ .../swiper/{widget => }/SwipeLayout.java | 58 +++++++++-- .../fragment/swiper/aop/SwipeInjection.java | 98 +++++++++++++++++++ 7 files changed, 203 insertions(+), 14 deletions(-) create mode 100644 rigger/src/main/java/com/jkb/fragment/swiper/SwipeActivityManager.java rename rigger/src/main/java/com/jkb/fragment/swiper/{widget => }/SwipeLayout.java (92%) create mode 100644 rigger/src/main/java/com/jkb/fragment/swiper/aop/SwipeInjection.java diff --git a/rigger/src/main/java/com/jkb/fragment/rigger/rigger/IRigger.java b/rigger/src/main/java/com/jkb/fragment/rigger/rigger/IRigger.java index 9290268..b05f8e3 100644 --- a/rigger/src/main/java/com/jkb/fragment/rigger/rigger/IRigger.java +++ b/rigger/src/main/java/com/jkb/fragment/rigger/rigger/IRigger.java @@ -7,7 +7,7 @@ import android.support.v4.app.Fragment; import com.jkb.fragment.rigger.annotation.Puppet; import com.jkb.fragment.rigger.exception.AlreadyExistException; -import com.jkb.fragment.swiper.widget.SwipeLayout; +import com.jkb.fragment.swiper.SwipeLayout; import java.util.Stack; /** diff --git a/rigger/src/main/java/com/jkb/fragment/rigger/rigger/_ActivityRigger.java b/rigger/src/main/java/com/jkb/fragment/rigger/rigger/_ActivityRigger.java index 228e4fa..8430016 100644 --- a/rigger/src/main/java/com/jkb/fragment/rigger/rigger/_ActivityRigger.java +++ b/rigger/src/main/java/com/jkb/fragment/rigger/rigger/_ActivityRigger.java @@ -9,7 +9,7 @@ import com.jkb.fragment.rigger.exception.UnSupportException; import com.jkb.fragment.rigger.utils.Logger; -import com.jkb.fragment.swiper.widget.SwipeLayout; +import com.jkb.fragment.swiper.SwipeLayout; /** * Activity Rigger.rig the Activity puppet. diff --git a/rigger/src/main/java/com/jkb/fragment/rigger/rigger/_FragmentRigger.java b/rigger/src/main/java/com/jkb/fragment/rigger/rigger/_FragmentRigger.java index c5c4aff..2866286 100644 --- a/rigger/src/main/java/com/jkb/fragment/rigger/rigger/_FragmentRigger.java +++ b/rigger/src/main/java/com/jkb/fragment/rigger/rigger/_FragmentRigger.java @@ -23,7 +23,7 @@ import com.jkb.fragment.rigger.exception.UnSupportException; import com.jkb.fragment.rigger.utils.Logger; import com.jkb.fragment.rigger.utils.RiggerConsts; -import com.jkb.fragment.swiper.widget.SwipeLayout; +import com.jkb.fragment.swiper.SwipeLayout; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.UUID; diff --git a/rigger/src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java b/rigger/src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java index c55d00e..98ebf0f 100644 --- a/rigger/src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java +++ b/rigger/src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java @@ -33,7 +33,7 @@ import com.jkb.fragment.rigger.helper.FragmentStackManager; import com.jkb.fragment.rigger.utils.Logger; import com.jkb.fragment.swiper.annotation.Swiper; -import com.jkb.fragment.swiper.widget.SwipeLayout; +import com.jkb.fragment.swiper.SwipeLayout; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; diff --git a/rigger/src/main/java/com/jkb/fragment/swiper/SwipeActivityManager.java b/rigger/src/main/java/com/jkb/fragment/swiper/SwipeActivityManager.java new file mode 100644 index 0000000..3626b23 --- /dev/null +++ b/rigger/src/main/java/com/jkb/fragment/swiper/SwipeActivityManager.java @@ -0,0 +1,53 @@ +package com.jkb.fragment.swiper; + +import android.app.Activity; +import android.support.annotation.NonNull; + +import java.util.Stack; + +/** + * This class is used to manage {@link android.app.Activity} and only used by {@link SwipeLayout}. + * + * @author JingYeoh + * Email me + * Github + * Blog + * @since Aug 1,2018 + */ +class SwipeActivityManager { + + private Stack mActivityStack; + + private static volatile SwipeActivityManager sInstance = null; + + private SwipeActivityManager() { + mActivityStack = new Stack<>(); + } + + /** + * Returns the instance of SwipeManager. + */ + static SwipeActivityManager getInstance() { + if (sInstance == null) { + synchronized (SwipeActivityManager.class) { + if (sInstance == null) { + sInstance = new SwipeActivityManager(); + } + } + } + return sInstance; + } + + private void addToStack(@NonNull Activity activity) { + mActivityStack.add(activity); + } + + private void removeFromStack(@NonNull Activity activity) { + mActivityStack.remove(activity); + } + + @NonNull + Stack getActivityStack() { + return mActivityStack; + } +} diff --git a/rigger/src/main/java/com/jkb/fragment/swiper/widget/SwipeLayout.java b/rigger/src/main/java/com/jkb/fragment/swiper/SwipeLayout.java similarity index 92% rename from rigger/src/main/java/com/jkb/fragment/swiper/widget/SwipeLayout.java rename to rigger/src/main/java/com/jkb/fragment/swiper/SwipeLayout.java index 5419267..7a60e5e 100644 --- a/rigger/src/main/java/com/jkb/fragment/swiper/widget/SwipeLayout.java +++ b/rigger/src/main/java/com/jkb/fragment/swiper/SwipeLayout.java @@ -1,4 +1,4 @@ -package com.jkb.fragment.swiper.widget; +package com.jkb.fragment.swiper; import android.annotation.SuppressLint; import android.app.Activity; @@ -14,8 +14,10 @@ import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; + import com.jkb.fragment.rigger.rigger.Rigger; import com.jkb.fragment.swiper.annotation.SwipeEdge; + import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -183,7 +185,7 @@ public int getViewVerticalDragRange(View child) { } @Override - public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { + public void onViewPositionChanged(@NonNull View changedView, int left, int top, int dx, int dy) { super.onViewPositionChanged(changedView, left, top, dx, dy); if ((mCurrentSwipeOrientation & ViewDragHelper.EDGE_LEFT) != 0) { @@ -210,6 +212,13 @@ public void onViewPositionChanged(View changedView, int left, int top, int dx, i preView.setX(0); preView.setY(0); } + } else { + Activity activity = getPreActivity(); + if (activity != null) { + View decorView = activity.getWindow().getDecorView(); + decorView.setX(0); + decorView.setY(0); + } } if (topFragment != null) { if (preFragment == null && mStickyWithHost) { @@ -262,12 +271,7 @@ public void computeScroll() { } } - private void computeScrollPreView() { - Fragment preFragment = getPreFragment(); - if (preFragment == null) { - return; - } - View view = preFragment.getView(); + private void computeScroll(@Nullable View view) { if (view == null) { return; } @@ -301,6 +305,27 @@ private void computeScrollPreView() { view.setY(yOffset); } + private void computeScrollPreView() { + Fragment preFragment = getPreFragment(); + if (preFragment == null) { + if (mPuppetHost instanceof Activity) { + computeScrollActivityView(); + } + return; + } + View view = preFragment.getView(); + computeScroll(view); + } + + private void computeScrollActivityView() { + Activity activity = getPreActivity(); + if (activity == null) { + return; + } + View decorView = activity.getWindow().getDecorView(); + computeScroll(decorView); + } + @Override public boolean dispatchTouchEvent(MotionEvent event) { switch (event.getAction()) { @@ -378,6 +403,19 @@ private Fragment getPreFragment() { return Rigger.getRigger(mPuppetHost).findFragmentByTag(topTag); } + @Nullable + private Activity getPreActivity() { + if (mPuppetHost instanceof Activity) { + Stack stack = SwipeActivityManager.getInstance().getActivityStack(); + int index = stack.indexOf(mPuppetHost); + if (index <= 0) { + return null; + } + return stack.get(index - 1); + } + return null; + } + ///////////////////////////// Attributes SETTER ///////////////////////////////////// public void setParallaxOffset(float parallaxOffset) { @@ -395,14 +433,14 @@ public void setSwipeEdgeSide(SwipeEdge[] swipeEdgeSide) { if (edge == SwipeEdge.NONE) { if (swipeEdgeSide.length > 1) { throw new IllegalArgumentException("The Swiper#edgeSide can not contain other value as" + - " the SwipeEdge.NONE is contained."); + " the SwipeEdge.NONE is contained."); } setEnableSwipe(false); return; } else if (edge == SwipeEdge.ALL) { if (swipeEdgeSide.length > 1) { throw new IllegalArgumentException("The Swiper#edgeSide can not contain other value as" + - " the SwipeEdge.ALL is contained."); + " the SwipeEdge.ALL is contained."); } } } diff --git a/rigger/src/main/java/com/jkb/fragment/swiper/aop/SwipeInjection.java b/rigger/src/main/java/com/jkb/fragment/swiper/aop/SwipeInjection.java new file mode 100644 index 0000000..586b940 --- /dev/null +++ b/rigger/src/main/java/com/jkb/fragment/swiper/aop/SwipeInjection.java @@ -0,0 +1,98 @@ +package com.jkb.fragment.swiper.aop; + +import android.app.Activity; +import android.os.Bundle; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; + +import java.lang.reflect.Method; + +/** + * Using AspectJ tools reach AOP. this class is used to inject + * {@link com.jkb.fragment.rigger.rigger.Rigger} to Activity's lifecycle and other methods. + * + * @author JingYeoh + * Email me + * Github + * Blog + * @since Nov 19,2017 + */ +@Aspect +public class SwipeInjection { + + //****************PointCut*********************************** + + /** + * PointCut method.find all classes that is marked by + * {@link com.jkb.fragment.swiper.annotation.Swiper} Annotation. + */ + @Pointcut("@target(com.jkb.fragment.swiper.annotation.Swiper)") + public void annotatedWithSwiper() { + } + + /** + * PointCut method.find all classes that is marked by + * {@link com.jkb.fragment.rigger.annotation.Puppet} Annotation. + */ + @Pointcut("@target(com.jkb.fragment.rigger.annotation.Puppet)") + public void annotatedWithPuppet() { + } + + //****************Helper************************************ && annotatedWithPuppet() && annotatedWithSwiper() + + @Pointcut("execution(* android.support.v4.app.FragmentActivity+.onCreate(..))") + public void onCreate() { + } + + @Pointcut("execution(* android.support.v4.app.FragmentActivity+.onDestroy(..))") + public void onDestroy() { + } + + //****************Process*********************************** + + @Around("onCreate()") + public Object onCreateProcess(ProceedingJoinPoint joinPoint) throws Throwable { + Object result = joinPoint.proceed(); + Object puppet = joinPoint.getTarget(); + //Only inject the class that marked by Puppet annotation. + + Method onCreate = invokeSwiperMethod("addToStack", Activity.class); + onCreate.invoke(getSwiperInstance(), puppet); + return result; + } + + @Around("onDestroy()") + public Object onDestroyProcess(ProceedingJoinPoint joinPoint) throws Throwable { + Object result = joinPoint.proceed(); + Object puppet = joinPoint.getTarget(); + //Only inject the class that marked by Puppet annotation. + + Method onDestroy = invokeSwiperMethod("removeFromStack", Activity.class); + onDestroy.invoke(getSwiperInstance(), puppet); + return result; + } + + /** + * Returns the instance of SwiperActivityManager class by reflect. + */ + Object getSwiperInstance() throws Exception { + Class riggerClazz = Class.forName("com.jkb.fragment.swiper.SwipeActivityManager"); + Method getInstance = riggerClazz.getDeclaredMethod("getInstance"); + getInstance.setAccessible(true); + return getInstance.invoke(null); + } + + /** + * Returns the method object of SwiperActivityManager by reflect. + */ + Method invokeSwiperMethod(String methodName, Class... params) throws Exception { + Object object = getSwiperInstance(); + Class clazz = object.getClass(); + Method method = clazz.getDeclaredMethod(methodName, params); + method.setAccessible(true); + return method; + } +}