From 66954cbbbfe1be9dac58768f0faf9869d7d1ffed Mon Sep 17 00:00:00 2001 From: Nguyen Dac Nam Date: Tue, 24 Jul 2018 18:01:11 +0700 Subject: [PATCH 01/15] add close if empty option (1/2) --- .../main/java/com/jkb/fragment/rigger/rigger/_Rigger.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java index 66b5333..0dff91c 100644 --- a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java +++ b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java @@ -67,6 +67,7 @@ static _Rigger create(@NonNull Object object) { @IdRes private int mContainerViewId; private boolean mBindContainerView; + private boolean mCloseIfEmpty; RiggerTransaction mRiggerTransaction; FragmentStackManager mStackManager; @@ -76,6 +77,7 @@ static _Rigger create(@NonNull Object object) { Class clazz = mPuppetTarget.getClass(); Puppet puppet = clazz.getAnnotation(Puppet.class); mBindContainerView = puppet.bondContainerView(); + mCloseOnEmpty = puppet.closeIfEmpty(); mContainerViewId = puppet.containerViewId(); if (mContainerViewId <= 0) { try { @@ -245,7 +247,10 @@ public void onBackPressed() { Logger.d(mPuppetTarget, "onRiggerBackPressed() method is called"); String topFragmentTag = mStackManager.peek(); if (TextUtils.isEmpty(topFragmentTag)) { - close(); + if(mCloseIfEmpty) { + Logger.d(mPuppetTarget, "Rigger was closed because of empty top"); + close(); + } } else { //call the top fragment's onBackPressed method. Fragment topFragment = mRiggerTransaction.find(topFragmentTag); From 044e37713d77dd8fb73465c578dd06a0eac1e0d6 Mon Sep 17 00:00:00 2001 From: Nguyen Dac Nam Date: Tue, 24 Jul 2018 18:04:18 +0700 Subject: [PATCH 02/15] add close if empty option (2/2) --- .../com/jkb/fragment/rigger/annotation/Puppet.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/annotation/Puppet.java b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/annotation/Puppet.java index 89ebcc9..4deab46 100644 --- a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/annotation/Puppet.java +++ b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/annotation/Puppet.java @@ -54,4 +54,15 @@ * @return The default value is false. */ boolean stickyStack() default false; + + /** + * Allow or not exit the host {@link android.app.Activity}/{@link android.support.v4.app.Fragment} when + * the stack size = 0 + * + * If the value is true , the host object(Activity/Fragment) will not be exit + * Otherwise , the host object(Activity/Fragment) will act as normal. + * + * @return The default value is true. + */ + boolean closeIfEmpty() default true; } From 3d8e43637c5500d96a46cad8fef324e3000d224c Mon Sep 17 00:00:00 2001 From: Nguyen Dac Nam Date: Tue, 24 Jul 2018 18:06:38 +0700 Subject: [PATCH 03/15] fixup close if empty --- .../src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java index 0dff91c..91c7e31 100644 --- a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java +++ b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java @@ -77,7 +77,7 @@ static _Rigger create(@NonNull Object object) { Class clazz = mPuppetTarget.getClass(); Puppet puppet = clazz.getAnnotation(Puppet.class); mBindContainerView = puppet.bondContainerView(); - mCloseOnEmpty = puppet.closeIfEmpty(); + mCloseIfEmpty = puppet.closeIfEmpty(); mContainerViewId = puppet.containerViewId(); if (mContainerViewId <= 0) { try { From e2d78d677c536b17a4989038f891488dc02e726c Mon Sep 17 00:00:00 2001 From: Nguyen Dac Nam Date: Tue, 24 Jul 2018 22:18:41 +0700 Subject: [PATCH 04/15] shared element transaction (2/3) --- .../rigger/rigger/RiggerTransactionImpl.java | 32 ++++++++++++++++--- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransactionImpl.java b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransactionImpl.java index 8b225eb..5c6acb4 100644 --- a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransactionImpl.java +++ b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransactionImpl.java @@ -28,9 +28,8 @@ final class RiggerTransactionImpl extends RiggerTransaction { private static final int OP_SHOW = 5; private static final int OP_DETACH = 6; private static final int OP_ATTACH = 7; - + private static final class Op { - Op next; Op prev; int cmd; @@ -39,6 +38,7 @@ private static final class Op { int containerViewId; int enterAnim; int exitAnim; + HashSet sharedElements; } private Op mHead; @@ -140,6 +140,19 @@ RiggerTransaction hide(String... tags) { } return this; } + + @Override + RiggerTransaction addSharedElements(int... ids) { + if (ids == null || ids.length == 0) return this; + if (mTail == null) return this; + for (int id : ids) { + if(mTail.sharedElements == null) { + mTail.sharedElements = new HashSet(); + } + mTail.sharedElements.add(id) + } + return this; + } @Override void commit() { @@ -183,6 +196,8 @@ private void executePendingTransaction() { if (op == null) return; FragmentTransaction ft = mFragmentManager.beginTransaction(); while (op != null) { + Fragment f = find(op.fragmentTag); + switch (op.cmd) { case OP_ADD: { ft.setCustomAnimations(op.enterAnim, op.exitAnim); @@ -190,7 +205,6 @@ private void executePendingTransaction() { } break; case OP_REMOVE: { - Fragment f = find(op.fragmentTag); if (f == null) { Logger.w(this, "Op:Remove.can not find fragment " + op.fragmentTag); } else { @@ -201,7 +215,6 @@ private void executePendingTransaction() { break; case OP_SHOW: { ft.setCustomAnimations(op.enterAnim, op.exitAnim); - Fragment f = find(op.fragmentTag); if (f == null) { Logger.w(this, "Op:Show.can not find fragment " + op.fragmentTag); } else { @@ -211,7 +224,6 @@ private void executePendingTransaction() { break; case OP_HIDE: { ft.setCustomAnimations(op.enterAnim, op.exitAnim); - Fragment f = find(op.fragmentTag); if (f == null) { Logger.w(this, "Op:Hide.can not find fragment " + op.fragmentTag); } else { @@ -220,6 +232,16 @@ private void executePendingTransaction() { } break; } + + if(op.sharedElements != null && f != null) { + for(int viewId : op.sharedElements) { + View v = f.getView().findViewById(viewId); + if(v != null) { + ft.addSharedElement(v, v.getTransitionName()); + } + } + } + op = op.next; } ft.commit(); From 5e7fe18ea9be577c801c8b41b4be5fe20a7eca2d Mon Sep 17 00:00:00 2001 From: Nguyen Dac Nam Date: Tue, 24 Jul 2018 22:18:44 +0700 Subject: [PATCH 05/15] shared element transaction (1/3) - add api addSharedElements that add shared element to last op (tail) --- .../jkb/fragment/rigger/rigger/RiggerTransaction.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransaction.java b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransaction.java index aa7ee93..b129d47 100644 --- a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransaction.java +++ b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransaction.java @@ -71,6 +71,15 @@ abstract class RiggerTransaction { * @return Returns the same RiggerTransaction instance. */ abstract RiggerTransaction hide(String... tags); + + /** + * Add shared element to the last Op. + * + * @param ids View Id that is shared. + * + * @return Returns the same RiggerTransaction instance. + */ + abstract RiggerTransaction addSharedElements(int... ids); /** * Schedules a commit of this transaction. The commit does From 5476616a0b895dcf8138580c7768129941cb6345 Mon Sep 17 00:00:00 2001 From: Nguyen Dac Nam Date: Tue, 24 Jul 2018 22:23:02 +0700 Subject: [PATCH 06/15] add fucking `;` missing --- .../com/jkb/fragment/rigger/rigger/RiggerTransactionImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransactionImpl.java b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransactionImpl.java index 5c6acb4..5c2eca2 100644 --- a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransactionImpl.java +++ b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransactionImpl.java @@ -149,7 +149,7 @@ RiggerTransaction addSharedElements(int... ids) { if(mTail.sharedElements == null) { mTail.sharedElements = new HashSet(); } - mTail.sharedElements.add(id) + mTail.sharedElements.add(id); } return this; } From d4a80b66be2b2a8ff7748d4e7112a3370b8f5689 Mon Sep 17 00:00:00 2001 From: Nguyen Dac Nam Date: Tue, 24 Jul 2018 22:25:15 +0700 Subject: [PATCH 07/15] add missing include --- .../com/jkb/fragment/rigger/rigger/RiggerTransactionImpl.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransactionImpl.java b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransactionImpl.java index 5c2eca2..c6ff90e 100644 --- a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransactionImpl.java +++ b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransactionImpl.java @@ -6,9 +6,11 @@ import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; import android.text.TextUtils; +import android.view.View; import com.jkb.fragment.rigger.utils.Logger; import java.lang.ref.WeakReference; import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedList; import java.util.Map; From f1500549d9c206aa291805f9877d3d72a414fb93 Mon Sep 17 00:00:00 2001 From: Nguyen Dac Nam Date: Tue, 24 Jul 2018 22:36:26 +0700 Subject: [PATCH 08/15] shared element transaction (2.5/3) add api interface --- .../main/java/com/jkb/fragment/rigger/rigger/IRigger.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/IRigger.java b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/IRigger.java index 12b9899..707d56d 100644 --- a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/IRigger.java +++ b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/IRigger.java @@ -35,6 +35,13 @@ public interface IRigger { * @return The fragment if found or null otherwise. */ Fragment findFragmentByTag(String tag); + + /** + * Add shared elements on next fragment transaction right before commit(). + * + * @param ids shared view id; + */ + void addSharedElements(int... ids); /** * Add fragments to parent's state.these fragments will not be added into the stack. From 3c261160c0a304f08138ed88329f000435a499cb Mon Sep 17 00:00:00 2001 From: Nguyen Dac Nam Date: Tue, 24 Jul 2018 22:47:12 +0700 Subject: [PATCH 09/15] shared element transaction (3/3) --- .../jkb/fragment/rigger/rigger/_Rigger.java | 46 ++++++++++++++++--- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java index 91c7e31..7588232 100644 --- a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java +++ b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java @@ -68,6 +68,7 @@ static _Rigger create(@NonNull Object object) { private int mContainerViewId; private boolean mBindContainerView; private boolean mCloseIfEmpty; + private int[] mSharedElements; RiggerTransaction mRiggerTransaction; FragmentStackManager mStackManager; @@ -266,6 +267,11 @@ public Fragment findFragmentByTag(String tag) { if (!mStackManager.contain(tag)) return null; return mRiggerTransaction.find(tag); } + + void addSharedElements(int... ids) { + mSharedElements = null; + mSharedElements = ids; + } @Override public void addFragment(@IdRes int containerViewId, Fragment... fragments) { @@ -283,6 +289,10 @@ public void addFragment(@IdRes int containerViewId, Fragment... fragments) { } fragment.setUserVisibleHint(false); } + if(mSharedElements != null) { + mRiggerTransaction.addSharedElements(mSharedElements); + mSharedElements = null; + } mRiggerTransaction.commit(); } @@ -297,6 +307,10 @@ public void startFragment(@NonNull Fragment fragment) { } addFragmentWithAnim(fragment, mContainerViewId); mRiggerTransaction.hide(getVisibleFragmentTags(getContainerViewId())); + if(mSharedElements != null) { + mRiggerTransaction.addSharedElements(mSharedElements); + mSharedElements = null; + } mRiggerTransaction.show(fragmentTAG).commit(); } @@ -339,6 +353,10 @@ void startPopFragment(Animation animation) { mRiggerTransaction.setCustomAnimations(0, 0); mRiggerTransaction.show(topFragmentTag); } + if(mSharedElements != null) { + mRiggerTransaction.addSharedElements(mSharedElements); + mSharedElements = null; + } mRiggerTransaction.commit(); } @@ -353,6 +371,10 @@ public void showFragment(@NonNull Fragment fragment, @IdRes int containerViewId, if (mStackManager.add(fragmentTAG, containerViewId)) { addFragmentWithAnim(fragment, containerViewId); } + if(mSharedElements != null) { + mRiggerTransaction.addSharedElements(mSharedElements); + mSharedElements = null; + } String[] fragmentTags = mStackManager.getFragmentTags(containerViewId); for (String tag : fragmentTags) { Fragment hideFrag = mRiggerTransaction.find(tag); @@ -388,8 +410,12 @@ public void hideFragment(@NonNull Fragment fragment) { _FragmentRigger rigger = (_FragmentRigger) Rigger.getRigger(fragment); String fragmentTAG = rigger.getFragmentTAG(); mRiggerTransaction.setCustomAnimations(rigger.mPopEnterAnim, rigger.mExitAnim); - mRiggerTransaction.hide(fragmentTAG) - .commit(); + mRiggerTransaction.hide(fragmentTAG); + if(mSharedElements != null) { + mRiggerTransaction.addSharedElements(mSharedElements); + mSharedElements = null; + } + mRiggerTransaction.commit(); } @Override @@ -404,9 +430,12 @@ public void hideFragment(@NonNull String tag) { public void replaceFragment(@NonNull Fragment fragment, @IdRes int containerViewId) { String fragmentTAG = Rigger.getRigger(fragment).getFragmentTAG(); addFragmentWithAnim(fragment, containerViewId); - mRiggerTransaction.remove(mStackManager.getFragmentTags(containerViewId)) - .show(fragmentTAG) - .commit(); + mRiggerTransaction.remove(mStackManager.getFragmentTags(containerViewId)).show(fragmentTAG); + if(mSharedElements != null) { + mRiggerTransaction.addSharedElements(mSharedElements); + mSharedElements = null; + } + mRiggerTransaction.commit(); mStackManager.remove(containerViewId); mStackManager.add(fragmentTAG, containerViewId); } @@ -423,7 +452,12 @@ public void close(@NonNull Fragment fragment) { } else { //if the puppet is not bond container,then remove the fragment onto the container. //and show the Fragment's content view. - mRiggerTransaction.remove(fragmentTAG).commit(); + mRiggerTransaction.remove(fragmentTAG); + if(mSharedElements != null) { + mRiggerTransaction.addSharedElements(mSharedElements); + mSharedElements = null; + } + mRiggerTransaction.commit(); } } From 04b335a7f005c6ebdcb0a6576a5d73e0197fa099 Mon Sep 17 00:00:00 2001 From: Nam Nguyen Date: Tue, 24 Jul 2018 22:59:50 +0700 Subject: [PATCH 10/15] fixup --- .../main/java/com/jkb/fragment/rigger/rigger/_Rigger.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java index 7588232..da8ee72 100644 --- a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java +++ b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java @@ -267,8 +267,9 @@ public Fragment findFragmentByTag(String tag) { if (!mStackManager.contain(tag)) return null; return mRiggerTransaction.find(tag); } - - void addSharedElements(int... ids) { + + @Override + public void addSharedElements(int... ids) { mSharedElements = null; mSharedElements = ids; } From 7b1e415919a17601a4a82ce1ada5b56908e3f782 Mon Sep 17 00:00:00 2001 From: Nam Nguyen Date: Tue, 24 Jul 2018 23:42:49 +0700 Subject: [PATCH 11/15] fixups --- .../rigger/rigger/RiggerTransactionImpl.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransactionImpl.java b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransactionImpl.java index c6ff90e..fae8219 100644 --- a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransactionImpl.java +++ b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransactionImpl.java @@ -5,6 +5,7 @@ import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; +import android.support.v4.view.ViewCompat; import android.text.TextUtils; import android.view.View; import com.jkb.fragment.rigger.utils.Logger; @@ -202,7 +203,9 @@ private void executePendingTransaction() { switch (op.cmd) { case OP_ADD: { - ft.setCustomAnimations(op.enterAnim, op.exitAnim); + if(op.sharedElements == null) { + ft.setCustomAnimations(op.enterAnim, op.exitAnim); + } ft.add(op.containerViewId, op.fragment, op.fragmentTag); } break; @@ -216,7 +219,9 @@ private void executePendingTransaction() { } break; case OP_SHOW: { - ft.setCustomAnimations(op.enterAnim, op.exitAnim); + if(op.sharedElements == null) { + ft.setCustomAnimations(op.enterAnim, op.exitAnim); + } if (f == null) { Logger.w(this, "Op:Show.can not find fragment " + op.fragmentTag); } else { @@ -225,7 +230,9 @@ private void executePendingTransaction() { } break; case OP_HIDE: { - ft.setCustomAnimations(op.enterAnim, op.exitAnim); + if(op.sharedElements == null) { + ft.setCustomAnimations(op.enterAnim, op.exitAnim); + } if (f == null) { Logger.w(this, "Op:Hide.can not find fragment " + op.fragmentTag); } else { @@ -239,7 +246,7 @@ private void executePendingTransaction() { for(int viewId : op.sharedElements) { View v = f.getView().findViewById(viewId); if(v != null) { - ft.addSharedElement(v, v.getTransitionName()); + ft.addSharedElement(v, ViewCompat.getTransitionName(v)); } } } From 297e351bdfb4360874106f9f50de4eec74952193 Mon Sep 17 00:00:00 2001 From: Nam Nguyen Date: Wed, 25 Jul 2018 00:00:39 +0700 Subject: [PATCH 12/15] fixups --- .../rigger/rigger/RiggerTransactionImpl.java | 2 +- .../jkb/fragment/rigger/rigger/_Rigger.java | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransactionImpl.java b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransactionImpl.java index fae8219..feb31ca 100644 --- a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransactionImpl.java +++ b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransactionImpl.java @@ -242,7 +242,7 @@ private void executePendingTransaction() { break; } - if(op.sharedElements != null && f != null) { + if(op.sharedElements != null && f != null && f.getView() != null) { for(int viewId : op.sharedElements) { View v = f.getView().findViewById(viewId); if(v != null) { diff --git a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java index da8ee72..fcc8ed7 100644 --- a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java +++ b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java @@ -284,16 +284,16 @@ public void addFragment(@IdRes int containerViewId, Fragment... fragments) { String fragmentTAG = Rigger.getRigger(fragment).getFragmentTAG(); if (mStackManager.add(fragmentTAG, containerViewId)) { addFragmentWithAnim(fragment, containerViewId); + if(mSharedElements != null) { + mRiggerTransaction.addSharedElements(mSharedElements); + mSharedElements = null; + } mRiggerTransaction.hide(fragmentTAG); } else { throwException(new AlreadyExistException(fragmentTAG)); } fragment.setUserVisibleHint(false); } - if(mSharedElements != null) { - mRiggerTransaction.addSharedElements(mSharedElements); - mSharedElements = null; - } mRiggerTransaction.commit(); } @@ -307,11 +307,11 @@ public void startFragment(@NonNull Fragment fragment) { throwException(new UnSupportException("ContainerViewId must be effective in class " + mPuppetTarget.getClass())); } addFragmentWithAnim(fragment, mContainerViewId); - mRiggerTransaction.hide(getVisibleFragmentTags(getContainerViewId())); if(mSharedElements != null) { mRiggerTransaction.addSharedElements(mSharedElements); mSharedElements = null; } + mRiggerTransaction.hide(getVisibleFragmentTags(getContainerViewId())); mRiggerTransaction.show(fragmentTAG).commit(); } @@ -371,10 +371,10 @@ public void showFragment(@NonNull Fragment fragment, @IdRes int containerViewId, String fragmentTAG = Rigger.getRigger(fragment).getFragmentTAG(); if (mStackManager.add(fragmentTAG, containerViewId)) { addFragmentWithAnim(fragment, containerViewId); - } - if(mSharedElements != null) { - mRiggerTransaction.addSharedElements(mSharedElements); - mSharedElements = null; + if(mSharedElements != null) { + mRiggerTransaction.addSharedElements(mSharedElements); + mSharedElements = null; + } } String[] fragmentTags = mStackManager.getFragmentTags(containerViewId); for (String tag : fragmentTags) { From fe2f6e5208f82784bc001776c688c0df151db595 Mon Sep 17 00:00:00 2001 From: Nam Nguyen Date: Wed, 25 Jul 2018 00:17:19 +0700 Subject: [PATCH 13/15] fixups --- .../rigger/rigger/RiggerTransaction.java | 2 ++ .../rigger/rigger/RiggerTransactionImpl.java | 19 +++++++++++++++++++ .../jkb/fragment/rigger/rigger/_Rigger.java | 3 +-- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransaction.java b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransaction.java index b129d47..81d88af 100644 --- a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransaction.java +++ b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransaction.java @@ -38,6 +38,8 @@ abstract class RiggerTransaction { */ abstract RiggerTransaction add(@IdRes int containerViewId, Fragment fragment, @NonNull String tag); + abstract RiggerTransaction replace(@IdRes int containerViewId, Fragment fragment, @NonNull String tag); + /** * Remove existing fragment. * diff --git a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransactionImpl.java b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransactionImpl.java index feb31ca..3e20d5b 100644 --- a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransactionImpl.java +++ b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransactionImpl.java @@ -99,6 +99,17 @@ RiggerTransaction add(@IdRes int containerViewId, Fragment fragment, @NonNull St return this; } + @Override + RiggerTransaction replace(@IdRes int containerViewId, Fragment fragment, @NonNull String tag) { + Op op = new Op(); + op.cmd = OP_REPLACE; + op.fragment = fragment; + op.fragmentTag = tag; + op.containerViewId = containerViewId; + addOp(op); + return this; + } + @Override RiggerTransaction remove(String... tags) { if (tags == null || tags.length == 0) return this; @@ -209,6 +220,14 @@ private void executePendingTransaction() { ft.add(op.containerViewId, op.fragment, op.fragmentTag); } break; + case OP_REPLACE: { + if (f == null) { + Logger.w(this, "Op:Remove.can not find fragment " + op.fragmentTag); + } else { + ft.replace(op.containerViewId, op.fragment, op.fragmentTag); + } + } + break; case OP_REMOVE: { if (f == null) { Logger.w(this, "Op:Remove.can not find fragment " + op.fragmentTag); diff --git a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java index fcc8ed7..7a0a01d 100644 --- a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java +++ b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java @@ -430,8 +430,7 @@ public void hideFragment(@NonNull String tag) { @Override public void replaceFragment(@NonNull Fragment fragment, @IdRes int containerViewId) { String fragmentTAG = Rigger.getRigger(fragment).getFragmentTAG(); - addFragmentWithAnim(fragment, containerViewId); - mRiggerTransaction.remove(mStackManager.getFragmentTags(containerViewId)).show(fragmentTAG); + mRiggerTransaction.replace(containerViewId, fragment, fragmentTAG); if(mSharedElements != null) { mRiggerTransaction.addSharedElements(mSharedElements); mSharedElements = null; From 250563ad03f9c72ccdc618e5ec7684373b46b339 Mon Sep 17 00:00:00 2001 From: Nam Nguyen Date: Fri, 27 Jul 2018 17:15:15 +0700 Subject: [PATCH 14/15] final fixups - add Shared Element object - fix replace functions --- .../fragment/rigger/helper/SharedElement.java | 20 + .../jkb/fragment/rigger/rigger/IRigger.java | 419 +++--- .../rigger/rigger/RiggerTransaction.java | 13 +- .../rigger/rigger/RiggerTransactionImpl.java | 442 ++++--- .../jkb/fragment/rigger/rigger/_Rigger.java | 1142 ++++++++--------- .../fragment/swiper/widget/SwiperLayout.java | 4 +- 6 files changed, 1015 insertions(+), 1025 deletions(-) create mode 100644 fragment-rigger/src/main/java/com/jkb/fragment/rigger/helper/SharedElement.java diff --git a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/helper/SharedElement.java b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/helper/SharedElement.java new file mode 100644 index 0000000..ac10bc3 --- /dev/null +++ b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/helper/SharedElement.java @@ -0,0 +1,20 @@ +package com.jkb.fragment.rigger.helper; + +import android.support.v4.view.ViewCompat; +import android.view.View; + +import java.lang.ref.WeakReference; + +public class SharedElement { + public WeakReference referenceView; + public String transactionName; + public static SharedElement create(View refView, String transName){ + SharedElement sharedElement = new SharedElement(); + sharedElement.referenceView = new WeakReference<>(refView); + sharedElement.transactionName = transName; + return sharedElement; + } + public static SharedElement create(View refView){ + return create(refView, ViewCompat.getTransitionName(refView)); + } +} diff --git a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/IRigger.java b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/IRigger.java index 707d56d..8c99a1d 100644 --- a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/IRigger.java +++ b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/IRigger.java @@ -4,228 +4,225 @@ import android.support.annotation.IdRes; import android.support.annotation.NonNull; import android.support.v4.app.Fragment; + import com.jkb.fragment.rigger.annotation.Puppet; import com.jkb.fragment.rigger.exception.AlreadyExistException; +import com.jkb.fragment.rigger.helper.SharedElement; + import java.util.Stack; /** * Rigger interface class.used to define the methods can be called. * * @author JingYeoh - * Email me - * Github - * Blog + * Email me + * Github + * Blog * @since Nov 20,2017 */ public interface IRigger { - /** - * Take care of popping the fragment back stack or finishing the activity - * as appropriate.the method is called when you click the back key. - */ - void onBackPressed(); - - /** - * Finds a fragment that was identified by the given tag either when inflated - * from XML or as supplied when added in a transaction. - * - * @param tag The fragment tag to be found. - * - * @return The fragment if found or null otherwise. - */ - Fragment findFragmentByTag(String tag); - - /** - * Add shared elements on next fragment transaction right before commit(). - * - * @param ids shared view id; - */ - void addSharedElements(int... ids); - - /** - * Add fragments to parent's state.these fragments will not be added into the stack. - * you can use these fragments with method {@link #showFragment(Fragment, int)}/{@link #showFragment(String)} - * or {@link #replaceFragment(Fragment, int)}. - * - * @param containerViewId containerViewId Optional identifier of the container this fragment is - * to be placed in. If 0, it will not be placed in a container. - * @param fragments the fragments to be added. - */ - void addFragment(@IdRes int containerViewId, Fragment... fragments); - - /** - * Adds and show a fragment into parent's containerView and hide other fragments that is placed in the - * containerView. - * - * @param fragment the fragment that will be showed. - */ - void startFragment(@NonNull Fragment fragment); - - /** - * Adds and shows a fragment for which you would like a result when it closed. - * When this fragment is exists,your onFragmentResult() method will be called with the given requestCode. - * - * @param receive The receive object of onFragmentResult method called back. - * @param fragment The fragment to be started. - * @param requestCode If >= 0,this codepublic will be returned in onFragmentResult() method when fragment exits. - */ - void startFragmentForResult(Object receive, @NonNull Fragment fragment, int requestCode); - - /** - * Adds and shows a fragment for which you would like a result when it closed. - * When this fragment is exists,your onFragmentResult() method will be called with the given requestCode. - * The onFragmentResult() method might not be called in the class that called this method, onFragmentResult() method - * will be called in the class that have the fragment's container. - * - * @param fragment The fragment to be started. - * @param requestCode If >= 0,this code will be returned in onFragmentResult() method when fragment exits. - */ - void startFragmentForResult(@NonNull Fragment fragment, int requestCode); - - /** - * Shows the pop fragment in the stack and hide the others.if the stack is empty,do none operation. - */ - void startPopFragment(); - - /** - * Shows a fragment and hide the others which is contained in the containerView.if the fragment is not added in the - * stack,then add first. - * - * The fragment added by this method is not pushed in the stack.if the method {@link #onBackPressed()} is - * called, this fragment has none operation. - * - * @param fragment the fragment to be showed. - * @param containerViewId the fragment's container view's id. - */ - void showFragment(@NonNull Fragment fragment, @IdRes int containerViewId); - - /** - * Shows a fragment and hide the others which is contained in the containerView.if the fragment is not added in the - * stack,then add first. - * - * The fragment added by this method is not pushed in the stack.if the method {@link #onBackPressed()} is - * called, this fragment has none operation. - * - * @param fragment the fragment to be showed. - * @param containerViewId the fragment's container view's id. - * @param showRepeatAnim trigger to show fragment transaction animation,if the fragment is already - * showed.method {@link #showFragment(Fragment, int)} default value is false. - */ - void showFragment(@NonNull Fragment fragment, @IdRes int containerViewId, boolean showRepeatAnim); - - /** - * Shows an existing fragment and hide the others which is contained in the containerView. - * If this fragment is already showed,then do nothing. - * - * @param tag the tag name of fragment to be showed. - */ - void showFragment(@NonNull String tag); - - /** - * Shows an existing fragment and hide the others which is contained in the containerView. - * - * @param tag the tag name of fragment to be showed. - * @param showRepeatAnim trigger to show fragment transaction animation,if the fragment is already - * showed.method {@link #showFragment(String)} default value is false. - */ - void showFragment(@NonNull String tag, boolean showRepeatAnim); - - /** - * Hides an existing fragment. - * - * @param fragment The fragment to be hidden. - */ - void hideFragment(@NonNull Fragment fragment); - - /** - * Hides an existing fragment and hide the others which is contained in the containerView. - * - * @param tag the tag name of fragment to be hidden. - */ - void hideFragment(@NonNull String tag); - - /** - * Shows a fragment and remove the others which is contained in the containerView. - * if the fragment is not added in the stack,then add first, - * if the fragment is already exist,then throw {@link AlreadyExistException}. - * - * The fragment added by this method is not pushed in the stack.if the method {@link #onBackPressed()} is - * called, this fragment has none operation. - * - * @param fragment the fragment to be showed. - * @param containerViewId the fragment's container view's id. - */ - void replaceFragment(@NonNull Fragment fragment, @IdRes int containerViewId); - - /** - * Returns the resume status of Activity/Fragment. - * - * @return is or not resumed. - */ - boolean isResumed(); - - /** - * Closes the current Activity/Fragment.if this method is called by {@link Fragment},then this fragment will be - * removed from the parent's fragment stack. - */ - void close(); - - /** - * Closes a fragment and remove it from stack. - * - * @param fragment the fragment that will be finished.this is the current's child fragment. - */ - void close(@NonNull Fragment fragment); - - /** - * Sets the tag of fragment.this method can only be effective before add fragment. - * - * @param tag the tag of fragment. - */ - void setFragmentTag(@NonNull String tag); - - /** - * Returns the tag of fragment.if the method is called by Activity,then return null. - */ - String getFragmentTAG(); - - /** - * Returns the optional identifier of the container this fragment is placed in. - */ - @IdRes - int getContainerViewId(); - - /** - * Returns the value of bondContainerView in {@link Puppet}. - */ - boolean isBondContainerView(); - - /** - * Returns the value of lazyloading in {@link com.jkb.fragment.rigger.annotation.LazyLoad} - */ - boolean isLazyLoading(); - - /** - * Call this to set the result that your fragment will return to its - * caller. - * - * @param resultCode The result code to propagate back to the originating - * fragment, often RESULT_CANCELED or RESULT_OK - * @param bundle The data to propagate back to the originating fragment. - * - * @see Rigger#RESULT_OK - * @see Rigger#RESULT_CANCELED - */ - void setResult(int resultCode, Bundle bundle); - - /** - * Returns the current fragment stack. - */ - Stack getFragmentStack(); - - /** - * Printf the current stack in logcat. - */ - void printStack(); + /** + * Take care of popping the fragment back stack or finishing the activity + * as appropriate.the method is called when you click the back key. + */ + void onBackPressed(); + + /** + * Finds a fragment that was identified by the given tag either when inflated + * from XML or as supplied when added in a transaction. + * + * @param tag The fragment tag to be found. + * @return The fragment if found or null otherwise. + */ + Fragment findFragmentByTag(String tag); + + + /** + * Add fragments to parent's state.these fragments will not be added into the stack. + * you can use these fragments with method {@link #showFragment(Fragment, int)}/{@link #showFragment(String)} + * or {@link #replaceFragment(Fragment, int)}. + * + * @param containerViewId containerViewId Optional identifier of the container this fragment is + * to be placed in. If 0, it will not be placed in a container. + * @param fragments the fragments to be added. + */ + void addFragment(@IdRes int containerViewId, Fragment... fragments); + + /** + * Adds and show a fragment into parent's containerView and hide other fragments that is placed in the + * containerView. + * + * @param fragment the fragment that will be showed. + */ + void startFragment(@NonNull Fragment fragment); + + /** + * Adds and shows a fragment for which you would like a result when it closed. + * When this fragment is exists,your onFragmentResult() method will be called with the given requestCode. + * + * @param receive The receive object of onFragmentResult method called back. + * @param fragment The fragment to be started. + * @param requestCode If >= 0,this codepublic will be returned in onFragmentResult() method when fragment exits. + */ + void startFragmentForResult(Object receive, @NonNull Fragment fragment, int requestCode); + + /** + * Adds and shows a fragment for which you would like a result when it closed. + * When this fragment is exists,your onFragmentResult() method will be called with the given requestCode. + * The onFragmentResult() method might not be called in the class that called this method, onFragmentResult() method + * will be called in the class that have the fragment's container. + * + * @param fragment The fragment to be started. + * @param requestCode If >= 0,this code will be returned in onFragmentResult() method when fragment exits. + */ + void startFragmentForResult(@NonNull Fragment fragment, int requestCode); + + /** + * Shows the pop fragment in the stack and hide the others.if the stack is empty,do none operation. + */ + void startPopFragment(); + + /** + * Shows a fragment and hide the others which is contained in the containerView.if the fragment is not added in the + * stack,then add first. + *

+ * The fragment added by this method is not pushed in the stack.if the method {@link #onBackPressed()} is + * called, this fragment has none operation. + * + * @param fragment the fragment to be showed. + * @param containerViewId the fragment's container view's id. + */ + void showFragment(@NonNull Fragment fragment, @IdRes int containerViewId); + + /** + * Shows a fragment and hide the others which is contained in the containerView.if the fragment is not added in the + * stack,then add first. + *

+ * The fragment added by this method is not pushed in the stack.if the method {@link #onBackPressed()} is + * called, this fragment has none operation. + * + * @param fragment the fragment to be showed. + * @param containerViewId the fragment's container view's id. + * @param showRepeatAnim trigger to show fragment transaction animation,if the fragment is already + * showed.method {@link #showFragment(Fragment, int)} default value is false. + */ + void showFragment(@NonNull Fragment fragment, @IdRes int containerViewId, boolean showRepeatAnim); + + /** + * Shows an existing fragment and hide the others which is contained in the containerView. + * If this fragment is already showed,then do nothing. + * + * @param tag the tag name of fragment to be showed. + */ + void showFragment(@NonNull String tag); + + /** + * Shows an existing fragment and hide the others which is contained in the containerView. + * + * @param tag the tag name of fragment to be showed. + * @param showRepeatAnim trigger to show fragment transaction animation,if the fragment is already + * showed.method {@link #showFragment(String)} default value is false. + */ + void showFragment(@NonNull String tag, boolean showRepeatAnim); + + /** + * Hides an existing fragment. + * + * @param fragment The fragment to be hidden. + */ + void hideFragment(@NonNull Fragment fragment); + + /** + * Hides an existing fragment and hide the others which is contained in the containerView. + * + * @param tag the tag name of fragment to be hidden. + */ + void hideFragment(@NonNull String tag); + + /** + * Shows a fragment and remove the others which is contained in the containerView. + * if the fragment is not added in the stack,then add first, + * if the fragment is already exist,then throw {@link AlreadyExistException}. + *

+ * The fragment added by this method is not pushed in the stack.if the method {@link #onBackPressed()} is + * called, this fragment has none operation. + * + * @param fragment the fragment to be showed. + * @param containerViewId the fragment's container view's id. + */ + void replaceFragment(@NonNull Fragment fragment, @IdRes int containerViewId); + // with shared elements transaction + void replaceFragment(@NonNull Fragment fragment, @IdRes int containerViewId, SharedElement... elements); + + /** + * Returns the resume status of Activity/Fragment. + * + * @return is or not resumed. + */ + boolean isResumed(); + + /** + * Closes the current Activity/Fragment.if this method is called by {@link Fragment},then this fragment will be + * removed from the parent's fragment stack. + */ + void close(); + + /** + * Closes a fragment and remove it from stack. + * + * @param fragment the fragment that will be finished.this is the current's child fragment. + */ + void close(@NonNull Fragment fragment); + + /** + * Sets the tag of fragment.this method can only be effective before add fragment. + * + * @param tag the tag of fragment. + */ + void setFragmentTag(@NonNull String tag); + + /** + * Returns the tag of fragment.if the method is called by Activity,then return null. + */ + String getFragmentTAG(); + + /** + * Returns the optional identifier of the container this fragment is placed in. + */ + @IdRes + int getContainerViewId(); + + /** + * Returns the value of bondContainerView in {@link Puppet}. + */ + boolean isBondContainerView(); + + /** + * Returns the value of lazyloading in {@link com.jkb.fragment.rigger.annotation.LazyLoad} + */ + boolean isLazyLoading(); + + /** + * Call this to set the result that your fragment will return to its + * caller. + * + * @param resultCode The result code to propagate back to the originating + * fragment, often RESULT_CANCELED or RESULT_OK + * @param bundle The data to propagate back to the originating fragment. + * @see Rigger#RESULT_OK + * @see Rigger#RESULT_CANCELED + */ + void setResult(int resultCode, Bundle bundle); + + /** + * Returns the current fragment stack. + */ + Stack getFragmentStack(); + + /** + * Printf the current stack in logcat. + */ + void printStack(); } diff --git a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransaction.java b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransaction.java index 81d88af..0dc4905 100644 --- a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransaction.java +++ b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransaction.java @@ -5,6 +5,8 @@ import android.support.v4.app.Fragment; import android.support.v4.app.FragmentTransaction; +import com.jkb.fragment.rigger.helper.SharedElement; + /** * API for performing a set of Fragment operations. * @@ -39,6 +41,7 @@ abstract class RiggerTransaction { abstract RiggerTransaction add(@IdRes int containerViewId, Fragment fragment, @NonNull String tag); abstract RiggerTransaction replace(@IdRes int containerViewId, Fragment fragment, @NonNull String tag); + abstract RiggerTransaction replace(@IdRes int containerViewId, Fragment fragment, @NonNull String tag, SharedElement... elements); /** * Remove existing fragment. @@ -73,15 +76,7 @@ abstract class RiggerTransaction { * @return Returns the same RiggerTransaction instance. */ abstract RiggerTransaction hide(String... tags); - - /** - * Add shared element to the last Op. - * - * @param ids View Id that is shared. - * - * @return Returns the same RiggerTransaction instance. - */ - abstract RiggerTransaction addSharedElements(int... ids); + /** * Schedules a commit of this transaction. The commit does diff --git a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransactionImpl.java b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransactionImpl.java index 3e20d5b..4865ed8 100644 --- a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransactionImpl.java +++ b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/RiggerTransactionImpl.java @@ -8,10 +8,12 @@ import android.support.v4.view.ViewCompat; import android.text.TextUtils; import android.view.View; + +import com.jkb.fragment.rigger.helper.SharedElement; import com.jkb.fragment.rigger.utils.Logger; + import java.lang.ref.WeakReference; import java.util.HashMap; -import java.util.HashSet; import java.util.LinkedList; import java.util.Map; @@ -20,259 +22,249 @@ */ final class RiggerTransactionImpl extends RiggerTransaction { - private FragmentManager mFragmentManager; - private IRigger mRigger; + private FragmentManager mFragmentManager; + private IRigger mRigger; - private static final int OP_NULL = 0; - private static final int OP_ADD = 1; - private static final int OP_REPLACE = 2; - private static final int OP_REMOVE = 3; - private static final int OP_HIDE = 4; - private static final int OP_SHOW = 5; - private static final int OP_DETACH = 6; - private static final int OP_ATTACH = 7; - - private static final class Op { - Op next; - Op prev; - int cmd; - Fragment fragment; - String fragmentTag; - int containerViewId; - int enterAnim; - int exitAnim; - HashSet sharedElements; - } + private static final int OP_NULL = 0; + private static final int OP_ADD = 1; + private static final int OP_REPLACE = 2; + private static final int OP_REMOVE = 3; + private static final int OP_HIDE = 4; + private static final int OP_SHOW = 5; + private static final int OP_DETACH = 6; + private static final int OP_ATTACH = 7; - private Op mHead; - private Op mTail; - private int mNumOp; - private int mEnterAnim; - private int mExitAnim; - private LinkedList mTransactions; - private Map> mAdded; + private static final class Op { + Op next; + Op prev; + int cmd; + Fragment fragment; + String fragmentTag; + int containerViewId; + int enterAnim; + int exitAnim; + SharedElement[] sharedElements; + } - RiggerTransactionImpl(IRigger rigger, FragmentManager mFragmentManager) { - this.mFragmentManager = mFragmentManager; - this.mRigger = rigger; - mAdded = new HashMap<>(); - } + private Op mHead; + private Op mTail; + private int mNumOp; + private int mEnterAnim; + private int mExitAnim; + private LinkedList mTransactions; + private Map> mAdded; - private void addOp(Op op) { - if (mHead == null) { - mHead = mTail = op; - } else { - op.prev = mTail; - mTail.next = op; - mTail = op; + RiggerTransactionImpl(IRigger rigger, FragmentManager mFragmentManager) { + this.mFragmentManager = mFragmentManager; + this.mRigger = rigger; + mAdded = new HashMap<>(); } - op.enterAnim = mEnterAnim; - op.exitAnim = mExitAnim; - mNumOp++; - } - @Override - Fragment find(String tag) { - if (TextUtils.isEmpty(tag)) return null; - Fragment fragment = mFragmentManager.findFragmentByTag(tag); - if (fragment == null && mAdded.containsKey(tag)) { - fragment = mAdded.get(tag).get(); - if (fragment == null) { - mAdded.remove(tag); - } + private void addOp(Op op) { + if (mHead == null) { + mHead = mTail = op; + } else { + op.prev = mTail; + mTail.next = op; + mTail = op; + } + op.enterAnim = mEnterAnim; + op.exitAnim = mExitAnim; + mNumOp++; } - return fragment; - } - @Override - RiggerTransaction add(@IdRes int containerViewId, Fragment fragment, @NonNull String tag) { - Op op = new Op(); - op.cmd = OP_ADD; - op.fragment = fragment; - op.fragmentTag = tag; - op.containerViewId = containerViewId; - addOp(op); - //add to list. - if (!mAdded.containsKey(tag)) { - mAdded.put(tag, new WeakReference<>(fragment)); + @Override + Fragment find(String tag) { + if (TextUtils.isEmpty(tag)) return null; + Fragment fragment = mFragmentManager.findFragmentByTag(tag); + if (fragment == null && mAdded.containsKey(tag)) { + fragment = mAdded.get(tag).get(); + if (fragment == null) { + mAdded.remove(tag); + } + } + return fragment; } - return this; - } - - @Override - RiggerTransaction replace(@IdRes int containerViewId, Fragment fragment, @NonNull String tag) { - Op op = new Op(); - op.cmd = OP_REPLACE; - op.fragment = fragment; - op.fragmentTag = tag; - op.containerViewId = containerViewId; - addOp(op); - return this; - } - @Override - RiggerTransaction remove(String... tags) { - if (tags == null || tags.length == 0) return this; - for (String tag : tags) { - Op op = new Op(); - op.cmd = OP_REMOVE; - op.fragmentTag = tag; - addOp(op); + @Override + RiggerTransaction add(@IdRes int containerViewId, Fragment fragment, @NonNull String tag) { + Op op = new Op(); + op.cmd = OP_ADD; + op.fragment = fragment; + op.fragmentTag = tag; + op.containerViewId = containerViewId; + addOp(op); + //add to list. + if (!mAdded.containsKey(tag)) { + mAdded.put(tag, new WeakReference<>(fragment)); + } + return this; } - return this; - } - @Override - RiggerTransaction removeAll() { - if (mAdded == null || mAdded.isEmpty()) return this; - for (String s : mAdded.keySet()) { - remove(s); + @Override + RiggerTransaction replace(@IdRes int containerViewId, Fragment fragment, @NonNull String tag) { + Op op = new Op(); + op.cmd = OP_ADD; + op.fragment = fragment; + op.fragmentTag = tag; + op.containerViewId = containerViewId; + addOp(op); + return this; } - return this; - } - @Override - RiggerTransaction show(String... tags) { - if (tags == null || tags.length == 0) return this; - for (String tag : tags) { - Op op = new Op(); - op.cmd = OP_SHOW; - op.fragmentTag = tag; - addOp(op); + @Override + RiggerTransaction replace(@IdRes int containerViewId, Fragment fragment, @NonNull String tag, SharedElement... elements) { + Op op = new Op(); + op.cmd = OP_REPLACE; + op.fragment = fragment; + op.fragmentTag = tag; + op.containerViewId = containerViewId; + op.sharedElements = elements; + addOp(op); + return this; } - return this; - } - @Override - RiggerTransaction hide(String... tags) { - if (tags == null || tags.length == 0) return this; - for (String tag : tags) { - Op op = new Op(); - op.cmd = OP_HIDE; - op.fragmentTag = tag; - addOp(op); + @Override + RiggerTransaction remove(String... tags) { + if (tags == null || tags.length == 0) return this; + for (String tag : tags) { + Op op = new Op(); + op.cmd = OP_REMOVE; + op.fragmentTag = tag; + addOp(op); + } + return this; } - return this; - } - - @Override - RiggerTransaction addSharedElements(int... ids) { - if (ids == null || ids.length == 0) return this; - if (mTail == null) return this; - for (int id : ids) { - if(mTail.sharedElements == null) { - mTail.sharedElements = new HashSet(); - } - mTail.sharedElements.add(id); + + @Override + RiggerTransaction removeAll() { + if (mAdded == null || mAdded.isEmpty()) return this; + for (String s : mAdded.keySet()) { + remove(s); + } + return this; } - return this; - } - @Override - void commit() { - //add the transaction to list. - if (mTransactions == null) { - mTransactions = new LinkedList<>(); + @Override + RiggerTransaction show(String... tags) { + if (tags == null || tags.length == 0) return this; + for (String tag : tags) { + Op op = new Op(); + op.cmd = OP_SHOW; + op.fragmentTag = tag; + addOp(op); + } + return this; } - if (mHead != null) { - Op op = mHead; - mTransactions.add(op); + + @Override + RiggerTransaction hide(String... tags) { + if (tags == null || tags.length == 0) return this; + for (String tag : tags) { + Op op = new Op(); + op.cmd = OP_HIDE; + op.fragmentTag = tag; + addOp(op); + } + return this; } - //clear the link list. - mHead = mTail = null; - mNumOp = 0; + @Override + void commit() { + //add the transaction to list. + if (mTransactions == null) { + mTransactions = new LinkedList<>(); + } + if (mHead != null) { + Op op = mHead; + mTransactions.add(op); + } - //initiating the real commit or wait to the next time. - executePendingTransaction(); - } + //clear the link list. + mHead = mTail = null; + mNumOp = 0; - @Override - void setCustomAnimations(int enter, int exit) { - mEnterAnim = enter; - mExitAnim = exit; - } + //initiating the real commit or wait to the next time. + executePendingTransaction(); + } - @Override - boolean isEmpty() { - return mNumOp == 0; - } + @Override + void setCustomAnimations(int enter, int exit) { + mEnterAnim = enter; + mExitAnim = exit; + } - /** - * executing the top transaction operation of link list if it's ready to commit; - */ - private void executePendingTransaction() { - if (!mRigger.isResumed()) { - Logger.w(this, "the rigger is not resumed,the commit will be delayed"); - return; + @Override + boolean isEmpty() { + return mNumOp == 0; } - Op op = mTransactions.poll(); - if (op == null) return; - FragmentTransaction ft = mFragmentManager.beginTransaction(); - while (op != null) { - Fragment f = find(op.fragmentTag); - - switch (op.cmd) { - case OP_ADD: { - if(op.sharedElements == null) { - ft.setCustomAnimations(op.enterAnim, op.exitAnim); - } - ft.add(op.containerViewId, op.fragment, op.fragmentTag); - } - break; - case OP_REPLACE: { - if (f == null) { - Logger.w(this, "Op:Remove.can not find fragment " + op.fragmentTag); - } else { - ft.replace(op.containerViewId, op.fragment, op.fragmentTag); - } - } - break; - case OP_REMOVE: { - if (f == null) { - Logger.w(this, "Op:Remove.can not find fragment " + op.fragmentTag); - } else { - ft.remove(f); - mAdded.remove(op.fragmentTag); - } - } - break; - case OP_SHOW: { - if(op.sharedElements == null) { - ft.setCustomAnimations(op.enterAnim, op.exitAnim); - } - if (f == null) { - Logger.w(this, "Op:Show.can not find fragment " + op.fragmentTag); - } else { - ft.show(f); - } + + /** + * executing the top transaction operation of link list if it's ready to commit; + */ + private void executePendingTransaction() { + if (!mRigger.isResumed()) { + Logger.w(this, "the rigger is not resumed,the commit will be delayed"); + return; } - break; - case OP_HIDE: { - if(op.sharedElements == null) { - ft.setCustomAnimations(op.enterAnim, op.exitAnim); - } - if (f == null) { - Logger.w(this, "Op:Hide.can not find fragment " + op.fragmentTag); - } else { - ft.hide(f); - } + Op op = mTransactions.poll(); + if (op == null) return; + FragmentTransaction ft = mFragmentManager.beginTransaction(); + while (op != null) { + Fragment f = find(op.fragmentTag); + + switch (op.cmd) { + case OP_ADD: { + ft.setCustomAnimations(mEnterAnim, mExitAnim); + ft.add(op.containerViewId, op.fragment, op.fragmentTag); + } + break; + case OP_REPLACE: { + processSharedElements(op, ft); + ft.replace(op.containerViewId, op.fragment, op.fragmentTag); + } + break; + case OP_REMOVE: { + if (f == null) { + Logger.w(this, "Op:Remove.can not find fragment " + op.fragmentTag); + } else { + ft.setCustomAnimations(mEnterAnim, mExitAnim); + ft.remove(f); + mAdded.remove(op.fragmentTag); + } + } + break; + case OP_SHOW: { + if (f == null) { + Logger.w(this, "Op:Show.can not find fragment " + op.fragmentTag); + } else { + ft.setCustomAnimations(mEnterAnim, mExitAnim); + ft.show(f); + } + } + break; + case OP_HIDE: { + if (f == null) { + Logger.w(this, "Op:Hide.can not find fragment " + op.fragmentTag); + } else { + ft.setCustomAnimations(mEnterAnim, mExitAnim); + ft.hide(f); + } + } + break; + } + + op = op.next; } - break; - } - - if(op.sharedElements != null && f != null && f.getView() != null) { - for(int viewId : op.sharedElements) { - View v = f.getView().findViewById(viewId); - if(v != null) { - ft.addSharedElement(v, ViewCompat.getTransitionName(v)); - } + ft.commit(); + executePendingTransaction(); + } + + private void processSharedElements(Op op, FragmentTransaction ft) { + if(op.sharedElements != null) { + for(SharedElement element : op.sharedElements) { + ft.addSharedElement(element.referenceView.get(), element.transactionName); + } } - } - - op = op.next; } - ft.commit(); - executePendingTransaction(); - } } diff --git a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java index 7a0a01d..4815347 100644 --- a/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java +++ b/fragment-rigger/src/main/java/com/jkb/fragment/rigger/rigger/_Rigger.java @@ -3,6 +3,7 @@ import static com.jkb.fragment.rigger.utils.RiggerConsts.METHOD_GET_CONTAINERVIEWID; import static com.jkb.fragment.rigger.utils.RiggerConsts.METHOD_ON_INTERRUPT_BACKPRESSED; +import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; import android.os.Bundle; @@ -22,13 +23,16 @@ import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.view.animation.AnimationSet; + import com.jkb.fragment.rigger.annotation.Puppet; import com.jkb.fragment.rigger.exception.AlreadyExistException; import com.jkb.fragment.rigger.exception.NotExistException; import com.jkb.fragment.rigger.exception.RiggerException; import com.jkb.fragment.rigger.exception.UnSupportException; import com.jkb.fragment.rigger.helper.FragmentStackManager; +import com.jkb.fragment.rigger.helper.SharedElement; import com.jkb.fragment.rigger.utils.Logger; + import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; @@ -38,610 +42,590 @@ * Rigger.Used to repeat different Rigger(Strategy pattern) * * @author JingYeoh - * Email me - * Github - * Blog + * Email me + * Github + * Blog * @since Nov 20,2017 */ abstract class _Rigger implements IRigger { - static final String BUNDLE_KEY_FOR_RESULT = "/bundle/key/for/result"; - static final String BUNDLE_KEY_FOR_RESULT_RECEIVE = BUNDLE_KEY_FOR_RESULT + 1; - static final String BUNDLE_KEY_FOR_RESULT_REQUEST_CODE = BUNDLE_KEY_FOR_RESULT + 2; - - static _Rigger create(@NonNull Object object) { - if (object instanceof AppCompatActivity) { - return new _ActivityRigger((AppCompatActivity) object); - } else if (object instanceof Fragment) { - return new _FragmentRigger((Fragment) object); - } else { - throw new RiggerException( - "Puppet Annotation class can only used on android.app.Activity or android.support.v4.app.Fragment"); - } - } - - private Object mPuppetTarget; - Context mContext; - //data - @IdRes - private int mContainerViewId; - private boolean mBindContainerView; - private boolean mCloseIfEmpty; - private int[] mSharedElements; - RiggerTransaction mRiggerTransaction; - FragmentStackManager mStackManager; - - _Rigger(Object puppetTarget) { - this.mPuppetTarget = puppetTarget; - //init containerViewId - Class clazz = mPuppetTarget.getClass(); - Puppet puppet = clazz.getAnnotation(Puppet.class); - mBindContainerView = puppet.bondContainerView(); - mCloseIfEmpty = puppet.closeIfEmpty(); - mContainerViewId = puppet.containerViewId(); - if (mContainerViewId <= 0) { - try { - Method containerViewId = clazz.getMethod(METHOD_GET_CONTAINERVIEWID); - mContainerViewId = (int) containerViewId.invoke(mPuppetTarget); - } catch (Exception ignored) { - } - } - //init helper - mStackManager = new FragmentStackManager(); - } - - /** - * Called when a fragment is first attached to its context. - * {@link #onCreate(Bundle)} will be called after this. - */ - void onAttach(Context context) { - } - - /** - * Called when the activity is starting.This is where most initialization should go. - * - * @param savedInstanceState If the activity/fragment is being re-created from - * a previous saved state, this is the state. - */ - void onCreate(Bundle savedInstanceState) { - if (savedInstanceState != null) { - mStackManager = FragmentStackManager.restoreStack(savedInstanceState); - } - } - - /** - * Called to have the fragment instantiate its user interface view. - * - * @param inflater The LayoutInflater object that can be used to inflate - * any views in the fragment, - * @param container If non-null, this is the parent view that the fragment's - * UI should be attached to. The fragment should not add the view itself, - * but this can be used to generate the LayoutParams of the view. - * @param savedInstanceState If non-null, this fragment is being re-constructed - * from a previous saved state as given here. - * - * @return Return the View for the fragment's UI, or null. - */ - View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) { - return null; - } - - /** - * Called immediately after {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)} - * has returned, but before any saved state has been restored in to the view. - * - * @param view The View returned by {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}. - * @param savedInstanceState If non-null, this fragment is being re-constructed - * from a previous saved state as given here. - */ - void onViewCreated(View view, @Nullable Bundle savedInstanceState) { - } - - /** - * This is the fragment-orientated version of {@link #onResume()} that you - * can override to perform operations in the Activity at the same point - * where its fragments are resumed. Be sure to always call through to - * the super-class. - */ - void onResumeFragments() { - } - - /** - * Called after {@link Activity#onRestoreInstanceState}, {@link Activity#onRestart}, or - * {@link #onPause}, for your activity to start interacting with the user. - * This is a good place to begin mAnimations - */ - abstract void onResume(); - - /** - * Called as part of the activity lifecycle when an activity is going into - * the background, but has not (yet) been killed. - */ - void onPause() { - } - - /** - * Called to retrieve per-instance state from an activity before being killed - * so that the state can be restored in {@link #onCreate} - * - * @param outState Bundle in which to place your saved state. - */ - abstract void onSaveInstanceState(Bundle outState); - - /** - * Perform any final cleanup before an activity is destroyed. - */ - abstract void onDestroy(); - - /** - * Called when the fragment is no longer attached to its activity. This - * is called after {@link #onDestroy()}. - */ - void onDetach() { - } - - /** - * Set a hint to the system about whether this fragment's UI is currently visible - * to the user. This hint defaults to true and is persistent across fragment instance - * state save and restore. - * - * @param isVisibleToUser true if this fragment's UI is currently visible to the user (default), - * false if it is not. - */ - void setUserVisibleHint(boolean isVisibleToUser) { - } - - /** - * Pass the touch back key event down. - */ - void dispatchBackPressed() { - Logger.d(mPuppetTarget, "dispatchBackPressed() method is called"); - boolean isInterrupt = onInterruptBackPressed(); - if (isInterrupt) { - onBackPressed(); - } else { - //call the fragment's dispatchBackPressed method that is not contained into the stack. - String[] fragmentsWithoutStack = mStackManager.getFragmentsWithoutStack(); - for (String tag : fragmentsWithoutStack) { - Fragment fragmentWithoutStack = mRiggerTransaction.find(tag); - if (fragmentWithoutStack == null) { - throwException(new NotExistException(tag)); + static final String BUNDLE_KEY_FOR_RESULT = "/bundle/key/for/result"; + static final String BUNDLE_KEY_FOR_RESULT_RECEIVE = BUNDLE_KEY_FOR_RESULT + 1; + static final String BUNDLE_KEY_FOR_RESULT_REQUEST_CODE = BUNDLE_KEY_FOR_RESULT + 2; + + static _Rigger create(@NonNull Object object) { + if (object instanceof AppCompatActivity) { + return new _ActivityRigger((AppCompatActivity) object); + } else if (object instanceof Fragment) { + return new _FragmentRigger((Fragment) object); + } else { + throw new RiggerException( + "Puppet Annotation class can only used on android.app.Activity or android.support.v4.app.Fragment"); + } + } + + private Object mPuppetTarget; + Context mContext; + //data + @IdRes + private int mContainerViewId; + private boolean mBindContainerView; + private boolean mCloseIfEmpty; + RiggerTransaction mRiggerTransaction; + FragmentStackManager mStackManager; + + _Rigger(Object puppetTarget) { + this.mPuppetTarget = puppetTarget; + //init containerViewId + Class clazz = mPuppetTarget.getClass(); + Puppet puppet = clazz.getAnnotation(Puppet.class); + mBindContainerView = puppet.bondContainerView(); + mCloseIfEmpty = puppet.closeIfEmpty(); + mContainerViewId = puppet.containerViewId(); + if (mContainerViewId <= 0) { + try { + Method containerViewId = clazz.getMethod(METHOD_GET_CONTAINERVIEWID); + mContainerViewId = (int) containerViewId.invoke(mPuppetTarget); + } catch (Exception ignored) { + } + } + //init helper + mStackManager = new FragmentStackManager(); + } + + /** + * Called when a fragment is first attached to its context. + * {@link #onCreate(Bundle)} will be called after this. + */ + void onAttach(Context context) { + } + + /** + * Called when the activity is starting.This is where most initialization should go. + * + * @param savedInstanceState If the activity/fragment is being re-created from + * a previous saved state, this is the state. + */ + void onCreate(Bundle savedInstanceState) { + if (savedInstanceState != null) { + mStackManager = FragmentStackManager.restoreStack(savedInstanceState); + } + } + + /** + * Called to have the fragment instantiate its user interface view. + * + * @param inflater The LayoutInflater object that can be used to inflate + * any views in the fragment, + * @param container If non-null, this is the parent view that the fragment's + * UI should be attached to. The fragment should not add the view itself, + * but this can be used to generate the LayoutParams of the view. + * @param savedInstanceState If non-null, this fragment is being re-constructed + * from a previous saved state as given here. + * @return Return the View for the fragment's UI, or null. + */ + View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { + return null; + } + + /** + * Called immediately after {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)} + * has returned, but before any saved state has been restored in to the view. + * + * @param view The View returned by {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}. + * @param savedInstanceState If non-null, this fragment is being re-constructed + * from a previous saved state as given here. + */ + void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + } + + /** + * This is the fragment-orientated version of {@link #onResume()} that you + * can override to perform operations in the Activity at the same point + * where its fragments are resumed. Be sure to always call through to + * the super-class. + */ + void onResumeFragments() { + } + + /** + * Called after {@link Activity#onRestoreInstanceState}, {@link Activity#onRestart}, or + * {@link #onPause}, for your activity to start interacting with the user. + * This is a good place to begin mAnimations + */ + abstract void onResume(); + + /** + * Called as part of the activity lifecycle when an activity is going into + * the background, but has not (yet) been killed. + */ + void onPause() { + } + + /** + * Called to retrieve per-instance state from an activity before being killed + * so that the state can be restored in {@link #onCreate} + * + * @param outState Bundle in which to place your saved state. + */ + abstract void onSaveInstanceState(Bundle outState); + + /** + * Perform any final cleanup before an activity is destroyed. + */ + abstract void onDestroy(); + + /** + * Called when the fragment is no longer attached to its activity. This + * is called after {@link #onDestroy()}. + */ + void onDetach() { + } + + /** + * Set a hint to the system about whether this fragment's UI is currently visible + * to the user. This hint defaults to true and is persistent across fragment instance + * state save and restore. + * + * @param isVisibleToUser true if this fragment's UI is currently visible to the user (default), + * false if it is not. + */ + void setUserVisibleHint(boolean isVisibleToUser) { + } + + /** + * Pass the touch back key event down. + */ + void dispatchBackPressed() { + Logger.d(mPuppetTarget, "dispatchBackPressed() method is called"); + boolean isInterrupt = onInterruptBackPressed(); + if (isInterrupt) { + onBackPressed(); + } else { + //call the fragment's dispatchBackPressed method that is not contained into the stack. + String[] fragmentsWithoutStack = mStackManager.getFragmentsWithoutStack(); + for (String tag : fragmentsWithoutStack) { + Fragment fragmentWithoutStack = mRiggerTransaction.find(tag); + if (fragmentWithoutStack == null) { + throwException(new NotExistException(tag)); + } + ((_Rigger) Rigger.getRigger(fragmentWithoutStack)).dispatchBackPressed(); + } + + String topFragmentTag = mStackManager.peek(); + if (!TextUtils.isEmpty(topFragmentTag)) { + Fragment topFragment = mRiggerTransaction.find(topFragmentTag); + if (topFragment == null) { + throwException(new NotExistException(topFragmentTag)); + } + //call the top fragment's onBackPressed method. + ((_Rigger) Rigger.getRigger(topFragment)).dispatchBackPressed(); + } + + // if this host contain non fragments , call onRiggerBackPressed method. + if (fragmentsWithoutStack.length == 0 && TextUtils.isEmpty(topFragmentTag)) { + onBackPressed(); + } + } + } + + /** + * If the puppet contain onInterruptBackPressed method , then interrupt the {@link #onBackPressed()} method. + */ + private boolean onInterruptBackPressed() { + Logger.d(mPuppetTarget, "onInterruptBackPressed() method is called"); + Class clazz = mPuppetTarget.getClass(); + try { + Method onBackPressed = clazz.getMethod(METHOD_ON_INTERRUPT_BACKPRESSED); + return (boolean) onBackPressed.invoke(mPuppetTarget); + } catch (Exception e) { + return false; + } + } + + @Override + public void onBackPressed() { + Logger.d(mPuppetTarget, "onRiggerBackPressed() method is called"); + String topFragmentTag = mStackManager.peek(); + if (TextUtils.isEmpty(topFragmentTag)) { + if (mCloseIfEmpty) { + Logger.d(mPuppetTarget, "Rigger was closed because of empty top"); + close(); + } + } else { + //call the top fragment's onBackPressed method. + Fragment topFragment = mRiggerTransaction.find(topFragmentTag); + if (topFragment == null) { + throwException(new NotExistException(topFragmentTag)); + } + ((_Rigger) Rigger.getRigger(topFragment)).dispatchBackPressed(); + } + } + + @Override + public Fragment findFragmentByTag(String tag) { + if (!mStackManager.contain(tag)) return null; + return mRiggerTransaction.find(tag); + } + + @Override + public void addFragment(@IdRes int containerViewId, Fragment... fragments) { + if (fragments == null) { + Logger.w(mPuppetTarget, "the fragments to be added is null."); + return; + } + for (Fragment fragment : fragments) { + String fragmentTAG = Rigger.getRigger(fragment).getFragmentTAG(); + if (mStackManager.add(fragmentTAG, containerViewId)) { + addFragmentWithAnim(fragment, containerViewId); + mRiggerTransaction.hide(fragmentTAG); + } else { + throwException(new AlreadyExistException(fragmentTAG)); + } + fragment.setUserVisibleHint(false); + } + mRiggerTransaction.commit(); + } + + @SuppressLint("ResourceType") + @Override + public void startFragment(@NonNull Fragment fragment) { + String fragmentTAG = Rigger.getRigger(fragment).getFragmentTAG(); + if (!mStackManager.push(fragmentTAG, mContainerViewId)) { + throwException(new AlreadyExistException(fragmentTAG)); + } + if (getContainerViewId() <= 0) { + throwException(new UnSupportException("ContainerViewId must be effective in class " + mPuppetTarget.getClass())); } - ((_Rigger) Rigger.getRigger(fragmentWithoutStack)).dispatchBackPressed(); - } + addFragmentWithAnim(fragment, mContainerViewId); + mRiggerTransaction.hide(getVisibleFragmentTags(getContainerViewId())); + mRiggerTransaction.show(fragmentTAG).commit(); + } - String topFragmentTag = mStackManager.peek(); - if (!TextUtils.isEmpty(topFragmentTag)) { + @Override + public void startFragmentForResult(Object receive, @NonNull Fragment fragment, int requestCode) { + Bundle arguments = fragment.getArguments(); + if (arguments == null) arguments = new Bundle(); + Bundle receiveArgs = new Bundle(); + if (receive != null) { + receiveArgs.putString(BUNDLE_KEY_FOR_RESULT_RECEIVE, Rigger.getRigger(receive).getFragmentTAG()); + } + receiveArgs.putInt(BUNDLE_KEY_FOR_RESULT_REQUEST_CODE, requestCode); + arguments.putParcelable(BUNDLE_KEY_FOR_RESULT, receiveArgs); + fragment.setArguments(arguments); + startFragment(fragment); + } + + @Override + public void startFragmentForResult(@NonNull Fragment fragment, int requestCode) { + startFragmentForResult(null, fragment, requestCode); + } + + @Override + public void startPopFragment() { + startPopFragment(null); + } + + /** + * show pop fragment and start animation. + */ + void startPopFragment(Animation animation) { + String topFragmentTag = mStackManager.peek(); + mRiggerTransaction.hide(getVisibleFragmentTags(getContainerViewId())); Fragment topFragment = mRiggerTransaction.find(topFragmentTag); - if (topFragment == null) { - throwException(new NotExistException(topFragmentTag)); + if (!TextUtils.isEmpty(topFragmentTag) && topFragment != null) { + if (animation != null) { + topFragment.getView().startAnimation(animation); + //cancel the default animation and use the custom animation. + } + mRiggerTransaction.setCustomAnimations(0, 0); + mRiggerTransaction.show(topFragmentTag); } - //call the top fragment's onBackPressed method. - ((_Rigger) Rigger.getRigger(topFragment)).dispatchBackPressed(); - } - - // if this host contain non fragments , call onRiggerBackPressed method. - if (fragmentsWithoutStack.length == 0 && TextUtils.isEmpty(topFragmentTag)) { - onBackPressed(); - } - } - } - - /** - * If the puppet contain onInterruptBackPressed method , then interrupt the {@link #onBackPressed()} method. - */ - private boolean onInterruptBackPressed() { - Logger.d(mPuppetTarget, "onInterruptBackPressed() method is called"); - Class clazz = mPuppetTarget.getClass(); - try { - Method onBackPressed = clazz.getMethod(METHOD_ON_INTERRUPT_BACKPRESSED); - return (boolean) onBackPressed.invoke(mPuppetTarget); - } catch (Exception e) { - return false; - } - } - - @Override - public void onBackPressed() { - Logger.d(mPuppetTarget, "onRiggerBackPressed() method is called"); - String topFragmentTag = mStackManager.peek(); - if (TextUtils.isEmpty(topFragmentTag)) { - if(mCloseIfEmpty) { - Logger.d(mPuppetTarget, "Rigger was closed because of empty top"); - close(); - } - } else { - //call the top fragment's onBackPressed method. - Fragment topFragment = mRiggerTransaction.find(topFragmentTag); - if (topFragment == null) { - throwException(new NotExistException(topFragmentTag)); - } - ((_Rigger) Rigger.getRigger(topFragment)).dispatchBackPressed(); - } - } - - @Override - public Fragment findFragmentByTag(String tag) { - if (!mStackManager.contain(tag)) return null; - return mRiggerTransaction.find(tag); - } - - @Override - public void addSharedElements(int... ids) { - mSharedElements = null; - mSharedElements = ids; - } - - @Override - public void addFragment(@IdRes int containerViewId, Fragment... fragments) { - if (fragments == null) { - Logger.w(mPuppetTarget, "the fragments to be added is null."); - return; - } - for (Fragment fragment : fragments) { - String fragmentTAG = Rigger.getRigger(fragment).getFragmentTAG(); - if (mStackManager.add(fragmentTAG, containerViewId)) { - addFragmentWithAnim(fragment, containerViewId); - if(mSharedElements != null) { - mRiggerTransaction.addSharedElements(mSharedElements); - mSharedElements = null; + mRiggerTransaction.commit(); + } + + @Override + public void showFragment(@NonNull Fragment fragment, @IdRes int containerViewId) { + showFragment(fragment, containerViewId, false); + } + + @Override + public void showFragment(@NonNull Fragment fragment, @IdRes int containerViewId, boolean showRepeatAnim) { + String fragmentTAG = Rigger.getRigger(fragment).getFragmentTAG(); + if (mStackManager.add(fragmentTAG, containerViewId)) { + addFragmentWithAnim(fragment, containerViewId); } + String[] fragmentTags = mStackManager.getFragmentTags(containerViewId); + for (String tag : fragmentTags) { + Fragment hideFrag = mRiggerTransaction.find(tag); + if (hideFrag == null) continue; + hideFrag.setUserVisibleHint(false); + } + fragment.setUserVisibleHint(true); + boolean hidden = fragment.isHidden(); + boolean added = fragment.isAdded(); + if (!added || hidden || showRepeatAnim) { + mRiggerTransaction.hide(getVisibleFragmentTags(containerViewId)); + showFragmentWithAnim(fragment); + } + mRiggerTransaction.commit(); + } + + @Override + public void showFragment(@NonNull String tag) { + showFragment(tag, false); + } + + @Override + public void showFragment(@NonNull String tag, boolean showRepeatAnim) { + int containerViewId = mStackManager.getContainer(tag); + if (containerViewId == 0) { + throwException(new NotExistException(tag)); + } + showFragment(mRiggerTransaction.find(tag), containerViewId, showRepeatAnim); + } + + @Override + public void hideFragment(@NonNull Fragment fragment) { + _FragmentRigger rigger = (_FragmentRigger) Rigger.getRigger(fragment); + String fragmentTAG = rigger.getFragmentTAG(); + mRiggerTransaction.setCustomAnimations(rigger.mPopEnterAnim, rigger.mExitAnim); mRiggerTransaction.hide(fragmentTAG); - } else { - throwException(new AlreadyExistException(fragmentTAG)); - } - fragment.setUserVisibleHint(false); - } - mRiggerTransaction.commit(); - } - - @Override - public void startFragment(@NonNull Fragment fragment) { - String fragmentTAG = Rigger.getRigger(fragment).getFragmentTAG(); - if (!mStackManager.push(fragmentTAG, mContainerViewId)) { - throwException(new AlreadyExistException(fragmentTAG)); - } - if (getContainerViewId() <= 0) { - throwException(new UnSupportException("ContainerViewId must be effective in class " + mPuppetTarget.getClass())); - } - addFragmentWithAnim(fragment, mContainerViewId); - if(mSharedElements != null) { - mRiggerTransaction.addSharedElements(mSharedElements); - mSharedElements = null; - } - mRiggerTransaction.hide(getVisibleFragmentTags(getContainerViewId())); - mRiggerTransaction.show(fragmentTAG).commit(); - } - - @Override - public void startFragmentForResult(Object receive, @NonNull Fragment fragment, int requestCode) { - Bundle arguments = fragment.getArguments(); - if (arguments == null) arguments = new Bundle(); - Bundle receiveArgs = new Bundle(); - if (receive != null) { - receiveArgs.putString(BUNDLE_KEY_FOR_RESULT_RECEIVE, Rigger.getRigger(receive).getFragmentTAG()); - } - receiveArgs.putInt(BUNDLE_KEY_FOR_RESULT_REQUEST_CODE, requestCode); - arguments.putParcelable(BUNDLE_KEY_FOR_RESULT, receiveArgs); - fragment.setArguments(arguments); - startFragment(fragment); - } - - @Override - public void startFragmentForResult(@NonNull Fragment fragment, int requestCode) { - startFragmentForResult(null, fragment, requestCode); - } - - @Override - public void startPopFragment() { - startPopFragment(null); - } - - /** - * show pop fragment and start animation. - */ - void startPopFragment(Animation animation) { - String topFragmentTag = mStackManager.peek(); - mRiggerTransaction.hide(getVisibleFragmentTags(getContainerViewId())); - Fragment topFragment = mRiggerTransaction.find(topFragmentTag); - if (!TextUtils.isEmpty(topFragmentTag) && topFragment != null) { - if (animation != null) { - topFragment.getView().startAnimation(animation); - //cancel the default animation and use the custom animation. - } - mRiggerTransaction.setCustomAnimations(0, 0); - mRiggerTransaction.show(topFragmentTag); - } - if(mSharedElements != null) { - mRiggerTransaction.addSharedElements(mSharedElements); - mSharedElements = null; - } - mRiggerTransaction.commit(); - } - - @Override - public void showFragment(@NonNull Fragment fragment, @IdRes int containerViewId) { - showFragment(fragment, containerViewId, false); - } - - @Override - public void showFragment(@NonNull Fragment fragment, @IdRes int containerViewId, boolean showRepeatAnim) { - String fragmentTAG = Rigger.getRigger(fragment).getFragmentTAG(); - if (mStackManager.add(fragmentTAG, containerViewId)) { - addFragmentWithAnim(fragment, containerViewId); - if(mSharedElements != null) { - mRiggerTransaction.addSharedElements(mSharedElements); - mSharedElements = null; - } - } - String[] fragmentTags = mStackManager.getFragmentTags(containerViewId); - for (String tag : fragmentTags) { - Fragment hideFrag = mRiggerTransaction.find(tag); - if (hideFrag == null) continue; - hideFrag.setUserVisibleHint(false); - } - fragment.setUserVisibleHint(true); - boolean hidden = fragment.isHidden(); - boolean added = fragment.isAdded(); - if (!added || hidden || showRepeatAnim) { - mRiggerTransaction.hide(getVisibleFragmentTags(containerViewId)); - showFragmentWithAnim(fragment); - } - mRiggerTransaction.commit(); - } - - @Override - public void showFragment(@NonNull String tag) { - showFragment(tag, false); - } - - @Override - public void showFragment(@NonNull String tag, boolean showRepeatAnim) { - int containerViewId = mStackManager.getContainer(tag); - if (containerViewId == 0) { - throwException(new NotExistException(tag)); - } - showFragment(mRiggerTransaction.find(tag), containerViewId, showRepeatAnim); - } - - @Override - public void hideFragment(@NonNull Fragment fragment) { - _FragmentRigger rigger = (_FragmentRigger) Rigger.getRigger(fragment); - String fragmentTAG = rigger.getFragmentTAG(); - mRiggerTransaction.setCustomAnimations(rigger.mPopEnterAnim, rigger.mExitAnim); - mRiggerTransaction.hide(fragmentTAG); - if(mSharedElements != null) { - mRiggerTransaction.addSharedElements(mSharedElements); - mSharedElements = null; - } - mRiggerTransaction.commit(); - } - - @Override - public void hideFragment(@NonNull String tag) { - if (!mStackManager.contain(tag)) { - throwException(new NotExistException(tag)); - } - hideFragment(mRiggerTransaction.find(tag)); - } - - @Override - public void replaceFragment(@NonNull Fragment fragment, @IdRes int containerViewId) { - String fragmentTAG = Rigger.getRigger(fragment).getFragmentTAG(); - mRiggerTransaction.replace(containerViewId, fragment, fragmentTAG); - if(mSharedElements != null) { - mRiggerTransaction.addSharedElements(mSharedElements); - mSharedElements = null; - } - mRiggerTransaction.commit(); - mStackManager.remove(containerViewId); - mStackManager.add(fragmentTAG, containerViewId); - } - - @Override - public void close(@NonNull Fragment fragment) { - String fragmentTAG = Rigger.getRigger(fragment).getFragmentTAG(); - if (!mStackManager.remove(fragmentTAG)) { - throwException(new NotExistException(fragmentTAG)); - } - //if the stack is empty and the puppet is bond container view.then close the fragment. - if (isBondContainerView() && mStackManager.getFragmentStack().empty()) { - close(); - } else { - //if the puppet is not bond container,then remove the fragment onto the container. - //and show the Fragment's content view. - mRiggerTransaction.remove(fragmentTAG); - if(mSharedElements != null) { - mRiggerTransaction.addSharedElements(mSharedElements); - mSharedElements = null; - } - mRiggerTransaction.commit(); - } - } - - @Override - public int getContainerViewId() { - return mContainerViewId; - } - - @Override - public boolean isBondContainerView() { - return mBindContainerView; - } - - @Override - public boolean isLazyLoading() { - return false; - } - - @Override - final public Stack getFragmentStack() { - if (mStackManager == null || mStackManager.getFragmentStack() == null) return new Stack<>(); - return (Stack) mStackManager.getFragmentStack().clone(); - } - - @Override - public void printStack() { - StringBuilder sb = new StringBuilder(); - sb.append(getFragmentTAG()); - Stack stack = mStackManager.getFragmentStack(); - printStack(sb, this, stack, 1); - Log.i("Rigger", sb.toString()); - } - - private void printStack(StringBuilder sb, _Rigger rigger, Stack stack, int level) { - if (stack == null || stack.empty()) return; - for (int p = stack.size() - 1; p >= 0; p--) { - String tag = stack.get(p); - sb.append("\n"); - sb.append("┃"); - if (level != 1) { - for (int i = 0; i < level; i++) { - sb.append(" ").append(" ").append(" ").append(" "); + mRiggerTransaction.commit(); + } + + @Override + public void hideFragment(@NonNull String tag) { + if (!mStackManager.contain(tag)) { + throwException(new NotExistException(tag)); } - } - for (int i = 0; i < level; i++) { - sb.append("\t"); - } - Fragment fragment = rigger.mRiggerTransaction.find(tag); - _Rigger childRigger = (_Rigger) Rigger.getRigger(fragment); - Stack childStack = childRigger.getFragmentStack(); - if (p > 0 && childStack.isEmpty()) { - sb.append("┠"); - } else { - sb.append("┖"); - } - sb.append("————"); - sb.append(tag); - printStack(sb, childRigger, childStack, level + 1); - } - } - - /** - * Add a fragment and set the fragment's mAnimations - */ - private void addFragmentWithAnim(Fragment fragment, int containerViewId) { - _FragmentRigger rigger = (_FragmentRigger) Rigger.getRigger(fragment); - mRiggerTransaction.setCustomAnimations(rigger.mEnterAnim, rigger.mPopExitAnim); - mRiggerTransaction.add(containerViewId, fragment, rigger.getFragmentTAG()); - } - - /** - * Show a fragment and set the fragment's mAnimations - */ - private void showFragmentWithAnim(Fragment fragment) { - _FragmentRigger rigger = (_FragmentRigger) Rigger.getRigger(fragment); - mRiggerTransaction.setCustomAnimations(rigger.mPopEnterAnim, rigger.mExitAnim); - mRiggerTransaction.show(rigger.getFragmentTAG()); - } - - /** - * Throw the exception. - */ - void throwException(RiggerException e) { - throw e; - } - - /** - * Return fragments tag which the fragment's view is visible and is add onto the container view. - * - * @param containerViewId The container view's id to be found. - * - * @return The fragment tags. - */ - private String[] getVisibleFragmentTags(@IdRes int containerViewId) { - List result = new ArrayList<>(); - String[] fragmentTags = mStackManager.getFragmentTags(containerViewId); - if (fragmentTags == null) return result.toArray(new String[result.size()]); - for (String tag : fragmentTags) { - Fragment fragment = mRiggerTransaction.find(tag); - if (fragment != null && !fragment.isHidden() && - fragment.getView() != null && fragment.getView().getVisibility() == View.VISIBLE) { - result.add(tag); - } - } - return result.toArray(new String[result.size()]); - } - - /** - * Sets the to be animated view on hardware layer during the animation.Note - * that calling this will replace any existing animation listener on the animation - * with a new one, as animations do not support more than one listeners. Therefore, - * animations that already have listeners should do the layer change operations - * in their existing listeners, rather than calling this function. - */ - void setHWLayerAnimListenerIfAlpha(View v, Animation anim) { - if (v == null || anim == null) { - return; - } - if (shouldRunOnHWLayer(v, anim)) { - anim.setAnimationListener(new AnimateOnHWLayerIfNeededListener(v, anim)); - } - } - - static boolean shouldRunOnHWLayer(View v, Animation anim) { - return ViewCompat.getLayerType(v) == ViewCompat.LAYER_TYPE_NONE - && ViewCompat.hasOverlappingRendering(v) - && modifiesAlpha(anim); - } - - static boolean modifiesAlpha(Animation anim) { - if (anim instanceof AlphaAnimation) { - return true; - } else if (anim instanceof AnimationSet) { - List anims = ((AnimationSet) anim).getAnimations(); - for (int i = 0; i < anims.size(); i++) { - if (anims.get(i) instanceof AlphaAnimation) { - return true; + hideFragment(mRiggerTransaction.find(tag)); + } + + @Override + public void replaceFragment(@NonNull Fragment fragment, @IdRes int containerViewId) { + String fragmentTAG = Rigger.getRigger(fragment).getFragmentTAG(); + addFragmentWithAnim(fragment, containerViewId); + mRiggerTransaction.remove(mStackManager.getFragmentTags(containerViewId)) + .show(fragmentTAG) + .commit(); + mStackManager.remove(containerViewId); + mStackManager.add(fragmentTAG, containerViewId); + } + + @Override + public void replaceFragment(@NonNull Fragment fragment, @IdRes int containerViewId, SharedElement... elements) { + String fragmentTAG = Rigger.getRigger(fragment).getFragmentTAG(); + if (!mStackManager.push(fragmentTAG, mContainerViewId)) { + throwException(new AlreadyExistException(fragmentTAG)); } - } + if (containerViewId <= 0) { + throwException(new UnSupportException("ContainerViewId must be effective in class " + mPuppetTarget.getClass())); + } + mRiggerTransaction.replace(containerViewId, fragment, fragmentTAG, elements); + mRiggerTransaction.hide(getVisibleFragmentTags(getContainerViewId())); + mRiggerTransaction.show(fragmentTAG).commit(); } - return false; - } - static class AnimateOnHWLayerIfNeededListener implements AnimationListener { + @Override + public void close(@NonNull Fragment fragment) { + String fragmentTAG = Rigger.getRigger(fragment).getFragmentTAG(); + if (!mStackManager.remove(fragmentTAG)) { + throwException(new NotExistException(fragmentTAG)); + } + //if the stack is empty and the puppet is bond container view.then close the fragment. + if (isBondContainerView() && mStackManager.getFragmentStack().empty()) { + close(); + } else { + //if the puppet is not bond container,then remove the fragment onto the container. + //and show the Fragment's content view. + mRiggerTransaction.remove(fragmentTAG); + mRiggerTransaction.commit(); + } + } - private boolean mShouldRunOnHWLayer = false; - private View mView; + @Override + public int getContainerViewId() { + return mContainerViewId; + } - AnimateOnHWLayerIfNeededListener(final View v, Animation anim) { - if (v == null || anim == null) { - return; - } - mView = v; + @Override + public boolean isBondContainerView() { + return mBindContainerView; } @Override - @CallSuper - public void onAnimationStart(Animation animation) { - mShouldRunOnHWLayer = shouldRunOnHWLayer(mView, animation); - if (mShouldRunOnHWLayer) { - mView.post(new Runnable() { - @Override - public void run() { - ViewCompat.setLayerType(mView, ViewCompat.LAYER_TYPE_HARDWARE, null); - } - }); - } + public boolean isLazyLoading() { + return false; } @Override - @CallSuper - public void onAnimationEnd(Animation animation) { - if (mShouldRunOnHWLayer) { - mView.post(new Runnable() { - @Override - public void run() { - ViewCompat.setLayerType(mView, ViewCompat.LAYER_TYPE_NONE, null); - } - }); - } + final public Stack getFragmentStack() { + if (mStackManager == null || mStackManager.getFragmentStack() == null) return new Stack<>(); + return (Stack) mStackManager.getFragmentStack().clone(); } @Override - public void onAnimationRepeat(Animation animation) { + public void printStack() { + StringBuilder sb = new StringBuilder(); + sb.append(getFragmentTAG()); + Stack stack = mStackManager.getFragmentStack(); + printStack(sb, this, stack, 1); + Log.i("Rigger", sb.toString()); + } + + private void printStack(StringBuilder sb, _Rigger rigger, Stack stack, int level) { + if (stack == null || stack.empty()) return; + for (int p = stack.size() - 1; p >= 0; p--) { + String tag = stack.get(p); + sb.append("\n"); + sb.append("┃"); + if (level != 1) { + for (int i = 0; i < level; i++) { + sb.append(" ").append(" ").append(" ").append(" "); + } + } + for (int i = 0; i < level; i++) { + sb.append("\t"); + } + Fragment fragment = rigger.mRiggerTransaction.find(tag); + _Rigger childRigger = (_Rigger) Rigger.getRigger(fragment); + Stack childStack = childRigger.getFragmentStack(); + if (p > 0 && childStack.isEmpty()) { + sb.append("┠"); + } else { + sb.append("┖"); + } + sb.append("————"); + sb.append(tag); + printStack(sb, childRigger, childStack, level + 1); + } + } + + /** + * Add a fragment and set the fragment's mAnimations + */ + private void addFragmentWithAnim(Fragment fragment, int containerViewId) { + _FragmentRigger rigger = (_FragmentRigger) Rigger.getRigger(fragment); + mRiggerTransaction.setCustomAnimations(rigger.mEnterAnim, rigger.mPopExitAnim); + mRiggerTransaction.add(containerViewId, fragment, rigger.getFragmentTAG()); + } + + /** + * Show a fragment and set the fragment's mAnimations + */ + private void showFragmentWithAnim(Fragment fragment) { + _FragmentRigger rigger = (_FragmentRigger) Rigger.getRigger(fragment); + mRiggerTransaction.setCustomAnimations(rigger.mPopEnterAnim, rigger.mExitAnim); + mRiggerTransaction.show(rigger.getFragmentTAG()); + } + + /** + * Throw the exception. + */ + void throwException(RiggerException e) { + throw e; + } + + /** + * Return fragments tag which the fragment's view is visible and is add onto the container view. + * + * @param containerViewId The container view's id to be found. + * @return The fragment tags. + */ + private String[] getVisibleFragmentTags(@IdRes int containerViewId) { + List result = new ArrayList<>(); + String[] fragmentTags = mStackManager.getFragmentTags(containerViewId); + if (fragmentTags == null) return result.toArray(new String[result.size()]); + for (String tag : fragmentTags) { + Fragment fragment = mRiggerTransaction.find(tag); + if (fragment != null && !fragment.isHidden() && + fragment.getView() != null && fragment.getView().getVisibility() == View.VISIBLE) { + result.add(tag); + } + } + return result.toArray(new String[result.size()]); + } + + /** + * Sets the to be animated view on hardware layer during the animation.Note + * that calling this will replace any existing animation listener on the animation + * with a new one, as animations do not support more than one listeners. Therefore, + * animations that already have listeners should do the layer change operations + * in their existing listeners, rather than calling this function. + */ + void setHWLayerAnimListenerIfAlpha(View v, Animation anim) { + if (v == null || anim == null) { + return; + } + if (shouldRunOnHWLayer(v, anim)) { + anim.setAnimationListener(new AnimateOnHWLayerIfNeededListener(v, anim)); + } + } + + static boolean shouldRunOnHWLayer(View v, Animation anim) { + return ViewCompat.getLayerType(v) == ViewCompat.LAYER_TYPE_NONE + && ViewCompat.hasOverlappingRendering(v) + && modifiesAlpha(anim); + } + + static boolean modifiesAlpha(Animation anim) { + if (anim instanceof AlphaAnimation) { + return true; + } else if (anim instanceof AnimationSet) { + List anims = ((AnimationSet) anim).getAnimations(); + for (int i = 0; i < anims.size(); i++) { + if (anims.get(i) instanceof AlphaAnimation) { + return true; + } + } + } + return false; + } + + static class AnimateOnHWLayerIfNeededListener implements AnimationListener { + + private boolean mShouldRunOnHWLayer = false; + private View mView; + + AnimateOnHWLayerIfNeededListener(final View v, Animation anim) { + if (v == null || anim == null) { + return; + } + mView = v; + } + + @Override + @CallSuper + public void onAnimationStart(Animation animation) { + mShouldRunOnHWLayer = shouldRunOnHWLayer(mView, animation); + if (mShouldRunOnHWLayer) { + mView.post(new Runnable() { + @Override + public void run() { + mView.setLayerType(View.LAYER_TYPE_NONE, null); + } + }); + } + } + + @Override + @CallSuper + public void onAnimationEnd(Animation animation) { + if (mShouldRunOnHWLayer) { + mView.post(new Runnable() { + @Override + public void run() { + mView.setLayerType(View.LAYER_TYPE_NONE, null); + } + }); + } + } + + @Override + public void onAnimationRepeat(Animation animation) { + } } - } } diff --git a/fragment-rigger/src/main/java/com/jkb/fragment/swiper/widget/SwiperLayout.java b/fragment-rigger/src/main/java/com/jkb/fragment/swiper/widget/SwiperLayout.java index ee423f6..0d8d6f6 100644 --- a/fragment-rigger/src/main/java/com/jkb/fragment/swiper/widget/SwiperLayout.java +++ b/fragment-rigger/src/main/java/com/jkb/fragment/swiper/widget/SwiperLayout.java @@ -9,7 +9,9 @@ import android.util.AttributeSet; import android.view.MotionEvent; import android.widget.FrameLayout; -import com.jkb.fragment.rigger.R; + +import com.jkb.fragment.R; + /** * Support {@link android.app.Activity}/{@link android.support.v4.app.Fragment} exit by finger swipe edge. From 009499df658e5ce8b5c45678e565532baa518b6e Mon Sep 17 00:00:00 2001 From: Nguyen Dac Nam Date: Sat, 28 Jul 2018 00:17:03 +0700 Subject: [PATCH 15/15] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 85fa6aa..1c28f54 100644 --- a/README.md +++ b/README.md @@ -61,9 +61,9 @@ You can use this `FragmentRigger` with one line annotation. - [x] **Option to configure fragment tag** - [x] **Add `onBackPressed` method support for the fragment that is not added into stack** - [ ] **Option to configure fragment launch mode** -- [ ] **Fragment shared elements transition animations** +- [x] **Fragment shared elements transition animations** - [ ] **Swipe edge to exit Fragment/Activity** -- [ ] **Support DialogFragment** +- [ ] **Support DialogFragment** [WIP] ### Problem solved * ~~Fragment view overlapping~~