Commit 7e948be5 by Wyh

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	base-module/src/main/java/com/gingersoft/gsa/cloud/constans/HttpsConstans.java
parents 181d2f99 b7c9e6a9
......@@ -52,6 +52,7 @@ buildscript {
dependencies {
// api project(':qm-skin-maker')
//support
api(rootProject.ext.dependencies["support-v4"]) {
exclude module: 'support-annotations'
......@@ -135,6 +136,14 @@ dependencies {
implementation rootProject.ext.dependencies["recyclerview-v7"]
implementation rootProject.ext.dependencies["cardview-v7"]
//可長按拖動 側滑刪除的recyclerview
api rootProject.ext.dependencies["yzjRecyclerView"]
//fragmentation
api project(':fragmentation_core')
// api rootProject.ext.dependencies["fragmentation"]
// api rootProject.ext.dependencies["fragmentation-core"]
// api rootProject.ext.dependencies["fragmentation-swipeback"]
//test
api rootProject.ext.dependencies["timber"]
implementation rootProject.ext.dependencies["retrofit-url-manager"]
......
......@@ -32,10 +32,13 @@ import com.jess.arms.integration.lifecycle.ActivityLifecycleable;
import com.jess.arms.mvp.IPresenter;
import com.jess.arms.utils.AndroidWorkaround;
import com.jess.arms.utils.ArmsUtils;
import com.qmuiteam.qmui.arch.QMUIActivity;
import com.qmuiteam.qmui.skin.QMUISkinManager;
import com.trello.rxlifecycle2.android.ActivityEvent;
import javax.inject.Inject;
import androidx.lifecycle.Lifecycle;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import io.reactivex.subjects.BehaviorSubject;
......@@ -125,6 +128,7 @@ public abstract class BaseActivity<P extends IPresenter> extends AppCompatActivi
this.mPresenter = null;
}
/**
* 是否使用eventBus,默认为使用(true),
*
......
......@@ -19,6 +19,7 @@ import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import com.jess.arms.base.delegate.IActivity;
......@@ -27,6 +28,8 @@ import com.jess.arms.integration.cache.CacheType;
import com.jess.arms.integration.lifecycle.ActivityLifecycleable;
import com.jess.arms.mvp.IPresenter;
import com.jess.arms.utils.ArmsUtils;
import com.qmuiteam.qmui.arch.QMUIFragmentActivity;
import com.qmuiteam.qmui.skin.QMUISkinManager;
import com.trello.rxlifecycle2.android.ActivityEvent;
import javax.inject.Inject;
......@@ -35,10 +38,17 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.Lifecycle;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import io.reactivex.subjects.BehaviorSubject;
import io.reactivex.subjects.Subject;
import me.yokeyword.fragmentation.ExtraTransaction;
import me.yokeyword.fragmentation.ISupportActivity;
import me.yokeyword.fragmentation.ISupportFragment;
import me.yokeyword.fragmentation.SupportActivityDelegate;
import me.yokeyword.fragmentation.SupportHelper;
import me.yokeyword.fragmentation.anim.FragmentAnimator;
import static com.jess.arms.utils.ThirdViewUtil.convertAutoView;
......@@ -52,7 +62,7 @@ import static com.jess.arms.utils.ThirdViewUtil.convertAutoView;
* <a href="https://github.com/JessYanCoding">Follow me</a>
* ================================================
*/
public abstract class BaseFragmentActivity<P extends IPresenter> extends FragmentActivity implements IActivity, ActivityLifecycleable {
public abstract class BaseFragmentActivity<P extends IPresenter> extends FragmentActivity implements IActivity, ISupportActivity, ActivityLifecycleable {
protected final String TAG = this.getClass().getSimpleName();
private final BehaviorSubject<ActivityEvent> mLifecycleSubject = BehaviorSubject.create();
private Cache<String, Object> mCache;
......@@ -62,6 +72,8 @@ public abstract class BaseFragmentActivity<P extends IPresenter> extends Fragmen
@Nullable
protected P mPresenter;//如果当前页面逻辑简单, Presenter 可以为 null
final SupportActivityDelegate mDelegate = new SupportActivityDelegate(this);
@NonNull
@Override
public synchronized Cache<String, Object> provideCache() {
......@@ -86,6 +98,7 @@ public abstract class BaseFragmentActivity<P extends IPresenter> extends Fragmen
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mDelegate.onCreate(savedInstanceState);
mContext = this;
//DecorView的背景对我来说无用,但是会产生一次Overdraw,这里去掉(过度绘制优化)
getWindow().setBackgroundDrawable(null);
......@@ -110,6 +123,7 @@ public abstract class BaseFragmentActivity<P extends IPresenter> extends Fragmen
@Override
protected void onDestroy() {
mDelegate.onDestroy();
super.onDestroy();
if (mUnbinder != null && mUnbinder != Unbinder.EMPTY)
mUnbinder.unbind();
......@@ -119,6 +133,167 @@ public abstract class BaseFragmentActivity<P extends IPresenter> extends Fragmen
this.mPresenter = null;
}
@Override
public SupportActivityDelegate getSupportDelegate() {
return mDelegate;
}
/**
* Perform some extra transactions.
* 额外的事务:自定义Tag,添加SharedElement动画,操作非回退栈Fragment
*/
@Override
public ExtraTransaction extraTransaction() {
return mDelegate.extraTransaction();
}
@Override
protected void onPostCreate(@Nullable Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
mDelegate.onPostCreate(savedInstanceState);
}
/**
* Note: return mDelegate.dispatchTouchEvent(ev) || super.dispatchTouchEvent(ev);
*/
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
return mDelegate.dispatchTouchEvent(ev) || super.dispatchTouchEvent(ev);
}
/**
* 不建议复写该方法,请使用 {@link #onBackPressedSupport} 代替
*/
@Override
final public void onBackPressed() {
mDelegate.onBackPressed();
}
/**
* 该方法回调时机为,Activity回退栈内Fragment的数量 小于等于1 时,默认finish Activity
* 请尽量复写该方法,避免复写onBackPress(),以保证SupportFragment内的onBackPressedSupport()回退事件正常执行
*/
@Override
public void onBackPressedSupport() {
mDelegate.onBackPressedSupport();
}
/**
* 获取设置的全局动画 copy
*
* @return FragmentAnimator
*/
@Override
public FragmentAnimator getFragmentAnimator() {
return mDelegate.getFragmentAnimator();
}
/**
* Set all fragments animation.
* 设置Fragment内的全局动画
*/
@Override
public void setFragmentAnimator(FragmentAnimator fragmentAnimator) {
mDelegate.setFragmentAnimator(fragmentAnimator);
}
/**
* Set all fragments animation.
* 构建Fragment转场动画
* <p/>
* 如果是在Activity内实现,则构建的是Activity内所有Fragment的转场动画,
* 如果是在Fragment内实现,则构建的是该Fragment的转场动画,此时优先级 > Activity的onCreateFragmentAnimator()
*
* @return FragmentAnimator对象
*/
@Override
public FragmentAnimator onCreateFragmentAnimator() {
return mDelegate.onCreateFragmentAnimator();
}
/**
* Causes the Runnable r to be added to the action queue.
* <p>
* The runnable will be run after all the previous action has been run.
* <p>
* 前面的事务全部执行后 执行该Action
*/
@Override
public void post(Runnable runnable) {
mDelegate.post(runnable);
}
/****************************************以下为可选方法(Optional methods)******************************************************/
// 选择性拓展其他方法
public void loadRootFragment(int containerId, @NonNull ISupportFragment toFragment) {
mDelegate.loadRootFragment(containerId, toFragment);
}
public void start(ISupportFragment toFragment) {
mDelegate.start(toFragment);
}
/**
* @param launchMode Same as Activity's LaunchMode.
*/
public void start(ISupportFragment toFragment, @ISupportFragment.LaunchMode int launchMode) {
mDelegate.start(toFragment, launchMode);
}
/**
* It is recommended to use {@link SupportFragment#startWithPopTo(ISupportFragment, Class, boolean)}.
*
* @see #popTo(Class, boolean)
* +
* @see #start(ISupportFragment)
*/
public void startWithPopTo(ISupportFragment toFragment, Class<?> targetFragmentClass, boolean includeTargetFragment) {
mDelegate.startWithPopTo(toFragment, targetFragmentClass, includeTargetFragment);
}
/**
* Pop the fragment.
*/
public void pop() {
mDelegate.pop();
}
/**
* Pop the last fragment transition from the manager's fragment
* back stack.
*/
public void popTo(Class<?> targetFragmentClass, boolean includeTargetFragment) {
mDelegate.popTo(targetFragmentClass, includeTargetFragment);
}
/**
* If you want to begin another FragmentTransaction immediately after popTo(), use this method.
* 如果你想在出栈后, 立刻进行FragmentTransaction操作,请使用该方法
*/
public void popTo(Class<?> targetFragmentClass, boolean includeTargetFragment, Runnable afterPopTransactionRunnable) {
mDelegate.popTo(targetFragmentClass, includeTargetFragment, afterPopTransactionRunnable);
}
public void popTo(Class<?> targetFragmentClass, boolean includeTargetFragment, Runnable afterPopTransactionRunnable, int popAnim) {
mDelegate.popTo(targetFragmentClass, includeTargetFragment, afterPopTransactionRunnable, popAnim);
}
/**
* 得到位于栈顶Fragment
*/
public ISupportFragment getTopFragment() {
return SupportHelper.getTopFragment(getSupportFragmentManager());
}
/**
* 获取栈内的fragment对象
*/
public <T extends ISupportFragment> T findFragment(Class<T> fragmentClass) {
return SupportHelper.findFragment(getSupportFragmentManager(), fragmentClass);
}
/**
* 是否使用eventBus,默认为使用(true),
*
......
......@@ -32,6 +32,7 @@ import com.gingersoft.gsa.cloud.database.DaoManager;
import com.hyweb.n5.lib.exception.NoInitPrinterException;
import com.hyweb.n5.lib.util.PrinterUtil;
import com.jess.arms.base.BaseApplication;
import com.qmuiteam.qmui.arch.QMUISwipeBackActivityManager;
import com.scwang.smartrefresh.layout.SmartRefreshLayout;
import com.scwang.smartrefresh.layout.api.DefaultRefreshFooterCreator;
import com.scwang.smartrefresh.layout.api.DefaultRefreshHeaderCreator;
......@@ -41,7 +42,7 @@ import com.scwang.smartrefresh.layout.api.RefreshLayout;
import com.scwang.smartrefresh.layout.footer.ClassicsFooter;
import com.scwang.smartrefresh.layout.header.ClassicsHeader;
import java.util.Locale;
import com.gingersoft.gsa.cloud.base.qmui.manager.QDSkinManager;
import com.qmuiteam.qmui.skin.manager.QDSkinManager;
import androidx.annotation.NonNull;
import me.jessyan.autosize.AutoSize;
import me.jessyan.autosize.AutoSizeConfig;
......@@ -101,6 +102,9 @@ public class GsaCloudApplication extends BaseApplication {
//初始化服務器地址
initDomainUrl();
//初始化側滑回退
// QMUISwipeBackActivityManager.init(this);
//初始化主題管理器
QDSkinManager.install(this);
//初始化上下拉刷新
initRefresh();
......@@ -311,9 +315,9 @@ public class GsaCloudApplication extends BaseApplication {
public void onConfigurationChanged(@NonNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if((newConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES){
QDSkinManager.changeSkin(QDSkinManager.SKIN_DARK);
}else if(QDSkinManager.getCurrentSkin() == QDSkinManager.SKIN_DARK){
QDSkinManager.changeSkin(QDSkinManager.SKIN_BLUE);
QDSkinManager.changeSkin(mAppContext,QDSkinManager.SKIN_DARK);
}else if(QDSkinManager.getCurrentSkin(mAppContext) == QDSkinManager.SKIN_DARK){
QDSkinManager.changeSkin(mAppContext,QDSkinManager.SKIN_BLUE);
}
}
......
......@@ -13,6 +13,7 @@ public class BaseResult {
private boolean success;
private long sysTime;
private String errMsg;
private Object data;
public boolean isSuccess() {
......@@ -31,6 +32,14 @@ public class BaseResult {
this.sysTime = sysTime;
}
public String getErrMsg() {
return errMsg;
}
public void setErrMsg(String errMsg) {
this.errMsg = errMsg;
}
public Object getData() {
return data;
}
......
......@@ -85,8 +85,8 @@ public class TableBean {
private String createBy;
private String qrCodeImg;
private int posTableId;
private int serviceCharge;
private int memberId;
private long serviceCharge;
private long memberId;
/**
* 未開檯 0
* 已開檯 1
......@@ -228,19 +228,19 @@ public class TableBean {
this.posTableId = posTableId;
}
public int getServiceCharge() {
public long getServiceCharge() {
return serviceCharge;
}
public void setServiceCharge(int serviceCharge) {
public void setServiceCharge(long serviceCharge) {
this.serviceCharge = serviceCharge;
}
public int getMemberId() {
public long getMemberId() {
return memberId;
}
public void setMemberId(int memberId) {
public void setMemberId(long memberId) {
this.memberId = memberId;
}
......
/*
* Tencent is pleased to support the open source community by making QMUI_Android available.
*
* Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* http://opensource.org/licenses/MIT
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.gingersoft.gsa.cloud.base.qmui.arch;
import android.annotation.SuppressLint;
import android.content.res.Configuration;
import android.os.Build;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
//Fix the bug: Only fullscreen activities can request orientation in Android version 26, 27
class InnerBaseActivity extends AppCompatActivity {
private static int NO_REQUESTED_ORIENTATION_SET = -100;
private boolean mConvertToTranslucentCauseOrientationChanged = false;
private int mPendingRequestedOrientation = NO_REQUESTED_ORIENTATION_SET;
void convertToTranslucentCauseOrientationChanged() {
Utils.convertActivityToTranslucent(this);
mConvertToTranslucentCauseOrientationChanged = true;
}
@Override
public void setRequestedOrientation(int requestedOrientation) {
if (mConvertToTranslucentCauseOrientationChanged && (Build.VERSION.SDK_INT == Build.VERSION_CODES.O
|| Build.VERSION.SDK_INT == Build.VERSION_CODES.O_MR1)) {
Log.i("InnerBaseActivity", "setRequestedOrientation when activity is translucent");
mPendingRequestedOrientation = requestedOrientation;
} else {
super.setRequestedOrientation(requestedOrientation);
}
}
@SuppressLint("WrongConstant")
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (mConvertToTranslucentCauseOrientationChanged) {
mConvertToTranslucentCauseOrientationChanged = false;
Utils.convertActivityFromTranslucent(this);
if (mPendingRequestedOrientation != NO_REQUESTED_ORIENTATION_SET) {
super.setRequestedOrientation(mPendingRequestedOrientation);
mPendingRequestedOrientation = NO_REQUESTED_ORIENTATION_SET;
}
}
}
}
/*
* Tencent is pleased to support the open source community by making QMUI_Android available.
*
* Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* http://opensource.org/licenses/MIT
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.gingersoft.gsa.cloud.base.qmui.arch;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import com.gingersoft.gsa.cloud.base.R;
import com.qmuiteam.qmui.util.QMUIStatusBarHelper;
import static com.gingersoft.gsa.cloud.base.qmui.arch.SwipeBackLayout.EDGE_LEFT;
import androidx.annotation.Nullable;
public class QMUIActivity extends InnerBaseActivity {
private static final String TAG = "QMUIActivity";
private SwipeBackLayout.ListenerRemover mListenerRemover;
private SwipeBackgroundView mSwipeBackgroundView;
private boolean mIsInSwipeBack = false;
private SwipeBackLayout.SwipeListener mSwipeListener = new SwipeBackLayout.SwipeListener() {
@Override
public void onScrollStateChange(int state, float scrollPercent) {
Log.i(TAG, "SwipeListener:onScrollStateChange: state = " + state + " ;scrollPercent = " + scrollPercent);
mIsInSwipeBack = state != SwipeBackLayout.STATE_IDLE;
if (state == SwipeBackLayout.STATE_IDLE) {
if (mSwipeBackgroundView != null) {
if (scrollPercent <= 0.0F) {
mSwipeBackgroundView.unBind();
mSwipeBackgroundView = null;
} else if (scrollPercent >= 1.0F) {
// unBind mSwipeBackgroundView until onDestroy
finish();
int exitAnim = mSwipeBackgroundView.hasChildWindow() ?
R.anim.swipe_back_exit_still : R.anim.swipe_back_exit;
overridePendingTransition(R.anim.swipe_back_enter, exitAnim);
}
}
}
}
@Override
public void onScroll(int edgeFlag, float scrollPercent) {
if (mSwipeBackgroundView != null) {
scrollPercent = Math.max(0f, Math.min(1f, scrollPercent));
int targetOffset = (int) (Math.abs(backViewInitOffset()) * (1 - scrollPercent));
SwipeBackLayout.offsetInScroll(mSwipeBackgroundView, edgeFlag, targetOffset);
}
}
@Override
public void onEdgeTouch(int edgeFlag) {
Log.i(TAG, "SwipeListener:onEdgeTouch: edgeFlag = " + edgeFlag);
onDragStart();
ViewGroup decorView = (ViewGroup) getWindow().getDecorView();
if (decorView != null) {
Activity prevActivity = QMUISwipeBackActivityManager.getInstance()
.getPenultimateActivity(QMUIActivity.this);
if (decorView.getChildAt(0) instanceof SwipeBackgroundView) {
mSwipeBackgroundView = (SwipeBackgroundView) decorView.getChildAt(0);
} else {
mSwipeBackgroundView = new SwipeBackgroundView(QMUIActivity.this);
decorView.addView(mSwipeBackgroundView, 0, new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
}
mSwipeBackgroundView.bind(prevActivity, QMUIActivity.this, restoreSubWindowWhenDragBack());
SwipeBackLayout.offsetInEdgeTouch(mSwipeBackgroundView, edgeFlag,
Math.abs(backViewInitOffset()));
}
}
@Override
public void onScrollOverThreshold() {
Log.i(TAG, "SwipeListener:onEdgeTouch:onScrollOverThreshold");
}
};
private SwipeBackLayout.Callback mSwipeCallback = new SwipeBackLayout.Callback() {
@Override
public boolean canSwipeBack() {
return QMUISwipeBackActivityManager.getInstance().canSwipeBack() && canDragBack();
}
};
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
QMUIStatusBarHelper.translucent(this);
}
@Override
public void setContentView(View view) {
super.setContentView(newSwipeBackLayout(view));
}
@Override
public void setContentView(int layoutResID) {
SwipeBackLayout swipeBackLayout = SwipeBackLayout.wrap(this,
layoutResID, dragBackEdge(), mSwipeCallback);
if (translucentFull()) {
swipeBackLayout.getContentView().setFitsSystemWindows(false);
} else {
swipeBackLayout.getContentView().setFitsSystemWindows(true);
}
mListenerRemover = swipeBackLayout.addSwipeListener(mSwipeListener);
super.setContentView(swipeBackLayout);
}
@Override
public void setContentView(View view, ViewGroup.LayoutParams params) {
super.setContentView(newSwipeBackLayout(view), params);
}
private View newSwipeBackLayout(View view) {
if (translucentFull()) {
view.setFitsSystemWindows(false);
} else {
view.setFitsSystemWindows(true);
}
final SwipeBackLayout swipeBackLayout = SwipeBackLayout.wrap(view, dragBackEdge(), mSwipeCallback);
mListenerRemover = swipeBackLayout.addSwipeListener(mSwipeListener);
return swipeBackLayout;
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mListenerRemover != null) {
mListenerRemover.remove();
}
if (mSwipeBackgroundView != null) {
mSwipeBackgroundView.unBind();
mSwipeBackgroundView = null;
}
}
/**
* final this method, if need override this method, use doOnBackPressed as an alternative
*/
@Override
public final void onBackPressed() {
if (!mIsInSwipeBack) {
doOnBackPressed();
}
}
protected void doOnBackPressed() {
super.onBackPressed();
}
public boolean isInSwipeBack() {
return mIsInSwipeBack;
}
/**
* disable or enable drag back
*
* @return
*/
protected boolean canDragBack() {
return true;
}
/**
* if enable drag back,
*
* @return
*/
protected int backViewInitOffset() {
return 0;
}
/**
* called when drag back started.
*/
protected void onDragStart() {
}
protected int dragBackEdge() {
return EDGE_LEFT;
}
/**
* Immersive processing
*
* @return if true, the area under status bar belongs to content; otherwise it belongs to padding
*/
protected boolean translucentFull() {
return false;
}
/**
* restore sub window(e.g dialog) when drag back to previous activity
*
* @return
*/
protected boolean restoreSubWindowWhenDragBack() {
return true;
}
}
/*
* Tencent is pleased to support the open source community by making QMUI_Android available.
*
* Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* http://opensource.org/licenses/MIT
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.gingersoft.gsa.cloud.base.qmui.arch;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.widget.FrameLayout;
import com.qmuiteam.qmui.util.QMUIStatusBarHelper;
import com.qmuiteam.qmui.widget.QMUIWindowInsetLayout;
import java.lang.reflect.Field;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
/**
* the container activity for {@link QMUIFragment}.
* Created by cgspine on 15/9/14.
*/
public abstract class QMUIFragmentActivity extends InnerBaseActivity {
private static final String TAG = "QMUIFragmentActivity";
private QMUIWindowInsetLayout mFragmentContainer;
@SuppressWarnings("SameReturnValue")
protected abstract int getContextViewId();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
QMUIStatusBarHelper.translucent(this);
mFragmentContainer = new QMUIWindowInsetLayout(this);
mFragmentContainer.setId(getContextViewId());
setContentView(mFragmentContainer);
}
public FrameLayout getFragmentContainer() {
return mFragmentContainer;
}
@Override
public void onBackPressed() {
QMUIFragment fragment = getCurrentFragment();
if (fragment != null && !fragment.isInSwipeBack()) {
fragment.onBackPressed();
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
QMUIFragment fragment = getCurrentFragment();
if (fragment != null && !fragment.isInSwipeBack() && fragment.onKeyDown(keyCode, event)) {
return true;
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
QMUIFragment fragment = getCurrentFragment();
if (fragment != null && !fragment.isInSwipeBack() && fragment.onKeyUp(keyCode, event)) {
return true;
}
return super.onKeyUp(keyCode, event);
}
/**
* get the current Fragment.
*/
public QMUIFragment getCurrentFragment() {
return (QMUIFragment) getSupportFragmentManager().findFragmentById(getContextViewId());
}
/**
* start a new fragment and then destroy current fragment.
* assume there is a fragment stack(A->B->C), and you use this method to start a new
* fragment D and destroy fragment C. Now you are in fragment D, if you want call
* {@link #popBackStack()} to back to B, what the animation should be? Sometimes we hope run
* animation generated by transition B->C, but sometimes we hope run animation generated by
* transition C->D. this why second parameter exists.
*
* @param fragment new fragment to start
* @param useNewTransitionConfigWhenPop if true, use animation generated by transition C->D,
* else, use animation generated by transition B->C
*/
public int startFragmentAndDestroyCurrent(final QMUIFragment fragment, final boolean useNewTransitionConfigWhenPop) {
final QMUIFragment.TransitionConfig transitionConfig = fragment.onFetchTransitionConfig();
String tagName = fragment.getClass().getSimpleName();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction()
.setCustomAnimations(transitionConfig.enter, transitionConfig.exit,
transitionConfig.popenter, transitionConfig.popout)
.replace(getContextViewId(), fragment, tagName);
int index = transaction.commit();
Utils.findAndModifyOpInBackStackRecord(fragmentManager, -1, new Utils.OpHandler() {
@Override
public boolean handle(Object op) {
Field cmdField = null;
try {
cmdField = op.getClass().getDeclaredField("cmd");
cmdField.setAccessible(true);
int cmd = (int) cmdField.get(op);
if (cmd == 1) {
if (useNewTransitionConfigWhenPop) {
Field popEnterAnimField = op.getClass().getDeclaredField("popEnterAnim");
popEnterAnimField.setAccessible(true);
popEnterAnimField.set(op, transitionConfig.popenter);
Field popExitAnimField = op.getClass().getDeclaredField("popExitAnim");
popExitAnimField.setAccessible(true);
popExitAnimField.set(op, transitionConfig.popout);
}
Field oldFragmentField = op.getClass().getDeclaredField("fragment");
oldFragmentField.setAccessible(true);
Object fragmentObj = oldFragmentField.get(op);
oldFragmentField.set(op, fragment);
Field backStackNestField = Fragment.class.getDeclaredField("mBackStackNesting");
backStackNestField.setAccessible(true);
int oldFragmentBackStackNest = (int) backStackNestField.get(fragmentObj);
backStackNestField.set(fragment, oldFragmentBackStackNest);
backStackNestField.set(fragmentObj, --oldFragmentBackStackNest);
return true;
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return false;
}
@Override
public boolean needReNameTag() {
return true;
}
@Override
public String newTagName() {
return fragment.getClass().getSimpleName();
}
});
return index;
}
public int startFragment(QMUIFragment fragment) {
Log.i(TAG, "startFragment");
QMUIFragment.TransitionConfig transitionConfig = fragment.onFetchTransitionConfig();
String tagName = fragment.getClass().getSimpleName();
return getSupportFragmentManager()
.beginTransaction()
.setCustomAnimations(transitionConfig.enter, transitionConfig.exit, transitionConfig.popenter, transitionConfig.popout)
.replace(getContextViewId(), fragment, tagName)
.addToBackStack(tagName)
.commit();
}
/**
* Exit the current Fragment。
*/
public void popBackStack() {
Log.i(TAG, "popBackStack: getSupportFragmentManager().getBackStackEntryCount() = " + getSupportFragmentManager().getBackStackEntryCount());
if (getSupportFragmentManager().getBackStackEntryCount() <= 1) {
QMUIFragment fragment = getCurrentFragment();
if (fragment == null) {
finish();
return;
}
QMUIFragment.TransitionConfig transitionConfig = fragment.onFetchTransitionConfig();
Object toExec = fragment.onLastFragmentFinish();
if (toExec != null) {
if (toExec instanceof QMUIFragment) {
QMUIFragment mFragment = (QMUIFragment) toExec;
startFragment(mFragment);
} else if (toExec instanceof Intent) {
Intent intent = (Intent) toExec;
finish();
startActivity(intent);
overridePendingTransition(transitionConfig.popenter, transitionConfig.popout);
} else {
throw new Error("can not handle the result in onLastFragmentFinish");
}
} else {
finish();
overridePendingTransition(transitionConfig.popenter, transitionConfig.popout);
}
} else {
getSupportFragmentManager().popBackStackImmediate();
}
}
/**
* pop back to a clazz type fragment
* <p>
* Assuming there is a back stack: Home -> List -> Detail. Perform popBackStack(Home.class),
* Home is the current fragment
* <p>
* if the clazz type fragment doest not exist in back stack, this method is Equivalent
* to popBackStack()
*
* @param clazz the type of fragment
*/
public void popBackStack(Class<? extends QMUIFragment> clazz) {
getSupportFragmentManager().popBackStack(clazz.getSimpleName(), 0);
}
/**
* pop back to a non-clazz type Fragment
*
* @param clazz the type of fragment
*/
public void popBackStackInclusive(Class<? extends QMUIFragment> clazz) {
getSupportFragmentManager().popBackStack(clazz.getSimpleName(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
}
\ No newline at end of file
/*
* Tencent is pleased to support the open source community by making QMUI_Android available.
*
* Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* http://opensource.org/licenses/MIT
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.gingersoft.gsa.cloud.base.qmui.arch;
import androidx.annotation.NonNull;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LifecycleRegistry;
import androidx.lifecycle.OnLifecycleEvent;
public class QMUIFragmentLazyLifecycleOwner implements LifecycleOwner, LifecycleObserver {
private LifecycleRegistry mLifecycleRegistry = null;
private boolean mIsViewVisible = true;
private Lifecycle.State mViewState = Lifecycle.State.INITIALIZED;
private Callback mCallback;
public QMUIFragmentLazyLifecycleOwner(@NonNull Callback callback){
mCallback = callback;
}
/**
* Initializes the underlying Lifecycle if it hasn't already been created.
*/
void initialize() {
if (mLifecycleRegistry == null) {
mLifecycleRegistry = new LifecycleRegistry(this);
}
}
void setViewVisible(boolean viewVisible) {
if(mViewState.compareTo(Lifecycle.State.CREATED) < 0 || !isInitialized()){
// not trust it before onCreate
return;
}
mIsViewVisible = viewVisible;
if (viewVisible) {
mLifecycleRegistry.markState(mViewState);
} else {
if (mViewState.compareTo(Lifecycle.State.CREATED) > 0) {
mLifecycleRegistry.markState(Lifecycle.State.CREATED);
} else {
mLifecycleRegistry.markState(mViewState);
}
}
}
/**
* @return True if the Lifecycle has been initialized.
*/
boolean isInitialized() {
return mLifecycleRegistry != null;
}
@NonNull
@Override
public Lifecycle getLifecycle() {
initialize();
return mLifecycleRegistry;
}
private void handleLifecycleEvent(@NonNull Lifecycle.Event event) {
initialize();
mLifecycleRegistry.handleLifecycleEvent(event);
}
@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
void onCreate(LifecycleOwner owner) {
mIsViewVisible = mCallback.isVisibleToUser();
mViewState = Lifecycle.State.CREATED;
handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
void onStart(LifecycleOwner owner) {
mViewState = Lifecycle.State.STARTED;
if (mIsViewVisible) {
handleLifecycleEvent(Lifecycle.Event.ON_START);
}
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
void onResume(LifecycleOwner owner) {
mViewState = Lifecycle.State.RESUMED;
if (mIsViewVisible && mLifecycleRegistry.getCurrentState() == Lifecycle.State.STARTED) {
handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
}
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
void onPause(LifecycleOwner owner) {
mViewState = Lifecycle.State.STARTED;
if (mLifecycleRegistry.getCurrentState().isAtLeast(Lifecycle.State.RESUMED)) {
handleLifecycleEvent(Lifecycle.Event.ON_PAUSE);
}
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
void onStop(LifecycleOwner owner) {
mViewState = Lifecycle.State.CREATED;
if (mLifecycleRegistry.getCurrentState().isAtLeast(Lifecycle.State.STARTED)) {
handleLifecycleEvent(Lifecycle.Event.ON_STOP);
}
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
void onDestroy(LifecycleOwner owner) {
mViewState = Lifecycle.State.DESTROYED;
handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
}
interface Callback {
boolean isVisibleToUser();
}
}
\ No newline at end of file
/*
* Tencent is pleased to support the open source community by making QMUI_Android available.
*
* Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* http://opensource.org/licenses/MIT
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.gingersoft.gsa.cloud.base.qmui.arch;
import android.annotation.SuppressLint;
import android.view.View;
import android.view.ViewGroup;
import com.qmuiteam.qmui.widget.QMUIPagerAdapter;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
public abstract class QMUIFragmentPagerAdapter extends QMUIPagerAdapter {
private final FragmentManager mFragmentManager;
private FragmentTransaction mCurrentTransaction;
private Fragment mCurrentPrimaryItem = null;
public QMUIFragmentPagerAdapter(@NonNull FragmentManager fm) {
mFragmentManager = fm;
}
public abstract Fragment createFragment(int position);
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == ((Fragment) object).getView();
}
@SuppressLint("CommitTransaction")
@Override
@NonNull
protected Object hydrate(@NonNull ViewGroup container, int position) {
String name = makeFragmentName(container.getId(), position);
if (mCurrentTransaction == null) {
mCurrentTransaction = mFragmentManager.beginTransaction();
}
Fragment fragment = mFragmentManager.findFragmentByTag(name);
if (fragment != null) {
return fragment;
}
return createFragment(position);
}
@SuppressLint("CommitTransaction")
@Override
protected void populate(@NonNull ViewGroup container, @NonNull Object item, int position) {
String name = makeFragmentName(container.getId(), position);
if (mCurrentTransaction == null) {
mCurrentTransaction = mFragmentManager.beginTransaction();
}
Fragment fragment = mFragmentManager.findFragmentByTag(name);
if (fragment != null) {
mCurrentTransaction.attach(fragment);
if (fragment.getView() != null && fragment.getView().getWidth() == 0) {
fragment.getView().requestLayout();
}
} else {
fragment = (Fragment) item;
mCurrentTransaction.add(container.getId(), fragment, name);
}
if (fragment != mCurrentPrimaryItem) {
fragment.setMenuVisibility(false);
fragment.setUserVisibleHint(false);
}
}
@SuppressLint("CommitTransaction")
@Override
protected void destroy(@NonNull ViewGroup container, int position, @NonNull Object object) {
if (mCurrentTransaction == null) {
mCurrentTransaction = mFragmentManager.beginTransaction();
}
mCurrentTransaction.detach((Fragment) object);
}
@Override
public void startUpdate(@NonNull ViewGroup container) {
if (container.getId() == View.NO_ID) {
throw new IllegalStateException("ViewPager with adapter " + this
+ " requires a view id");
}
}
@Override
public void finishUpdate(@NonNull ViewGroup container) {
if (mCurrentTransaction != null) {
mCurrentTransaction.commitNowAllowingStateLoss();
mCurrentTransaction = null;
}
}
@Override
public void setPrimaryItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
Fragment fragment = (Fragment) object;
if (fragment != mCurrentPrimaryItem) {
if (mCurrentPrimaryItem != null) {
mCurrentPrimaryItem.setMenuVisibility(false);
mCurrentPrimaryItem.setUserVisibleHint(false);
}
fragment.setMenuVisibility(true);
fragment.setUserVisibleHint(true);
mCurrentPrimaryItem = fragment;
}
}
private String makeFragmentName(int viewId, long id) {
return "QMUIFragmentPagerAdapter:" + viewId + ":" + id;
}
}
\ No newline at end of file
/*
* Tencent is pleased to support the open source community by making QMUI_Android available.
*
* Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* http://opensource.org/licenses/MIT
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.gingersoft.gsa.cloud.base.qmui.arch;
import android.app.Activity;
import android.app.Application;
import android.os.Bundle;
import java.util.Stack;
import androidx.annotation.MainThread;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public class QMUISwipeBackActivityManager implements Application.ActivityLifecycleCallbacks {
private static QMUISwipeBackActivityManager sInstance;
private Stack<Activity> mActivityStack = new Stack<>();
@MainThread
public static QMUISwipeBackActivityManager getInstance() {
if (sInstance == null) {
throw new IllegalAccessError("the QMUISwipeBackActivityManager is not initialized; " +
"please call QMUISwipeBackActivityManager.init(Application) in your application.");
}
return sInstance;
}
private QMUISwipeBackActivityManager() {
}
public static void init(@NonNull Application application) {
if (sInstance == null) {
sInstance = new QMUISwipeBackActivityManager();
application.registerActivityLifecycleCallbacks(sInstance);
}
}
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
mActivityStack.add(activity);
}
@Override
public void onActivityDestroyed(Activity activity) {
mActivityStack.remove(activity);
}
@Override
public void onActivityStarted(Activity activity) {
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
/**
*
* refer to https://github.com/bingoogolapple/BGASwipeBackLayout-Android/
* @param currentActivity the last activity
* @return
*/
@Nullable
public Activity getPenultimateActivity(Activity currentActivity) {
Activity activity = null;
try {
if (mActivityStack.size() > 1) {
activity = mActivityStack.get(mActivityStack.size() - 2);
if (currentActivity.equals(activity)) {
int index = mActivityStack.indexOf(currentActivity);
if (index > 0) {
// if memory leaks or the last activity is being finished
activity = mActivityStack.get(index - 1);
} else if (mActivityStack.size() == 2) {
// if screen orientation changes, there may be an error sequence in the stack
activity = mActivityStack.lastElement();
}
}
}
} catch (Exception ignored) {
}
return activity;
}
public boolean canSwipeBack() {
return mActivityStack.size() > 1;
}
}
/*
* Tencent is pleased to support the open source community by making QMUI_Android available.
*
* Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* http://opensource.org/licenses/MIT
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.gingersoft.gsa.cloud.base.qmui.arch;
import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.IBinder;
import android.util.AttributeSet;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import com.qmuiteam.qmui.util.QMUIColorHelper;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
class SwipeBackgroundView extends View {
private ArrayList<ViewInfo> mViewWeakReference;
private boolean mDoRotate = false;
public SwipeBackgroundView(Context context) {
super(context);
}
public SwipeBackgroundView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public void bind(Activity activity, Activity swipeActivity, boolean restoreForSubWindow) {
mDoRotate = false;
if (mViewWeakReference != null) {
mViewWeakReference.clear();
}
int orientation = activity.getResources().getConfiguration().orientation;
if (orientation != getResources().getConfiguration().orientation) {
// the screen orientation changed, reMeasure and reLayout
int requestedOrientation = activity.getRequestedOrientation();
if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE ||
requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
// TODO is it suitable for fixed screen orientation
// the prev activity has locked the screen orientation
mDoRotate = true;
} else if (swipeActivity instanceof InnerBaseActivity) {
swipeActivity.getWindow().getDecorView().setBackgroundColor(0);
((InnerBaseActivity) swipeActivity).convertToTranslucentCauseOrientationChanged();
invalidate();
return;
}
}
if (!restoreForSubWindow) {
View contentView = activity.findViewById(Window.ID_ANDROID_CONTENT);
if (mViewWeakReference == null) {
mViewWeakReference = new ArrayList<>();
}
mViewWeakReference.add(new ViewInfo(contentView, null, true));
invalidate();
return;
}
try {
IBinder windowToken = activity.getWindow().getDecorView().getWindowToken();
Field windowManagerGlobalField = activity.getWindowManager().getClass().getDeclaredField("mGlobal");
windowManagerGlobalField.setAccessible(true);
Object windowManagerGlobal = windowManagerGlobalField.get(activity.getWindowManager());
if (windowManagerGlobal != null) {
Field viewsField = windowManagerGlobal.getClass().getDeclaredField("mViews");
viewsField.setAccessible(true);
Field paramsField = windowManagerGlobal.getClass().getDeclaredField("mParams");
paramsField.setAccessible(true);
List<WindowManager.LayoutParams> params = (List<WindowManager.LayoutParams>) paramsField.get(windowManagerGlobal);
List<View> views = (List<View>) viewsField.get(windowManagerGlobal);
IBinder activityToken = null;
// reverse order
for (int i = params.size() - 1; i >= 0; i--) {
WindowManager.LayoutParams lp = params.get(i);
View view = views.get(i);
if (view.getWindowToken() == windowToken) {
activityToken = lp.token;
break;
}
}
if (activityToken != null) {
// reverse order
for (int i = params.size() - 1; i >= 0; i--) {
WindowManager.LayoutParams lp = params.get(i);
View view = views.get(i);
boolean isMain = view.getWindowToken() == windowToken;
// Dialog use activityToken in lp
// PopupWindow use windowToken in lp
if (isMain || lp.token == activityToken || lp.token == windowToken) {
View prevContentView = view.findViewById(Window.ID_ANDROID_CONTENT);
if (mViewWeakReference == null) {
mViewWeakReference = new ArrayList<>();
}
if (prevContentView != null) {
mViewWeakReference.add(new ViewInfo(prevContentView, lp, isMain));
}else {
// PopupWindow doest not exist a descendant view with id Window.ID_ANDROID_CONTENT
mViewWeakReference.add(new ViewInfo(view, lp, isMain));
}
}
}
}
}
} catch (Exception ignored) {
} finally {
// sure get one view
if (mViewWeakReference == null || mViewWeakReference.isEmpty()) {
View contentView = activity.findViewById(Window.ID_ANDROID_CONTENT);
if (mViewWeakReference == null) {
mViewWeakReference = new ArrayList<>();
}
mViewWeakReference.add(new ViewInfo(contentView, null, true));
}
}
invalidate();
}
public void unBind() {
if (mViewWeakReference != null) {
mViewWeakReference.clear();
}
mViewWeakReference = null;
mDoRotate = false;
}
boolean hasChildWindow() {
return mViewWeakReference != null && mViewWeakReference.size() > 1;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mViewWeakReference != null && mViewWeakReference.size() > 0) {
if (mDoRotate) {
canvas.translate(0, getHeight());
canvas.rotate(-90, 0, 0);
}
// reverse order
for (int i = mViewWeakReference.size() - 1; i >= 0; i--) {
mViewWeakReference.get(i).draw(canvas);
}
}
}
static class ViewInfo {
WeakReference<View> viewRef;
WindowManager.LayoutParams lp;
boolean isMain;
private int[] tempLocations = new int[2];
public ViewInfo(@NonNull View view, @Nullable WindowManager.LayoutParams lp, boolean isMain) {
this.viewRef = new WeakReference<>(view);
this.lp = lp;
this.isMain = isMain;
}
void draw(Canvas canvas) {
View view = viewRef.get();
if (view != null) {
if (isMain || lp == null) {
view.draw(canvas);
} else {
canvas.drawColor(QMUIColorHelper.setColorAlpha(Color.BLACK, lp.dimAmount));
view.getLocationOnScreen(tempLocations);
canvas.translate(tempLocations[0], tempLocations[1]);
view.draw(canvas);
canvas.translate(-tempLocations[0], -tempLocations[1]);
}
}
}
}
}
/*
* Tencent is pleased to support the open source community by making QMUI_Android available.
*
* Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* http://opensource.org/licenses/MIT
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.gingersoft.gsa.cloud.base.qmui.arch;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.ActivityOptions;
import android.os.Build;
import android.os.Looper;
import com.qmuiteam.qmui.QMUILog;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import androidx.fragment.app.FragmentManager;
/**
* Created by Chaojun Wang on 6/9/14.
*/
public class Utils {
private Utils() {
}
/**
* Convert a translucent themed Activity
* {@link android.R.attr#windowIsTranslucent} to a fullscreen opaque
* Activity.
* <p>
* Call this whenever the background of a translucent Activity has changed
* to become opaque. Doing so will allow the {@link android.view.Surface} of
* the Activity behind to be released.
* <p>
* This call has no effect on non-translucent activities or on activities
* with the {@link android.R.attr#windowIsFloating} attribute.
*/
public static void convertActivityFromTranslucent(Activity activity) {
try {
@SuppressLint("PrivateApi") Method method = Activity.class.getDeclaredMethod("convertFromTranslucent");
method.setAccessible(true);
method.invoke(activity);
} catch (Throwable ignore) {
}
}
/**
* Convert a translucent themed Activity
* {@link android.R.attr#windowIsTranslucent} back from opaque to
* translucent following a call to
* {@link #convertActivityFromTranslucent(Activity)} .
* <p>
* Calling this allows the Activity behind this one to be seen again. Once
* all such Activities have been redrawn
* <p>
* This call has no effect on non-translucent activities or on activities
* with the {@link android.R.attr#windowIsFloating} attribute.
*/
public static void convertActivityToTranslucent(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
convertActivityToTranslucentAfterL(activity);
} else {
convertActivityToTranslucentBeforeL(activity);
}
}
/**
* Calling the convertToTranslucent method on platforms before Android 5.0
*/
private static void convertActivityToTranslucentBeforeL(Activity activity) {
try {
Class<?>[] classes = Activity.class.getDeclaredClasses();
Class<?> translucentConversionListenerClazz = null;
for (Class clazz : classes) {
if (clazz.getSimpleName().contains("TranslucentConversionListener")) {
translucentConversionListenerClazz = clazz;
}
}
@SuppressLint("PrivateApi") Method method = Activity.class.getDeclaredMethod("convertToTranslucent",
translucentConversionListenerClazz);
method.setAccessible(true);
method.invoke(activity, new Object[]{
null
});
} catch (Throwable ignore) {
}
}
/**
* Calling the convertToTranslucent method on platforms after Android 5.0
*/
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static void convertActivityToTranslucentAfterL(Activity activity) {
try {
@SuppressLint("PrivateApi") Method getActivityOptions = Activity.class.getDeclaredMethod("getActivityOptions");
getActivityOptions.setAccessible(true);
Object options = getActivityOptions.invoke(activity);
Class<?>[] classes = Activity.class.getDeclaredClasses();
Class<?> translucentConversionListenerClazz = null;
for (Class clazz : classes) {
if (clazz.getSimpleName().contains("TranslucentConversionListener")) {
translucentConversionListenerClazz = clazz;
}
}
@SuppressLint("PrivateApi") Method convertToTranslucent = Activity.class.getDeclaredMethod("convertToTranslucent",
translucentConversionListenerClazz, ActivityOptions.class);
convertToTranslucent.setAccessible(true);
convertToTranslucent.invoke(activity, null, options);
} catch (Throwable ignore) {
}
}
public static void assertInMainThread() {
if (Looper.myLooper() != Looper.getMainLooper()) {
StackTraceElement[] elements = Thread.currentThread().getStackTrace();
String methodMsg = null;
if (elements != null && elements.length >= 4) {
methodMsg = elements[3].toString();
}
throw new IllegalStateException("Call the method must be in main thread: " + methodMsg);
}
}
static void findAndModifyOpInBackStackRecord(FragmentManager fragmentManager, int backStackIndex, OpHandler handler) {
if (fragmentManager == null || handler == null) {
return;
}
int backStackCount = fragmentManager.getBackStackEntryCount();
if (backStackCount > 0) {
if (backStackIndex >= backStackCount || backStackIndex < -backStackCount) {
QMUILog.d("findAndModifyOpInBackStackRecord", "backStackIndex error: " +
"backStackIndex = " + backStackIndex + " ; backStackCount = " + backStackCount);
return;
}
if (backStackIndex < 0) {
backStackIndex = backStackCount + backStackIndex;
}
try {
FragmentManager.BackStackEntry backStackEntry = fragmentManager.getBackStackEntryAt(backStackIndex);
if (handler.needReNameTag()) {
Field nameField = backStackEntry.getClass().getDeclaredField("mName");
nameField.setAccessible(true);
nameField.set(backStackEntry, handler.newTagName());
}
Field opsField = backStackEntry.getClass().getDeclaredField("mOps");
opsField.setAccessible(true);
Object opsObj = opsField.get(backStackEntry);
if (opsObj instanceof List<?>) {
List<?> ops = (List<?>) opsObj;
for (Object op : ops) {
if (handler.handle(op)) {
return;
}
}
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
interface OpHandler {
boolean handle(Object op);
boolean needReNameTag();
String newTagName();
}
}
......@@ -4,6 +4,7 @@ import android.content.Context;
import android.util.Log;
import com.gingersoft.gsa.cloud.base.utils.other.SPUtils;
import com.zhy.autolayout.utils.L;
/**
* Created by Wyh on 2019/12/21.
......@@ -42,6 +43,7 @@ public class HttpsConstans {
public static String ROOT_SERVER_YOU_CHANG_HK = "http://192.168.1.142:9012/api/"; //友常本地
public static String ROOT_SERVER_SHI_WEI_HK = "http://192.168.1.154:9012/api/"; //世維本地
public static String ROOT_SERVER_SHI_SHU_HK = "http://192.168.1.154:9012/api/"; //石书本地
//------------------------------------------外賣接單---------------------------------------------------------------------------
public static final String ROOT_SZ_URL = "http://192.168.1.74:6060";//友常本地
......@@ -64,8 +66,14 @@ public class HttpsConstans {
/**
* 修改這個值控制是否是正式
* 1=正式
* 2=香港
* 3=友常
* 4=世维
* 5=石书
*/
public static boolean isFormal = true;
public static int isFormal = 2;
//沽清控制地址
public static String _SERVER_ADDRESS;// = (isFormal ? HTTP_ADDRESS_URL_FORMAL : "http://a.ricepon.com:61177") + "/member-web/api/";
......@@ -74,7 +82,7 @@ public class HttpsConstans {
public static String ROOT_SETTLEMENT_REPORT_SERVER_ADDRESS_FORMAL;// = isFormal ? HTTP_ADDRESS_URL_FORMAL : REPORT_TEST_ADDRESS;
//默認url,配置這個值修改環境
public static String ROOT_SERVER_ADDRESS_FORMAL = (isFormal ? HTTP_ADDRESS_URL_FORMAL : HTTP_ADDRESS_URL_HK) + PATH;
public static String ROOT_SERVER_ADDRESS_FORMAL = (isFormal == 1 ? HTTP_ADDRESS_URL_FORMAL : HTTP_ADDRESS_URL_HK) + PATH;
//修改這個值,配置外賣接單環境
public static String ROOT_URL;// = isFormal ? ROOT_FORMAL_URL : ROOT_HK_TEST_URL;//正式:ROOT_FORMAL_URL 測試:ROOT_HK_TEST_URL
......@@ -86,13 +94,58 @@ public class HttpsConstans {
public static String WECHAR_REPORT_SERVER_ADDRESS;// = (isFormal ? WECHAR_REPORT_FORMAL_ADDRESS : WECHAR_REPORT_TEST_ADDRESS) + WECHAR_REPORT_PATH;//正式:WECHAR_REPORT_FORMAL_ADDRESS 測試:WECHAR_REPORT_TEST_ADDRESS
public static void init(Context context) {
isFormal = (boolean) SPUtils.get(context, "isFormal", true);
_SERVER_ADDRESS = (isFormal ? HTTP_ADDRESS_URL_FORMAL : "http://a.ricepon.com:61177") + "/member-web/api/";
ROOT_SETTLEMENT_REPORT_SERVER_ADDRESS_FORMAL = isFormal ? HTTP_ADDRESS_URL_FORMAL : REPORT_TEST_ADDRESS;
ROOT_SERVER_ADDRESS_FORMAL = (isFormal ? HTTP_ADDRESS_URL_FORMAL : HTTP_ADDRESS_URL_HK) + PATH;
ROOT_URL = isFormal ? ROOT_FORMAL_URL : ROOT_HK_TEST_URL;//正式:ROOT_FORMAL_URL 測試:ROOT_HK_TEST_URL
REPORT_SERVER_ADDRESS = (isFormal ? REPORT_FORMAL_ADDRESS : REPORT_TEST_ADDRESS) + REPORT_PATH;//測試:REPORT_FORMAL_ADDRESS 正式:REPORT_TEST_ADDRESS
WECHAR_REPORT_SERVER_ADDRESS = (isFormal ? WECHAR_REPORT_FORMAL_ADDRESS : WECHAR_REPORT_TEST_ADDRESS) + WECHAR_REPORT_PATH;//正式:WECHAR_REPORT_FORMAL_ADDRESS 測試:WECHAR_REPORT_TEST_ADDRESS
isFormal = (int) SPUtils.get(context, "isFormal", 2);
Log.e("eee", "是否正式" + isFormal);
// _SERVER_ADDRESS = (isFormal == 1 ? HTTP_ADDRESS_URL_FORMAL : "http://a.ricepon.com:61177") + "/member-web/api/";
// ROOT_SETTLEMENT_REPORT_SERVER_ADDRESS_FORMAL = isFormal ==1 ? HTTP_ADDRESS_URL_FORMAL : REPORT_TEST_ADDRESS;
// ROOT_SERVER_ADDRESS_FORMAL = (isFormal == 1 ? HTTP_ADDRESS_URL_FORMAL : HTTP_ADDRESS_URL_HK) + PATH;
// ROOT_URL = isFormal ==1 ? ROOT_FORMAL_URL : ROOT_HK_TEST_URL;//正式:ROOT_FORMAL_URL 測試:ROOT_HK_TEST_URL
// REPORT_SERVER_ADDRESS = (isFormal ==1 ? REPORT_FORMAL_ADDRESS : REPORT_TEST_ADDRESS) + REPORT_PATH;//測試:REPORT_FORMAL_ADDRESS 正式:REPORT_TEST_ADDRESS
// WECHAR_REPORT_SERVER_ADDRESS = (isFormal == 1 ? WECHAR_REPORT_FORMAL_ADDRESS : WECHAR_REPORT_TEST_ADDRESS) + WECHAR_REPORT_PATH;//正式:WECHAR_REPORT_FORMAL_ADDRESS 測試:WECHAR_REPORT_TEST_ADDRESS
switch (isFormal){
case 1:
_SERVER_ADDRESS = HTTP_ADDRESS_URL_FORMAL + "/member-web/api/";
ROOT_SETTLEMENT_REPORT_SERVER_ADDRESS_FORMAL = HTTP_ADDRESS_URL_FORMAL ;
ROOT_SERVER_ADDRESS_FORMAL = HTTP_ADDRESS_URL_FORMAL + PATH;
ROOT_URL = ROOT_FORMAL_URL ;
REPORT_SERVER_ADDRESS = REPORT_FORMAL_ADDRESS +REPORT_PATH;
WECHAR_REPORT_SERVER_ADDRESS = WECHAR_REPORT_FORMAL_ADDRESS + WECHAR_REPORT_PATH;//正式:WECHAR_REPORT_FORMAL_ADDRESS 測試:WECHAR_REPORT_TEST_ADDRESS
break;
case 2:
_SERVER_ADDRESS = "http://a.ricepon.com:61177" + "/member-web/api/";
ROOT_SETTLEMENT_REPORT_SERVER_ADDRESS_FORMAL = REPORT_TEST_ADDRESS ;
ROOT_SERVER_ADDRESS_FORMAL = HTTP_ADDRESS_URL_HK + PATH;
ROOT_URL = ROOT_HK_TEST_URL ;
REPORT_SERVER_ADDRESS = REPORT_TEST_ADDRESS +REPORT_PATH;
WECHAR_REPORT_SERVER_ADDRESS = WECHAR_REPORT_TEST_ADDRESS + WECHAR_REPORT_PATH;//正式:WECHAR_REPORT_FORMAL_ADDRESS 測試:WECHAR_REPORT_TEST_ADDRESS
break;
case 3:
_SERVER_ADDRESS = ROOT_SERVER_YOU_CHANG_HK + "/member-web/api/";
ROOT_SETTLEMENT_REPORT_SERVER_ADDRESS_FORMAL = REPORT_TEST_ADDRESS ;
ROOT_SERVER_ADDRESS_FORMAL = HTTP_ADDRESS_URL_HK + PATH;
ROOT_URL = ROOT_SZ_URL ;
REPORT_SERVER_ADDRESS = REPORT_TEST_ADDRESS +REPORT_PATH;
WECHAR_REPORT_SERVER_ADDRESS = WECHAR_REPORT_TEST_ADDRESS + WECHAR_REPORT_PATH;//正式:WECHAR_REPORT_FORMAL_ADDRESS 測試:WECHAR_REPORT_TEST_ADDRESS
break;
case 4:
_SERVER_ADDRESS = ROOT_SERVER_SHI_WEI_HK + "/member-web/api/";
ROOT_SETTLEMENT_REPORT_SERVER_ADDRESS_FORMAL = REPORT_TEST_ADDRESS ;
ROOT_SERVER_ADDRESS_FORMAL = HTTP_ADDRESS_URL_HK + PATH;
ROOT_URL = ROOT_SZ_URL ;
REPORT_SERVER_ADDRESS = REPORT_TEST_ADDRESS +REPORT_PATH;
WECHAR_REPORT_SERVER_ADDRESS = WECHAR_REPORT_TEST_ADDRESS + WECHAR_REPORT_PATH;//正式:WECHAR_REPORT_FORMAL_ADDRESS 測試:WECHAR_REPORT_TEST_ADDRESS
break;
case 5:
_SERVER_ADDRESS = ROOT_SERVER_SHI_SHU_HK + "/member-web/api/";
ROOT_SETTLEMENT_REPORT_SERVER_ADDRESS_FORMAL = REPORT_TEST_ADDRESS ;
ROOT_SERVER_ADDRESS_FORMAL = HTTP_ADDRESS_URL_HK + PATH;
ROOT_URL = ROOT_SZ_URL ;
REPORT_SERVER_ADDRESS = REPORT_TEST_ADDRESS +REPORT_PATH;
WECHAR_REPORT_SERVER_ADDRESS = WECHAR_REPORT_TEST_ADDRESS + WECHAR_REPORT_PATH;//正式:WECHAR_REPORT_FORMAL_ADDRESS 測試:WECHAR_REPORT_TEST_ADDRESS
break;
}
}
......
......@@ -124,6 +124,17 @@ public class ComboItem {
/*** 是否备注细项*/
@Transient
private boolean isModifier;
/**
* 0=顯示, 1=隱藏, 2=暫停,3=只显示,不操作
*/
@Transient
private long invisible;
@Transient
/**最大選中數*/
private String maxNumber = "";
/**動態的最大選中數*/
@Transient
private String currentMaxNumber= "";
/*** 背景顏色*/
@Transient
private int bgColor = Color.parseColor("#067878");
......@@ -174,6 +185,30 @@ public class ComboItem {
return fid;
}
public long getInvisible() {
return invisible;
}
public void setInvisible(long invisible) {
this.invisible = invisible;
}
public String getMaxNumber() {
return maxNumber;
}
public void setMaxNumber(String maxNumber) {
this.maxNumber = maxNumber;
}
public String getCurrentMaxNumber() {
return currentMaxNumber;
}
public void setCurrentMaxNumber(String currentMaxNumber) {
this.currentMaxNumber = currentMaxNumber;
}
public Long getQty() {
return qty;
}
......
......@@ -772,10 +772,6 @@ public class Modifier {
this.imageUrl = imageUrl;
}
public void setInvisible(Long invisible) {
this.invisible = invisible;
}
public void setCost(Double cost) {
this.cost = cost;
}
......
......@@ -162,7 +162,7 @@ public class ComboItemDaoUtils {
ArrayList<ComboItem> comboItems = new ArrayList<>();
// String sql = "SELECT c.*,f.FOOD_NAME,f.FOOD_NAME1,f.FOOD_NAME2,f.PRICE,f.AUTO_MOD FROM COMBO_ITEM c join FOOD f on c.FID=f.FID and f.INVISIBLE=0 join FOOD_COMBO r on r.COM_ID=c.COM_ID ";
String sql = "SELECT c.*,f.FOOD_NAME,f.FOOD_NAME1,f.FOOD_NAME2,f.PRICE,f.AUTO_MOD,DEF_MODIFIER,SELECT_QTY FROM COMBO_ITEM c join FOOD f on c.FID=f.FID and f.INVISIBLE=0 join FOOD_COMBO r on r.COM_ID=c.COM_ID ";
String sql = "SELECT c.*,f.FOOD_NAME,f.FOOD_NAME1,f.FOOD_NAME2,f.PRICE,f.AUTO_MOD,DEF_MODIFIER,SELECT_QTY,INVISIBLE FROM COMBO_ITEM c join FOOD f on c.FID=f.FID and f.INVISIBLE!=1 join FOOD_COMBO r on r.COM_ID=c.COM_ID ";
if (fid > 0) {
sql = sql + " where r.FID='" + fid + "'";
......@@ -181,6 +181,7 @@ public class ComboItemDaoUtils {
order.setVisible(c.getLong(c.getColumnIndex("VISIBLE")));
order.setAutoMode(c.getInt(c.getColumnIndex("AUTO_MOD")));
order.setSelectQty(c.getInt(c.getColumnIndex("SELECT_QTY")));
order.setInvisible(c.getLong(c.getColumnIndex("INVISIBLE")));
String defmodifier = c.getString(c.getColumnIndex("DEF_MODIFIER"));
if (!TextUtils.isEmpty(defmodifier) && !", ".equals(defmodifier)) {
order.setDefmodifier(defmodifier);
......
......@@ -182,7 +182,16 @@ public class FoodDaoUtils {
long currentTime = System.currentTimeMillis();
return queryBuilder.where(queryBuilder.and(
FoodDao.Properties.ParentId.eq(parentId),
FoodDao.Properties.Invisible.eq(0),
FoodDao.Properties.Invisible.notEq(1),
FoodDao.Properties.StartDate.le(currentTime),
FoodDao.Properties.EndDate.ge(currentTime))).orderAsc(FoodDao.Properties.SeqNo).list();
}
public List<Food> queryAllFoodByQueryBuilder() {
QueryBuilder<Food> queryBuilder = mManager.getDaoSession().queryBuilder(Food.class);
long currentTime = System.currentTimeMillis();
return queryBuilder.where(queryBuilder.and(
FoodDao.Properties.ParentId.notEq(0),
FoodDao.Properties.StartDate.le(currentTime),
FoodDao.Properties.EndDate.ge(currentTime))).orderAsc(FoodDao.Properties.SeqNo).list();
}
......
......@@ -200,10 +200,12 @@ public class ModifierDaoUtils {
ArrayList<Modifier> fms = new ArrayList<>();
// QueryBuilder<Modifier> queryBuilder = mManager.getDaoSession().queryBuilder(Modifier.class);
String parentSql = "SELECT * FROM MODIFIER WHERE MOD_MSG=1 and VISIBLE=0 and IS_PARENT=1";
// String parentSql = "SELECT * FROM MODIFIER WHERE MOD_MSG=1 and VISIBLE=0 and IS_PARENT=1";
String parentSql = "SELECT * FROM MODIFIER WHERE MOD_MSG=1 and IS_PARENT=1";
List<Modifier> parentModifiers = query_modifier_Child_new(parentSql, 0);
String childSql = "SELECT * FROM MODIFIER WHERE MOD_MSG=1 and VISIBLE=0 and IS_PARENT=0";
// String childSql = "SELECT * FROM MODIFIER WHERE MOD_MSG=1 and VISIBLE=0 and IS_PARENT=0";
String childSql = "SELECT * FROM MODIFIER WHERE MOD_MSG=1 and IS_PARENT=0";
List<Modifier> childModifiers = query_modifier_Child_new(childSql, 0);
fms.addAll(parentModifiers);
......@@ -233,10 +235,12 @@ public class ModifierDaoUtils {
// ModifierDao.Properties.Visible.eq(visible),
// ModifierDao.Properties.IsParent.eq(0))).orderAsc(ModifierDao.Properties.SeqNo).list();
String parentSql = "SELECT * FROM MODIFIER WHERE MOD_TASTE=1 and VISIBLE=0 and IS_PARENT=1";
// String parentSql = "SELECT * FROM MODIFIER WHERE MOD_TASTE=1 and VISIBLE=0 and IS_PARENT=1";
String parentSql = "SELECT * FROM MODIFIER WHERE MOD_TASTE=1 and IS_PARENT=1";
List<Modifier> parentModifiers = query_modifier_Child_new(parentSql, 0);
String childSql = "SELECT * FROM MODIFIER WHERE MOD_TASTE=1 and VISIBLE=0 and IS_PARENT=0";
// String childSql = "SELECT * FROM MODIFIER WHERE MOD_TASTE=1 and VISIBLE=0 and IS_PARENT=0";
String childSql = "SELECT * FROM MODIFIER WHERE MOD_TASTE=1 and IS_PARENT=0";
List<Modifier> childModifiers = query_modifier_Child_new(childSql, 0);
fms.addAll(parentModifiers);
......@@ -266,10 +270,12 @@ public class ModifierDaoUtils {
// ModifierDao.Properties.Visible.eq(visible),
// ModifierDao.Properties.IsParent.eq(0))).orderAsc(ModifierDao.Properties.SeqNo).list();
String parentSql = "SELECT * FROM MODIFIER WHERE MOD_COMM=1 and VISIBLE=0 and IS_PARENT=1";
// String parentSql = "SELECT * FROM MODIFIER WHERE MOD_COMM=1 and VISIBLE=0 and IS_PARENT=1";
String parentSql = "SELECT * FROM MODIFIER WHERE MOD_COMM=1 and IS_PARENT=1";
List<Modifier> parentModifiers = query_modifier_Child_new(parentSql, 0);
String childSql = "SELECT * FROM MODIFIER WHERE MOD_COMM=1 and VISIBLE=0 and IS_PARENT=0";
// String childSql = "SELECT * FROM MODIFIER WHERE MOD_COMM=1 and VISIBLE=0 and IS_PARENT=0";
String childSql = "SELECT * FROM MODIFIER WHERE MOD_COMM=1 and IS_PARENT=0";
List<Modifier> childModifiers = query_modifier_Child_new(childSql, 0);
fms.addAll(parentModifiers);
......@@ -318,8 +324,8 @@ public class ModifierDaoUtils {
// String sql = " SELECT MODIFIER.mid,MODIFIER_NAME,MODIFIER_NAME1,MODIFIER_NAME2,TOP_ID,PRICE,MOD_COMM,MOD_TASTE,MOD_MSG,VISIBLE,MULTIPLE,IS_PARENT" +
// " FROM MODIFIER join FOOD_MODIFIER on MODIFIER.MID=FOOD_MODIFIER.MID where MODIFIER.VISIBLE=0 and FOOD_MODIFIER.FID='" + fid + "' order by FOOD_MODIFIER.seq,MODIFIER.SEQ_NO";
String sql = " SELECT MODIFIER.MID,MODIFIER_NAME,MODIFIER_NAME1,MODIFIER_NAME2,TOP_ID,PRICE,MOD_COMM,MOD_TASTE,MOD_MSG,VISIBLE,MULTIPLE,IS_PARENT,MAX_QTY,MIN_QTY" +
" FROM MODIFIER join FOOD_MODIFIER fm on MODIFIER.MID=FOOD_MODIFIER.MID where MODIFIER.INVISIBLE=0 and FOOD_MODIFIER.FID='" + fid + "' order by FOOD_MODIFIER.SEQ_NO,MODIFIER.SEQ_NO";
String sql = " SELECT MODIFIER.MID,MODIFIER_NAME,MODIFIER_NAME1,MODIFIER_NAME2,TOP_ID,PRICE,MOD_COMM,MOD_TASTE,MOD_MSG,INVISIBLE,VISIBLE,MULTIPLE,IS_PARENT,MAX_QTY,MIN_QTY" +
" FROM MODIFIER join FOOD_MODIFIER fm on MODIFIER.MID=FOOD_MODIFIER.MID where MODIFIER.INVISIBLE!=1 and FOOD_MODIFIER.FID='" + fid + "' order by FOOD_MODIFIER.SEQ_NO,MODIFIER.SEQ_NO";
List<Modifier> mfs_child = new ArrayList<>();
......@@ -331,15 +337,15 @@ public class ModifierDaoUtils {
switch (mode) {
case modifierMode_All:
sqlstr = " SELECT m.MID,MODIFIER_NAME,MODIFIER_NAME1,MODIFIER_NAME2,TOP_ID,PRICE,MOD_COMM,MOD_TASTE,MOD_MSG,VISIBLE,MULTIPLE,IS_PARENT,DEFMODIFIER,MAX_QTY,MIN_QTY" +
" FROM MODIFIER m join FOOD_MODIFIER fm on m.TOP_ID=fm.MID where m.INVISIBLE=0 and m.IS_PARENT=1 and fm.FID='" + fid + "' order by fm.SEQ_NO,m.SEQ_NO";
sqlstr = " SELECT m.MID,MODIFIER_NAME,MODIFIER_NAME1,MODIFIER_NAME2,TOP_ID,PRICE,MOD_COMM,MOD_TASTE,MOD_MSG,INVISIBLE,VISIBLE,MULTIPLE,IS_PARENT,DEFMODIFIER,MAX_QTY,MIN_QTY" +
" FROM MODIFIER m join FOOD_MODIFIER fm on m.TOP_ID=fm.MID where m.INVISIBLE!=1 and m.IS_PARENT=1 and fm.FID='" + fid + "' order by fm.SEQ_NO,m.SEQ_NO";
mfs_child1 = query_modifier_Child_new(sqlstr, fid);
List<Modifier> mfs_child2 = new ArrayList<>();
sqlstr = " SELECT m.MID,MODIFIER_NAME,MODIFIER_NAME1,MODIFIER_NAME2,TOP_ID,PRICE,MOD_COMM,MOD_TASTE,MOD_MSG,VISIBLE,MULTIPLE,IS_PARENT,DEFMODIFIER,MAX_QTY,MIN_QTY" +
" FROM MODIFIER m join FOOD_MODIFIER fm on m.TOP_ID=fm.MID where m.INVISIBLE=0 and m.IS_PARENT=0 and fm.FID='" + fid + "' order by fm.SEQ_NO,m.SEQ_NO";
sqlstr = " SELECT m.MID,MODIFIER_NAME,MODIFIER_NAME1,MODIFIER_NAME2,TOP_ID,PRICE,MOD_COMM,MOD_TASTE,MOD_MSG,INVISIBLE,VISIBLE,MULTIPLE,IS_PARENT,DEFMODIFIER,MAX_QTY,MIN_QTY" +
" FROM MODIFIER m join FOOD_MODIFIER fm on m.TOP_ID=fm.MID where m.INVISIBLE!=1 and m.IS_PARENT=0 and fm.FID='" + fid + "' order by fm.SEQ_NO,m.SEQ_NO";
mfs_child2 = query_modifier_Child_new(sqlstr, fid);
mfs_child1.addAll(mfs_child2);
......@@ -391,6 +397,7 @@ public class ModifierDaoUtils {
order.setModMsg(c.getLong(c.getColumnIndex("MOD_MSG")));
order.setModTaste(c.getLong(c.getColumnIndex("MOD_TASTE")));
order.setMultiple(c.getDouble(c.getColumnIndex("MULTIPLE")));
order.setInvisible(c.getLong(c.getColumnIndex("INVISIBLE")));
if (fid != 0) {
//非公共細項
order.setMaxNumber(String.valueOf(c.getInt(c.getColumnIndex("MAX_QTY"))));
......
......@@ -13,6 +13,7 @@ import com.gingersoft.gsa.cloud.base.common.bean.mealManage.MyOrderManage;
import com.gingersoft.gsa.cloud.base.common.bean.mealManage.OpenTableManage;
import com.gingersoft.gsa.cloud.base.utils.log.LogUtil;
import com.gingersoft.gsa.cloud.base.utils.toast.ToastUtils;
import com.gingersoft.gsa.cloud.ui.widget.dialog.CommonTipDialog;
import com.google.gson.JsonIOException;
import com.google.gson.JsonParseException;
import com.jess.arms.utils.ArmsUtils;
......@@ -73,7 +74,7 @@ public class MyResponseErrorListener implements ResponseErrorListener {
Activity activity = GsaCloudApplication.getAppContext().getCurrentActivity();
if (!showloggedDialog && activity != null) {
showloggedDialog = true;
showloggedDialog(activity, ArmsUtils.getString(context, R.string.response_error_request_logged));
showloggedDialog(activity,ArmsUtils.getString(context, R.string.response_error_request_logged));
}
} else {
msg = httpException.message();
......@@ -81,12 +82,13 @@ public class MyResponseErrorListener implements ResponseErrorListener {
return msg;
}
private void showloggedDialog(Activity context, String msg) {
private void showloggedDialog(Activity context,String msg) {
QMUIDialog.MessageDialogBuilder dialogBuilder = new QMUIDialog.MessageDialogBuilder(context);
dialogBuilder.setTitle("溫馨提示");
dialogBuilder.setMessage(msg);
dialogBuilder.setTitleIcon(R.drawable.qmui_icon_dialog_warn);
dialogBuilder.addAction(0, "確認", QMUIDialogAction.ACTION_PROP_NEGATIVE, (dialog, index) -> {
//清空用戶信息
GsaCloudApplication.clearMemberInfo();
//清空賬單數據
MyOrderManage.getInstance().clear();
//清空開檯數據
......
......@@ -7,6 +7,9 @@ import com.gingersoft.gsa.cloud.base.BuildConfig;
import com.jess.arms.base.delegate.AppLifecycles;
import com.squareup.leakcanary.LeakCanary;
import com.squareup.leakcanary.RefWatcher;
import me.yokeyword.fragmentation.Fragmentation;
import me.yokeyword.fragmentation.helper.ExceptionHandler;
//import com.alibaba.android.arouter.launcher.ARouter;
......@@ -18,7 +21,7 @@ public class MyAppLifecycles implements AppLifecycles {
public void onCreate(Application application) {
// initTimber();
initLeakCanary(application);
// initFragmentation();
initFragmentation();
// initARouter(application);
}
......@@ -41,24 +44,24 @@ public class MyAppLifecycles implements AppLifecycles {
// ARouter.init(application);
}
// private void initFragmentation() {
// Fragmentation.builder()
// // 设置 栈视图 模式为 悬浮球模式 SHAKE: 摇一摇唤出 默认NONE:隐藏, 仅在Debug环境生效
private void initFragmentation() {
Fragmentation.builder()
// 设置 栈视图 模式为 悬浮球模式 SHAKE: 摇一摇唤出 默认NONE:隐藏, 仅在Debug环境生效
// .stackViewMode(Fragmentation.BUBBLE)
// // 开发环境:true时,遇到异常:"Can not perform this action after onSaveInstanceState!"时,抛出,并Crash;
// // 生产环境:false时,不抛出,不会Crash,会捕获,可以在handleException()里监听到
// .debug(BuildConfig.DEBUG)
// // 生产环境时,捕获上述异常(避免crash),会捕获
// // 建议在回调处上传下面异常到崩溃监控服务器
// .handleException(new ExceptionHandler() {
// @Override
// public void onException(Exception e) {
// // 以Bugtags为例子: 把捕获到的 Exception 传到 Bugtags 后台。
// // Bugtags.sendException(e);
// }
// })
// .install();
// }
// 开发环境:true时,遇到异常:"Can not perform this action after onSaveInstanceState!"时,抛出,并Crash;
// 生产环境:false时,不抛出,不会Crash,会捕获,可以在handleException()里监听到
.debug(BuildConfig.DEBUG)
// 生产环境时,捕获上述异常(避免crash),会捕获
// 建议在回调处上传下面异常到崩溃监控服务器
.handleException(new ExceptionHandler() {
@Override
public void onException(Exception e) {
// 以Bugtags为例子: 把捕获到的 Exception 传到 Bugtags 后台。
// Bugtags.sendException(e);
}
})
.install();
}
private void initLeakCanary(Application application) {
......
......@@ -8,7 +8,8 @@ import com.gingersoft.gsa.cloud.base.R;
import com.gingersoft.gsa.cloud.base.R2;
import com.gingersoft.gsa.cloud.ui.bean.view.SectionHeader;
import com.gingersoft.gsa.cloud.ui.bean.view.SectionTextItem;
import com.gingersoft.gsa.cloud.ui.view.BaseTextSection;
import com.gingersoft.gsa.cloud.ui.view.section.BaseTextSection;
import com.gingersoft.gsa.cloud.ui.view.section.QDSectionHeaderView;
import com.qmuiteam.qmui.widget.section.QMUIDefaultStickySectionAdapter;
import com.qmuiteam.qmui.widget.section.QMUISection;
import com.qmuiteam.qmui.widget.section.QMUIStickySectionAdapter;
......@@ -29,7 +30,7 @@ public class BasTextSectiontAdapter extends QMUIDefaultStickySectionAdapter<Sect
@NonNull
@Override
protected QMUIStickySectionAdapter.ViewHolder onCreateSectionHeaderViewHolder(@NonNull ViewGroup viewGroup) {
return new QMUIStickySectionAdapter.ViewHolder(new BaseTextSection(viewGroup.getContext()));
return new QMUIStickySectionAdapter.ViewHolder(new QDSectionHeaderView(viewGroup.getContext()));
}
@NonNull
......@@ -41,8 +42,15 @@ public class BasTextSectiontAdapter extends QMUIDefaultStickySectionAdapter<Sect
@Override
protected void onBindSectionHeader(QMUIStickySectionAdapter.ViewHolder holder, int position, QMUISection<SectionHeader, SectionTextItem> section) {
super.onBindSectionHeader(holder, position, section);
BaseTextSection itemView = (BaseTextSection) holder.itemView;
QDSectionHeaderView itemView = (QDSectionHeaderView) holder.itemView;
itemView.render(section.getHeader(), section.isFold());
itemView.getArrowView().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int pos = holder.isForStickyHeader ? position : holder.getAdapterPosition();
toggleFold(pos, false);
}
});
}
@Override
......
......@@ -8,7 +8,7 @@ import com.gingersoft.gsa.cloud.base.R;
import com.gingersoft.gsa.cloud.base.R2;
import com.gingersoft.gsa.cloud.ui.bean.view.SectionHeader;
import com.gingersoft.gsa.cloud.ui.bean.view.SectionImageItem;
import com.gingersoft.gsa.cloud.ui.view.BaseTextSection;
import com.gingersoft.gsa.cloud.ui.view.section.BaseTextSection;
import com.qmuiteam.qmui.widget.section.QMUIDefaultStickySectionAdapter;
import com.qmuiteam.qmui.widget.section.QMUISection;
import com.qmuiteam.qmui.widget.section.QMUIStickySectionAdapter;
......
......@@ -136,4 +136,23 @@ public class SectionTextItem3 {
return sectionTextItem3List;
}
public static SectionTextItem3 roundingTransSectionTextItem3(double amuout) {
SectionTextItem3 sectionTextItem3 = new SectionTextItem3();
sectionTextItem3.setLeftText("賬單小數");
sectionTextItem3.setCenterText(String.valueOf(0));
sectionTextItem3.setRightText(String.valueOf(amuout));
sectionTextItem3.setLeftTextStyle(R.style.order_paymethod_text_style);
sectionTextItem3.setRightTextStyle(R.style.order_paymethod_text_style);
return sectionTextItem3;
}
public static SectionTextItem3 serviceAmountTransSectionTextItem3(double amuout) {
SectionTextItem3 sectionTextItem3 = new SectionTextItem3();
sectionTextItem3.setLeftText("服务费");
sectionTextItem3.setCenterText(String.valueOf(0));
sectionTextItem3.setRightText(String.valueOf(amuout));
sectionTextItem3.setLeftTextStyle(R.style.order_paymethod_text_style);
sectionTextItem3.setRightTextStyle(R.style.order_paymethod_text_style);
return sectionTextItem3;
}
}
/*
* Tencent is pleased to support the open source community by making QMUI_Android available.
*
* Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* http://opensource.org/licenses/MIT
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.gingersoft.gsa.cloud.ui.view.qm;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.Gravity;
import android.widget.FrameLayout;
import com.qmuiteam.qmui.util.QMUIDisplayHelper;
import com.qmuiteam.qmui.widget.QMUILoadingView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public class QDLoadingItemView extends FrameLayout {
private QMUILoadingView mLoadingView;
public QDLoadingItemView(@NonNull Context context) {
this(context, null);
}
public QDLoadingItemView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mLoadingView = new QMUILoadingView(context,
QMUIDisplayHelper.dp2px(context, 24), Color.LTGRAY);
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
lp.gravity = Gravity.CENTER;
addView(mLoadingView, lp);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(
QMUIDisplayHelper.dp2px(getContext(), 48), MeasureSpec.EXACTLY));
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mLoadingView.start();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mLoadingView.stop();
}
}
package com.gingersoft.gsa.cloud.ui.view;
package com.gingersoft.gsa.cloud.ui.view.section;
import android.content.Context;
import android.graphics.Color;
......@@ -6,11 +6,14 @@ import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.gingersoft.gsa.cloud.base.R;
import com.gingersoft.gsa.cloud.ui.bean.view.SectionHeader;
import com.qmuiteam.qmui.util.QMUIDisplayHelper;
import androidx.annotation.Nullable;
/**
......@@ -52,7 +55,12 @@ public class BaseTextSection extends LinearLayout {
public void render(SectionHeader header, boolean isFold) {
mTitleTv.setText(header.getText());
}
//
public void setBackgroundColor(int color) {
if (color != -1)
setBackgroundColor(color);
}
// @Override
// protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(headerHeight, MeasureSpec.EXACTLY));
......
/*
* Tencent is pleased to support the open source community by making QMUI_Android available.
*
* Copyright (C) 2017-2018 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the MIT License (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* http://opensource.org/licenses/MIT
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.gingersoft.gsa.cloud.ui.view.section;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.gingersoft.gsa.cloud.base.R;
import com.gingersoft.gsa.cloud.ui.bean.view.SectionHeader;
import com.qmuiteam.qmui.util.QMUIDisplayHelper;
import com.qmuiteam.qmui.util.QMUIResHelper;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatImageView;
public class QDSectionHeaderView extends LinearLayout {
private TextView mTitleTv;
private ImageView mArrowView;
private int headerHeight = QMUIDisplayHelper.dp2px(getContext(), 56);
public QDSectionHeaderView(Context context) {
this(context, null);
}
public QDSectionHeaderView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
setOrientation(LinearLayout.HORIZONTAL);
setGravity(Gravity.CENTER_VERTICAL);
setBackgroundColor(Color.WHITE);
int paddingHor = QMUIDisplayHelper.dp2px(context, 20);
mTitleTv = new TextView(getContext());
mTitleTv.setTextSize(16);
mTitleTv.setTextColor(Color.BLACK);
mTitleTv.setPadding(paddingHor, 0, paddingHor, 0);
addView(mTitleTv, new LinearLayout.LayoutParams(
0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f));
mArrowView = new AppCompatImageView(context);
mArrowView.setImageDrawable(QMUIResHelper.getAttrDrawable(getContext(),
R.attr.qmui_common_list_item_chevron));
mArrowView.setScaleType(ImageView.ScaleType.CENTER);
addView(mArrowView, new LinearLayout.LayoutParams(headerHeight, headerHeight));
}
public ImageView getArrowView() {
return mArrowView;
}
public void render(SectionHeader header, boolean isFold) {
mTitleTv.setText(header.getText());
mArrowView.setRotation(isFold ? 0f : 90f);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec,
MeasureSpec.makeMeasureSpec(headerHeight, MeasureSpec.EXACTLY));
}
}
......@@ -35,9 +35,9 @@ public class CommonTipDialog {
dialogBuilder.setTitleIcon(R.drawable.qmui_icon_dialog_doubt);
dialogBuilder.setMessage(msg);
if(!TextUtils.isEmpty(methodName)) {
dialogBuilder.addAction("取消", (dialog, index) -> dialog.dismiss());
dialogBuilder.addAction(R.drawable.shape_3c_cancel_btn_bg,"取消", (dialog, index) -> dialog.dismiss());
}
dialogBuilder.addAction(0, "確認", QMUIDialogAction.ACTION_PROP_NEGATIVE, (dialog, index) -> {
dialogBuilder.addAction(R.drawable.shape_red_five_radius_bg, "確認", QMUIDialogAction.ACTION_PROP_NEGATIVE, (dialog, index) -> {
dialog.dismiss();
if(TextUtils.isEmpty(methodName)){
return;
......
......@@ -9,18 +9,30 @@ project.dependencies.add('api', project(':cc')) //用最新版
//project.dependencies.add('api', "com.billy.android:cc:2.1.6") //用最新版
dependencies {
if (project.name != 'base-module' && project.name != 'arms' && project.name != 'qm-qmui') {
if (project.name != 'base-module' && project.name != 'arms' && project.name != 'fragmentation_core' && project.name != 'qm-qmui' && project.name != 'qm-arch' && project.name != 'qm-skin-maker') {
api project(':base-module')
}
if (project.name != 'arms') {
implementation project(':arms')
if (project.name != 'arms' && project.name != 'fragmentation_core' && project.name != 'qm-qmui' && project.name != 'qm-arch' && project.name != 'qm-skin-maker') {
api project(':arms')
}
//
if (project.name != 'qm-qmui' && project.name != 'arms') {
if (project.name != 'qm-qmui' && project.name != 'arms' && project.name != 'fragmentation_core' && project.name != 'qm-arch' && project.name != 'qm-skin-maker') {
// if (project.name != 'arms') {
implementation project(':qm-qmui')
api project(':qm-qmui')
// implementation rootProject.ext.dependencies["qmui"]
}
if (project.name != 'qm-arch' && project.name != 'qm-qmui' && project.name != 'base-module' && project.name != 'qm-skin-maker') {
api project(':qm-arch')
}
if (project.name != 'qm-skin-maker' && project.name != 'qm-arch' && project.name != 'qm-qmui') {
api project(':qm-skin-maker')
}
// if (project.name == 'main-module') {
// api project(':updateApk')
// }
// if (project.name == 'arms') {
// api project(':fragmentation_core')
// }
implementation rootProject.ext.dependencies["retrofit-url-manager"]
annotationProcessor rootProject.ext.dependencies["butterknife-compiler"]
// annotationProcessor rootProject.ext.dependencies["dagger2-compiler"]//依赖插件
......
......@@ -18,7 +18,7 @@ ext {
rxlifecycleSdkVersion : "1.0",
rxlifecycle2SdkVersion : "2.2.1",
espressoSdkVersion : "3.0.1",
// fragmentationVersion : "1.1.6",
fragmentationVersion : "1.3.8",
canarySdkVersion : "1.5.4"
]
......@@ -92,9 +92,9 @@ ext {
"progressmanager" : "me.jessyan:progressmanager:1.5.0",
"retrofit-url-manager" : "me.jessyan:retrofit-url-manager:1.4.0",
"lifecyclemodel" : "me.jessyan:lifecyclemodel:1.0.1",
// "fragmentation" : "me.yokeyword:fragmentation:${version["fragmentationVersion"]}",
// "fragmentation-core" : "me.yokeyword:fragmentation-core:${version["fragmentationVersion"]}",
// "fragmentation-swipeback" : "me.yokeyword:fragmentation-swipeback:${version["fragmentationVersion"]}",
// "fragmentation" : "me.yokeyword:fragmentation:${version["fragmentationVersion"]}",
// "fragmentation-core" : "me.yokeyword:fragmentation-core:${version["fragmentationVersion"]}",
// "fragmentation-swipeback" : "me.yokeyword:fragmentation-swipeback:${version["fragmentationVersion"]}",
"constraintlayout" : "androidx.constraintlayout:constraintlayout:1.1.3",//constraintlayout約束佈局
//test
......
......@@ -49,7 +49,7 @@ public interface DownloadContract {
List<Food> queryDB_FoodList(Context context, int parentId);
Observable<FunctionRespone> downFunctionList();
Observable<FunctionRespone> downFunctionList(long userId);
Observable<FoodBean> downFoodList(int restaurantId);
......
......@@ -72,9 +72,9 @@ public class DownloadModel extends BaseModel implements DownloadContract.Model {
}
@Override
public Observable<FunctionRespone> downFunctionList() {
public Observable<FunctionRespone> downFunctionList(long userId) {
return mRepositoryManager.obtainRetrofitService(DownloadService.class)
.downFunctionList();
.downFunctionList(userId);
}
@Override
......
......@@ -20,7 +20,7 @@ import retrofit2.http.Query;
public interface DownloadService {
@GET("user/resource/list" + RetrofitUrlManager.IDENTIFICATION_PATH_SIZE + 2)
Observable<FunctionRespone> downFunctionList();
Observable<FunctionRespone> downFunctionList(@Query("userId") long userId);
@GET(Api.food_list + RetrofitUrlManager.IDENTIFICATION_PATH_SIZE + 2)
Observable<FoodBean> downFoodList(@Query("restaurantId") int restaurantId);
......
......@@ -117,6 +117,18 @@ public class DownloadActivity extends BaseActivity<DownloadPresenter> implements
mWaveHelper.cancel();
}
// @Override
// protected void doOnBackPressed() {
// if (fromPage == 1) {
// CC.obtainBuilder("Component.Main")
// .setActionName("showMainActivity")
// .build()
// .call();
// }
// killMyself();
// }
@Override
public void onBackPressed() {
if (fromPage == 1) {
......
ext.alwaysLib = true //虽然apply了cc-settings-2.gradle,但一直作为library编译,否则别的组件依赖此module时会报错
apply from: rootProject.file("cc-settings.gradle")
android {
compileSdkVersion rootProject.ext.android["compileSdkVersion"]
useLibrary 'org.apache.http.legacy'
compileOptions {
targetCompatibility JavaVersion.VERSION_1_8
sourceCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
minSdkVersion rootProject.ext.android["minSdkVersion"]
targetSdkVersion rootProject.ext.android["targetSdkVersion"]
}
lintOptions {
abortOnError false
}
}
dependencies {
api(rootProject.ext.dependencies["appcompat-v7"]) {
exclude module: 'support-annotations'
exclude module: 'support-v4'
}
}
//publish {
// artifactId = 'fragmentation-core'
// userOrg = rootProject.userOrg
// groupId = rootProject.groupId
// uploadName = 'Fragmentation-Core'
// publishVersion = rootProject.publishVersion
// description = rootProject.desc
// website = rootProject.website
// licences = rootProject.licences
//}
\ No newline at end of file
# Fragmentation
-keep class * extends android.support.v4.app.FragmentManager{ *; }
\ No newline at end of file
<manifest package="me.yokeyword.fragmentation"
xmlns:android="http://schemas.android.com/apk/res/android">
<application/>
</manifest>
package androidx.fragment.app;
import java.util.List;
/**
* Created by YoKey on 16/1/22.
*/
public class FragmentationMagician {
public static boolean isStateSaved(FragmentManager fragmentManager) {
if (!(fragmentManager instanceof FragmentManagerImpl))
return false;
try {
FragmentManagerImpl fragmentManagerImpl = (FragmentManagerImpl) fragmentManager;
return fragmentManagerImpl.isStateSaved();
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* Like {@link FragmentManager#popBackStack()}} but allows the commit to be executed after an
* activity's state is saved. This is dangerous because the action can
* be lost if the activity needs to later be restored from its state, so
* this should only be used for cases where it is okay for the UI state
* to change unexpectedly on the user.
*/
public static void popBackStackAllowingStateLoss(final FragmentManager fragmentManager) {
FragmentationMagician.hookStateSaved(fragmentManager, new Runnable() {
@Override
public void run() {
fragmentManager.popBackStack();
}
});
}
/**
* Like {@link FragmentManager#popBackStackImmediate()}} but allows the commit to be executed after an
* activity's state is saved.
*/
public static void popBackStackImmediateAllowingStateLoss(final FragmentManager fragmentManager) {
FragmentationMagician.hookStateSaved(fragmentManager, new Runnable() {
@Override
public void run() {
fragmentManager.popBackStackImmediate();
}
});
}
/**
* Like {@link FragmentManager#popBackStackImmediate(String, int)}} but allows the commit to be executed after an
* activity's state is saved.
*/
public static void popBackStackAllowingStateLoss(final FragmentManager fragmentManager, final String name, final int flags) {
FragmentationMagician.hookStateSaved(fragmentManager, new Runnable() {
@Override
public void run() {
fragmentManager.popBackStack(name, flags);
}
});
}
/**
* Like {@link FragmentManager#executePendingTransactions()} but allows the commit to be executed after an
* activity's state is saved.
*/
public static void executePendingTransactionsAllowingStateLoss(final FragmentManager fragmentManager) {
FragmentationMagician.hookStateSaved(fragmentManager, new Runnable() {
@Override
public void run() {
fragmentManager.executePendingTransactions();
}
});
}
public static List<Fragment> getActiveFragments(FragmentManager fragmentManager) {
return fragmentManager.getFragments();
}
private static void hookStateSaved(FragmentManager fragmentManager, Runnable runnable) {
if (!(fragmentManager instanceof FragmentManagerImpl)) return;
FragmentManagerImpl fragmentManagerImpl = (FragmentManagerImpl) fragmentManager;
if (isStateSaved(fragmentManager)) {
// boolean tempStateSaved = fragmentManagerImpl.mStateSaved;
// boolean tempStopped = fragmentManagerImpl.mStopped;
// fragmentManagerImpl.mStateSaved = false;
// fragmentManagerImpl.mStopped = false;
runnable.run();
// fragmentManagerImpl.mStopped = tempStopped;
// fragmentManagerImpl.mStateSaved = tempStateSaved;
} else {
runnable.run();
}
}
}
\ No newline at end of file
package me.yokeyword.fragmentation;
import androidx.annotation.IntDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import me.yokeyword.fragmentation.helper.ExceptionHandler;
/**
* Created by YoKey on 17/2/5.
*/
public class Fragmentation {
/**
* Dont display stack view.
*/
public static final int NONE = 0;
/**
* Shake it to display stack view.
*/
public static final int SHAKE = 1;
/**
* As a bubble display stack view.
*/
public static final int BUBBLE = 2;
static volatile Fragmentation INSTANCE;
private boolean debug;
private int mode = BUBBLE;
private ExceptionHandler handler;
@IntDef({NONE, SHAKE, BUBBLE})
@Retention(RetentionPolicy.SOURCE)
@interface StackViewMode {
}
public static Fragmentation getDefault() {
if (INSTANCE == null) {
synchronized (Fragmentation.class) {
if (INSTANCE == null) {
INSTANCE = new Fragmentation(new FragmentationBuilder());
}
}
}
return INSTANCE;
}
Fragmentation(FragmentationBuilder builder) {
debug = builder.debug;
if (debug) {
mode = builder.mode;
} else {
mode = NONE;
}
handler = builder.handler;
}
public boolean isDebug() {
return debug;
}
public void setDebug(boolean debug) {
this.debug = debug;
}
public ExceptionHandler getHandler() {
return handler;
}
public void setHandler(ExceptionHandler handler) {
this.handler = handler;
}
public int getMode() {
return mode;
}
public void setMode(@StackViewMode int mode) {
this.mode = mode;
}
public static FragmentationBuilder builder() {
return new FragmentationBuilder();
}
public static class FragmentationBuilder {
private boolean debug;
private int mode;
private ExceptionHandler handler;
/**
* @param debug Suppressed Exception("Can not perform this action after onSaveInstanceState!") when debug=false
*/
public FragmentationBuilder debug(boolean debug) {
this.debug = debug;
return this;
}
/**
* Sets the mode to display the stack view
* <p>
* None if debug(false).
* <p>
* Default:NONE
*/
public FragmentationBuilder stackViewMode(@StackViewMode int mode) {
this.mode = mode;
return this;
}
/**
* @param handler Handled Exception("Can not perform this action after onSaveInstanceState!") when debug=false.
*/
public FragmentationBuilder handleException(ExceptionHandler handler) {
this.handler = handler;
return this;
}
public Fragmentation install() {
Fragmentation.INSTANCE = new Fragmentation(this);
return Fragmentation.INSTANCE;
}
}
}
package me.yokeyword.fragmentation;
import android.view.MotionEvent;
import me.yokeyword.fragmentation.anim.FragmentAnimator;
/**
* Created by YoKey on 17/6/13.
*/
public interface ISupportActivity {
SupportActivityDelegate getSupportDelegate();
ExtraTransaction extraTransaction();
FragmentAnimator getFragmentAnimator();
void setFragmentAnimator(FragmentAnimator fragmentAnimator);
FragmentAnimator onCreateFragmentAnimator();
void post(Runnable runnable);
void onBackPressed();
void onBackPressedSupport();
boolean dispatchTouchEvent(MotionEvent ev);
}
package me.yokeyword.fragmentation;
import android.os.Bundle;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import me.yokeyword.fragmentation.anim.FragmentAnimator;
/**
* Created by YoKey on 17/6/23.
*/
public interface ISupportFragment {
// LaunchMode
int STANDARD = 0;
int SINGLETOP = 1;
int SINGLETASK = 2;
// ResultCode
int RESULT_CANCELED = 0;
int RESULT_OK = -1;
@IntDef({STANDARD, SINGLETOP, SINGLETASK})
@Retention(RetentionPolicy.SOURCE)
public @interface LaunchMode {
}
SupportFragmentDelegate getSupportDelegate();
ExtraTransaction extraTransaction();
void enqueueAction(Runnable runnable);
void post(Runnable runnable);
void onEnterAnimationEnd(@Nullable Bundle savedInstanceState);
void onLazyInitView(@Nullable Bundle savedInstanceState);
void onSupportVisible();
void onSupportInvisible();
boolean isSupportVisible();
FragmentAnimator onCreateFragmentAnimator();
FragmentAnimator getFragmentAnimator();
void setFragmentAnimator(FragmentAnimator fragmentAnimator);
void setFragmentResult(int resultCode, Bundle bundle);
void onFragmentResult(int requestCode, int resultCode, Bundle data);
void onNewBundle(Bundle args);
void putNewBundle(Bundle newBundle);
boolean onBackPressedSupport();
}
package me.yokeyword.fragmentation;
import android.content.Context;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentationMagician;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import java.util.ArrayList;
import java.util.List;
/**
* Created by YoKey on 17/6/13.
*/
public class SupportHelper {
private static final long SHOW_SPACE = 200L;
private SupportHelper() {
}
/**
* 显示软键盘
*/
public static void showSoftInput(final View view) {
if (view == null || view.getContext() == null) return;
final InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
view.requestFocus();
view.postDelayed(new Runnable() {
@Override
public void run() {
imm.showSoftInput(view, InputMethodManager.SHOW_FORCED);
}
}, SHOW_SPACE);
}
/**
* 隐藏软键盘
*/
public static void hideSoftInput(View view) {
if (view == null || view.getContext() == null) return;
InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
/**
* 显示栈视图dialog,调试时使用
*/
public static void showFragmentStackHierarchyView(ISupportActivity support) {
support.getSupportDelegate().showFragmentStackHierarchyView();
}
/**
* 显示栈视图日志,调试时使用
*/
public static void logFragmentStackHierarchy(ISupportActivity support, String TAG) {
support.getSupportDelegate().logFragmentStackHierarchy(TAG);
}
/**
* 获得栈顶SupportFragment
*/
public static ISupportFragment getTopFragment(FragmentManager fragmentManager) {
return getTopFragment(fragmentManager, 0);
}
public static ISupportFragment getTopFragment(FragmentManager fragmentManager, int containerId) {
List<Fragment> fragmentList = FragmentationMagician.getActiveFragments(fragmentManager);
if (fragmentList == null) return null;
for (int i = fragmentList.size() - 1; i >= 0; i--) {
Fragment fragment = fragmentList.get(i);
if (fragment instanceof ISupportFragment) {
ISupportFragment iFragment = (ISupportFragment) fragment;
if (containerId == 0) return iFragment;
if (containerId == iFragment.getSupportDelegate().mContainerId) {
return iFragment;
}
}
}
return null;
}
/**
* 获取目标Fragment的前一个SupportFragment
*
* @param fragment 目标Fragment
*/
public static ISupportFragment getPreFragment(Fragment fragment) {
FragmentManager fragmentManager = fragment.getFragmentManager();
if (fragmentManager == null) return null;
List<Fragment> fragmentList = FragmentationMagician.getActiveFragments(fragmentManager);
if (fragmentList == null) return null;
int index = fragmentList.indexOf(fragment);
for (int i = index - 1; i >= 0; i--) {
Fragment preFragment = fragmentList.get(i);
if (preFragment instanceof ISupportFragment) {
return (ISupportFragment) preFragment;
}
}
return null;
}
/**
* Same as fragmentManager.findFragmentByTag(fragmentClass.getName());
* find Fragment from FragmentStack
*/
@SuppressWarnings("unchecked")
public static <T extends ISupportFragment> T findFragment(FragmentManager fragmentManager, Class<T> fragmentClass) {
return findStackFragment(fragmentClass, null, fragmentManager);
}
/**
* Same as fragmentManager.findFragmentByTag(fragmentTag);
* <p>
* find Fragment from FragmentStack
*/
@SuppressWarnings("unchecked")
public static <T extends ISupportFragment> T findFragment(FragmentManager fragmentManager, String fragmentTag) {
return findStackFragment(null, fragmentTag, fragmentManager);
}
/**
* 从栈顶开始,寻找FragmentManager以及其所有子栈, 直到找到状态为show & userVisible的Fragment
*/
public static ISupportFragment getActiveFragment(FragmentManager fragmentManager) {
return getActiveFragment(fragmentManager, null);
}
@SuppressWarnings("unchecked")
static <T extends ISupportFragment> T findStackFragment(Class<T> fragmentClass, String toFragmentTag, FragmentManager fragmentManager) {
Fragment fragment = null;
if (toFragmentTag == null) {
List<Fragment> fragmentList = FragmentationMagician.getActiveFragments(fragmentManager);
if (fragmentList == null) return null;
int sizeChildFrgList = fragmentList.size();
for (int i = sizeChildFrgList - 1; i >= 0; i--) {
Fragment brotherFragment = fragmentList.get(i);
if (brotherFragment instanceof ISupportFragment && brotherFragment.getClass().getName().equals(fragmentClass.getName())) {
fragment = brotherFragment;
break;
}
}
} else {
fragment = fragmentManager.findFragmentByTag(toFragmentTag);
if (fragment == null) return null;
}
return (T) fragment;
}
private static ISupportFragment getActiveFragment(FragmentManager fragmentManager, ISupportFragment parentFragment) {
List<Fragment> fragmentList = FragmentationMagician.getActiveFragments(fragmentManager);
if (fragmentList == null) {
return parentFragment;
}
for (int i = fragmentList.size() - 1; i >= 0; i--) {
Fragment fragment = fragmentList.get(i);
if (fragment instanceof ISupportFragment) {
if (fragment.isResumed() && !fragment.isHidden() && fragment.getUserVisibleHint()) {
return getActiveFragment(fragment.getChildFragmentManager(), (ISupportFragment) fragment);
}
}
}
return parentFragment;
}
/**
* Get the topFragment from BackStack
*/
public static ISupportFragment getBackStackTopFragment(FragmentManager fragmentManager) {
return getBackStackTopFragment(fragmentManager, 0);
}
/**
* Get the topFragment from BackStack
*/
public static ISupportFragment getBackStackTopFragment(FragmentManager fragmentManager, int containerId) {
int count = fragmentManager.getBackStackEntryCount();
for (int i = count - 1; i >= 0; i--) {
FragmentManager.BackStackEntry entry = fragmentManager.getBackStackEntryAt(i);
Fragment fragment = fragmentManager.findFragmentByTag(entry.getName());
if (fragment instanceof ISupportFragment) {
ISupportFragment supportFragment = (ISupportFragment) fragment;
if (containerId == 0) return supportFragment;
if (containerId == supportFragment.getSupportDelegate().mContainerId) {
return supportFragment;
}
}
}
return null;
}
@SuppressWarnings("unchecked")
static <T extends ISupportFragment> T findBackStackFragment(Class<T> fragmentClass, String toFragmentTag, FragmentManager fragmentManager) {
int count = fragmentManager.getBackStackEntryCount();
if (toFragmentTag == null) {
toFragmentTag = fragmentClass.getName();
}
for (int i = count - 1; i >= 0; i--) {
FragmentManager.BackStackEntry entry = fragmentManager.getBackStackEntryAt(i);
if (toFragmentTag.equals(entry.getName())) {
Fragment fragment = fragmentManager.findFragmentByTag(entry.getName());
if (fragment instanceof ISupportFragment) {
return (T) fragment;
}
}
}
return null;
}
static List<Fragment> getWillPopFragments(FragmentManager fm, String targetTag, boolean includeTarget) {
Fragment target = fm.findFragmentByTag(targetTag);
List<Fragment> willPopFragments = new ArrayList<>();
List<Fragment> fragmentList = FragmentationMagician.getActiveFragments(fm);
if (fragmentList == null) return willPopFragments;
int size = fragmentList.size();
int startIndex = -1;
for (int i = size - 1; i >= 0; i--) {
if (target == fragmentList.get(i)) {
if (includeTarget) {
startIndex = i;
} else if (i + 1 < size) {
startIndex = i + 1;
}
break;
}
}
if (startIndex == -1) return willPopFragments;
for (int i = size - 1; i >= startIndex; i--) {
Fragment fragment = fragmentList.get(i);
if (fragment != null && fragment.getView() != null) {
willPopFragments.add(fragment);
}
}
return willPopFragments;
}
}
package me.yokeyword.fragmentation.anim;
import android.os.Parcel;
import android.os.Parcelable;
import me.yokeyword.fragmentation.R;
/**
* Created by YoKeyword on 16/2/5.
*/
public class DefaultHorizontalAnimator extends FragmentAnimator implements Parcelable{
public DefaultHorizontalAnimator() {
enter = R.anim.h_fragment_enter;
exit = R.anim.h_fragment_exit;
popEnter = R.anim.h_fragment_pop_enter;
popExit = R.anim.h_fragment_pop_exit;
}
protected DefaultHorizontalAnimator(Parcel in) {
super(in);
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<DefaultHorizontalAnimator> CREATOR = new Creator<DefaultHorizontalAnimator>() {
@Override
public DefaultHorizontalAnimator createFromParcel(Parcel in) {
return new DefaultHorizontalAnimator(in);
}
@Override
public DefaultHorizontalAnimator[] newArray(int size) {
return new DefaultHorizontalAnimator[size];
}
};
}
package me.yokeyword.fragmentation.anim;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by YoKeyword on 16/2/15.
*/
public class DefaultNoAnimator extends FragmentAnimator implements Parcelable {
public DefaultNoAnimator() {
enter = 0;
exit = 0;
popEnter = 0;
popExit = 0;
}
protected DefaultNoAnimator(Parcel in) {
super(in);
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<DefaultNoAnimator> CREATOR = new Creator<DefaultNoAnimator>() {
@Override
public DefaultNoAnimator createFromParcel(Parcel in) {
return new DefaultNoAnimator(in);
}
@Override
public DefaultNoAnimator[] newArray(int size) {
return new DefaultNoAnimator[size];
}
};
}
package me.yokeyword.fragmentation.anim;
import android.os.Parcel;
import android.os.Parcelable;
import me.yokeyword.fragmentation.R;
/**
* Created by YoKeyword on 16/2/5.
*/
public class DefaultVerticalAnimator extends FragmentAnimator implements Parcelable{
public DefaultVerticalAnimator() {
enter = R.anim.v_fragment_enter;
exit = R.anim.v_fragment_exit;
popEnter = R.anim.v_fragment_pop_enter;
popExit = R.anim.v_fragment_pop_exit;
}
protected DefaultVerticalAnimator(Parcel in) {
super(in);
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<DefaultVerticalAnimator> CREATOR = new Creator<DefaultVerticalAnimator>() {
@Override
public DefaultVerticalAnimator createFromParcel(Parcel in) {
return new DefaultVerticalAnimator(in);
}
@Override
public DefaultVerticalAnimator[] newArray(int size) {
return new DefaultVerticalAnimator[size];
}
};
}
package me.yokeyword.fragmentation.anim;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.AnimRes;
/**
* Fragment动画实体类
* Created by YoKeyword on 16/2/4.
*/
public class FragmentAnimator implements Parcelable {
@AnimRes
protected int enter;
@AnimRes
protected int exit;
@AnimRes
protected int popEnter;
@AnimRes
protected int popExit;
public FragmentAnimator() {
}
public FragmentAnimator(int enter, int exit) {
this.enter = enter;
this.exit = exit;
}
public FragmentAnimator(int enter, int exit, int popEnter, int popExit) {
this.enter = enter;
this.exit = exit;
this.popEnter = popEnter;
this.popExit = popExit;
}
public FragmentAnimator copy() {
return new FragmentAnimator(getEnter(), getExit(), getPopEnter(), getPopExit());
}
protected FragmentAnimator(Parcel in) {
enter = in.readInt();
exit = in.readInt();
popEnter = in.readInt();
popExit = in.readInt();
}
public static final Creator<FragmentAnimator> CREATOR = new Creator<FragmentAnimator>() {
@Override
public FragmentAnimator createFromParcel(Parcel in) {
return new FragmentAnimator(in);
}
@Override
public FragmentAnimator[] newArray(int size) {
return new FragmentAnimator[size];
}
};
public int getEnter() {
return enter;
}
public FragmentAnimator setEnter(int enter) {
this.enter = enter;
return this;
}
public int getExit() {
return exit;
}
/**
* enter animation
*/
public FragmentAnimator setExit(int exit) {
this.exit = exit;
return this;
}
public int getPopEnter() {
return popEnter;
}
public FragmentAnimator setPopEnter(int popEnter) {
this.popEnter = popEnter;
return this;
}
public int getPopExit() {
return popExit;
}
public FragmentAnimator setPopExit(int popExit) {
this.popExit = popExit;
return this;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(enter);
dest.writeInt(exit);
dest.writeInt(popEnter);
dest.writeInt(popExit);
}
}
package me.yokeyword.fragmentation.debug;
import java.util.List;
/**
* 为了调试时 查看栈视图
* Created by YoKeyword on 16/2/21.
*/
public class DebugFragmentRecord {
public CharSequence fragmentName;
public List<DebugFragmentRecord> childFragmentRecord;
public DebugFragmentRecord(CharSequence fragmentName, List<DebugFragmentRecord> childFragmentRecord) {
this.fragmentName = fragmentName;
this.childFragmentRecord = childFragmentRecord;
}
}
package me.yokeyword.fragmentation.debug;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import androidx.annotation.NonNull;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
import me.yokeyword.fragmentation.R;
/**
* Created by YoKeyword on 16/2/21.
*/
public class DebugHierarchyViewContainer extends ScrollView {
private Context mContext;
private LinearLayout mLinearLayout;
private LinearLayout mTitleLayout;
private int mItemHeight;
private int mPadding;
public DebugHierarchyViewContainer(Context context) {
super(context);
initView(context);
}
public DebugHierarchyViewContainer(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
public DebugHierarchyViewContainer(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context);
}
private void initView(Context context) {
mContext = context;
HorizontalScrollView hScrollView = new HorizontalScrollView(context);
mLinearLayout = new LinearLayout(context);
mLinearLayout.setOrientation(LinearLayout.VERTICAL);
hScrollView.addView(mLinearLayout);
addView(hScrollView);
mItemHeight = dip2px(50);
mPadding = dip2px(16);
}
private int dip2px(float dp) {
float scale = mContext.getResources().getDisplayMetrics().density;
return (int) (dp * scale + 0.5f);
}
public void bindFragmentRecords(List<DebugFragmentRecord> fragmentRecords) {
mLinearLayout.removeAllViews();
LinearLayout ll = getTitleLayout();
mLinearLayout.addView(ll);
if (fragmentRecords == null) return;
DebugHierarchyViewContainer.this.setView(fragmentRecords, 0, null);
}
@NonNull
private LinearLayout getTitleLayout() {
if (mTitleLayout != null) return mTitleLayout;
mTitleLayout = new LinearLayout(mContext);
mTitleLayout.setPadding(dip2px(24), dip2px(24), 0, dip2px(8));
mTitleLayout.setOrientation(LinearLayout.HORIZONTAL);
ViewGroup.LayoutParams flParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
mTitleLayout.setLayoutParams(flParams);
TextView title = new TextView(mContext);
title.setText(R.string.fragmentation_stack_view);
title.setTextSize(20);
title.setTextColor(Color.BLACK);
LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
p.gravity = Gravity.CENTER_VERTICAL;
title.setLayoutParams(p);
mTitleLayout.addView(title);
ImageView img = new ImageView(mContext);
img.setImageResource(R.drawable.fragmentation_help);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.leftMargin = dip2px(16);
params.gravity = Gravity.CENTER_VERTICAL;
img.setLayoutParams(params);
mTitleLayout.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(mContext, R.string.fragmentation_stack_help, Toast.LENGTH_LONG).show();
}
});
mTitleLayout.addView(img);
return mTitleLayout;
}
private void setView(final List<DebugFragmentRecord> fragmentRecordList, final int hierarchy, final TextView tvItem) {
for (int i = fragmentRecordList.size() - 1; i >= 0; i--) {
DebugFragmentRecord child = fragmentRecordList.get(i);
int tempHierarchy = hierarchy;
final TextView childTvItem;
childTvItem = getTextView(child, tempHierarchy);
childTvItem.setTag(R.id.hierarchy, tempHierarchy);
final List<DebugFragmentRecord> childFragmentRecord = child.childFragmentRecord;
if (childFragmentRecord != null && childFragmentRecord.size() > 0) {
tempHierarchy++;
childTvItem.setCompoundDrawablesWithIntrinsicBounds(R.drawable.fragmentation_ic_right, 0, 0, 0);
final int finalChilHierarchy = tempHierarchy;
childTvItem.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (v.getTag(R.id.isexpand) != null) {
boolean isExpand = (boolean) v.getTag(R.id.isexpand);
if (isExpand) {
childTvItem.setCompoundDrawablesWithIntrinsicBounds(R.drawable.fragmentation_ic_right, 0, 0, 0);
DebugHierarchyViewContainer.this.removeView(finalChilHierarchy);
} else {
handleExpandView(childFragmentRecord, finalChilHierarchy, childTvItem);
}
v.setTag(R.id.isexpand, !isExpand);
} else {
childTvItem.setTag(R.id.isexpand, true);
handleExpandView(childFragmentRecord, finalChilHierarchy, childTvItem);
}
}
});
} else {
childTvItem.setPadding(childTvItem.getPaddingLeft() + mPadding, 0, mPadding, 0);
}
if (tvItem == null) {
mLinearLayout.addView(childTvItem);
} else {
mLinearLayout.addView(childTvItem, mLinearLayout.indexOfChild(tvItem) + 1);
}
}
}
private void handleExpandView(List<DebugFragmentRecord> childFragmentRecord, int finalChilHierarchy, TextView childTvItem) {
DebugHierarchyViewContainer.this.setView(childFragmentRecord, finalChilHierarchy, childTvItem);
childTvItem.setCompoundDrawablesWithIntrinsicBounds(R.drawable.fragmentation_ic_expandable, 0, 0, 0);
}
private void removeView(int hierarchy) {
int size = mLinearLayout.getChildCount();
for (int i = size - 1; i >= 0; i--) {
View view = mLinearLayout.getChildAt(i);
if (view.getTag(R.id.hierarchy) != null && (int) view.getTag(R.id.hierarchy) >= hierarchy) {
mLinearLayout.removeView(view);
}
}
}
private TextView getTextView(DebugFragmentRecord fragmentRecord, int hierarchy) {
TextView tvItem = new TextView(mContext);
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, mItemHeight);
tvItem.setLayoutParams(params);
if (hierarchy == 0) {
tvItem.setTextColor(Color.parseColor("#333333"));
tvItem.setTextSize(16);
}
tvItem.setGravity(Gravity.CENTER_VERTICAL);
tvItem.setPadding((int) (mPadding + hierarchy * mPadding * 1.5), 0, mPadding, 0);
tvItem.setCompoundDrawablePadding(mPadding / 2);
TypedArray a = mContext.obtainStyledAttributes(new int[]{android.R.attr.selectableItemBackground});
tvItem.setBackgroundDrawable(a.getDrawable(0));
a.recycle();
tvItem.setText(fragmentRecord.fragmentName);
return tvItem;
}
}
package me.yokeyword.fragmentation.exception;
import android.util.Log;
/**
* Perform the transaction action after onSaveInstanceState.
* <p>
* This is dangerous because the action can
* be lost if the activity needs to later be restored from its state.
* <p>
* <p>
* If you don't want to lost the action:
* <p>
* // // ReceiverActivity or Fragment:
* // void start() {
* // startActivityForResult(new Intent(this, SenderActivity.class), 100);
* // }
* //
* // @Override
* // protected void onActivityResult(int requestCode, int resultCode, Intent data) {
* // super.onActivityResult(requestCode, resultCode, data);
* // if (requestCode == 100 && resultCode == 100) {
* // // begin transaction
* // }
* // }
* //
* // // SenderActivity or Fragment:
* // void do(){ // Let ReceiverActivity(or Fragment)begin transaction
* // setResult(100);
* // finish();
* // }
* <p>
* Created by YoKey on 17/12/26.
*/
public class AfterSaveStateTransactionWarning extends RuntimeException {
public AfterSaveStateTransactionWarning(String action) {
super("Warning: Perform this " + action + " action after onSaveInstanceState!");
Log.w("Fragmentation", getMessage());
}
}
package me.yokeyword.fragmentation.helper;
import androidx.annotation.NonNull;
/**
* Created by YoKey on 17/2/5.
*/
public interface ExceptionHandler {
void onException(@NonNull Exception e);
}
package me.yokeyword.fragmentation.helper.internal;
import android.content.Context;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import me.yokeyword.fragmentation.R;
import me.yokeyword.fragmentation.anim.FragmentAnimator;
/**
* @Hide Created by YoKeyword on 16/7/26.
*/
public final class AnimatorHelper {
private Animation noneAnim, noneAnimFixed;
public Animation enterAnim, exitAnim, popEnterAnim, popExitAnim;
private Context context;
private FragmentAnimator fragmentAnimator;
public AnimatorHelper(Context context, FragmentAnimator fragmentAnimator) {
this.context = context;
notifyChanged(fragmentAnimator);
}
public void notifyChanged(FragmentAnimator fragmentAnimator) {
this.fragmentAnimator = fragmentAnimator;
initEnterAnim();
initExitAnim();
initPopEnterAnim();
initPopExitAnim();
}
public Animation getNoneAnim() {
if (noneAnim == null) {
noneAnim = AnimationUtils.loadAnimation(context, R.anim.no_anim);
}
return noneAnim;
}
public Animation getNoneAnimFixed() {
if (noneAnimFixed == null) {
noneAnimFixed = new Animation() {
};
}
return noneAnimFixed;
}
@Nullable
public Animation compatChildFragmentExitAnim(Fragment fragment) {
if ((fragment.getTag() != null && fragment.getTag().startsWith("android:switcher:") && fragment.getUserVisibleHint()) ||
(fragment.getParentFragment() != null && fragment.getParentFragment().isRemoving() && !fragment.isHidden())) {
Animation animation = new Animation() {
};
animation.setDuration(exitAnim.getDuration());
return animation;
}
return null;
}
private Animation initEnterAnim() {
if (fragmentAnimator.getEnter() == 0) {
enterAnim = AnimationUtils.loadAnimation(context, R.anim.no_anim);
} else {
enterAnim = AnimationUtils.loadAnimation(context, fragmentAnimator.getEnter());
}
return enterAnim;
}
private Animation initExitAnim() {
if (fragmentAnimator.getExit() == 0) {
exitAnim = AnimationUtils.loadAnimation(context, R.anim.no_anim);
} else {
exitAnim = AnimationUtils.loadAnimation(context, fragmentAnimator.getExit());
}
return exitAnim;
}
private Animation initPopEnterAnim() {
if (fragmentAnimator.getPopEnter() == 0) {
popEnterAnim = AnimationUtils.loadAnimation(context, R.anim.no_anim);
} else {
popEnterAnim = AnimationUtils.loadAnimation(context, fragmentAnimator.getPopEnter());
}
return popEnterAnim;
}
private Animation initPopExitAnim() {
if (fragmentAnimator.getPopExit() == 0) {
popExitAnim = AnimationUtils.loadAnimation(context, R.anim.no_anim);
} else {
popExitAnim = AnimationUtils.loadAnimation(context, fragmentAnimator.getPopExit());
}
return popExitAnim;
}
}
package me.yokeyword.fragmentation.helper.internal;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
/**
* @Hide
* Result 记录
* Created by YoKeyword on 16/6/2.
*/
public final class ResultRecord implements Parcelable {
public int requestCode;
public int resultCode = 0;
public Bundle resultBundle;
public ResultRecord() {
}
protected ResultRecord(Parcel in) {
requestCode = in.readInt();
resultCode = in.readInt();
resultBundle = in.readBundle(getClass().getClassLoader());
}
public static final Creator<ResultRecord> CREATOR = new Creator<ResultRecord>() {
@Override
public ResultRecord createFromParcel(Parcel in) {
return new ResultRecord(in);
}
@Override
public ResultRecord[] newArray(int size) {
return new ResultRecord[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(requestCode);
dest.writeInt(resultCode);
dest.writeBundle(resultBundle);
}
}
package me.yokeyword.fragmentation.helper.internal;
import android.view.View;
import java.util.ArrayList;
/**
* @hide Created by YoKey on 16/11/25.
*/
public final class TransactionRecord {
public String tag;
public int targetFragmentEnter = Integer.MIN_VALUE;
public int currentFragmentPopExit = Integer.MIN_VALUE;
public int currentFragmentPopEnter = Integer.MIN_VALUE;
public int targetFragmentExit = Integer.MIN_VALUE;
public boolean dontAddToBackStack = false;
public ArrayList<SharedElement> sharedElementList;
public static class SharedElement {
public View sharedElement;
public String sharedName;
public SharedElement(View sharedElement, String sharedName) {
this.sharedElement = sharedElement;
this.sharedName = sharedName;
}
}
}
package me.yokeyword.fragmentation.helper.internal;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import java.util.List;
import androidx.fragment.app.FragmentationMagician;
import me.yokeyword.fragmentation.ISupportFragment;
/**
* Created by YoKey on 17/4/4.
*/
public class VisibleDelegate {
private static final String FRAGMENTATION_STATE_SAVE_IS_INVISIBLE_WHEN_LEAVE = "fragmentation_invisible_when_leave";
private static final String FRAGMENTATION_STATE_SAVE_COMPAT_REPLACE = "fragmentation_compat_replace";
// SupportVisible相关
private boolean mIsSupportVisible;
private boolean mNeedDispatch = true;
private boolean mInvisibleWhenLeave;
private boolean mIsFirstVisible = true;
private boolean mFirstCreateViewCompatReplace = true;
private boolean mAbortInitVisible = false;
private Runnable taskDispatchSupportVisible;
private Handler mHandler;
private Bundle mSaveInstanceState;
private ISupportFragment mSupportF;
private Fragment mFragment;
public VisibleDelegate(ISupportFragment fragment) {
this.mSupportF = fragment;
this.mFragment = (Fragment) fragment;
}
public void onCreate(@Nullable Bundle savedInstanceState) {
if (savedInstanceState != null) {
mSaveInstanceState = savedInstanceState;
// setUserVisibleHint() may be called before onCreate()
mInvisibleWhenLeave = savedInstanceState.getBoolean(FRAGMENTATION_STATE_SAVE_IS_INVISIBLE_WHEN_LEAVE);
mFirstCreateViewCompatReplace = savedInstanceState.getBoolean(FRAGMENTATION_STATE_SAVE_COMPAT_REPLACE);
}
}
public void onSaveInstanceState(Bundle outState) {
outState.putBoolean(FRAGMENTATION_STATE_SAVE_IS_INVISIBLE_WHEN_LEAVE, mInvisibleWhenLeave);
outState.putBoolean(FRAGMENTATION_STATE_SAVE_COMPAT_REPLACE, mFirstCreateViewCompatReplace);
}
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
if (!mFirstCreateViewCompatReplace && mFragment.getTag() != null && mFragment.getTag().startsWith("android:switcher:")) {
return;
}
if (mFirstCreateViewCompatReplace) {
mFirstCreateViewCompatReplace = false;
}
initVisible();
}
private void initVisible() {
if (!mInvisibleWhenLeave && !mFragment.isHidden() && mFragment.getUserVisibleHint()) {
if ((mFragment.getParentFragment() != null && isFragmentVisible(mFragment.getParentFragment()))
|| mFragment.getParentFragment() == null) {
mNeedDispatch = false;
safeDispatchUserVisibleHint(true);
}
}
}
public void onResume() {
if (!mIsFirstVisible) {
if (!mIsSupportVisible && !mInvisibleWhenLeave && isFragmentVisible(mFragment)) {
mNeedDispatch = false;
dispatchSupportVisible(true);
}
} else {
if (mAbortInitVisible) {
mAbortInitVisible = false;
initVisible();
}
}
}
public void onPause() {
if (taskDispatchSupportVisible != null) {
getHandler().removeCallbacks(taskDispatchSupportVisible);
mAbortInitVisible = true;
return;
}
if (mIsSupportVisible && isFragmentVisible(mFragment)) {
mNeedDispatch = false;
mInvisibleWhenLeave = false;
dispatchSupportVisible(false);
} else {
mInvisibleWhenLeave = true;
}
}
public void onHiddenChanged(boolean hidden) {
if (!hidden && !mFragment.isResumed()) {
//if fragment is shown but not resumed, ignore...
onFragmentShownWhenNotResumed();
return;
}
if (hidden) {
safeDispatchUserVisibleHint(false);
} else {
enqueueDispatchVisible();
}
}
private void onFragmentShownWhenNotResumed() {
mInvisibleWhenLeave = false;
dispatchChildOnFragmentShownWhenNotResumed();
}
private void dispatchChildOnFragmentShownWhenNotResumed() {
FragmentManager fragmentManager = mFragment.getChildFragmentManager();
List<Fragment> childFragments = FragmentationMagician.getActiveFragments(fragmentManager);
if (childFragments != null) {
for (Fragment child : childFragments) {
if (child instanceof ISupportFragment && !child.isHidden() && child.getUserVisibleHint()) {
((ISupportFragment) child).getSupportDelegate().getVisibleDelegate().onFragmentShownWhenNotResumed();
}
}
}
}
public void onDestroyView() {
mIsFirstVisible = true;
}
public void setUserVisibleHint(boolean isVisibleToUser) {
if (mFragment.isResumed() || (!mFragment.isAdded() && isVisibleToUser)) {
if (!mIsSupportVisible && isVisibleToUser) {
safeDispatchUserVisibleHint(true);
} else if (mIsSupportVisible && !isVisibleToUser) {
dispatchSupportVisible(false);
}
}
}
private void safeDispatchUserVisibleHint(boolean visible) {
if (mIsFirstVisible) {
if (!visible) return;
enqueueDispatchVisible();
} else {
dispatchSupportVisible(visible);
}
}
private void enqueueDispatchVisible() {
taskDispatchSupportVisible = new Runnable() {
@Override
public void run() {
taskDispatchSupportVisible = null;
dispatchSupportVisible(true);
}
};
getHandler().post(taskDispatchSupportVisible);
}
private void dispatchSupportVisible(boolean visible) {
if (visible && isParentInvisible()) return;
if (mIsSupportVisible == visible) {
mNeedDispatch = true;
return;
}
mIsSupportVisible = visible;
if (visible) {
if (checkAddState()) return;
mSupportF.onSupportVisible();
if (mIsFirstVisible) {
mIsFirstVisible = false;
mSupportF.onLazyInitView(mSaveInstanceState);
}
dispatchChild(true);
} else {
dispatchChild(false);
mSupportF.onSupportInvisible();
}
}
private void dispatchChild(boolean visible) {
if (!mNeedDispatch) {
mNeedDispatch = true;
} else {
if (checkAddState()) return;
FragmentManager fragmentManager = mFragment.getChildFragmentManager();
List<Fragment> childFragments = FragmentationMagician.getActiveFragments(fragmentManager);
if (childFragments != null) {
for (Fragment child : childFragments) {
if (child instanceof ISupportFragment && !child.isHidden() && child.getUserVisibleHint()) {
((ISupportFragment) child).getSupportDelegate().getVisibleDelegate().dispatchSupportVisible(visible);
}
}
}
}
}
private boolean isParentInvisible() {
Fragment parentFragment = mFragment.getParentFragment();
if (parentFragment instanceof ISupportFragment) {
return !((ISupportFragment) parentFragment).isSupportVisible();
}
return parentFragment != null && !parentFragment.isVisible();
}
private boolean checkAddState() {
if (!mFragment.isAdded()) {
mIsSupportVisible = !mIsSupportVisible;
return true;
}
return false;
}
private boolean isFragmentVisible(Fragment fragment) {
return !fragment.isHidden() && fragment.getUserVisibleHint();
}
public boolean isSupportVisible() {
return mIsSupportVisible;
}
private Handler getHandler() {
if (mHandler == null) {
mHandler = new Handler(Looper.getMainLooper());
}
return mHandler;
}
}
package me.yokeyword.fragmentation.queue;
import androidx.fragment.app.FragmentManager;
/**
* Created by YoKey on 17/12/28.
*/
public abstract class Action {
public static final long DEFAULT_POP_TIME = 300L;
public static final int ACTION_NORMAL = 0;
public static final int ACTION_POP = 1;
public static final int ACTION_POP_MOCK = 2;
public static final int ACTION_BACK = 3;
public static final int ACTION_LOAD = 4;
public FragmentManager fragmentManager;
public int action = ACTION_NORMAL;
public long duration = 0;
public Action() {
}
public Action(int action) {
this.action = action;
}
public Action(int action, FragmentManager fragmentManager) {
this(action);
this.fragmentManager = fragmentManager;
}
public abstract void run();
}
package me.yokeyword.fragmentation.queue;
import android.os.Handler;
import android.os.Looper;
import java.util.LinkedList;
import java.util.Queue;
import me.yokeyword.fragmentation.ISupportFragment;
import me.yokeyword.fragmentation.SupportHelper;
/**
* The queue of perform action.
* <p>
* Created by YoKey on 17/12/29.
*/
public class ActionQueue {
private Queue<Action> mQueue = new LinkedList<>();
private Handler mMainHandler;
public ActionQueue(Handler mainHandler) {
this.mMainHandler = mainHandler;
}
public void enqueue(final Action action) {
if (isThrottleBACK(action)) return;
if (action.action == Action.ACTION_LOAD && mQueue.isEmpty()
&& Thread.currentThread() == Looper.getMainLooper().getThread()) {
action.run();
return;
}
mMainHandler.post(new Runnable() {
@Override
public void run() {
enqueueAction(action);
}
});
}
private void enqueueAction(Action action) {
mQueue.add(action);
if (mQueue.size() == 1) {
handleAction();
}
}
private void handleAction() {
if (mQueue.isEmpty()) return;
Action action = mQueue.peek();
action.run();
executeNextAction(action);
}
private void executeNextAction(Action action) {
if (action.action == Action.ACTION_POP) {
ISupportFragment top = SupportHelper.getBackStackTopFragment(action.fragmentManager);
action.duration = top == null ? Action.DEFAULT_POP_TIME : top.getSupportDelegate().getExitAnimDuration();
}
mMainHandler.postDelayed(new Runnable() {
@Override
public void run() {
mQueue.poll();
handleAction();
}
}, action.duration);
}
private boolean isThrottleBACK(Action action) {
if (action.action == Action.ACTION_BACK) {
Action head = mQueue.peek();
if (head != null && head.action == Action.ACTION_POP) {
return true;
}
}
return false;
}
}
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="300"
android:fromXDelta="100%p"
android:interpolator="@android:anim/decelerate_interpolator"
android:toXDelta="0"/>
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set
xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="300"
android:fromXDelta="0"
android:interpolator="@android:anim/accelerate_interpolator"
android:toXDelta="100%p"/>
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300">
<translate
android:fromXDelta="-26%p"
android:toXDelta="0"/>
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300">
<translate
android:fromXDelta="0%p"
android:toXDelta="-26%p"/>
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="0">
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300">
<alpha
android:fromAlpha="1.0"
android:toAlpha="1.0"/>
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
** Copyright 2009, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false"
android:zAdjustment="top">
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
android:interpolator="@android:anim/decelerate_interpolator"
android:fillEnabled="true"
android:fillBefore="false" android:fillAfter="true"
android:duration="200"/>
<translate android:fromYDelta="8%" android:toYDelta="0"
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
android:interpolator="@android:anim/decelerate_interpolator"
android:duration="300"/>
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
** Copyright 2009, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false" android:zAdjustment="top">
<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
android:interpolator="@android:anim/linear_interpolator"
android:fillEnabled="true"
android:fillBefore="false" android:fillAfter="true"
android:startOffset="100"
android:duration="150"/>
<translate android:fromYDelta="0%" android:toYDelta="8%"
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
android:interpolator="@android:anim/accelerate_interpolator"
android:duration="250"/>
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
** Copyright 2009, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
-->
<set xmlns:android="http://schemas.android.com/apk/res/android" android:zAdjustment="normal">
<alpha android:fromAlpha="0.7" android:toAlpha="1.0"
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
android:interpolator="@android:anim/accelerate_interpolator"
android:duration="250"/>
</set>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
** Copyright 2009, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:zAdjustment="normal">
<alpha android:fromAlpha="1.0" android:toAlpha="0.9"
android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true"
android:interpolator="@android:anim/decelerate_interpolator"
android:duration="300"/>
</set>
\ No newline at end of file
<resources>
<string name="fragmentation_stack_view">栈视图</string>
<string name="fragmentation_stack_help">*: 不在回退栈中\n☀: 可见的Fragment</string>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item type="id" name="hierarchy"></item>
<item type="id" name="isexpand"></item>
</resources>
\ No newline at end of file
<resources>
<string name="fragmentation_stack_view">Stack</string>
<string name="fragmentation_stack_help">*: Not in backStack\n☀: Visible</string>
</resources>
......@@ -4,11 +4,13 @@ import android.content.Intent;
import android.os.Bundle;
import android.widget.Button;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.billy.cc.core.component.CC;
import com.gingersoft.gsa.cloud.base.application.GsaCloudApplication;
import com.gingersoft.gsa.cloud.base.utils.other.SPUtils;
import com.gingersoft.gsa.cloud.constans.HttpsConstans;
......@@ -40,15 +42,25 @@ import static com.jess.arms.utils.Preconditions.checkNotNull;
*/
public class SwitchServerActivity extends BaseActivity<SwitchServerPresenter> implements SwitchServerContract.View {
@BindView(R2.id.radioGroup)
RadioGroup radioGroup;
@BindView(R2.id.rb_server_hk)
RadioButton rbHK;
@BindView(R2.id.rb_server_formal)
RadioButton rbFormal;
@BindView(R2.id.rb_youchang)
RadioButton rb_youchang;
@BindView(R2.id.rb_shiwei)
RadioButton rb_shiwei;
@BindView(R2.id.rb_shishu)
RadioButton rb_shishu;
@BindView(R2.id.btn_switch_server)
Button switchServer;
@BindView(R2.id.tv_now_server)
TextView tvNowServer;
private int[] rbIds = new int[]{R.id.rb_server_hk, R.id.rb_server_formal, R.id.rb_youchang, R.id.rb_shiwei, R.id.rb_shishu};
@Override
public void setupActivityComponent(@NonNull AppComponent appComponent) {
DaggerSwitchServerComponent //如找不到该类,请编译一下项目
......@@ -68,32 +80,92 @@ public class SwitchServerActivity extends BaseActivity<SwitchServerPresenter> im
public void initData(@Nullable Bundle savedInstanceState) {
String nowServer = HttpsConstans.ROOT_SERVER_ADDRESS_FORMAL;
tvNowServer.setText("當前服務器:" + nowServer);
if (HttpsConstans.isFormal) {
rbFormal.setChecked(true);
} else {
rbHK.setChecked(true);
}
setChecked((Integer) SPUtils.get(this, "isFormal", 2));
// if (HttpsConstans.isFormal) {
// rbFormal.setChecked(true);
// } else {
// rbHK.setChecked(true);
// }
rbHK.setText("測試服務器");
rbFormal.setText("正式服務器");
switchServer.setOnClickListener(v -> {
if (rbHK.isChecked()) {
SPUtils.put(this, "isFormal", false);
} else {
SPUtils.put(this, "isFormal", true);
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
for (int i = 0; i < rbIds.length; i++) {
if (rbIds[i] == checkedId) {
setChecked(i + 1);
break;
}
}
}
});
switchServer.setOnClickListener(v -> {
// if (rbHK.isChecked()) {
// SPUtils.put(this, "isFormal", false);
// } else {
// SPUtils.put(this, "isFormal", true);
// }
GsaCloudApplication.initDomainUrl();
GsaCloudApplication.isLogin = false;
CC.obtainBuilder("User.Component.Login")
.setActionName("showActivityA")
.build()
.call();
finish();
try {
Thread.sleep(2000);
System.exit(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
// try {
// Thread.sleep(2000);
// System.exit(0);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
});
}
private void setChecked(int i) {
switch (i) {
case 1:
rbHK.setChecked(false);
rbFormal.setChecked(true);
rb_youchang.setChecked(false);
rb_shiwei.setChecked(false);
rb_shishu.setChecked(false);
break;
case 2:
rbHK.setChecked(true);
rbFormal.setChecked(false);
rb_youchang.setChecked(false);
rb_shiwei.setChecked(false);
rb_shishu.setChecked(false);
break;
case 3:
rbHK.setChecked(false);
rbFormal.setChecked(false);
rb_youchang.setChecked(true);
rb_shiwei.setChecked(false);
rb_shishu.setChecked(false);
break;
case 4:
rbHK.setChecked(false);
rbFormal.setChecked(false);
rb_youchang.setChecked(false);
rb_shiwei.setChecked(true);
rb_shishu.setChecked(false);
break;
case 5:
rbHK.setChecked(false);
rbFormal.setChecked(false);
rb_youchang.setChecked(false);
rb_shiwei.setChecked(false);
rb_shishu.setChecked(true);
break;
}
SPUtils.put(this, "isFormal", i);
}
@Override
public void initIntent() {
......
......@@ -101,9 +101,11 @@ public class WelcomeActivity extends LoginInterfaceImpl<WelcomePresenter> implem
//自動登陸
String pwd = Aes.aesDecrypt((String) SPUtils.get(mContext, UserConstans.LOGIN_PASSWORD, ""));
mPresenter.login(SPUtils.get(mContext, UserConstans.LOGIN_USERNAME, "") + "", pwd);
// jumpMainActivity();
} else {
killMyself();
startActivity(new Intent(mContext, LoginActivity.class));
// jumpMainActivity();
}
}
}
......@@ -146,6 +148,14 @@ public class WelcomeActivity extends LoginInterfaceImpl<WelcomePresenter> implem
killMyself();
}
private void jumpMainActivity() {
CC.obtainBuilder("Component.Main")
.setActionName("showMainActivity")
.build()
.call();
killMyself();
}
private void updateUI(int position) {
mTvGuideTitle.setText(guideBeanList.get(position).getTitle());
mTvGuideDetails.setText(guideBeanList.get(position).getDetails());
......
......@@ -6,6 +6,7 @@
android:orientation="vertical">
<RadioGroup
android:id="@+id/radioGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content">
......@@ -26,6 +27,33 @@
android:text="正式環境"
android:textColor="@color/theme_333_color"
android:textSize="@dimen/sp_16" />
<RadioButton
android:id="@+id/rb_youchang"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/dp_10"
android:text="友常"
android:textColor="@color/theme_333_color"
android:textSize="@dimen/sp_16" />
<RadioButton
android:id="@+id/rb_shiwei"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/dp_10"
android:text="世维"
android:textColor="@color/theme_333_color"
android:textSize="@dimen/sp_16" />
<RadioButton
android:id="@+id/rb_shishu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/dp_10"
android:text="石书"
android:textColor="@color/theme_333_color"
android:textSize="@dimen/sp_16" />
</RadioGroup>
<TextView
......
<resources>
<string name="user_login_name" translatable="false">GSA-Cloud</string>
<string name="user_login_name" translatable="false">Ricepon POS</string>
<string name="user_login_welcome_login" translatable="false">歡迎登陸商戶端</string>
</resources>
......@@ -24,6 +24,7 @@ public class ComponentMain implements IComponent {
/**首頁- 管理*/
public static final FModule [] manager = {
new FModule("main/manager", 0,0) ,
new FModule("main/manager/takeaway", R.drawable.ic_meals_menu_management, R.drawable.ic_meals_menu_management_close) ,
new FModule("main/manager/bill", R.drawable.ic_meals_menu_management, R.drawable.ic_meals_menu_management_close) ,
new FModule("main/manager/table", R.drawable.ic_dining_table_management,R.drawable.ic_dining_table_management_close) ,
new FModule("main/manager/printer",R.drawable.ic_print_management,R.drawable.ic_print_management_close),
......
......@@ -19,6 +19,8 @@ public class SendSettlement {
*/
private boolean success;
private String errCode;
private String errMsg;
private long sysTime;
private DataBean data;
......@@ -30,6 +32,22 @@ public class SendSettlement {
this.success = success;
}
public String getErrCode() {
return errCode;
}
public void setErrCode(String errCode) {
this.errCode = errCode;
}
public String getErrMsg() {
return errMsg;
}
public void setErrMsg(String errMsg) {
this.errMsg = errMsg;
}
public long getSysTime() {
return sysTime;
}
......
......@@ -61,6 +61,24 @@ public class SettlementReport {
private RestaurantOperationBean restaurantOperation;
private List<AnalysisBean> analysis;
private List<CashBean> cash;
private String currentTime;
private String startTime;
public String getCurrentTime() {
return currentTime;
}
public void setCurrentTime(String currentTime) {
this.currentTime = currentTime;
}
public String getStartTime() {
return startTime;
}
public void setStartTime(String startTime) {
this.startTime = startTime;
}
public String getYesterdayTime() {
return yesterdayTime;
......
......@@ -12,6 +12,7 @@ import com.gingersoft.gsa.cloud.main.mvp.ui.adapter.SettlementReportItem5Adapter
import com.gingersoft.gsa.cloud.main.mvp.ui.adapter.SettlementReportItemAdapter;
import com.gingersoft.gsa.cloud.ui.bean.view.SectionTextItem3;
import com.gingersoft.gsa.cloud.ui.bean.view.SectionTextItem5;
import com.gingersoft.gsa.cloud.ui.widget.dialog.CommonTipDialog;
import com.jess.arms.di.scope.ActivityScope;
import com.jess.arms.http.imageloader.ImageLoader;
import com.jess.arms.integration.AppManager;
......@@ -141,7 +142,12 @@ public class SettlementReportPresenter extends BasePresenter<SettlementReportCon
//打印清機報表
mRootView.printRepore();
}
} else {
} else if(info.getErrCode().equals("restaurant.operation.0003")){
Class[] parameterTypes = {};
Object[] parameters = {};
CommonTipDialog.showDoubtDialog(IActivity,"今天已清機過,是否繼續清機", SettlementReportPresenter.class, SettlementReportPresenter.this,
"sendSettlement", parameterTypes, parameters);
}else {
mRootView.showMessage("清機失敗");
}
}
......@@ -165,6 +171,11 @@ public class SettlementReportPresenter extends BasePresenter<SettlementReportCon
}
@Override
public void onError(Throwable t) {
super.onError(t);
}
@Override
public void onNext(@NonNull SettlementReport info) {
if (info != null && info.isSuccess()) {
if (info.getData() != null) {
......
......@@ -4,8 +4,6 @@ import android.content.Intent;
import android.os.Bundle;
import android.view.KeyEvent;
import android.widget.BaseAdapter;
import com.gingersoft.gsa.cloud.base.qmui.arch.QMUIFragmentPagerAdapter;
import com.gingersoft.gsa.cloud.base.utils.toast.ToastUtils;
import com.gingersoft.gsa.cloud.main.R;
import com.gingersoft.gsa.cloud.main.R2;
......@@ -17,6 +15,8 @@ import com.gingersoft.gsa.cloud.main.mvp.ui.fragment.MyFragment;
import com.jess.arms.base.BaseFragmentActivity;
import com.jess.arms.di.component.AppComponent;
import com.jess.arms.utils.ArmsUtils;
import com.qmuiteam.qmui.arch.QMUIFragment;
import com.qmuiteam.qmui.arch.QMUIFragmentPagerAdapter;
import com.qmuiteam.qmui.util.QMUIDisplayHelper;
import com.qmuiteam.qmui.widget.QMUIViewPager;
import com.qmuiteam.qmui.widget.tab.QMUITab;
......@@ -65,6 +65,11 @@ public class MainActivity extends BaseFragmentActivity<MainPresenter> implements
.inject(this);
}
// @Override
// protected int getContextViewId() {
// return R.layout.main_activity_main;
// }
@Override
public int initView(@Nullable Bundle savedInstanceState) {
return R.layout.main_activity_main; //如果你不需要框架帮你设置 setContentView(id) 需要自行设置,请返回 0
......@@ -202,9 +207,9 @@ public class MainActivity extends BaseFragmentActivity<MainPresenter> implements
// gv_function.setAdapter(adapter);
}
private long mExitTime;
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
......
......@@ -46,6 +46,7 @@ import com.gingersoft.gsa.cloud.ui.bean.mode.LoginBean;
import com.gingersoft.gsa.cloud.ui.widget.dialog.ChooseRestaurantDialog;
import com.gingersoft.gsa.cloud.ui.widget.dialog.CommonTipDialog;
import com.jess.arms.base.BaseActivity;
import com.jess.arms.base.BaseFragmentActivity;
import com.jess.arms.di.component.AppComponent;
import com.jess.arms.utils.ArmsUtils;
import com.scwang.smartrefresh.layout.SmartRefreshLayout;
......@@ -73,7 +74,7 @@ import static com.jess.arms.utils.Preconditions.checkNotNull;
* <a href="https://github.com/JessYanCoding/MVPArmsTemplate">模版请保持更新</a>
* ================================================
*/
public class NewMainActivity extends BaseActivity<NewMainPresenter> implements NewMainContract.View, View.OnClickListener {
public class NewMainActivity extends BaseFragmentActivity<NewMainPresenter> implements NewMainContract.View, View.OnClickListener {
@BindView(R2.id.rv_side_menu)
RecyclerView mRvSideMenu;
@BindView(R2.id.rv_ordering_meals)
......@@ -234,13 +235,13 @@ public class NewMainActivity extends BaseActivity<NewMainPresenter> implements N
// functions.addAll(FunctionManager.getDefault().getFunctionByResModule(this, ComponentMain.Function.class, ComponentMain.Function.manager,"manager"));
functions.add(new Function((long) 151, 0, 5, "管理", 0, 0));
// functions.add(new Function((long) 142, 151, 5, "賬單管理", R.drawable.ic_meals_menu_management, 0));
functions.add(new Function((long) 142, 151, 5, "賬單管理", R.drawable.ic_meals_menu_management, 0));
functions.add(new Function((long) 142, 151, 5, "外賣接單", R.drawable.ic_takeaway_orders, 0));
// functions.add(new Function((long) 143, 151, 5, "餐臺管理", R.drawable.ic_dining_table_management, 0));
functions.add(new Function((long) 143, 151, 5, "餐臺管理", R.drawable.ic_dining_table_management, 0));
functions.add(new Function((long) 144, 151, 5, "打印管理", R.drawable.ic_print_management, 0));
// functions.add(new Function((long) 145, 151, 5, "支付管理", R.drawable.ic_pay_management_close, 1));
// functions.add(new Function((long) 146, 151, 5, "折扣管理", R.drawable.ic_discount_management_close, 1));
// functions.add(new Function((long) 147, 151, 5, "沽清管理", R.drawable.ic_sell_off_manger, 0));
functions.add(new Function((long) 147, 151, 5, "沽清管理", R.drawable.ic_sell_off_manger, 0));
// functions.addAll(FunctionManager.getDefault().getFunctionByResModule(this, ComponentMain.Function.class, ComponentMain.Function.employee,"employee"));
functions.add(new Function((long) 152, 0, 5, "員工", 0, 0));
......
......@@ -17,6 +17,7 @@ import com.gingersoft.gsa.cloud.main.mvp.ui.fragment.SalesFragment;
import com.gingersoft.gsa.cloud.ui.adapter.TabFragmentAdapter;
import com.google.android.material.tabs.TabLayout;
import com.jess.arms.base.BaseActivity;
import com.jess.arms.base.BaseFragmentActivity;
import com.jess.arms.di.component.AppComponent;
import com.jess.arms.utils.ArmsUtils;
import com.qmuiteam.qmui.widget.QMUITopBar;
......@@ -47,7 +48,7 @@ import static com.jess.arms.utils.Preconditions.checkNotNull;
* ================================================
* 報表頁面
*/
public class ReportActivity extends BaseActivity<ReportPresenter> implements ReportContract.View {
public class ReportActivity extends BaseFragmentActivity<ReportPresenter> implements ReportContract.View {
@BindView(R2.id.report_topbar)
QMUITopBar mTopBar;
@BindView(R2.id.table_layout)
......
......@@ -71,7 +71,7 @@ public class SettlementActivity extends BaseActivity<SettlementPresenter> implem
@Override
public void initData(@Nullable Bundle savedInstanceState) {
// tv_settlement_time.setVisibility(View.GONE);
mPresenter.getSettlementReport();
}
......@@ -158,7 +158,7 @@ public class SettlementActivity extends BaseActivity<SettlementPresenter> implem
this.mSettlementReportBean = datasBean;
if(mSettlementReportBean.getRestaurantOperation() != null) {
String lastSettlementText = LanguageUtils.get_language_system(this, "", "上次清機時間:");
setLastTime(lastSettlementText + TimeUtils.getStringByFormat(mSettlementReportBean.getRestaurantOperation().getOpenTime(), TimeUtils.dateFormatYMDHMS) );
setLastTime(lastSettlementText + TimeUtils.getStringByFormat(mSettlementReportBean.getRestaurantOperation().getCreateTime(), TimeUtils.dateFormatYMDHMS) );
}
}
......
......@@ -202,7 +202,7 @@
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dp_15"
android:layout_marginTop="@dimen/dp_20"
android:visibility="gone"
android:visibility="visible"
android:textColor="#181818"
android:textSize="@dimen/dp_14" />
......@@ -210,7 +210,7 @@
android:id="@+id/rv_staff_management"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:visibility="visible"
android:layout_marginLeft="@dimen/main_recyclerview_marginLeft"
android:layout_marginTop="@dimen/dp_10"
android:layout_marginRight="@dimen/main_recyclerview_marginRight" />
......@@ -226,7 +226,7 @@
android:layout_marginRight="@dimen/dp_10"
app:hl_cornerRadius="@dimen/dp_4"
app:hl_dy="@dimen/main_shadow_dy"
android:visibility="gone"
android:visibility="visible"
app:hl_shadowBackColor="@color/white"
app:hl_shadowColor="@color/shadow_color"
app:hl_shadowLimit="@dimen/main_shadow_limit">
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment