diff --git a/arch/src/main/java/com/qmuiteam/qmui/arch/InnerBaseActivity.java b/arch/src/main/java/com/qmuiteam/qmui/arch/InnerBaseActivity.java index 5e21bd0d..6a1de06b 100644 --- a/arch/src/main/java/com/qmuiteam/qmui/arch/InnerBaseActivity.java +++ b/arch/src/main/java/com/qmuiteam/qmui/arch/InnerBaseActivity.java @@ -32,6 +32,7 @@ import com.qmuiteam.qmui.QMUIConfig; import com.qmuiteam.qmui.arch.annotation.LatestVisitRecord; import com.qmuiteam.qmui.arch.record.LatestVisitArgumentCollector; import com.qmuiteam.qmui.arch.record.RecordArgumentEditor; +import com.qmuiteam.qmui.arch.scheme.QMUISchemeHandler; import com.qmuiteam.qmui.skin.QMUISkinLayoutInflaterFactory; import com.qmuiteam.qmui.skin.QMUISkinManager; @@ -159,6 +160,10 @@ class InnerBaseActivity extends AppCompatActivity implements LatestVisitArgument } } + public final boolean isStartedByScheme() { + return getIntent().getBooleanExtra(QMUISchemeHandler.ARG_FROM_SCHEME, false); + } + protected boolean useQMUISkinLayoutInflaterFactory() { return true; } diff --git a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java index 0fa4057b..74042be5 100644 --- a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java +++ b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java @@ -61,6 +61,7 @@ import com.qmuiteam.qmui.arch.effect.QMUIFragmentEffectRegistry; import com.qmuiteam.qmui.arch.effect.QMUIFragmentResultEffectHandler; import com.qmuiteam.qmui.arch.record.LatestVisitArgumentCollector; import com.qmuiteam.qmui.arch.record.RecordArgumentEditor; +import com.qmuiteam.qmui.arch.scheme.QMUISchemeHandler; import com.qmuiteam.qmui.util.QMUIDisplayHelper; import com.qmuiteam.qmui.util.QMUIKeyboardHelper; import com.qmuiteam.qmui.util.QMUIViewHelper; @@ -1362,6 +1363,13 @@ public abstract class QMUIFragment extends Fragment implements return true; } + + public final boolean isStartedByScheme(){ + Bundle arguments = getArguments(); + return arguments != null && arguments.getBoolean(QMUISchemeHandler.ARG_FROM_SCHEME, false); + } + + /** * Fragment Transition Controller */ diff --git a/arch/src/main/java/com/qmuiteam/qmui/arch/scheme/ActivitySchemeItem.java b/arch/src/main/java/com/qmuiteam/qmui/arch/scheme/ActivitySchemeItem.java index 2f416222..cd43b38a 100644 --- a/arch/src/main/java/com/qmuiteam/qmui/arch/scheme/ActivitySchemeItem.java +++ b/arch/src/main/java/com/qmuiteam/qmui/arch/scheme/ActivitySchemeItem.java @@ -33,7 +33,7 @@ class ActivitySchemeItem extends SchemeItem { @NonNull private final Class mActivityClass; - @NonNull + @Nullable private final Class mIntentFactoryCls; public ActivitySchemeItem(@NonNull Class activityClass, @@ -46,31 +46,33 @@ class ActivitySchemeItem extends SchemeItem { @Nullable String[] keysForDouble) { super(required, keysForInt, keysForBool, keysForLong, keysForFloat, keysForDouble); mActivityClass = activityClass; - if (intentFactoryCls == null) { - mIntentFactoryCls = QMUIDefaultSchemeIntentFactory.class; - } else { - mIntentFactoryCls = intentFactoryCls; - } + mIntentFactoryCls = intentFactoryCls; } @Override - public boolean handle(@NonNull Activity activity, @NonNull Map scheme) { + public boolean handle(@NonNull QMUISchemeHandler handler, + @NonNull Activity activity, + @Nullable Map scheme) { if (sFactories == null) { sFactories = new HashMap<>(); } - QMUISchemeIntentFactory factory = sFactories.get(mIntentFactoryCls); + Class factoryCls = mIntentFactoryCls; + if(factoryCls == null){ + factoryCls = handler.getDefaultIntentFactory(); + } + + QMUISchemeIntentFactory factory = sFactories.get(factoryCls); if (factory == null) { try { - factory = mIntentFactoryCls.newInstance(); - sFactories.put(mIntentFactoryCls, factory); + factory = factoryCls.newInstance(); + sFactories.put(factoryCls, factory); } catch (Exception e) { QMUILog.printErrStackTrace(QMUISchemeHandler.TAG, e, - "error to instance QMUISchemeIntentFactory: %d", mIntentFactoryCls.getSimpleName()); + "error to instance QMUISchemeIntentFactory: %d", factoryCls.getSimpleName()); } } if (factory != null) { - if (factory.shouldBlockJump(activity, mActivityClass, scheme)) { return true; } diff --git a/arch/src/main/java/com/qmuiteam/qmui/arch/scheme/FragmentSchemeItem.java b/arch/src/main/java/com/qmuiteam/qmui/arch/scheme/FragmentSchemeItem.java index b07ef798..d8f81cfc 100644 --- a/arch/src/main/java/com/qmuiteam/qmui/arch/scheme/FragmentSchemeItem.java +++ b/arch/src/main/java/com/qmuiteam/qmui/arch/scheme/FragmentSchemeItem.java @@ -37,7 +37,7 @@ class FragmentSchemeItem extends SchemeItem { private final Class[] mActivityClsList; private final boolean mForceNewActivity; private final String mForceNewActivityKey; - @NonNull + @Nullable private final Class mFragmentFactoryCls; public FragmentSchemeItem(@NonNull Class fragmentCls, @@ -56,15 +56,13 @@ class FragmentSchemeItem extends SchemeItem { mActivityClsList = activityClsList; mForceNewActivity = forceNewActivity; mForceNewActivityKey = forceNewActivityKey; - if(fragmentFactoryCls == null){ - mFragmentFactoryCls = QMUIDefaultSchemeFragmentFactory.class; - }else{ - mFragmentFactoryCls = fragmentFactoryCls; - } + mFragmentFactoryCls = fragmentFactoryCls; } @Override - public boolean handle(@NonNull Activity activity, @Nullable Map scheme) { + public boolean handle(@NonNull QMUISchemeHandler handler, + @NonNull Activity activity, + @Nullable Map scheme) { if (mActivityClsList.length == 0) { QMUILog.d(QMUISchemeHandler.TAG, "Can not start a new fragment because the host is't provided"); return false; @@ -72,21 +70,27 @@ class FragmentSchemeItem extends SchemeItem { if (sFactories == null) { sFactories = new HashMap<>(); } - QMUISchemeFragmentFactory factory = sFactories.get(mFragmentFactoryCls); + + Class factoryCls = mFragmentFactoryCls; + if (factoryCls == null) { + factoryCls = handler.getDefaultFragmentFactory(); + } + + QMUISchemeFragmentFactory factory = sFactories.get(factoryCls); if (factory == null) { try { - factory = mFragmentFactoryCls.newInstance(); - sFactories.put(mFragmentFactoryCls, factory); + factory = factoryCls.newInstance(); + sFactories.put(factoryCls, factory); } catch (Exception e) { QMUILog.printErrStackTrace(QMUISchemeHandler.TAG, e, - "error to instance QMUISchemeFragmentFactory: %d", mFragmentFactoryCls.getSimpleName()); + "error to instance QMUISchemeFragmentFactory: %d", factoryCls.getSimpleName()); } } if (factory == null) { return false; } - if(factory.shouldBlockJump(activity, mFragmentCls, scheme)){ + if (factory.shouldBlockJump(activity, mFragmentCls, scheme)) { return true; } diff --git a/arch/src/main/java/com/qmuiteam/qmui/arch/scheme/QMUISchemeHandleInterpolator.java b/arch/src/main/java/com/qmuiteam/qmui/arch/scheme/QMUISchemeHandleInterpolator.java index 7fe61c98..f7734ff1 100644 --- a/arch/src/main/java/com/qmuiteam/qmui/arch/scheme/QMUISchemeHandleInterpolator.java +++ b/arch/src/main/java/com/qmuiteam/qmui/arch/scheme/QMUISchemeHandleInterpolator.java @@ -18,8 +18,15 @@ package com.qmuiteam.qmui.arch.scheme; import android.app.Activity; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import java.util.Map; public interface QMUISchemeHandleInterpolator { - boolean intercept(Activity activity, String action, Map params, String origin); + boolean intercept(@NonNull QMUISchemeHandler schemeHandler, + @NonNull Activity activity, + @NonNull String action, + @Nullable Map params, + @NonNull String origin); } diff --git a/arch/src/main/java/com/qmuiteam/qmui/arch/scheme/QMUISchemeHandler.java b/arch/src/main/java/com/qmuiteam/qmui/arch/scheme/QMUISchemeHandler.java index 76178302..4290e617 100644 --- a/arch/src/main/java/com/qmuiteam/qmui/arch/scheme/QMUISchemeHandler.java +++ b/arch/src/main/java/com/qmuiteam/qmui/arch/scheme/QMUISchemeHandler.java @@ -64,10 +64,12 @@ public class QMUISchemeHandler { } } - private final String mPrefix; private final List mInterpolatorList; private final long mBlockSameSchemeTimeout; + private final Class mDefaultIntentFactory; + private final Class mDefaultFragmentFactory; + private String mLastHandledScheme = null; private long mLastSchemeHandledTime = 0; @@ -80,6 +82,26 @@ public class QMUISchemeHandler { mInterpolatorList = null; } mBlockSameSchemeTimeout = builder.mBlockSameSchemeTimeout; + mDefaultIntentFactory = builder.mDefaultIntentFactory; + mDefaultFragmentFactory = builder.mDefaultFragmentFactory; + + } + + public String getPrefix() { + return mPrefix; + } + + public Class getDefaultFragmentFactory() { + return mDefaultFragmentFactory; + } + + public Class getDefaultIntentFactory() { + return mDefaultIntentFactory; + } + + @Nullable + public SchemeItem getSchemeItem(String action, Map params){ + return sSchemeMap.findScheme(action, params); } public boolean handle(String scheme){ @@ -116,7 +138,7 @@ public class QMUISchemeHandler { boolean handled = false; if(mInterpolatorList != null && !mInterpolatorList.isEmpty()){ for(QMUISchemeHandleInterpolator interpolator: mInterpolatorList){ - if(interpolator.intercept(currentActivity, action, params, scheme)){ + if(interpolator.intercept(this, currentActivity, action, params, scheme)){ handled = true; break; } @@ -126,7 +148,7 @@ public class QMUISchemeHandler { if(!handled){ SchemeItem schemeItem = sSchemeMap.findScheme(action, params); if(schemeItem != null){ - handled = schemeItem.handle(currentActivity, schemeItem.convertFrom(params)); + handled = schemeItem.handle(this, currentActivity, schemeItem.convertFrom(params)); } } @@ -177,6 +199,8 @@ public class QMUISchemeHandler { private String mPrefix; private List mInterpolatorList; private long mBlockSameSchemeTimeout = BLOCK_SAME_SCHEME_DEFAULT_TIMEOUT; + private Class mDefaultIntentFactory = QMUIDefaultSchemeIntentFactory.class; + private Class mDefaultFragmentFactory = QMUIDefaultSchemeFragmentFactory.class; public Builder(@NonNull String prefix) { mPrefix = prefix; @@ -190,11 +214,21 @@ public class QMUISchemeHandler { return this; } - public Builder setBlockSameSchemeTimeout(long blockSameSchemeTimeout) { + public Builder blockSameSchemeTimeout(long blockSameSchemeTimeout) { mBlockSameSchemeTimeout = blockSameSchemeTimeout; return this; } + public Builder defaultFragmentFactory(Class defaultFragmentFactory) { + mDefaultFragmentFactory = defaultFragmentFactory; + return this; + } + + public Builder defaultIntentFactory(Class defaultIntentFactory) { + mDefaultIntentFactory = defaultIntentFactory; + return this; + } + public QMUISchemeHandler build() { return new QMUISchemeHandler(this); } diff --git a/arch/src/main/java/com/qmuiteam/qmui/arch/scheme/QMUISchemeParamValueDecoder.java b/arch/src/main/java/com/qmuiteam/qmui/arch/scheme/QMUISchemeParamValueDecoder.java index 6bde7fcd..e94cc3c2 100644 --- a/arch/src/main/java/com/qmuiteam/qmui/arch/scheme/QMUISchemeParamValueDecoder.java +++ b/arch/src/main/java/com/qmuiteam/qmui/arch/scheme/QMUISchemeParamValueDecoder.java @@ -19,12 +19,19 @@ package com.qmuiteam.qmui.arch.scheme; import android.app.Activity; import android.net.Uri; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import java.util.Map; public class QMUISchemeParamValueDecoder implements QMUISchemeHandleInterpolator { @Override - public boolean intercept(Activity activity, String action, Map params, String origin) { + public boolean intercept(@NonNull QMUISchemeHandler schemeHandler, + @NonNull Activity activity, + @NonNull String action, + @Nullable Map params, + @NonNull String origin) { if (params != null) { for (String key : params.keySet()) { String oldValue = params.get(key); diff --git a/qmui/src/main/java/com/qmuiteam/qmui/util/QMUIViewOffsetHelper.java b/qmui/src/main/java/com/qmuiteam/qmui/util/QMUIViewOffsetHelper.java index 6b1e68ae..deba84b3 100644 --- a/qmui/src/main/java/com/qmuiteam/qmui/util/QMUIViewOffsetHelper.java +++ b/qmui/src/main/java/com/qmuiteam/qmui/util/QMUIViewOffsetHelper.java @@ -61,15 +61,18 @@ public final class QMUIViewOffsetHelper { } public void onViewLayout() { - // Now grab the intended top - mLayoutTop = mView.getTop(); - mLayoutLeft = mView.getLeft(); - - // And offset it as needed - updateOffsets(); + onViewLayout(true); } - private void updateOffsets() { + public void onViewLayout(boolean applyOffset) { + mLayoutTop = mView.getTop(); + mLayoutLeft = mView.getLeft(); + if(applyOffset){ + applyOffsets(); + } + } + + public void applyOffsets() { ViewCompat.offsetTopAndBottom(mView, mOffsetTop - (mView.getTop() - mLayoutTop)); ViewCompat.offsetLeftAndRight(mView, mOffsetLeft - (mView.getLeft() - mLayoutLeft)); } @@ -83,7 +86,7 @@ public final class QMUIViewOffsetHelper { public boolean setTopAndBottomOffset(int offset) { if (mVerticalOffsetEnabled && mOffsetTop != offset) { mOffsetTop = offset; - updateOffsets(); + applyOffsets(); return true; } return false; @@ -98,7 +101,7 @@ public final class QMUIViewOffsetHelper { public boolean setLeftAndRightOffset(int offset) { if (mHorizontalOffsetEnabled && mOffsetLeft != offset) { mOffsetLeft = offset; - updateOffsets(); + applyOffsets(); return true; } return false; @@ -111,7 +114,7 @@ public final class QMUIViewOffsetHelper { if (mOffsetLeft != leftOffset || mOffsetTop != topOffset) { mOffsetLeft = leftOffset; mOffsetTop = topOffset; - updateOffsets(); + applyOffsets(); return true; } return false; diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDTabSegmentScrollableModeFragment.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDTabSegmentScrollableModeFragment.java index 17a0938c..b20cf1ad 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDTabSegmentScrollableModeFragment.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDTabSegmentScrollableModeFragment.java @@ -60,7 +60,7 @@ import butterknife.ButterKnife; @FragmentScheme( name = "tab", activities = {QDMainActivity.class}, - required = {"mode=2"}, + required = {"mode=2", "name"}, keysWithIntValue = {"mode"}) public class QDTabSegmentScrollableModeFragment extends BaseFragment { @SuppressWarnings("FieldCanBeLocal") private final int TAB_COUNT = 10; @@ -115,6 +115,22 @@ public class QDTabSegmentScrollableModeFragment extends BaseFragment { } }; + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if(isStartedByScheme()){ + Toast.makeText(getContext(), "started by scheme", Toast.LENGTH_SHORT).show(); + + Bundle args = getArguments(); + if(args != null){ + int mode = args.getInt("mode"); + Toast.makeText(getContext(), "mode = " + mode, Toast.LENGTH_SHORT).show(); + } + } + } + + + @Override protected View onCreateView() { View rootView = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_tab_viewpager_layout, null); diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/manager/QDSchemeManager.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/manager/QDSchemeManager.java index 0881d664..83244359 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/manager/QDSchemeManager.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/manager/QDSchemeManager.java @@ -20,6 +20,9 @@ import android.app.Activity; import android.util.Log; import android.widget.Toast; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.qmuiteam.qmui.arch.QMUISwipeBackActivityManager; import com.qmuiteam.qmui.arch.scheme.QMUISchemeHandleInterpolator; import com.qmuiteam.qmui.arch.scheme.QMUISchemeHandler; @@ -43,10 +46,14 @@ public class QDSchemeManager { private QDSchemeManager() { mSchemeHandler = new QMUISchemeHandler.Builder(SCHEME_PREFIX) - .setBlockSameSchemeTimeout(1000) + .blockSameSchemeTimeout(1000) .addInterpolator(new QMUISchemeHandleInterpolator() { @Override - public boolean intercept(Activity activity, String action, Map params, String origin) { + public boolean intercept(@NonNull QMUISchemeHandler schemeHandler, + @NonNull Activity activity, + @NonNull String action, + @Nullable Map params, + @NonNull String origin) { // Log the scheme. Log.i(TAG, "handle scheme: " + origin); return false;