From aace616e033e3033da2f7e45954987429d2c57de Mon Sep 17 00:00:00 2001 From: cgspine Date: Fri, 22 Dec 2017 19:02:49 +0800 Subject: [PATCH 001/887] bugfix: qmui_radius QMUIRoundButton in not work after version 1.0.4 #125 --- .../qmui/widget/roundwidget/QMUIRoundButtonDrawable.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/qmui/src/main/java/com/qmuiteam/qmui/widget/roundwidget/QMUIRoundButtonDrawable.java b/qmui/src/main/java/com/qmuiteam/qmui/widget/roundwidget/QMUIRoundButtonDrawable.java index 2eb4c376e..1d3309164 100644 --- a/qmui/src/main/java/com/qmuiteam/qmui/widget/roundwidget/QMUIRoundButtonDrawable.java +++ b/qmui/src/main/java/com/qmuiteam/qmui/widget/roundwidget/QMUIRoundButtonDrawable.java @@ -138,6 +138,9 @@ public static QMUIRoundButtonDrawable fromAttributeSet(Context context, Attribut isRadiusAdjustBounds = false; } else { bg.setCornerRadius(mRadius); + if(mRadius > 0){ + isRadiusAdjustBounds = false; + } } bg.setIsRadiusAdjustBounds(isRadiusAdjustBounds); return bg; From 2c2bac3825e8c4a19dec098507c811318e2c4db3 Mon Sep 17 00:00:00 2001 From: cgspine Date: Fri, 22 Dec 2017 20:34:47 +0800 Subject: [PATCH 002/887] 1. update: add theme control to QMUICommonListItemView; 2. add space between title and detail #127 --- .../grouplist/QMUICommonListItemView.java | 112 +++++++------ .../main/res/layout/qmui_common_list_item.xml | 20 ++- qmui/src/main/res/values/config_dimens.xml | 14 -- qmui/src/main/res/values/qmui_attrs_base.xml | 13 ++ qmui/src/main/res/values/qmui_dimens.xml | 1 - qmui/src/main/res/values/qmui_themes.xml | 15 ++ .../main/res/values/qmui_themes_compat.xml | 155 +++++++++++++----- .../components/QDGroupListViewFragment.java | 4 +- 8 files changed, 212 insertions(+), 122 deletions(-) delete mode 100644 qmui/src/main/res/values/config_dimens.xml diff --git a/qmui/src/main/java/com/qmuiteam/qmui/widget/grouplist/QMUICommonListItemView.java b/qmui/src/main/java/com/qmuiteam/qmui/widget/grouplist/QMUICommonListItemView.java index edea184b7..d8b63fe44 100644 --- a/qmui/src/main/java/com/qmuiteam/qmui/widget/grouplist/QMUICommonListItemView.java +++ b/qmui/src/main/java/com/qmuiteam/qmui/widget/grouplist/QMUICommonListItemView.java @@ -4,6 +4,7 @@ import android.content.res.TypedArray; import android.graphics.drawable.Drawable; import android.support.annotation.IntDef; +import android.support.v4.widget.Space; import android.text.SpannableString; import android.util.AttributeSet; import android.util.TypedValue; @@ -32,11 +33,11 @@ * 作为通用列表 {@link QMUIGroupListView} 里的 item 使用,也可以单独使用。 * 支持以下样式: * * * @author chantchen @@ -61,16 +62,6 @@ public class QMUICommonListItemView extends RelativeLayout { */ public final static int ACCESSORY_TYPE_CUSTOM = 3; - @IntDef({ACCESSORY_TYPE_NONE, ACCESSORY_TYPE_CHEVRON, ACCESSORY_TYPE_SWITCH, ACCESSORY_TYPE_CUSTOM}) - @Retention(RetentionPolicy.SOURCE) - public @interface QMUICommonListItemAccessoryType {} - - /** - * Item 右侧的 View 的类型 - */ - private @QMUICommonListItemAccessoryType int mAccessoryType; - private ViewGroup mAccessoryView; - /** * detailText 在 title 文字的下方 */ @@ -80,16 +71,6 @@ public class QMUICommonListItemView extends RelativeLayout { */ public final static int HORIZONTAL = 1; - @IntDef({VERTICAL, HORIZONTAL}) - @Retention(RetentionPolicy.SOURCE) - public @interface QMUICommonListItemOrientation {} - - /** - * 控制 detailText 是在 title 文字的下方还是 item 的右方 - */ - private int mOrientation = HORIZONTAL; - protected TextView mDetailTextView; - /** * 红点在左边 */ @@ -99,17 +80,47 @@ public class QMUICommonListItemView extends RelativeLayout { */ public final static int REDDOT_POSITION_RIGHT = 1; + @IntDef({ACCESSORY_TYPE_NONE, ACCESSORY_TYPE_CHEVRON, ACCESSORY_TYPE_SWITCH, ACCESSORY_TYPE_CUSTOM}) + @Retention(RetentionPolicy.SOURCE) + public @interface QMUICommonListItemAccessoryType { + } + + @IntDef({VERTICAL, HORIZONTAL}) + @Retention(RetentionPolicy.SOURCE) + public @interface QMUICommonListItemOrientation { + } + @IntDef({REDDOT_POSITION_LEFT, REDDOT_POSITION_RIGHT}) @Retention(RetentionPolicy.SOURCE) - public @interface QMUICommonListItemRedDotPosition {} + public @interface QMUICommonListItemRedDotPosition { + } + + /** + * Item 右侧的 View 的类型 + */ + @QMUICommonListItemAccessoryType + private int mAccessoryType; + + /** + * 控制 detailText 是在 title 文字的下方还是 item 的右方 + */ + private int mOrientation = HORIZONTAL; + + /** + * 控制红点的位置 + */ + @QMUICommonListItemRedDotPosition + private int mRedDotPosition = REDDOT_POSITION_LEFT; - private @QMUICommonListItemRedDotPosition int mRedDotPosition = REDDOT_POSITION_LEFT; - private ImageView mRedDot; protected ImageView mImageView; + private ViewGroup mAccessoryView; + protected LinearLayout mTextContainer; protected TextView mTextView; + protected TextView mDetailTextView; + protected Space mTextDetailSpace; protected CheckBox mSwitch; - protected LinearLayout mTextContainer; + private ImageView mRedDot; private ViewStub mNewTipViewStub; private View mNewTip; @@ -143,10 +154,11 @@ protected void init(Context context, AttributeSet attrs, int defStyleAttr) { mRedDot = (ImageView) findViewById(R.id.group_list_item_tips_dot); mNewTipViewStub = (ViewStub) findViewById(R.id.group_list_item_tips_new); mDetailTextView = (TextView) findViewById(R.id.group_list_item_detailTextView); + mTextDetailSpace = (Space) findViewById(R.id.group_list_item_space); mDetailTextView.setTextColor(initDetailColor); LinearLayout.LayoutParams detailTextViewLP = (LinearLayout.LayoutParams) mDetailTextView.getLayoutParams(); if (QMUIViewHelper.getIsLastLineSpacingExtraError()) { - detailTextViewLP.bottomMargin = -getResources().getDimensionPixelOffset(R.dimen.qmui_list_item_detail_lineSpacingExtra); + detailTextViewLP.bottomMargin = -QMUIResHelper.getAttrDimen(context, R.attr.qmui_common_list_item_detail_line_space); } if (orientation == VERTICAL) { detailTextViewLP.topMargin = QMUIDisplayHelper.dp2px(getContext(), 6); @@ -172,16 +184,6 @@ public void setRedDotPosition(@QMUICommonListItemRedDotPosition int redDotPositi requestLayout(); } - - public void setText(SpannableString text) { - mTextView.setText(text); - if (QMUILangHelper.isNullOrEmpty(text)) { - mTextView.setVisibility(View.GONE); - } else { - mTextView.setVisibility(View.VISIBLE); - } - } - public CharSequence getText() { return mTextView.getText(); } @@ -220,9 +222,6 @@ public void showNewTip(boolean isShow) { } mNewTip.setVisibility(View.VISIBLE); mRedDot.setVisibility(GONE); -// // 要调requestLayout强制layout一次,否则位置不对! -// this.invalidate(); -// this.requestLayout(); } else { if (mNewTip != null && mNewTip.getVisibility() == View.VISIBLE) { mNewTip.setVisibility(View.GONE); @@ -244,33 +243,31 @@ public void setDetailText(CharSequence text) { } } - public - @QMUICommonListItemOrientation - int getOrientation() { + public int getOrientation() { return mOrientation; } public void setOrientation(@QMUICommonListItemOrientation int orientation) { mOrientation = orientation; - LinearLayout.LayoutParams titleLp = (LinearLayout.LayoutParams) mTextView.getLayoutParams(); + LinearLayout.LayoutParams spaceLp = (LinearLayout.LayoutParams) mTextDetailSpace.getLayoutParams(); // 默认文字是水平布局的 if (mOrientation == VERTICAL) { mTextContainer.setOrientation(LinearLayout.VERTICAL); mTextContainer.setGravity(Gravity.LEFT); - titleLp.width = ViewGroup.LayoutParams.WRAP_CONTENT; - titleLp.weight = 0; - titleLp.bottomMargin = QMUIDisplayHelper.dp2px(getContext(), 4); - mTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimensionPixelSize(R.dimen.list_item_textSize_title_style_vertical)); - mDetailTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimensionPixelSize(R.dimen.list_item_textSize_detail_style_vertical)); + spaceLp.width = ViewGroup.LayoutParams.WRAP_CONTENT; + spaceLp.height = QMUIDisplayHelper.dp2px(getContext(), 4); + spaceLp.weight = 0; + mTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, QMUIResHelper.getAttrDimen(getContext(), R.attr.qmui_common_list_item_title_v_text_size)); + mDetailTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, QMUIResHelper.getAttrDimen(getContext(), R.attr.qmui_common_list_item_detail_v_text_size)); } else { mTextContainer.setOrientation(LinearLayout.HORIZONTAL); mTextContainer.setGravity(Gravity.CENTER_VERTICAL); - titleLp.width = 0; - titleLp.weight = 1; - titleLp.bottomMargin = QMUIDisplayHelper.dp2px(getContext(), 0); - mTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimensionPixelSize(R.dimen.list_item_textSize_title)); - mDetailTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimensionPixelSize(R.dimen.list_item_textSize_detail)); + spaceLp.width = 0; + spaceLp.height = 0; + spaceLp.weight = 1; + mTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, QMUIResHelper.getAttrDimen(getContext(), R.attr.qmui_common_list_item_title_h_text_size)); + mDetailTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, QMUIResHelper.getAttrDimen(getContext(), R.attr.qmui_common_list_item_detail_h_text_size)); } } @@ -406,4 +403,5 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) { } } + } diff --git a/qmui/src/main/res/layout/qmui_common_list_item.xml b/qmui/src/main/res/layout/qmui_common_list_item.xml index da27ff8cb..40f6a19b3 100644 --- a/qmui/src/main/res/layout/qmui_common_list_item.xml +++ b/qmui/src/main/res/layout/qmui_common_list_item.xml @@ -9,7 +9,7 @@ android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_centerVertical="true" - android:layout_marginRight="12dp" + android:layout_marginRight="?attr/qmui_common_list_item_icon_margin_right" android:contentDescription="@null" android:scaleType="centerCrop" android:visibility="gone"/> @@ -20,7 +20,7 @@ android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_centerVertical="true" - android:layout_marginLeft="14dp" + android:layout_marginLeft="?attr/qmui_common_list_item_accessory_margin_left" android:visibility="gone"/> + android:textSize="?attr/qmui_common_list_item_title_h_text_size"/> + + diff --git a/qmui/src/main/res/values/config_dimens.xml b/qmui/src/main/res/values/config_dimens.xml deleted file mode 100644 index 9b5a2b5d1..000000000 --- a/qmui/src/main/res/values/config_dimens.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - 32dp - - - - 16sp - 15sp - 14sp - 13sp - - - - diff --git a/qmui/src/main/res/values/qmui_attrs_base.xml b/qmui/src/main/res/values/qmui_attrs_base.xml index 44c7fd418..49ab48d09 100644 --- a/qmui/src/main/res/values/qmui_attrs_base.xml +++ b/qmui/src/main/res/values/qmui_attrs_base.xml @@ -91,6 +91,19 @@ + + + + + + + + + + + 56dp 103dp - 5dp 8dp 13sp diff --git a/qmui/src/main/res/values/qmui_themes.xml b/qmui/src/main/res/values/qmui_themes.xml index 2899689b2..a35f161a4 100644 --- a/qmui/src/main/res/values/qmui_themes.xml +++ b/qmui/src/main/res/values/qmui_themes.xml @@ -131,6 +131,21 @@ ?attr/qmui_content_spacing_horizontal 12dp ?attr/qmui_content_padding_horizontal + + + + + 12dp + 14dp + 15sp + 16sp + 14dp + 13sp + 14sp + 5dp + diff --git a/qmui/src/main/res/values/qmui_themes_compat.xml b/qmui/src/main/res/values/qmui_themes_compat.xml index 15948c203..2e0092968 100644 --- a/qmui/src/main/res/values/qmui_themes_compat.xml +++ b/qmui/src/main/res/values/qmui_themes_compat.xml @@ -1,8 +1,9 @@ - - - - diff --git a/qmui/src/main/res/values/qmui_themes_compat.xml b/qmui/src/main/res/values/qmui_themes_compat.xml index 2e0092968..85ebea156 100644 --- a/qmui/src/main/res/values/qmui_themes_compat.xml +++ b/qmui/src/main/res/values/qmui_themes_compat.xml @@ -15,7 +15,17 @@ @style/TextView.Compat - + + \ No newline at end of file diff --git a/arch/src/test/java/com/qmuiteam/qmui/arch/ExampleUnitTest.java b/arch/src/test/java/com/qmuiteam/qmui/arch/ExampleUnitTest.java new file mode 100644 index 000000000..b5ce7cd1f --- /dev/null +++ b/arch/src/test/java/com/qmuiteam/qmui/arch/ExampleUnitTest.java @@ -0,0 +1,17 @@ +package com.qmuiteam.qmui.arch; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Example local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class ExampleUnitTest { + @Test + public void addition_isCorrect() throws Exception { + assertEquals(4, 2 + 2); + } +} \ No newline at end of file diff --git a/qmuidemo/build.gradle b/qmuidemo/build.gradle index 9080ac34f..31ab6861e 100644 --- a/qmuidemo/build.gradle +++ b/qmuidemo/build.gradle @@ -66,6 +66,7 @@ dependencies { annotationProcessor 'com.jakewharton:butterknife-compiler:8.4.0' compile project(':qmui') compile project(':lib') + compile project(':arch') annotationProcessor project(':compiler') //leak diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/base/BaseFragment.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/base/BaseFragment.java index 0a7fd2440..76774ce80 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/base/BaseFragment.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/base/BaseFragment.java @@ -1,219 +1,17 @@ package com.qmuiteam.qmuidemo.base; -import android.content.Context; -import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.support.v4.view.ViewCompat; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.animation.AlphaAnimation; -import android.view.animation.Animation; -import android.view.animation.AnimationUtils; -import android.view.inputmethod.InputMethod; -import android.view.inputmethod.InputMethodManager; -import android.widget.FrameLayout; - -import com.qmuiteam.qmui.util.QMUIViewHelper; -import com.qmuiteam.qmui.widget.QMUIWindowInsetLayout; -import com.qmuiteam.qmuidemo.R; +import com.qmuiteam.qmui.arch.QMUIFragment; /** - * 基础 Fragment 类,提供各种基础功能。 - * Created by cgspine on 15/9/14. + * Created by cgspine on 2018/1/7. */ -public abstract class BaseFragment extends Fragment { - // 资源,放在业务初始化,会在业务层 - protected static final TransitionConfig SLIDE_TRANSITION_CONFIG = new TransitionConfig( - R.anim.slide_in_right, R.anim.slide_out_left, - R.anim.slide_in_left, R.anim.slide_out_right); - - - //============================= UI ================================ - protected static final TransitionConfig SCALE_TRANSITION_CONFIG = new TransitionConfig( - R.anim.scale_enter, R.anim.slide_still, R.anim.slide_still, - R.anim.scale_exit); - private static final String TAG = BaseFragment.class.getSimpleName(); - private View mBaseView; - - public BaseFragment() { - super(); - } - - public final BaseFragmentActivity getBaseFragmentActivity() { - return (BaseFragmentActivity) getActivity(); - } - - public boolean isAttachedToActivity() { - return !isRemoving() && mBaseView != null; - } - - @Override - public void onDetach() { - super.onDetach(); - mBaseView = null; - } - - protected void startFragment(BaseFragment fragment) { - BaseFragmentActivity baseFragmentActivity = this.getBaseFragmentActivity(); - if (baseFragmentActivity != null) { - if (this.isAttachedToActivity()) { - baseFragmentActivity.startFragment(fragment); - } else { - Log.e("BaseFragment", "fragment not attached:" + this); - } - } else { - Log.e("BaseFragment", "startFragment null:" + this); - } - } - - /** - * 显示键盘 - */ - protected void showKeyBoard() { - InputMethodManager imm = (InputMethodManager) getActivity().getApplicationContext().getSystemService(Context.INPUT_METHOD_SERVICE); - imm.toggleSoftInput(0, InputMethod.SHOW_FORCED); - } - - /** - * 隐藏键盘 - */ - protected boolean hideKeyBoard() { - final InputMethodManager imm = (InputMethodManager) getActivity().getApplicationContext() - .getSystemService(Context.INPUT_METHOD_SERVICE); - return imm.hideSoftInputFromWindow(getActivity().findViewById(android.R.id.content) - .getWindowToken(), 0); - } - - - //============================= 生命周期 ================================ - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View view = onCreateView(); - if (translucentFull()) { - if (view instanceof QMUIWindowInsetLayout) { - view.setFitsSystemWindows(false); - mBaseView = view; - } else { - mBaseView = new QMUIWindowInsetLayout(getActivity()); - ((QMUIWindowInsetLayout) mBaseView).addView(view, new FrameLayout.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); - } - } else { - view.setFitsSystemWindows(true); - mBaseView = view; - } - QMUIViewHelper.requestApplyInsets(getActivity().getWindow()); - return mBaseView; - } - - protected void popBackStack() { - getBaseFragmentActivity().popBackStack(); - } - - @Override - public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) { - if (!enter && getParentFragment() != null && getParentFragment().isRemoving()) { - // This is a workaround for the bug where child fragments disappear when - // the parent is removed (as all children are first removed from the parent) - // See https://code.google.com/p/android/issues/detail?id=55228 - Animation doNothingAnim = new AlphaAnimation(1, 1); - doNothingAnim.setDuration(R.integer.qmui_anim_duration); - return doNothingAnim; - } - - // bugfix: 使用scale enter时看不到效果, 因为两个fragment的动画在同一个层级,被退出动画遮挡了 - // http://stackoverflow.com/questions/13005961/fragmenttransaction-animation-to-slide-in-over-top#33816251 - if (nextAnim != R.anim.scale_enter || !enter) { - return super.onCreateAnimation(transit, enter, nextAnim); - } - try { - Animation nextAnimation = AnimationUtils.loadAnimation(getContext(), nextAnim); - nextAnimation.setAnimationListener(new Animation.AnimationListener() { - - private float mOldTranslationZ; - - @Override - public void onAnimationStart(Animation animation) { - if (getView() != null) { - mOldTranslationZ = ViewCompat.getTranslationZ(getView()); - ViewCompat.setTranslationZ(getView(), 100.f); - } - } - - @Override - public void onAnimationEnd(Animation animation) { - if (getView() != null) { - getView().postDelayed(new Runnable() { - @Override - public void run() { - //延迟回复z-index,如果退出动画更长,这里可能会失效 - ViewCompat.setTranslationZ(getView(), mOldTranslationZ); - } - }, 100); - - } - } - - @Override - public void onAnimationRepeat(Animation animation) { - } - }); - return nextAnimation; - } catch (Exception ignored) { +public abstract class BaseFragment extends QMUIFragment { - } - return null; - } - - /** - * onCreateView - */ - protected abstract View onCreateView(); - - //============================= 新流程 ================================ - - /** - * 沉浸式处理,返回 false,则状态栏下为内容区域,返回 true, 则状态栏下为 padding 区域 - */ - protected boolean translucentFull() { - return false; - } - /** - * 如果是最后一个Fragment,finish后执行的方法 - */ - @SuppressWarnings("SameReturnValue") - public Object onLastFragmentFinish() { - return null; - } - /** - * 转场动画控制 - */ - public TransitionConfig onFetchTransitionConfig() { - return SLIDE_TRANSITION_CONFIG; + public BaseFragment() { } - ////////界面跳转动画 - public static final class TransitionConfig { - public final int enter; - public final int exit; - public final int popenter; - public final int popout; - - public TransitionConfig(int enter, int popout) { - this(enter, 0, 0, popout); - } - public TransitionConfig(int enter, int exit, int popenter, int popout) { - this.enter = enter; - this.exit = exit; - this.popenter = popenter; - this.popout = popout; - } - } } - diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/base/BaseFragmentActivity.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/base/BaseFragmentActivity.java index 7f25c19b7..f16f337ee 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/base/BaseFragmentActivity.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/base/BaseFragmentActivity.java @@ -1,121 +1,10 @@ package com.qmuiteam.qmuidemo.base; -import android.content.Intent; -import android.os.Bundle; -import android.support.v4.app.FragmentManager; -import android.support.v7.app.AppCompatActivity; -import android.util.Log; -import android.view.View; -import android.view.ViewGroup; -import android.widget.FrameLayout; - -import com.qmuiteam.qmui.util.QMUIStatusBarHelper; - -import java.lang.reflect.Field; -import java.util.ArrayList; +import com.qmuiteam.qmui.arch.QMUIFragmentActivity; /** - * 基础的 Activity,配合 {@link BaseFragment} 使用。 - * Created by cgspine on 15/9/14. + * Created by cgspine on 2018/1/7. */ -public abstract class BaseFragmentActivity extends AppCompatActivity { - private static final String TAG = "BaseFragmentActivity"; - private FrameLayout mFragmentContainer; - - @SuppressWarnings("SameReturnValue") - protected abstract int getContextViewId(); - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - QMUIStatusBarHelper.translucent(this); - mFragmentContainer = new FrameLayout(this); - mFragmentContainer.setId(getContextViewId()); - setContentView(mFragmentContainer); - } - - @Override - public void onBackPressed() { - BaseFragment fragment = getCurrentFragment(); - if (fragment != null) { - popBackStack(); - } - } - - /** - * 获取当前的 Fragment。 - */ - public BaseFragment getCurrentFragment() { - return (BaseFragment) getSupportFragmentManager().findFragmentById(getContextViewId()); - } - - public void startFragment(BaseFragment fragment) { - Log.i(TAG, "startFragment"); - BaseFragment.TransitionConfig transitionConfig = fragment.onFetchTransitionConfig(); - String tagName = fragment.getClass().getSimpleName(); - getSupportFragmentManager() - .beginTransaction() - .setCustomAnimations(transitionConfig.enter, transitionConfig.exit, transitionConfig.popenter, transitionConfig.popout) - .replace(getContextViewId(), fragment, tagName) - .addToBackStack(tagName) - .commit(); - } - - /** - * 退出当前的 Fragment。 - */ - public void popBackStack() { - Log.i(TAG, "popBackStack: getSupportFragmentManager().getBackStackEntryCount() = " + getSupportFragmentManager().getBackStackEntryCount()); - if (getSupportFragmentManager().getBackStackEntryCount() <= 1) { - BaseFragment fragment = getCurrentFragment(); - if (fragment == null) { - finish(); - return; - } - BaseFragment.TransitionConfig transitionConfig = fragment.onFetchTransitionConfig(); - Object toExec = fragment.onLastFragmentFinish(); - if (toExec != null) { - if (toExec instanceof BaseFragment) { - BaseFragment mFragment = (BaseFragment) 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(); - } - } - - /** - *
-     * 返回到clazz类型的Fragment,
-     * 如 Home --> List --> Detail,
-     * popBackStack(Home.class)之后,就是Home
-     *
-     * 如果堆栈没有clazz或者就是当前的clazz(如上例的popBackStack(Detail.class)),就相当于popBackStack()
-     * 
- */ - public void popBackStack(Class clazz) { - getSupportFragmentManager().popBackStack(clazz.getSimpleName(), 0); - } - /** - *
-     * 返回到非clazz类型的Fragment
-     *
-     * 如果上一个是目标clazz,则会继续pop,直到上一个不是clazz。
-     * 
- */ - public void popBackStackInclusive(Class clazz) { - getSupportFragmentManager().popBackStack(clazz.getSimpleName(), FragmentManager.POP_BACK_STACK_INCLUSIVE); - } -} \ No newline at end of file +public abstract class BaseFragmentActivity extends QMUIFragmentActivity { +} diff --git a/settings.gradle b/settings.gradle index a0816c6ef..69a671761 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -include ':qmuidemo', ':qmui', ':lib', ':compiler', ':qmuilint', ':qmuilintrule' +include ':qmuidemo', ':qmui', ':lib', ':compiler', ':qmuilint', ':qmuilintrule', ':arch' From 63bd9200186f7dd57e528b9a08c62ca0edc71742 Mon Sep 17 00:00:00 2001 From: cgspine Date: Thu, 11 Jan 2018 20:20:55 +0800 Subject: [PATCH 006/887] swipe back --- .../com/qmuiteam/qmui/arch/QMUIFragment.java | 147 +++++++++++++++++- .../qmui/arch/QMUIFragmentActivity.java | 9 +- .../qmuiteam/qmui/arch/SwipeBackLayout.java | 7 - 3 files changed, 153 insertions(+), 10 deletions(-) diff --git a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java index abd6286e0..3cec05ff2 100644 --- a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java +++ b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java @@ -2,6 +2,7 @@ import android.os.Bundle; import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; import android.support.v4.view.ViewCompat; import android.util.Log; import android.view.LayoutInflater; @@ -13,11 +14,15 @@ import com.qmuiteam.qmui.util.QMUIViewHelper; +import java.lang.reflect.Field; +import java.util.List; + /** * 基础 Fragment 类,提供各种基础功能。 * Created by cgspine on 15/9/14. */ public abstract class QMUIFragment extends Fragment { + private static final String SWIPE_BACK_VIEW = "swipe_back_view"; private static final String TAG = QMUIFragment.class.getSimpleName(); @@ -33,6 +38,8 @@ public abstract class QMUIFragment extends Fragment { com.qmuiteam.qmui.arch.R.anim.scale_exit); private View mBaseView; + private View mSwipeBackCacheView; + private boolean mCreateForSwipBack = false; public QMUIFragment() { super(); @@ -70,15 +77,153 @@ protected void startFragment(QMUIFragment fragment) { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + if (mSwipeBackCacheView != null) { + View swipeBackView = mSwipeBackCacheView; + if (!mCreateForSwipBack) { + mSwipeBackCacheView = null; + } + return swipeBackView; + } mBaseView = onCreateView(); SwipeBackLayout swipeBackLayout = SwipeBackLayout.wrap(mBaseView); + swipeBackLayout.addSwipeListener(new SwipeBackLayout.SwipeListener() { + @Override + public void onScrollStateChange(int state, float scrollPercent) { + Log.i(TAG, "SwipeListener:onScrollStateChange: state = " + state + " ;scrollPercent = " + scrollPercent); + ViewGroup container = getBaseFragmentActivity().getFragmentContainer(); + int childCount = container.getChildCount(); + if (state == SwipeBackLayout.STATE_IDLE) { + if (scrollPercent <= 0.0F) { + for (int i = childCount - 1; i >= 0; i--) { + View view = container.getChildAt(i); + Object tag = view.getTag(-1); + if (tag != null && SWIPE_BACK_VIEW.equals(tag)) { + container.removeView(view); + } + } + } else if (scrollPercent >= 1.0F) { + for (int i = childCount - 1; i >= 0; i--) { + View view = container.getChildAt(i); + Object tag = view.getTag(-1); + if (tag != null && SWIPE_BACK_VIEW.equals(tag)) { + container.removeView(view); + } + } + FragmentManager fragmentManager = getFragmentManager(); + if (fragmentManager == null) { + return; + } + int backstackCount = fragmentManager.getBackStackEntryCount(); + if (backstackCount > 0) { + try { + FragmentManager.BackStackEntry backStackEntry = fragmentManager.getBackStackEntryAt(backstackCount - 1); + + 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) { + Field cmdField = op.getClass().getDeclaredField("cmd"); + cmdField.setAccessible(true); + int cmd = (int) cmdField.get(op); + if (cmd == 1) { + Field popEnterAnimField = op.getClass().getDeclaredField("popExitAnim"); + popEnterAnimField.setAccessible(true); + popEnterAnimField.set(op, 0); + } + } + } + } catch (NoSuchFieldException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + + + popBackStack(); + } + } + + } + + @Override + public void onEdgeTouch(int edgeFlag) { + Log.i(TAG, "SwipeListener:onEdgeTouch: edgeFlag = " + edgeFlag); + FragmentManager fragmentManager = getFragmentManager(); + if (fragmentManager == null) { + return; + } + int backstackCount = fragmentManager.getBackStackEntryCount(); + if (backstackCount > 1) { + try { + FragmentManager.BackStackEntry backStackEntry = fragmentManager.getBackStackEntryAt(backstackCount - 1); + + 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) { + Field cmdField = op.getClass().getDeclaredField("cmd"); + cmdField.setAccessible(true); + int cmd = (int) cmdField.get(op); + if (cmd == 3) { + Field popEnterAnimField = op.getClass().getDeclaredField("popEnterAnim"); + popEnterAnimField.setAccessible(true); + popEnterAnimField.set(op, 0); + + Field fragmentField = op.getClass().getDeclaredField("fragment"); + fragmentField.setAccessible(true); + Object fragmentObject = fragmentField.get(op); + if (fragmentObject instanceof QMUIFragment) { + QMUIFragment fragment = (QMUIFragment) fragmentObject; + ViewGroup container = getBaseFragmentActivity().getFragmentContainer(); + fragment.mCreateForSwipBack = true; + View baseView = fragment.onCreateView(LayoutInflater.from(getContext()), container, null); + fragment.mCreateForSwipBack = false; + if (baseView != null) { + if (baseView.getParent() != null) { + ((ViewGroup) baseView.getParent()).removeView(baseView); + } + baseView.setTag(-1, SWIPE_BACK_VIEW); + container.addView(baseView, 0); + } + } + } + } + } + + + } catch (NoSuchFieldException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + + } + + @Override + public void onScrollOverThreshold() { + Log.i(TAG, "SwipeListener:onEdgeTouch:onScrollOverThreshold"); + } + }); swipeBackLayout.setFitsSystemWindows(false); if (translucentFull()) { mBaseView.setFitsSystemWindows(false); } else { mBaseView.setFitsSystemWindows(true); } - QMUIViewHelper.requestApplyInsets(getActivity().getWindow()); + if (getActivity() != null) { + QMUIViewHelper.requestApplyInsets(getActivity().getWindow()); + } + + if (mCreateForSwipBack) { + mSwipeBackCacheView = swipeBackLayout; + } + return swipeBackLayout; } diff --git a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragmentActivity.java b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragmentActivity.java index 424105ba7..65ee4a217 100644 --- a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragmentActivity.java +++ b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragmentActivity.java @@ -8,6 +8,7 @@ import android.widget.FrameLayout; import com.qmuiteam.qmui.util.QMUIStatusBarHelper; +import com.qmuiteam.qmui.widget.QMUIWindowInsetLayout; /** * 基础的 Activity,配合 {@link QMUIFragment} 使用。 @@ -15,7 +16,7 @@ */ public abstract class QMUIFragmentActivity extends AppCompatActivity { private static final String TAG = "QMUIFragmentActivity"; - private FrameLayout mFragmentContainer; + private QMUIWindowInsetLayout mFragmentContainer; @SuppressWarnings("SameReturnValue") protected abstract int getContextViewId(); @@ -24,11 +25,15 @@ public abstract class QMUIFragmentActivity extends AppCompatActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); QMUIStatusBarHelper.translucent(this); - mFragmentContainer = new FrameLayout(this); + mFragmentContainer = new QMUIWindowInsetLayout(this); mFragmentContainer.setId(getContextViewId()); setContentView(mFragmentContainer); } + public FrameLayout getFragmentContainer() { + return mFragmentContainer; + } + @Override public void onBackPressed() { QMUIFragment fragment = getCurrentFragment(); diff --git a/arch/src/main/java/com/qmuiteam/qmui/arch/SwipeBackLayout.java b/arch/src/main/java/com/qmuiteam/qmui/arch/SwipeBackLayout.java index f683ee121..a92bea4b6 100644 --- a/arch/src/main/java/com/qmuiteam/qmui/arch/SwipeBackLayout.java +++ b/arch/src/main/java/com/qmuiteam/qmui/arch/SwipeBackLayout.java @@ -527,13 +527,6 @@ public void onViewPositionChanged(View changedView, int left, int top, int dx, i listener.onScrollOverThreshold(); } } - - if (mScrollPercent >= 1) { - if (!mActivity.isFinishing()) { - mActivity.finish(); - mActivity.overridePendingTransition(0, 0); - } - } } @Override From daf9759b0e27eecdb98816e15bfa95f228ec1883 Mon Sep 17 00:00:00 2001 From: cgspine Date: Fri, 12 Jan 2018 13:43:13 +0800 Subject: [PATCH 007/887] swipe back --- .../com/qmuiteam/qmui/arch/QMUIFragment.java | 171 +++++++++++------- .../qmuiteam/qmui/arch/SwipeBackLayout.java | 4 + arch/src/main/res/values/ids.xml | 4 + .../qmuidemo/fragment/QDAboutFragment.java | 7 +- .../qmuidemo/fragment/home/HomeFragment.java | 5 + 5 files changed, 121 insertions(+), 70 deletions(-) create mode 100644 arch/src/main/res/values/ids.xml diff --git a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java index 3cec05ff2..621052821 100644 --- a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java +++ b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java @@ -1,6 +1,8 @@ package com.qmuiteam.qmui.arch; import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.view.ViewCompat; @@ -10,11 +12,12 @@ import android.view.ViewGroup; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; -import android.view.animation.AnimationUtils; import com.qmuiteam.qmui.util.QMUIViewHelper; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.List; /** @@ -38,8 +41,9 @@ public abstract class QMUIFragment extends Fragment { com.qmuiteam.qmui.arch.R.anim.scale_exit); private View mBaseView; - private View mSwipeBackCacheView; - private boolean mCreateForSwipBack = false; + private SwipeBackLayout mCacheView; + private boolean isCreateForSwipeBack = false; + private int mBackStackIndex = 0; public QMUIFragment() { super(); @@ -75,17 +79,32 @@ protected void startFragment(QMUIFragment fragment) { //============================= 生命周期 ================================ + @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - if (mSwipeBackCacheView != null) { - View swipeBackView = mSwipeBackCacheView; - if (!mCreateForSwipBack) { - mSwipeBackCacheView = null; + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + FragmentManager fragmentManager = getFragmentManager(); + if (fragmentManager != null) { + int backStackEntryCount = fragmentManager.getBackStackEntryCount(); + for (int i = backStackEntryCount - 1; i >= 0; i--) { + FragmentManager.BackStackEntry entry = fragmentManager.getBackStackEntryAt(i); + if (getClass().getSimpleName().equals(entry.getName())) { + mBackStackIndex = i; + break; + } } - return swipeBackView; } - mBaseView = onCreateView(); - SwipeBackLayout swipeBackLayout = SwipeBackLayout.wrap(mBaseView); + } + + private SwipeBackLayout newSwipeBackLayout() { + View rootView = onCreateView(); + if (translucentFull()) { + rootView.setFitsSystemWindows(false); + } else { + rootView.setFitsSystemWindows(true); + } + SwipeBackLayout swipeBackLayout = SwipeBackLayout.wrap(rootView); + swipeBackLayout.setEnableGesture(canDragBack()); swipeBackLayout.addSwipeListener(new SwipeBackLayout.SwipeListener() { @Override public void onScrollStateChange(int state, float scrollPercent) { @@ -96,7 +115,7 @@ public void onScrollStateChange(int state, float scrollPercent) { if (scrollPercent <= 0.0F) { for (int i = childCount - 1; i >= 0; i--) { View view = container.getChildAt(i); - Object tag = view.getTag(-1); + Object tag = view.getTag(R.id.qmui_arch_swipe_layout_in_back); if (tag != null && SWIPE_BACK_VIEW.equals(tag)) { container.removeView(view); } @@ -104,7 +123,7 @@ public void onScrollStateChange(int state, float scrollPercent) { } else if (scrollPercent >= 1.0F) { for (int i = childCount - 1; i >= 0; i--) { View view = container.getChildAt(i); - Object tag = view.getTag(-1); + Object tag = view.getTag(R.id.qmui_arch_swipe_layout_in_back); if (tag != null && SWIPE_BACK_VIEW.equals(tag)) { container.removeView(view); } @@ -140,8 +159,6 @@ public void onScrollStateChange(int state, float scrollPercent) { e.printStackTrace(); } } - - popBackStack(); } } @@ -180,14 +197,11 @@ public void onEdgeTouch(int edgeFlag) { if (fragmentObject instanceof QMUIFragment) { QMUIFragment fragment = (QMUIFragment) fragmentObject; ViewGroup container = getBaseFragmentActivity().getFragmentContainer(); - fragment.mCreateForSwipBack = true; + fragment.isCreateForSwipeBack = true; View baseView = fragment.onCreateView(LayoutInflater.from(getContext()), container, null); - fragment.mCreateForSwipBack = false; + fragment.isCreateForSwipeBack = false; if (baseView != null) { - if (baseView.getParent() != null) { - ((ViewGroup) baseView.getParent()).removeView(baseView); - } - baseView.setTag(-1, SWIPE_BACK_VIEW); + baseView.setTag(R.id.qmui_arch_swipe_layout_in_back, SWIPE_BACK_VIEW); container.addView(baseView, 0); } } @@ -210,18 +224,75 @@ public void onScrollOverThreshold() { Log.i(TAG, "SwipeListener:onEdgeTouch:onScrollOverThreshold"); } }); - swipeBackLayout.setFitsSystemWindows(false); - if (translucentFull()) { - mBaseView.setFitsSystemWindows(false); + return swipeBackLayout; + } + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + SwipeBackLayout swipeBackLayout; + if (mCacheView == null) { + swipeBackLayout = newSwipeBackLayout(); + mCacheView = swipeBackLayout; + } else if (isCreateForSwipeBack) { + // in swipe back, must not in animation + swipeBackLayout = mCacheView; } else { - mBaseView.setFitsSystemWindows(true); + boolean isInRemoving = false; + try { + Method method = getClass().getDeclaredMethod("getAnimatingAway"); + method.setAccessible(true); + Object object = method.invoke(this); + if (object != null) { + isInRemoving = true; + } + } catch (NoSuchMethodException e) { + isInRemoving = true; + e.printStackTrace(); + } catch (IllegalAccessException e) { + isInRemoving = true; + e.printStackTrace(); + } catch (InvocationTargetException e) { + isInRemoving = true; + e.printStackTrace(); + } + if (isInRemoving) { + swipeBackLayout = newSwipeBackLayout(); + mCacheView = swipeBackLayout; + } else { + swipeBackLayout = mCacheView; + } } + + + if (!isCreateForSwipeBack) { + mBaseView = swipeBackLayout.getContentView(); + swipeBackLayout.setTag(R.id.qmui_arch_swipe_layout_in_back, null); + } + + ViewCompat.setTranslationZ(swipeBackLayout, mBackStackIndex); + + swipeBackLayout.setFitsSystemWindows(false); + if (getActivity() != null) { QMUIViewHelper.requestApplyInsets(getActivity().getWindow()); } - if (mCreateForSwipBack) { - mSwipeBackCacheView = swipeBackLayout; + if (swipeBackLayout.getParent() != null) { + ViewGroup viewGroup = (ViewGroup) swipeBackLayout.getParent(); + if(viewGroup.indexOfChild(swipeBackLayout) > -1){ + viewGroup.removeView(swipeBackLayout); + }else{ + // see https://issuetracker.google.com/issues/71879409 + try { + Field parentField = View.class.getDeclaredField("mParent"); + parentField.setAccessible(true); + parentField.set(swipeBackLayout, null); + } catch (NoSuchFieldException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } } return swipeBackLayout; @@ -241,48 +312,6 @@ public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) { doNothingAnim.setDuration(R.integer.qmui_anim_duration); return doNothingAnim; } - - // bugfix: 使用scale enter时看不到效果, 因为两个fragment的动画在同一个层级,被退出动画遮挡了 - // http://stackoverflow.com/questions/13005961/fragmenttransaction-animation-to-slide-in-over-top#33816251 - if (nextAnim != R.anim.scale_enter || !enter) { - return super.onCreateAnimation(transit, enter, nextAnim); - } - try { - Animation nextAnimation = AnimationUtils.loadAnimation(getContext(), nextAnim); - nextAnimation.setAnimationListener(new Animation.AnimationListener() { - - private float mOldTranslationZ; - - @Override - public void onAnimationStart(Animation animation) { - if (getView() != null) { - mOldTranslationZ = ViewCompat.getTranslationZ(getView()); - ViewCompat.setTranslationZ(getView(), 100.f); - } - } - - @Override - public void onAnimationEnd(Animation animation) { - if (getView() != null) { - getView().postDelayed(new Runnable() { - @Override - public void run() { - //延迟回复z-index,如果退出动画更长,这里可能会失效 - ViewCompat.setTranslationZ(getView(), mOldTranslationZ); - } - }, 100); - - } - } - - @Override - public void onAnimationRepeat(Animation animation) { - } - }); - return nextAnimation; - } catch (Exception ignored) { - - } return null; } @@ -291,6 +320,10 @@ public void onAnimationRepeat(Animation animation) { */ protected abstract View onCreateView(); + protected boolean canDragBack() { + return true; + } + //============================= 新流程 ================================ /** diff --git a/arch/src/main/java/com/qmuiteam/qmui/arch/SwipeBackLayout.java b/arch/src/main/java/com/qmuiteam/qmui/arch/SwipeBackLayout.java index a92bea4b6..d1450f1e2 100644 --- a/arch/src/main/java/com/qmuiteam/qmui/arch/SwipeBackLayout.java +++ b/arch/src/main/java/com/qmuiteam/qmui/arch/SwipeBackLayout.java @@ -171,6 +171,10 @@ private void setContentView(View view) { mContentView = view; } + public View getContentView() { + return mContentView; + } + public void setEnableGesture(boolean enable) { mEnable = enable; } diff --git a/arch/src/main/res/values/ids.xml b/arch/src/main/res/values/ids.xml new file mode 100644 index 000000000..a5a3ec2a9 --- /dev/null +++ b/arch/src/main/res/values/ids.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/QDAboutFragment.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/QDAboutFragment.java index 92d01cf59..5e4fdfe2f 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/QDAboutFragment.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/QDAboutFragment.java @@ -20,7 +20,7 @@ /** * 关于界面 - * + *

* Created by Kayo on 2016/11/18. */ public class QDAboutFragment extends BaseFragment { @@ -77,4 +77,9 @@ public void onClick(View v) { mTopBar.setTitle(getResources().getString(R.string.about_title)); } + + @Override + public TransitionConfig onFetchTransitionConfig() { + return SCALE_TRANSITION_CONFIG; + } } diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/home/HomeFragment.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/home/HomeFragment.java index 4737856f6..ffa9f2b5f 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/home/HomeFragment.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/home/HomeFragment.java @@ -171,4 +171,9 @@ public static Pager getPagerFromPositon(int position) { } } } + + @Override + protected boolean canDragBack() { + return false; + } } \ No newline at end of file From 4c92b29af12987c51a0cae28f783b8d182d9c095 Mon Sep 17 00:00:00 2001 From: cgspine Date: Fri, 12 Jan 2018 14:02:39 +0800 Subject: [PATCH 008/887] swipe back --- .../com/qmuiteam/qmui/arch/QMUIFragment.java | 9 +- .../qmuiteam/qmui/arch/SwipeBackLayout.java | 24 +--- .../java/com/qmuiteam/qmui/arch/Utils.java | 105 ++++++++++++++++++ 3 files changed, 114 insertions(+), 24 deletions(-) create mode 100644 arch/src/main/java/com/qmuiteam/qmui/arch/Utils.java diff --git a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java index 621052821..51ec6a477 100644 --- a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java +++ b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java @@ -215,6 +215,11 @@ public void onEdgeTouch(int edgeFlag) { } catch (IllegalAccessException e) { e.printStackTrace(); } + } else { + if (getActivity() != null) { + getActivity().getWindow().getDecorView().setBackgroundColor(0); + Utils.convertActivityToTranslucent(getActivity()); + } } } @@ -279,9 +284,9 @@ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, if (swipeBackLayout.getParent() != null) { ViewGroup viewGroup = (ViewGroup) swipeBackLayout.getParent(); - if(viewGroup.indexOfChild(swipeBackLayout) > -1){ + if (viewGroup.indexOfChild(swipeBackLayout) > -1) { viewGroup.removeView(swipeBackLayout); - }else{ + } else { // see https://issuetracker.google.com/issues/71879409 try { Field parentField = View.class.getDeclaredField("mParent"); diff --git a/arch/src/main/java/com/qmuiteam/qmui/arch/SwipeBackLayout.java b/arch/src/main/java/com/qmuiteam/qmui/arch/SwipeBackLayout.java index d1450f1e2..c263cf1f2 100644 --- a/arch/src/main/java/com/qmuiteam/qmui/arch/SwipeBackLayout.java +++ b/arch/src/main/java/com/qmuiteam/qmui/arch/SwipeBackLayout.java @@ -1,6 +1,5 @@ package com.qmuiteam.qmui.arch; -import android.app.Activity; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; @@ -21,6 +20,8 @@ /** * Created by cgspine on 2018/1/7. + *

+ * modified from https://github.com/ikew0ng/SwipeBackLayout */ @@ -91,8 +92,6 @@ public class SwipeBackLayout extends QMUIWindowInsetLayout { */ private float mScrollThreshold = DEFAULT_SCROLL_THRESHOLD; - private Activity mActivity; - private boolean mEnable = true; private View mContentView; @@ -350,8 +349,6 @@ public boolean onInterceptTouchEvent(MotionEvent event) { try { return mDragHelper.shouldInterceptTouchEvent(event); } catch (ArrayIndexOutOfBoundsException e) { - // FIXME: handle exception - // issues #9 return false; } } @@ -436,23 +433,6 @@ private void drawShadow(Canvas canvas, View child) { } } - public void attachToActivity(Activity activity) { - mActivity = activity; - TypedArray a = activity.getTheme().obtainStyledAttributes(new int[]{ - android.R.attr.windowBackground - }); - int background = a.getResourceId(0, 0); - a.recycle(); - - ViewGroup decor = (ViewGroup) activity.getWindow().getDecorView(); - ViewGroup decorChild = (ViewGroup) decor.getChildAt(0); - decorChild.setBackgroundResource(background); - decor.removeView(decorChild); - addView(decorChild); - setContentView(decorChild); - decor.addView(this); - } - @Override public void computeScroll() { mScrimOpacity = 1 - mScrollPercent; diff --git a/arch/src/main/java/com/qmuiteam/qmui/arch/Utils.java b/arch/src/main/java/com/qmuiteam/qmui/arch/Utils.java new file mode 100644 index 000000000..b7a419b3b --- /dev/null +++ b/arch/src/main/java/com/qmuiteam/qmui/arch/Utils.java @@ -0,0 +1,105 @@ +package com.qmuiteam.qmui.arch; + +import android.annotation.SuppressLint; +import android.annotation.TargetApi; +import android.app.Activity; +import android.app.ActivityOptions; +import android.os.Build; + +import java.lang.reflect.Method; + +/** + * 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. + *

+ * 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. + *

+ * 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(android.app.Activity)} . + *

+ * Calling this allows the Activity behind this one to be seen again. Once + * all such Activities have been redrawn + *

+ * 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) { + } + } +} From d7e0f5896574e21f17dd4d3a6902b0ae17f3356a Mon Sep 17 00:00:00 2001 From: cgspine Date: Fri, 12 Jan 2018 14:56:58 +0800 Subject: [PATCH 009/887] bugfix: The text flashes while scrolling in QMUITabSegment #141 --- .../qmuiteam/qmui/widget/QMUITabSegment.java | 51 ++++++++++++++----- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/qmui/src/main/java/com/qmuiteam/qmui/widget/QMUITabSegment.java b/qmui/src/main/java/com/qmuiteam/qmui/widget/QMUITabSegment.java index 839fa04d9..e563ccf96 100644 --- a/qmui/src/main/java/com/qmuiteam/qmui/widget/QMUITabSegment.java +++ b/qmui/src/main/java/com/qmuiteam/qmui/widget/QMUITabSegment.java @@ -22,11 +22,13 @@ import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.view.animation.LinearInterpolator; import android.widget.FrameLayout; import android.widget.HorizontalScrollView; import android.widget.RelativeLayout; import android.widget.TextView; +import com.qmuiteam.qmui.QMUIInterpolatorStaticHolder; import com.qmuiteam.qmui.R; import com.qmuiteam.qmui.util.QMUIColorHelper; import com.qmuiteam.qmui.util.QMUIDisplayHelper; @@ -159,6 +161,12 @@ public class QMUITabSegment extends HorizontalScrollView { * typeface */ private TypefaceProvider mTypefaceProvider; + + /** + * 记录 ViewPager 的 scrollState + */ + private int mViewPagerScrollState = ViewPager.SCROLL_STATE_IDLE; + private boolean mIsAnimating; private OnTabClickListener mOnTabClickListener; private boolean mForceIndicatorNotDoLayoutWhenParentLayout = false; @@ -518,8 +526,15 @@ private void preventLayoutToChangeTabColor(TextView textView, int color, Tab mod mForceIndicatorNotDoLayoutWhenParentLayout = false; } - private void changeTabColor(TextView textView, int color, Tab model, int status) { - textView.setTextColor(color); + private void changeTabColor(TextView textView, int color, Tab model, int status){ + changeTabColor(textView, color, model, status, false); + } + + private void changeTabColor(TextView textView, int color, Tab model, int status, boolean preventColorChange) { + if(!preventColorChange){ + textView.setTextColor(color); + } + if (!model.isDynamicChangeIconColor()) { if (status == STATUS_NORMAL || model.getSelectedIcon() == null) { setDrawable(textView, model.getNormalIcon(), getTabIconPosition(model)); @@ -528,13 +543,17 @@ private void changeTabColor(TextView textView, int color, Tab model, int status) } return; } - Drawable drawable = textView.getCompoundDrawables()[getTabIconPosition(model)]; - if (drawable == null) { - return; + + if(!preventColorChange){ + Drawable drawable = textView.getCompoundDrawables()[getTabIconPosition(model)]; + if (drawable == null) { + return; + } + // 这里要拿textView已经set并mutate的drawable + QMUIDrawableHelper.setDrawableTintColor(drawable, color); + setDrawable(textView, model.getNormalIcon(), getTabIconPosition(model)); } - // 这里要拿textView已经set并mutate的drawable - QMUIDrawableHelper.setDrawableTintColor(drawable, color); - setDrawable(textView, model.getNormalIcon(), getTabIconPosition(model)); + } public void selectTab(int index) { @@ -587,11 +606,8 @@ private void selectTab(final int index, boolean preventAnim) { if (preventAnim) { setTextViewTypeface(prevView.getTextView(), false); setTextViewTypeface(nowView.getTextView(), true); - changeTabColor(prevView.getTextView(), getTabNormalColor(prevModel), prevModel, STATUS_NORMAL); - changeTabColor(nowView.getTextView(), getTabSelectedColor(nowModel), nowModel, STATUS_SELECTED); - dispatchTabUnselected(prev); - dispatchTabSelected(index); - mSelectedIndex = index; + changeTabColor(prevView.getTextView(), getTabNormalColor(prevModel), prevModel, STATUS_NORMAL, true); + changeTabColor(nowView.getTextView(), getTabSelectedColor(nowModel), nowModel, STATUS_SELECTED, true); if (getScrollX() > nowView.getLeft()) { smoothScrollTo(nowView.getLeft(), 0); } else { @@ -600,12 +616,17 @@ private void selectTab(final int index, boolean preventAnim) { smoothScrollBy(nowView.getRight() - realWidth - getScrollX(), 0); } } + + dispatchTabUnselected(prev); + dispatchTabSelected(index); + mSelectedIndex = index; return; } final int leftDistance = nowModel.getContentLeft() - prevModel.getContentLeft(); final int widthDistance = nowModel.getContentWidth() - prevModel.getContentWidth(); ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f); + animator.setInterpolator(QMUIInterpolatorStaticHolder.LINEAR_INTERPOLATOR); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { @@ -941,6 +962,10 @@ public TabLayoutOnPageChangeListener(QMUITabSegment tabSegment) { @Override public void onPageScrollStateChanged(final int state) { + final QMUITabSegment tabSegment = mTabSegmentRef.get(); + if (tabSegment != null) { + tabSegment.mViewPagerScrollState = state; + } } From e8c0feceeaff2171077e249c68362a778d0243dc Mon Sep 17 00:00:00 2001 From: cgspine Date: Sat, 13 Jan 2018 12:39:47 +0800 Subject: [PATCH 010/887] swipe back offset control --- .../com/qmuiteam/qmui/arch/QMUIFragment.java | 70 +++++++++++++++++-- .../qmuiteam/qmui/arch/SwipeBackLayout.java | 25 +++++-- .../qmuiteam/qmuidemo/base/BaseFragment.java | 7 +- 3 files changed, 88 insertions(+), 14 deletions(-) diff --git a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java index 51ec6a477..1dc578aae 100644 --- a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java +++ b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java @@ -26,16 +26,28 @@ */ public abstract class QMUIFragment extends Fragment { private static final String SWIPE_BACK_VIEW = "swipe_back_view"; - private static final String TAG = QMUIFragment.class.getSimpleName(); - // 资源,放在业务初始化,会在业务层 + /** + * Edge flag indicating that the left edge should be affected. + */ + public static final int EDGE_LEFT = SwipeBackLayout.EDGE_LEFT; + + /** + * Edge flag indicating that the right edge should be affected. + */ + public static final int EDGE_RIGHT = SwipeBackLayout.EDGE_RIGHT; + + /** + * Edge flag indicating that the bottom edge should be affected. + */ + public static final int EDGE_BOTTOM = SwipeBackLayout.EDGE_BOTTOM; + + // === 提供两种默认的进入退出动画 === protected static final TransitionConfig SLIDE_TRANSITION_CONFIG = new TransitionConfig( com.qmuiteam.qmui.arch.R.anim.slide_in_right, com.qmuiteam.qmui.arch.R.anim.slide_out_left, com.qmuiteam.qmui.arch.R.anim.slide_in_left, com.qmuiteam.qmui.arch.R.anim.slide_out_right); - - //============================= UI ================================ protected static final TransitionConfig SCALE_TRANSITION_CONFIG = new TransitionConfig( com.qmuiteam.qmui.arch.R.anim.scale_enter, com.qmuiteam.qmui.arch.R.anim.slide_still, com.qmuiteam.qmui.arch.R.anim.slide_still, com.qmuiteam.qmui.arch.R.anim.scale_exit); @@ -103,7 +115,7 @@ private SwipeBackLayout newSwipeBackLayout() { } else { rootView.setFitsSystemWindows(true); } - SwipeBackLayout swipeBackLayout = SwipeBackLayout.wrap(rootView); + SwipeBackLayout swipeBackLayout = SwipeBackLayout.wrap(rootView, dragBackEdge()); swipeBackLayout.setEnableGesture(canDragBack()); swipeBackLayout.addSwipeListener(new SwipeBackLayout.SwipeListener() { @Override @@ -162,7 +174,27 @@ public void onScrollStateChange(int state, float scrollPercent) { popBackStack(); } } + } + @Override + public void onScroll(int edgeFlag, float scrollPercent) { + int targetOffset = (int) (Math.abs(backViewInitOffset()) * (1 - scrollPercent)); + ViewGroup container = getBaseFragmentActivity().getFragmentContainer(); + int childCount = container.getChildCount(); + for (int i = childCount - 1; i >= 0; i--) { + View view = container.getChildAt(i); + Object tag = view.getTag(R.id.qmui_arch_swipe_layout_in_back); + if (tag != null && SWIPE_BACK_VIEW.equals(tag)) { + if (edgeFlag == EDGE_BOTTOM) { + ViewCompat.offsetTopAndBottom(view, targetOffset - view.getTop()); + } else if (edgeFlag == EDGE_RIGHT) { + ViewCompat.offsetLeftAndRight(view, targetOffset - view.getLeft()); + } else { + Log.i(TAG, "targetOffset = " + targetOffset + " ; view.getLeft() = " + view.getLeft()); + ViewCompat.offsetLeftAndRight(view, -targetOffset - view.getLeft()); + } + } + } } @Override @@ -203,6 +235,14 @@ public void onEdgeTouch(int edgeFlag) { if (baseView != null) { baseView.setTag(R.id.qmui_arch_swipe_layout_in_back, SWIPE_BACK_VIEW); container.addView(baseView, 0); + int offset = Math.abs(backViewInitOffset()); + if (edgeFlag == EDGE_BOTTOM) { + ViewCompat.offsetTopAndBottom(baseView, offset); + } else if (edgeFlag == EDGE_RIGHT) { + ViewCompat.offsetLeftAndRight(baseView, offset); + } else { + ViewCompat.offsetLeftAndRight(baseView, -1 * offset); + } } } } @@ -244,7 +284,7 @@ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, } else { boolean isInRemoving = false; try { - Method method = getClass().getDeclaredMethod("getAnimatingAway"); + Method method = Fragment.class.getDeclaredMethod("getAnimatingAway"); method.setAccessible(true); Object object = method.invoke(this); if (object != null) { @@ -325,10 +365,28 @@ public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) { */ protected abstract View onCreateView(); + /** + * disable or enable drag back + * + * @return + */ protected boolean canDragBack() { return true; } + /** + * if enable drag back, + * + * @return + */ + protected int backViewInitOffset() { + return 0; + } + + protected int dragBackEdge(){ + return EDGE_LEFT; + } + //============================= 新流程 ================================ /** diff --git a/arch/src/main/java/com/qmuiteam/qmui/arch/SwipeBackLayout.java b/arch/src/main/java/com/qmuiteam/qmui/arch/SwipeBackLayout.java index c263cf1f2..88629c246 100644 --- a/arch/src/main/java/com/qmuiteam/qmui/arch/SwipeBackLayout.java +++ b/arch/src/main/java/com/qmuiteam/qmui/arch/SwipeBackLayout.java @@ -256,6 +256,14 @@ public interface SwipeListener { */ void onScrollStateChange(int state, float scrollPercent); + /** + * Invoke when scrolling + * + * @param edgeFlag flag to describe edge + * @param scrollPercent scroll percent of this view + */ + void onScroll(int edgeFlag, float scrollPercent); + /** * Invoke when edge touched * @@ -503,12 +511,16 @@ public void onViewPositionChanged(View changedView, int left, int top, int dx, i if (mScrollPercent < mScrollThreshold && !mIsScrollOverValid) { mIsScrollOverValid = true; } - if (mListeners != null && !mListeners.isEmpty() - && mDragHelper.getViewDragState() == STATE_DRAGGING - && mScrollPercent >= mScrollThreshold && mIsScrollOverValid) { - mIsScrollOverValid = false; + if (mListeners != null && !mListeners.isEmpty()){ + if(mDragHelper.getViewDragState() == STATE_DRAGGING && + mScrollPercent >= mScrollThreshold && mIsScrollOverValid){ + mIsScrollOverValid = false; + for (SwipeListener listener : mListeners) { + listener.onScrollOverThreshold(); + } + } for (SwipeListener listener : mListeners) { - listener.onScrollOverThreshold(); + listener.onScroll(mTrackingEdge, mScrollPercent); } } } @@ -565,8 +577,9 @@ public void onViewDragStateChanged(int state) { } } - public static SwipeBackLayout wrap(View child) { + public static SwipeBackLayout wrap(View child, int edgeFlag) { SwipeBackLayout wrapper = new SwipeBackLayout(child.getContext()); + wrapper.setEdgeTrackingEnabled(edgeFlag); FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); child.setLayoutParams(lp); wrapper.addView(child); diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/base/BaseFragment.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/base/BaseFragment.java index 76774ce80..9daa8fe25 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/base/BaseFragment.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/base/BaseFragment.java @@ -1,6 +1,7 @@ package com.qmuiteam.qmuidemo.base; import com.qmuiteam.qmui.arch.QMUIFragment; +import com.qmuiteam.qmui.util.QMUIDisplayHelper; /** * Created by cgspine on 2018/1/7. @@ -9,9 +10,11 @@ public abstract class BaseFragment extends QMUIFragment { - public BaseFragment() { } - + @Override + protected int backViewInitOffset() { + return QMUIDisplayHelper.dp2px(getContext(), 100); + } } From 3a99bd0159672794c56c2f4bdf9b909f4de700c2 Mon Sep 17 00:00:00 2001 From: cgspine Date: Sat, 13 Jan 2018 15:36:21 +0800 Subject: [PATCH 011/887] reflect: topbar theme control --- .../qmuiteam/qmui/util/QMUIDisplayHelper.java | 42 ++++++-- .../com/qmuiteam/qmui/widget/QMUITopBar.java | 102 +++++++++--------- .../qmui/widget/QMUITopBarLayout.java | 11 +- qmui/src/main/res/values/qmui_attrs.xml | 12 +++ qmui/src/main/res/values/qmui_attrs_base.xml | 12 --- .../src/main/res/values/qmui_style_widget.xml | 36 +++++-- qmui/src/main/res/values/qmui_themes.xml | 12 --- .../main/res/values/qmui_themes_compat.xml | 12 --- qmuidemo/src/main/res/layout/home_layout.xml | 8 +- qmuidemo/src/main/res/values/styles.xml | 10 +- 10 files changed, 136 insertions(+), 121 deletions(-) diff --git a/qmui/src/main/java/com/qmuiteam/qmui/util/QMUIDisplayHelper.java b/qmui/src/main/java/com/qmuiteam/qmui/util/QMUIDisplayHelper.java index 7c70b4cca..1177f65de 100644 --- a/qmui/src/main/java/com/qmuiteam/qmui/util/QMUIDisplayHelper.java +++ b/qmui/src/main/java/com/qmuiteam/qmui/util/QMUIDisplayHelper.java @@ -1,5 +1,6 @@ package com.qmuiteam.qmui.util; +import android.annotation.TargetApi; import android.app.Activity; import android.content.Context; import android.content.pm.PackageInfo; @@ -32,11 +33,8 @@ public class QMUIDisplayHelper { */ public static final float DENSITY = Resources.getSystem() .getDisplayMetrics().density; - private static final String TAG = "Devices"; - /** - * 屏幕密度 - */ - public static float sDensity = 0f; + private static final String TAG = "QMUIDisplayHelper"; + /** * 是否有摄像头 */ @@ -75,10 +73,11 @@ public static int pxToDp(float pxValue) { } public static float getDensity(Context context) { - if (sDensity == 0f) { - sDensity = getDisplayMetrics(context).density; - } - return sDensity; + return context.getResources().getDisplayMetrics().density; + } + + public static float getFontDensity(Context context) { + return context.getResources().getDisplayMetrics().scaledDensity; } /** @@ -105,9 +104,10 @@ public static int getScreenHeight(Context context) { * @param context * @return */ + public static int[] getRealScreenSize(Context context) { int[] size = new int[2]; - int widthPixels = 0, heightPixels = 0; + int widthPixels, heightPixels; WindowManager w = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); Display d = w.getDefaultDisplay(); DisplayMetrics metrics = new DisplayMetrics(); @@ -161,6 +161,16 @@ public static int dp2px(Context context, int dp) { return (int) (getDensity(context) * dp + 0.5); } + /** + * 单位转换: sp -> px + * + * @param sp + * @return + */ + public static int sp2px(Context context, int sp) { + return (int) (getFontDensity(context) * sp + 0.5); + } + /** * 单位转换:px -> dp * @@ -171,6 +181,16 @@ public static int px2dp(Context context, int px) { return (int) (px / getDensity(context) + 0.5); } + /** + * 单位转换:px -> sp + * + * @param px + * @return + */ + public static int px2sp(Context context, int px) { + return (int) (px / getFontDensity(context) + 0.5); + } + /** * 判断是否有状态栏 * @@ -233,7 +253,7 @@ public static int getStatusBarHeight(Context context) { * @return */ public static int getNavMenuHeight(Context context) { - if(!isNavMenuExist(context)){ + if (!isNavMenuExist(context)) { return 0; } // 小米4没有nav bar, 而 navigation_bar_height 有值 diff --git a/qmui/src/main/java/com/qmuiteam/qmui/widget/QMUITopBar.java b/qmui/src/main/java/com/qmuiteam/qmui/widget/QMUITopBar.java index a0ee958a1..4eb7bed14 100644 --- a/qmui/src/main/java/com/qmuiteam/qmui/widget/QMUITopBar.java +++ b/qmui/src/main/java/com/qmuiteam/qmui/widget/QMUITopBar.java @@ -1,6 +1,7 @@ package com.qmuiteam.qmui.widget; import android.content.Context; +import android.content.res.ColorStateList; import android.content.res.TypedArray; import android.graphics.Color; import android.graphics.Rect; @@ -59,10 +60,19 @@ public class QMUITopBar extends RelativeLayout { private int mTitleGravity; private int mLeftBackDrawableRes; + private int mTitleTextSize; + private int mTitleTextSizeWithSubTitle; + private int mSubTitleTextSize; + private int mTitleTextColor; + private int mSubTitleTextColor; + private int mTitleMarginHorWhenNoBtnAside; + private int mTitleContainerPaddingHor; + private int mTopBarImageBtnWidth; + private int mTopBarImageBtnHeight; + private int mTopBarTextBtnPaddingHor; + private ColorStateList mTopBarTextBtnTextColor; + private int mTopBarTextBtnTextSize; private int mTopbarHeight = -1; - private int mTopbarImageBtnWidth = -1; - private int mTopbarImageBtnHeight = -1; - private int mTopbarTextBtnPaddingHorizontal = -1; private Rect mTitleContainerRect; public QMUITopBar(Context context, AttributeSet attrs, int defStyleAttr) { @@ -85,18 +95,16 @@ public QMUITopBar(Context context) { // ========================= title 相关的方法 // 这个构造器只用于QMUI内部,不开放给外面用,目前用于QMUITopBarLayout - QMUITopBar(Context context, boolean inTopBarLayout, int leftBackDrawableRes) { + QMUITopBar(Context context, boolean inTopBarLayout) { super(context); initVar(); if (inTopBarLayout) { int transparentColor = ContextCompat.getColor(context, R.color.qmui_config_color_transparent); mTopBarSeparatorColor = transparentColor; mTopBarSeparatorHeight = 0; - mLeftBackDrawableRes = leftBackDrawableRes; mTopBarBgColor = transparentColor; } else { init(context, null, R.attr.QMUITopBarStyle); - mLeftBackDrawableRes = leftBackDrawableRes; } } @@ -113,14 +121,31 @@ private void init(Context context, AttributeSet attrs, int defStyleAttr) { ContextCompat.getColor(context, R.color.qmui_config_color_separator)); mTopBarSeparatorHeight = array.getDimensionPixelSize(R.styleable.QMUITopBar_qmui_topbar_separator_height, 1); mTopBarBgColor = array.getColor(R.styleable.QMUITopBar_qmui_topbar_bg_color, Color.WHITE); - mLeftBackDrawableRes = array.getResourceId(R.styleable.QMUITopBar_qmui_topbar_left_back_drawable_id, R.id.qmui_topbar_item_left_back); - mTitleGravity = array.getInt(R.styleable.QMUITopBar_qmui_topbar_title_gravity, Gravity.CENTER); + getCommonFieldFormTypedArray(context, array); boolean hasSeparator = array.getBoolean(R.styleable.QMUITopBar_qmui_topbar_need_separator, true); array.recycle(); setBackgroundDividerEnabled(hasSeparator); } + void getCommonFieldFormTypedArray(Context context, TypedArray array) { + mLeftBackDrawableRes = array.getResourceId(R.styleable.QMUITopBar_qmui_topbar_left_back_drawable_id, R.id.qmui_topbar_item_left_back); + mTitleGravity = array.getInt(R.styleable.QMUITopBar_qmui_topbar_title_gravity, Gravity.CENTER); + mTitleTextSize = array.getDimensionPixelSize(R.styleable.QMUITopBar_qmui_topbar_title_text_size, QMUIDisplayHelper.sp2px(context, 17)); + mTitleTextSizeWithSubTitle = array.getDimensionPixelSize(R.styleable.QMUITopBar_qmui_topbar_title_text_size, QMUIDisplayHelper.sp2px(context, 16)); + mSubTitleTextSize = array.getDimensionPixelSize(R.styleable.QMUITopBar_qmui_topbar_subtitle_text_size, QMUIDisplayHelper.sp2px(context, 11)); + mTitleTextColor = array.getColor(R.styleable.QMUITopBar_qmui_topbar_title_color, QMUIResHelper.getAttrColor(context, R.attr.qmui_config_color_gray_1)); + mSubTitleTextColor = array.getColor(R.styleable.QMUITopBar_qmui_topbar_subtitle_color, QMUIResHelper.getAttrColor(context, R.attr.qmui_config_color_gray_4)); + mTitleMarginHorWhenNoBtnAside = array.getDimensionPixelSize(R.styleable.QMUITopBar_qmui_topbar_title_margin_horizontal_when_no_btn_aside, 0); + mTitleContainerPaddingHor = array.getDimensionPixelSize(R.styleable.QMUITopBar_qmui_topbar_title_container_padding_horizontal, 0); + mTopBarImageBtnWidth = array.getDimensionPixelSize(R.styleable.QMUITopBar_qmui_topbar_image_btn_width, QMUIDisplayHelper.dp2px(context, 48)); + mTopBarImageBtnHeight = array.getDimensionPixelSize(R.styleable.QMUITopBar_qmui_topbar_image_btn_height, QMUIDisplayHelper.dp2px(context, 48)); + mTopBarTextBtnPaddingHor = array.getDimensionPixelSize(R.styleable.QMUITopBar_qmui_topbar_text_btn_padding_horizontal, QMUIDisplayHelper.dp2px(context, 12)); + mTopBarTextBtnTextColor = array.getColorStateList(R.styleable.QMUITopBar_qmui_topbar_text_btn_color_state_list); + mTopBarTextBtnTextSize = array.getDimensionPixelSize(R.styleable.QMUITopBar_qmui_topbar_text_btn_text_size, QMUIDisplayHelper.sp2px(context, 16)); + + } + @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); @@ -211,7 +236,7 @@ private TextView getTitleView(boolean isEmoji) { mTitleView.setGravity(Gravity.CENTER); mTitleView.setSingleLine(true); mTitleView.setEllipsize(TruncateAt.MIDDLE); - mTitleView.setTextColor(QMUIResHelper.getAttrColor(getContext(), R.attr.qmui_topbar_title_color)); + mTitleView.setTextColor(mTitleTextColor); updateTitleViewStyle(); LinearLayout.LayoutParams titleLp = generateTitleViewAndSubTitleViewLp(); makeSureTitleContainerView().addView(mTitleView, titleLp); @@ -226,9 +251,9 @@ private TextView getTitleView(boolean isEmoji) { private void updateTitleViewStyle() { if (mTitleView != null) { if (mSubTitleView == null || QMUILangHelper.isNullOrEmpty(mSubTitleView.getText())) { - mTitleView.setTextSize(TypedValue.COMPLEX_UNIT_PX, QMUIResHelper.getAttrDimen(getContext(), R.attr.qmui_topbar_title_text_size)); + mTitleView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTitleTextSize); } else { - mTitleView.setTextSize(TypedValue.COMPLEX_UNIT_PX, QMUIResHelper.getAttrDimen(getContext(), R.attr.qmui_topbar_title_text_size_with_subtitle)); + mTitleView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTitleTextSizeWithSubTitle); } } } @@ -265,8 +290,8 @@ private TextView getSubTitleView() { mSubTitleView.setGravity(Gravity.CENTER); mSubTitleView.setSingleLine(true); mSubTitleView.setEllipsize(TruncateAt.MIDDLE); - mSubTitleView.setTextSize(TypedValue.COMPLEX_UNIT_PX, QMUIResHelper.getAttrDimen(getContext(), R.attr.qmui_topbar_subtitle_text_size)); - mSubTitleView.setTextColor(QMUIResHelper.getAttrColor(getContext(), R.attr.qmui_topbar_subtitle_color)); + mSubTitleView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mSubTitleTextSize); + mSubTitleView.setTextColor(mSubTitleTextColor); LinearLayout.LayoutParams titleLp = generateTitleViewAndSubTitleViewLp(); titleLp.topMargin = QMUIDisplayHelper.dp2px(getContext(), 1); makeSureTitleContainerView().addView(mSubTitleView, titleLp); @@ -315,8 +340,7 @@ private LinearLayout makeSureTitleContainerView() { // 垂直,后面要支持水平的话可以加个接口来设置 mTitleContainerView.setOrientation(LinearLayout.VERTICAL); mTitleContainerView.setGravity(Gravity.CENTER); - int horPadding = QMUIResHelper.getAttrDimen(getContext(), R.attr.qmui_topbar_title_container_padding_horizontal); - mTitleContainerView.setPadding(horPadding, 0, horPadding, 0); + mTitleContainerView.setPadding(mTitleContainerPaddingHor, 0, mTitleContainerPaddingHor, 0); addView(mTitleContainerView, generateTitleContainerViewLp()); } return mTitleContainerView; @@ -420,8 +444,8 @@ public void addRightView(View view, int viewId, LayoutParams layoutParams) { * 生成一个 LayoutParams,当把 Button addView 到 TopBar 时,使用这个 LayouyParams */ public LayoutParams generateTopBarImageButtonLayoutParams() { - LayoutParams lp = new LayoutParams(getTopBarImageBtnWidth(), getTopBarImageBtnHeight()); - lp.topMargin = Math.max(0, (getTopBarHeight() - getTopBarImageBtnHeight()) / 2); + LayoutParams lp = new LayoutParams(mTopBarImageBtnWidth, mTopBarImageBtnHeight); + lp.topMargin = Math.max(0, (getTopBarHeight() - mTopBarImageBtnHeight) / 2); return lp; } @@ -455,8 +479,8 @@ public QMUIAlphaImageButton addLeftImageButton(int drawableResId, int viewId) { * 生成一个LayoutParams,当把 Button addView 到 TopBar 时,使用这个 LayouyParams */ public LayoutParams generateTopBarTextButtonLayoutParams() { - LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, getTopBarImageBtnHeight()); - lp.topMargin = Math.max(0, (getTopBarHeight() - getTopBarImageBtnHeight()) / 2); + LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, mTopBarImageBtnHeight); + lp.topMargin = Math.max(0, (getTopBarHeight() - mTopBarImageBtnHeight) / 2); return lp; } @@ -521,10 +545,9 @@ private Button generateTopBarTextButton(String text) { button.setMinHeight(0); button.setMinimumWidth(0); button.setMinimumHeight(0); - int paddingHorizontal = getTopBarTextBtnPaddingHorizontal(); - button.setPadding(paddingHorizontal, 0, paddingHorizontal, 0); - button.setTextColor(QMUIResHelper.getAttrColorStateList(getContext(), R.attr.qmui_topbar_text_btn_color_state_list)); - button.setTextSize(TypedValue.COMPLEX_UNIT_PX, QMUIResHelper.getAttrDimen(getContext(), R.attr.qmui_topbar_text_btn_text_size)); + button.setPadding(mTopBarTextBtnPaddingHor, 0, mTopBarTextBtnPaddingHor, 0); + button.setTextColor(mTopBarTextBtnTextColor); + button.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTopBarTextBtnTextSize); button.setGravity(Gravity.CENTER); button.setText(text); return button; @@ -599,27 +622,6 @@ private int getTopBarHeight() { return mTopbarHeight; } - protected int getTopBarImageBtnWidth() { - if (mTopbarImageBtnWidth == -1) { - mTopbarImageBtnWidth = QMUIResHelper.getAttrDimen(getContext(), R.attr.qmui_topbar_image_btn_height); - } - return mTopbarImageBtnWidth; - } - - protected int getTopBarImageBtnHeight() { - if (mTopbarImageBtnHeight == -1) { - mTopbarImageBtnHeight = QMUIResHelper.getAttrDimen(getContext(), R.attr.qmui_topbar_image_btn_height); - } - return mTopbarImageBtnHeight; - } - - private int getTopBarTextBtnPaddingHorizontal() { - if (mTopbarTextBtnPaddingHorizontal == -1) { - mTopbarTextBtnPaddingHorizontal = QMUIResHelper.getAttrDimen(getContext(), R.attr.qmui_topbar_text_btn_padding_horizontal); - } - return mTopbarTextBtnPaddingHorizontal; - } - // ======================== TopBar自身相关的方法 /** @@ -686,10 +688,8 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if ((mTitleGravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.CENTER_HORIZONTAL) { if (leftViewWidth == 0 && rightViewWidth == 0) { // 左右没有按钮时,title 距离 TopBar 左右边缘的距离 - int titleMarginHorizontalWithoutButton = QMUIResHelper.getAttrDimen(getContext(), - R.attr.qmui_topbar_title_margin_horizontal_when_no_btn_aside); - leftViewWidth += titleMarginHorizontalWithoutButton; - rightViewWidth += titleMarginHorizontalWithoutButton; + leftViewWidth += mTitleMarginHorWhenNoBtnAside; + rightViewWidth += mTitleMarginHorWhenNoBtnAside; } // 标题水平居中,左右两侧的占位要保持一致 @@ -697,12 +697,10 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { } else { // 标题非水平居中,左右没有按钮时,间距分别计算 if (leftViewWidth == 0) { - leftViewWidth += QMUIResHelper.getAttrDimen(getContext(), - R.attr.qmui_topbar_title_margin_horizontal_when_no_btn_aside); + leftViewWidth += mTitleMarginHorWhenNoBtnAside; } if (rightViewWidth == 0) { - rightViewWidth += QMUIResHelper.getAttrDimen(getContext(), - R.attr.qmui_topbar_title_margin_horizontal_when_no_btn_aside); + rightViewWidth += mTitleMarginHorWhenNoBtnAside; } // 标题非水平居中,左右两侧的占位按实际计算即可 diff --git a/qmui/src/main/java/com/qmuiteam/qmui/widget/QMUITopBarLayout.java b/qmui/src/main/java/com/qmuiteam/qmui/widget/QMUITopBarLayout.java index 0ecc2b84e..ae6d85374 100644 --- a/qmui/src/main/java/com/qmuiteam/qmui/widget/QMUITopBarLayout.java +++ b/qmui/src/main/java/com/qmuiteam/qmui/widget/QMUITopBarLayout.java @@ -13,11 +13,11 @@ import android.widget.RelativeLayout; import android.widget.TextView; -import com.qmuiteam.qmui.alpha.QMUIAlphaImageButton; -import com.qmuiteam.qmui.util.QMUIViewHelper; import com.qmuiteam.qmui.R; +import com.qmuiteam.qmui.alpha.QMUIAlphaImageButton; import com.qmuiteam.qmui.util.QMUIDrawableHelper; import com.qmuiteam.qmui.util.QMUIResHelper; +import com.qmuiteam.qmui.util.QMUIViewHelper; /** * 这是一个对 {@link QMUITopBar} 的代理类,需要它的原因是: @@ -54,17 +54,18 @@ public QMUITopBarLayout(Context context, AttributeSet attrs, int defStyleAttr) { ContextCompat.getColor(context, R.color.qmui_config_color_separator)); mTopBarSeparatorHeight = array.getDimensionPixelSize(R.styleable.QMUITopBar_qmui_topbar_separator_height, 1); mTopBarBgColor = array.getColor(R.styleable.QMUITopBar_qmui_topbar_bg_color, Color.WHITE); - int leftBackResId = array.getResourceId(R.styleable.QMUITopBar_qmui_topbar_left_back_drawable_id, R.id.qmui_topbar_item_left_back); boolean hasSeparator = array.getBoolean(R.styleable.QMUITopBar_qmui_topbar_need_separator, true); - array.recycle(); // 构造一个透明的背景且无分隔线的TopBar,背景与分隔线有QMUITopBarLayout控制 - mTopBar = new QMUITopBar(context, true, leftBackResId); + mTopBar = new QMUITopBar(context, true); + mTopBar.getCommonFieldFormTypedArray(context, array); FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, QMUIResHelper.getAttrDimen(context, R.attr.qmui_topbar_height)); addView(mTopBar, lp); + array.recycle(); + setBackgroundDividerEnabled(hasSeparator); } diff --git a/qmui/src/main/res/values/qmui_attrs.xml b/qmui/src/main/res/values/qmui_attrs.xml index 52c659a99..458730286 100755 --- a/qmui/src/main/res/values/qmui_attrs.xml +++ b/qmui/src/main/res/values/qmui_attrs.xml @@ -79,6 +79,18 @@ + + + + + + + + + + + + diff --git a/qmui/src/main/res/values/qmui_attrs_base.xml b/qmui/src/main/res/values/qmui_attrs_base.xml index 49ab48d09..26493c450 100644 --- a/qmui/src/main/res/values/qmui_attrs_base.xml +++ b/qmui/src/main/res/values/qmui_attrs_base.xml @@ -182,18 +182,6 @@ * qmui topbar * ***********************************************--> - - - - - - - - - - - - @@ -71,16 +76,28 @@ center 4dp 4dp + ?attr/qmui_config_color_gray_1 + 17sp + 16sp + 0dp + 8dp + 11sp + @color/qmui_config_color_gray_1 + 48dp + 48dp + 12dp + @color/qmui_topbar_text_color + 16sp @@ -119,7 +136,8 @@ ?attr/qmui_dialog_background_dim_amount true @android:color/transparent - @null + @null + match_parent @@ -161,9 +179,9 @@ 5dp - - - \ No newline at end of file diff --git a/qmui/src/main/res/values/qmui_style_widget.xml b/qmui/src/main/res/values/qmui_style_widget.xml index 5780c0654..637d2233a 100644 --- a/qmui/src/main/res/values/qmui_style_widget.xml +++ b/qmui/src/main/res/values/qmui_style_widget.xml @@ -1,6 +1,5 @@ - + + + + + + + + + + + + + + + + + + diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDDialogFragment.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDDialogFragment.java index 783269756..0d6b6e7de 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDDialogFragment.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDDialogFragment.java @@ -4,6 +4,7 @@ import android.content.DialogInterface; import android.support.v4.content.ContextCompat; import android.text.InputType; +import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -21,6 +22,7 @@ import com.qmuiteam.qmui.util.QMUIResHelper; import com.qmuiteam.qmui.util.QMUIViewHelper; import com.qmuiteam.qmui.widget.QMUITopBar; +import com.qmuiteam.qmui.widget.dialog.QMUIBottomSheet; import com.qmuiteam.qmui.widget.dialog.QMUIDialog; import com.qmuiteam.qmui.widget.dialog.QMUIDialogAction; import com.qmuiteam.qmuidemo.manager.QDDataManager; @@ -47,6 +49,7 @@ public class QDDialogFragment extends BaseFragment { @BindView(R.id.listview) ListView mListView; private QDItemDescription mQDItemDescription; + private int mCurrentDialogStyle = com.qmuiteam.qmui.R.style.QMUI_Dialog; @Override protected View onCreateView() { @@ -66,6 +69,14 @@ public void onClick(View v) { } }); + mTopBar.addRightImageButton(R.mipmap.icon_topbar_overflow, R.id.topbar_right_change_button) + .setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + showBottomSheet(); + } + }); + mTopBar.setTitle(mQDItemDescription.getName()); } @@ -145,7 +156,7 @@ public void onClick(QMUIDialog dialog, int index) { Toast.makeText(getActivity(), "发送成功", Toast.LENGTH_SHORT).show(); } }) - .show(); + .create(mCurrentDialogStyle).show(); } private void showMessageNegativeDialog() { @@ -165,7 +176,7 @@ public void onClick(QMUIDialog dialog, int index) { dialog.dismiss(); } }) - .show(); + .create(mCurrentDialogStyle).show(); } private void showLongMessageDialog() { @@ -188,7 +199,7 @@ public void onClick(QMUIDialog dialog, int index) { dialog.dismiss(); } }) - .show(); + .create(mCurrentDialogStyle).show(); } private void showConfirmMessageDialog() { @@ -208,7 +219,7 @@ public void onClick(QMUIDialog dialog, int index) { dialog.dismiss(); } }) - .show(); + .create(mCurrentDialogStyle).show(); } private void showMenuDialog() { @@ -221,7 +232,7 @@ public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }) - .show(); + .create(mCurrentDialogStyle).show(); } private void showSingleChoiceDialog() { @@ -236,7 +247,7 @@ public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }) - .show(); + .create(mCurrentDialogStyle).show(); } private void showMultiChoiceDialog() { @@ -266,7 +277,7 @@ public void onClick(QMUIDialog dialog, int index) { dialog.dismiss(); } }); - builder.show(); + builder.create(mCurrentDialogStyle).show(); } private void showNumerousMultiChoiceDialog() { @@ -300,7 +311,7 @@ public void onClick(QMUIDialog dialog, int index) { dialog.dismiss(); } }); - builder.show(); + builder.create(mCurrentDialogStyle).show(); } private void showEditTextDialog() { @@ -326,7 +337,7 @@ public void onClick(QMUIDialog dialog, int index) { } } }) - .show(); + .create(mCurrentDialogStyle).show(); } private void showAutoDialog() { @@ -344,7 +355,7 @@ public void onClick(QMUIDialog dialog, int index) { dialog.dismiss(); } }); - autoTestDialogBuilder.show(); + autoTestDialogBuilder.create(mCurrentDialogStyle).show(); QMUIKeyboardHelper.showKeyboard(autoTestDialogBuilder.getEditText(), true); } @@ -387,4 +398,26 @@ public View onBuildContent(QMUIDialog dialog, ScrollView parent) { return layout; } } + + + private void showBottomSheet() { + new QMUIBottomSheet.BottomListSheetBuilder(getContext()) + .addItem("使用 QMUI 默认 Dialog 样式") + .addItem("自定义样式") + .setOnSheetItemClickListener(new QMUIBottomSheet.BottomListSheetBuilder.OnSheetItemClickListener() { + @Override + public void onClick(QMUIBottomSheet dialog, View itemView, int position, String tag) { + switch (position) { + case 0: + mCurrentDialogStyle = com.qmuiteam.qmui.R.style.QMUI_Dialog; + break; + case 1: + mCurrentDialogStyle = R.style.DialogTheme2; + break; + } + dialog.dismiss(); + } + }) + .build().show(); + } } diff --git a/qmuidemo/src/main/res/values/styles.xml b/qmuidemo/src/main/res/values/styles.xml index c669ee3d0..3a11fdc29 100644 --- a/qmuidemo/src/main/res/values/styles.xml +++ b/qmuidemo/src/main/res/values/styles.xml @@ -83,4 +83,75 @@ @drawable/qmui_divider_bottom_bitmap + + + + + + + + + + + + + + + + From b991dd5395c24e16f2a4444827fe3c13e17ed8c7 Mon Sep 17 00:00:00 2001 From: cgspine Date: Thu, 22 Mar 2018 15:01:51 +0800 Subject: [PATCH 039/887] qmui layout demo --- .../qmui/layout/QMUILayoutHelper.java | 13 +- .../fragment/components/QDLayoutFragment.java | 131 ++++++++++++++++ .../qmuidemo/manager/QDDataManager.java | 2 + .../qmuidemo/view/QDShadowAdjustLayout.java | 54 +++++++ .../src/main/res/layout/fragment_layout.xml | 145 ++++++++++++++++++ qmuidemo/src/main/res/values/ids.xml | 2 + 6 files changed, 341 insertions(+), 6 deletions(-) create mode 100644 qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDLayoutFragment.java create mode 100644 qmuidemo/src/main/java/com/qmuiteam/qmuidemo/view/QDShadowAdjustLayout.java create mode 100644 qmuidemo/src/main/res/layout/fragment_layout.xml diff --git a/qmui/src/main/java/com/qmuiteam/qmui/layout/QMUILayoutHelper.java b/qmui/src/main/java/com/qmuiteam/qmui/layout/QMUILayoutHelper.java index b6580aa3d..6e6f822ce 100644 --- a/qmui/src/main/java/com/qmuiteam/qmui/layout/QMUILayoutHelper.java +++ b/qmui/src/main/java/com/qmuiteam/qmui/layout/QMUILayoutHelper.java @@ -86,7 +86,7 @@ public class QMUILayoutHelper { private RectF mBorderRect; private int mBorderColor = 0; private int mBorderWidth = 1; - private int mOuterNormalColor; + private int mOuterNormalColor = 0; private WeakReference mOwner; private boolean mIsOutlineExcludePadding = false; private Path mPath = new Path(); @@ -112,7 +112,6 @@ public QMUILayoutHelper(Context context, AttributeSet attrs, int defAttr, View o mClipPaint.setAntiAlias(true); mShadowAlpha = QMUIResHelper.getAttrFloatValue(context, R.attr.qmui_general_shadow_alpha); mBorderRect = new RectF(); - mOuterNormalColor = ContextCompat.getColor(context, R.color.qmui_config_color_white); int radius = 0, shadow = 0; boolean useThemeGeneralShadowElevation = false; @@ -555,7 +554,7 @@ public void dispatchRoundBorderDraw(Canvas canvas) { if (owner == null) { return; } - if (mBorderColor == 0) { + if (mBorderColor == 0 && (mRadius == 0 || mOuterNormalColor == 0)) { return; } @@ -564,8 +563,7 @@ public void dispatchRoundBorderDraw(Canvas canvas) { } int width = canvas.getWidth(), height = canvas.getHeight(); - mClipPaint.setColor(mBorderColor); - mClipPaint.setStrokeWidth(mBorderWidth); + // react if (mIsOutlineExcludePadding) { mBorderRect.set(1 + owner.getPaddingLeft(), 1 + owner.getPaddingTop(), @@ -574,7 +572,7 @@ public void dispatchRoundBorderDraw(Canvas canvas) { mBorderRect.set(1, 1, width - 1, height - 1); } - if (mRadius == 0) { + if (mRadius == 0 || (!useFeature() && mOuterNormalColor == 0)) { mClipPaint.setStyle(Paint.Style.STROKE); canvas.drawRect(mBorderRect, mClipPaint); return; @@ -584,6 +582,7 @@ public void dispatchRoundBorderDraw(Canvas canvas) { if (!useFeature()) { int layerId = canvas.saveLayer(0, 0, width, height, null, Canvas.ALL_SAVE_FLAG); canvas.drawColor(mOuterNormalColor); + mClipPaint.setColor(mOuterNormalColor); mClipPaint.setStyle(Paint.Style.FILL); mClipPaint.setXfermode(mMode); if (mRadiusArray == null) { @@ -595,6 +594,8 @@ public void dispatchRoundBorderDraw(Canvas canvas) { canvas.restoreToCount(layerId); } + mClipPaint.setColor(mBorderColor); + mClipPaint.setStrokeWidth(mBorderWidth); mClipPaint.setStyle(Paint.Style.STROKE); if (mRadiusArray == null) { canvas.drawRoundRect(mBorderRect, mRadius, mRadius, mClipPaint); diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDLayoutFragment.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDLayoutFragment.java new file mode 100644 index 000000000..a3ac2e18c --- /dev/null +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDLayoutFragment.java @@ -0,0 +1,131 @@ +package com.qmuiteam.qmuidemo.fragment.components; + +import android.view.LayoutInflater; +import android.view.View; +import android.widget.RadioGroup; +import android.widget.SeekBar; +import android.widget.TextView; + +import com.qmuiteam.qmui.layout.QMUILayoutHelper; +import com.qmuiteam.qmui.layout.QMUILinearLayout; +import com.qmuiteam.qmui.util.QMUIDisplayHelper; +import com.qmuiteam.qmui.widget.QMUITopBarLayout; +import com.qmuiteam.qmuidemo.R; +import com.qmuiteam.qmuidemo.base.BaseFragment; +import com.qmuiteam.qmuidemo.lib.annotation.Widget; +import com.qmuiteam.qmuidemo.manager.QDDataManager; +import com.qmuiteam.qmuidemo.model.QDItemDescription; + +import butterknife.BindView; +import butterknife.ButterKnife; + +/** + * Created by cgspine on 2018/3/22. + */ + +@Widget(name = "QMUILayout", iconRes = R.mipmap.icon_grid_dialog) +public class QDLayoutFragment extends BaseFragment { + + @BindView(R.id.topbar) QMUITopBarLayout mTopBar; + @BindView(R.id.layout_for_test) QMUILinearLayout mTestLayout; + @BindView(R.id.test_seekbar_alpha) SeekBar mAlphaSeekBar; + @BindView(R.id.test_seekbar_elevation) SeekBar mElevationSeekBar; + @BindView(R.id.alpha_tv) TextView mAlphaTv; + @BindView(R.id.elevation_tv) TextView mElevationTv; + @BindView(R.id.hide_radius_group) RadioGroup mHideRadiusGroup; + + private QDItemDescription mQDItemDescription; + private float mShadowAlpha = 0.25f; + private int mShadowElevationDp = 14; + private int mRadius; + + @Override + protected View onCreateView() { + mRadius = QMUIDisplayHelper.dp2px(getContext(), 15); + View view = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_layout, null); + ButterKnife.bind(this, view); + mQDItemDescription = QDDataManager.getInstance().getDescription(this.getClass()); + initTopBar(); + initLayout(); + return view; + } + + private void initTopBar() { + mTopBar.addLeftBackImageButton().setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + popBackStack(); + } + }); + mTopBar.setTitle(mQDItemDescription.getName()); + } + + private void initLayout() { + mAlphaSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + mShadowAlpha = progress * 1f / 100; + mAlphaTv.setText("alpha: " + mShadowAlpha); + mTestLayout.setRadiusAndShadow(mRadius, + QMUIDisplayHelper.dp2px(getContext(), mShadowElevationDp), + mShadowAlpha); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + + } + }); + + mElevationSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + mShadowElevationDp = progress; + mElevationTv.setText("elevation: " + progress + "dp"); + mTestLayout.setRadiusAndShadow(mRadius, + QMUIDisplayHelper.dp2px(getActivity(), mShadowElevationDp), mShadowAlpha); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + + } + }); + + mAlphaSeekBar.setProgress((int) (mShadowAlpha * 100)); + mElevationSeekBar.setProgress(mShadowElevationDp); + + mHideRadiusGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(RadioGroup group, int checkedId) { + switch (checkedId) { + case R.id.hide_radius_none: + mTestLayout.setRadius(mRadius, QMUILayoutHelper.HIDE_RADIUS_SIDE_NONE); + break; + case R.id.hide_radius_left: + mTestLayout.setRadius(mRadius, QMUILayoutHelper.HIDE_RADIUS_SIDE_LEFT); + break; + case R.id.hide_radius_top: + mTestLayout.setRadius(mRadius, QMUILayoutHelper.HIDE_RADIUS_SIDE_TOP); + break; + case R.id.hide_radius_bottom: + mTestLayout.setRadius(mRadius, QMUILayoutHelper.HIDE_RADIUS_SIDE_BOTTOM); + break; + case R.id.hide_radius_right: + mTestLayout.setRadius(mRadius, QMUILayoutHelper.HIDE_RADIUS_SIDE_RIGHT); + break; + } + } + }); + } +} diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/manager/QDDataManager.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/manager/QDDataManager.java index 8c79cdba9..3a5068b4c 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/manager/QDDataManager.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/manager/QDDataManager.java @@ -8,6 +8,7 @@ import com.qmuiteam.qmuidemo.fragment.components.QDEmptyViewFragment; import com.qmuiteam.qmuidemo.fragment.components.QDFloatLayoutFragment; import com.qmuiteam.qmuidemo.fragment.components.QDGroupListViewFragment; +import com.qmuiteam.qmuidemo.fragment.components.QDLayoutFragment; import com.qmuiteam.qmuidemo.fragment.components.QDLinkTextViewFragment; import com.qmuiteam.qmuidemo.fragment.components.QDPopupFragment; import com.qmuiteam.qmuidemo.fragment.components.QDProgressBarFragment; @@ -84,6 +85,7 @@ private void initComponentsDesc() { mComponentsNames.add(QDSpanFragment.class); mComponentsNames.add(QDCollapsingTopBarLayoutFragment.class); mComponentsNames.add(QDViewPagerFragment.class); + mComponentsNames.add(QDLayoutFragment.class); } /** diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/view/QDShadowAdjustLayout.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/view/QDShadowAdjustLayout.java new file mode 100644 index 000000000..cd5ce2561 --- /dev/null +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/view/QDShadowAdjustLayout.java @@ -0,0 +1,54 @@ +package com.qmuiteam.qmuidemo.view; + +import android.content.Context; +import android.support.v4.widget.ViewDragHelper; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; + +import com.qmuiteam.qmui.layout.QMUIFrameLayout; +import com.qmuiteam.qmuidemo.R; + +/** + * Created by cgspine on 2018/3/22. + */ + +public class QDShadowAdjustLayout extends QMUIFrameLayout { + ViewDragHelper viewDragHelper; + + public QDShadowAdjustLayout(Context context) { + this(context, null); + } + + public QDShadowAdjustLayout(Context context, AttributeSet attrs) { + super(context, attrs); + + viewDragHelper = ViewDragHelper.create(this, new ViewDragHelper.Callback() { + @Override + public boolean tryCaptureView(View child, int pointerId) { + return child.getId() == R.id.layout_for_test; + } + + @Override + public int clampViewPositionHorizontal(View child, int left, int dx) { + return left; + } + + @Override + public int clampViewPositionVertical(View child, int top, int dy) { + return top; + } + }); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent event) { + return viewDragHelper.shouldInterceptTouchEvent(event); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + viewDragHelper.processTouchEvent(event); + return true; + } +} diff --git a/qmuidemo/src/main/res/layout/fragment_layout.xml b/qmuidemo/src/main/res/layout/fragment_layout.xml new file mode 100644 index 000000000..48dcc7800 --- /dev/null +++ b/qmuidemo/src/main/res/layout/fragment_layout.xml @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/qmuidemo/src/main/res/values/ids.xml b/qmuidemo/src/main/res/values/ids.xml index 35ed6ceec..c2cc62a0b 100644 --- a/qmuidemo/src/main/res/values/ids.xml +++ b/qmuidemo/src/main/res/values/ids.xml @@ -7,4 +7,6 @@ + + \ No newline at end of file From d48b60998bf75de952386eb45916c0873ac93afc Mon Sep 17 00:00:00 2001 From: cgspine Date: Thu, 22 Mar 2018 15:24:22 +0800 Subject: [PATCH 040/887] bugfix:fix the error in determining direction in QMUIPopup. #210 --- .../src/main/java/com/qmuiteam/qmui/widget/popup/QMUIPopup.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qmui/src/main/java/com/qmuiteam/qmui/widget/popup/QMUIPopup.java b/qmui/src/main/java/com/qmuiteam/qmui/widget/popup/QMUIPopup.java index fa6137064..b89504147 100644 --- a/qmui/src/main/java/com/qmuiteam/qmui/widget/popup/QMUIPopup.java +++ b/qmui/src/main/java/com/qmuiteam/qmui/widget/popup/QMUIPopup.java @@ -147,7 +147,7 @@ private void calculatePosition(View attachedView) { break; case DIRECTION_BOTTOM: mY = attachedViewLocation[1] + attachedView.getHeight(); - if (mY > mScreenSize.y - mPopupTopBottomMinMargin) { + if (mY > mScreenSize.y - mPopupTopBottomMinMargin - mWindowHeight) { mY = attachedViewLocation[1] - mWindowHeight; mDirection = DIRECTION_TOP; } From e5f112b366cbbbd2367139fac34d9f4109211079 Mon Sep 17 00:00:00 2001 From: cgspine Date: Fri, 23 Mar 2018 10:04:32 +0800 Subject: [PATCH 041/887] bugfix: start dragging and then quickly click on the tab will bring an error #198 --- .../qmuiteam/qmui/widget/QMUITabSegment.java | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/qmui/src/main/java/com/qmuiteam/qmui/widget/QMUITabSegment.java b/qmui/src/main/java/com/qmuiteam/qmui/widget/QMUITabSegment.java index 94b109c77..83c987ac6 100644 --- a/qmui/src/main/java/com/qmuiteam/qmui/widget/QMUITabSegment.java +++ b/qmui/src/main/java/com/qmuiteam/qmui/widget/QMUITabSegment.java @@ -14,8 +14,11 @@ import android.support.v4.content.ContextCompat; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; +import android.support.v7.widget.AppCompatTextView; import android.text.TextUtils; import android.util.AttributeSet; +import android.util.Log; +import android.util.Pair; import android.util.TypedValue; import android.view.GestureDetector; import android.view.Gravity; @@ -172,7 +175,7 @@ public class QMUITabSegment extends HorizontalScrollView { protected OnClickListener mTabOnClickListener = new OnClickListener() { @Override public void onClick(View v) { - if (mIsAnimating) { + if (mIsAnimating || mViewPagerScrollState != ViewPager.SCROLL_STATE_IDLE) { return; } int index = (int) v.getTag(); @@ -194,6 +197,7 @@ public void onClick(View v) { private ViewPager.OnPageChangeListener mOnPageChangeListener; private OnTabSelectedListener mViewPagerSelectedListener; // private AdapterChangeListener mAdapterChangeListener; + private boolean mIsInSelectTab = false; public QMUITabSegment(Context context) { this(context, null); @@ -563,16 +567,23 @@ public void selectTab(int index) { * 只有点击 tab 才会自己产生动画变化,其它需要使用 updateIndicatorPosition 做驱动 */ private void selectTab(final int index, boolean preventAnim) { + if(mIsInSelectTab){ + return; + } + mIsInSelectTab = true; if (mContentLayout.getTabAdapter().getSize() == 0 || mContentLayout.getTabAdapter().getSize() <= index) { + mIsInSelectTab = false; return; } if (mSelectedIndex == index) { dispatchTabReselected(index); + mIsInSelectTab = false; return; } if (mIsAnimating) { mPendingSelectedIndex = index; + mIsInSelectTab = false; return; } @@ -594,6 +605,7 @@ private void selectTab(final int index, boolean preventAnim) { changeTabColor(selectedTv, getTabSelectedColor(model), model, STATUS_SELECTED); dispatchTabSelected(index); mSelectedIndex = index; + mIsInSelectTab = false; return; } final int prev = mSelectedIndex; @@ -603,6 +615,8 @@ private void selectTab(final int index, boolean preventAnim) { final TabItemView nowView = listViews.get(index); if (preventAnim) { + dispatchTabUnselected(prev); + dispatchTabSelected(index); setTextViewTypeface(prevView.getTextView(), false); setTextViewTypeface(nowView.getTextView(), true); changeTabColor(prevView.getTextView(), getTabNormalColor(prevModel), prevModel, STATUS_NORMAL, mViewPagerScrollState != ViewPager.SCROLL_STATE_IDLE); @@ -615,10 +629,8 @@ private void selectTab(final int index, boolean preventAnim) { smoothScrollBy(nowView.getRight() - realWidth - getScrollX(), 0); } } - - dispatchTabUnselected(prev); - dispatchTabSelected(index); mSelectedIndex = index; + mIsInSelectTab = false; return; } @@ -677,6 +689,7 @@ public void onAnimationRepeat(Animator animation) { }); animator.setDuration(200); animator.start(); + mIsInSelectTab = false; } private void setTextViewTypeface(TextView tv, boolean selected) { @@ -687,13 +700,11 @@ private void setTextViewTypeface(TextView tv, boolean selected) { tv.setTypeface(null, isBold ? Typeface.BOLD : Typeface.NORMAL); } - public void updateIndicatorPosition(int index, float offsetPercent) { - if (mIsAnimating) { - return; - } - if (offsetPercent == 0) { + public void updateIndicatorPosition(final int index, float offsetPercent) { + if (mIsAnimating || mIsInSelectTab || offsetPercent == 0) { return; } + int targetIndex; if (offsetPercent < 0) { targetIndex = index - 1; @@ -1334,7 +1345,7 @@ protected void bind(Tab item, TabItemView view, int position) { } } - public class InnerTextView extends TextView { + public class InnerTextView extends AppCompatTextView { public InnerTextView(Context context) { super(context); From 3fd67696c4b251d975f193445f547027ccf9e5df Mon Sep 17 00:00:00 2001 From: cgspine Date: Fri, 23 Mar 2018 16:00:45 +0800 Subject: [PATCH 042/887] QMUILayout add a interface for constraint --- .../com/qmuiteam/qmui/layout/IQMUILayout.java | 277 ++++++++++++++++++ .../com/qmuiteam/qmui/layout/QMUIButton.java | 94 +++++- .../qmuiteam/qmui/layout/QMUIFrameLayout.java | 87 +++++- .../qmui/layout/QMUILayoutHelper.java | 109 +++++-- .../qmui/layout/QMUILinearLayout.java | 73 ++++- .../qmui/layout/QMUIRelativeLayout.java | 75 ++++- 6 files changed, 645 insertions(+), 70 deletions(-) create mode 100644 qmui/src/main/java/com/qmuiteam/qmui/layout/IQMUILayout.java diff --git a/qmui/src/main/java/com/qmuiteam/qmui/layout/IQMUILayout.java b/qmui/src/main/java/com/qmuiteam/qmui/layout/IQMUILayout.java new file mode 100644 index 000000000..9331faa3c --- /dev/null +++ b/qmui/src/main/java/com/qmuiteam/qmui/layout/IQMUILayout.java @@ -0,0 +1,277 @@ +package com.qmuiteam.qmui.layout; + +import android.support.annotation.ColorInt; +import android.support.annotation.IntDef; +import android.view.View; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Created by cgspine on 2018/3/23. + */ + +public interface IQMUILayout { + int HIDE_RADIUS_SIDE_NONE = 0; + int HIDE_RADIUS_SIDE_TOP = 1; + int HIDE_RADIUS_SIDE_RIGHT = 2; + int HIDE_RADIUS_SIDE_BOTTOM = 3; + int HIDE_RADIUS_SIDE_LEFT = 4; + + @IntDef(value = { + HIDE_RADIUS_SIDE_NONE, + HIDE_RADIUS_SIDE_TOP, + HIDE_RADIUS_SIDE_RIGHT, + HIDE_RADIUS_SIDE_BOTTOM, + HIDE_RADIUS_SIDE_LEFT}) + @Retention(RetentionPolicy.SOURCE) + @interface HideRadiusSide { + } + + /** + * limit the width of a layout + * + * @param widthLimit + * @return + */ + boolean setWidthLimit(int widthLimit); + + /** + * limit the height of a layout + * + * @param heightLimit + * @return + */ + boolean setHeightLimit(int heightLimit); + + /** + * use the shadow elevation from the theme + */ + void setUseThemeGeneralShadowElevation(); + + /** + * determine if the outline contain the padding area, usually false + * + * @param outlineExcludePadding + */ + void setOutlineExcludePadding(boolean outlineExcludePadding); + + /** + * See {@link android.view.View#setElevation(float)} + * + * @param elevation + */ + void setShadowElevation(int elevation); + + /** + * See {@link View#getElevation()} + * + * @return + */ + int getShadowElevation(); + + /** + * set the outline alpha, which will change the shadow + * + * @param shadowAlpha + */ + void setShadowAlpha(float shadowAlpha); + + /** + * get the outline alpha we set + * + * @return + */ + float getShadowAlpha(); + + /** + * set the layout radius + * @param radius + */ + void setRadius(int radius); + + /** + * set the layout radius with one or none side been hidden + * @param radius + * @param hideRadiusSide + */ + void setRadius(int radius, @QMUILayoutHelper.HideRadiusSide int hideRadiusSide); + + /** + * get the layout radius + * @return + */ + int getRadius(); + + /** + * inset the outline if needed + * + * @param left + * @param top + * @param right + * @param bottom + */ + void setOutlineInset(int left, int top, int right, int bottom); + + /** + * the shadow elevation only work after L, so we provide a downgrading compatible solutions for android 4.x + * usually we use border, but the border may be redundant for android L+. so will not show border default, + * if your designer like the border exists with shadow, you can call setShowBorderOnlyBeforeL(false) + * + * @param showBorderOnlyBeforeL + */ + void setShowBorderOnlyBeforeL(boolean showBorderOnlyBeforeL); + + /** + * in some case, we maybe hope the layout only have radius in one side. + * but there is no convenient way to write the code like canvas.drawPath, + * so we take another way that hide one radius side + * + * @param hideRadiusSide + */ + void setHideRadiusSide(@HideRadiusSide int hideRadiusSide); + + /** + * get the side that we have hidden the radius + * + * @return + */ + int getHideRadiusSide(); + + /** + * this method will determine the radius and shadow. + * + * @param radius + * @param shadowElevation + * @param shadowAlpha + */ + void setRadiusAndShadow(int radius, int shadowElevation, float shadowAlpha); + + /** + * this method will determine the radius and shadow with one or none side be hidden + * + * @param radius + * @param hideRadiusSide + * @param shadowElevation + * @param shadowAlpha + */ + void setRadiusAndShadow(int radius, @HideRadiusSide int hideRadiusSide, int shadowElevation, float shadowAlpha); + + /** + * border color, if you don not set it, the layout will not draw the border + * + * @param borderColor + */ + void setBorderColor(@ColorInt int borderColor); + + /** + * border width, default is 1px, usually no need to set + * + * @param borderWidth + */ + void setBorderWidth(int borderWidth); + + /** + * config the top divider + * + * @param topInsetLeft + * @param topInsetRight + * @param topDividerHeight + * @param topDividerColor + */ + void updateTopDivider(int topInsetLeft, int topInsetRight, int topDividerHeight, int topDividerColor); + + /** + * config the bottom divider + * + * @param bottomInsetLeft + * @param bottomInsetRight + * @param bottomDividerHeight + * @param bottomDividerColor + */ + void updateBottomDivider(int bottomInsetLeft, int bottomInsetRight, int bottomDividerHeight, int bottomDividerColor); + + /** + * config the left divider + * + * @param leftInsetTop + * @param leftInsetBottom + * @param leftDividerWidth + * @param leftDividerColor + */ + void updateLeftDivider(int leftInsetTop, int leftInsetBottom, int leftDividerWidth, int leftDividerColor); + + /** + * config the right divider + * + * @param rightInsetTop + * @param rightInsetBottom + * @param rightDividerWidth + * @param rightDividerColor + */ + void updateRightDivider(int rightInsetTop, int rightInsetBottom, int rightDividerWidth, int rightDividerColor); + + /** + * show top divider, and hide others + * + * @param topInsetLeft + * @param topInsetRight + * @param topDividerHeight + * @param topDividerColor + */ + void onlyShowTopDivider(int topInsetLeft, int topInsetRight, int topDividerHeight, int topDividerColor); + + /** + * show bottom divider, and hide others + * + * @param bottomInsetLeft + * @param bottomInsetRight + * @param bottomDividerHeight + * @param bottomDividerColor + */ + void onlyShowBottomDivider(int bottomInsetLeft, int bottomInsetRight, int bottomDividerHeight, int bottomDividerColor); + + /** + * show left divider, and hide others + * + * @param leftInsetTop + * @param leftInsetBottom + * @param leftDividerWidth + * @param leftDividerColor + */ + void onlyShowLeftDivider(int leftInsetTop, int leftInsetBottom, int leftDividerWidth, int leftDividerColor); + + /** + * show right divider, and hide others + * + * @param rightInsetTop + * @param rightInsetBottom + * @param rightDividerWidth + * @param rightDividerColor + */ + void onlyShowRightDivider(int rightInsetTop, int rightInsetBottom, int rightDividerWidth, int rightDividerColor); + + /** + * after config the border, sometimes we need change the alpha of divider with animation, + * so we provide a method to individually change the alpha + * + * @param dividerAlpha [0, 255] + */ + void setTopDividerAlpha(int dividerAlpha); + + /** + * @param dividerAlpha [0, 255] + */ + void setBottomDividerAlpha(int dividerAlpha); + + /** + * @param dividerAlpha [0, 255] + */ + void setLeftDividerAlpha(int dividerAlpha); + + /** + * @param dividerAlpha [0, 255] + */ + void setRightDividerAlpha(int dividerAlpha); + +} diff --git a/qmui/src/main/java/com/qmuiteam/qmui/layout/QMUIButton.java b/qmui/src/main/java/com/qmuiteam/qmui/layout/QMUIButton.java index 42a2f660f..3fccaa01d 100644 --- a/qmui/src/main/java/com/qmuiteam/qmui/layout/QMUIButton.java +++ b/qmui/src/main/java/com/qmuiteam/qmui/layout/QMUIButton.java @@ -11,7 +11,7 @@ * Created by cgspine on 2018/3/1. */ -public class QMUIButton extends QMUIAlphaButton { +public class QMUIButton extends QMUIAlphaButton implements IQMUILayout { private QMUILayoutHelper mLayoutHelper; public QMUIButton(Context context) { @@ -35,16 +35,19 @@ private void init(Context context, AttributeSet attrs, int defStyleAttr) { setChangeAlphaWhenPress(false); } + @Override public void updateTopDivider(int topInsetLeft, int topInsetRight, int topDividerHeight, int topDividerColor) { mLayoutHelper.updateTopDivider(topInsetLeft, topInsetRight, topDividerHeight, topDividerColor); invalidate(); } + @Override public void updateBottomDivider(int bottomInsetLeft, int bottomInsetRight, int bottomDividerHeight, int bottomDividerColor) { mLayoutHelper.updateBottomDivider(bottomInsetLeft, bottomInsetRight, bottomDividerHeight, bottomDividerColor); invalidate(); } + @Override public void updateLeftDivider(int leftInsetTop, int leftInsetBottom, int leftDividerWidth, int leftDividerColor) { mLayoutHelper.updateLeftDivider(leftInsetTop, leftInsetBottom, leftDividerWidth, leftDividerColor); invalidate(); @@ -55,33 +58,67 @@ public void updateRightDivider(int rightInsetTop, int rightInsetBottom, int righ invalidate(); } + @Override public void onlyShowTopDivider(int topInsetLeft, int topInsetRight, int topDividerHeight, int topDividerColor) { mLayoutHelper.onlyShowTopDivider(topInsetLeft, topInsetRight, topDividerHeight, topDividerColor); invalidate(); } + @Override public void onlyShowBottomDivider(int bottomInsetLeft, int bottomInsetRight, int bottomDividerHeight, int bottomDividerColor) { mLayoutHelper.onlyShowBottomDivider(bottomInsetLeft, bottomInsetRight, bottomDividerHeight, bottomDividerColor); invalidate(); } + @Override public void onlyShowLeftDivider(int leftInsetTop, int leftInsetBottom, int leftDividerWidth, int leftDividerColor) { mLayoutHelper.onlyShowLeftDivider(leftInsetTop, leftInsetBottom, leftDividerWidth, leftDividerColor); invalidate(); } + @Override public void onlyShowRightDivider(int rightInsetTop, int rightInsetBottom, int rightDividerWidth, int rightDividerColor) { mLayoutHelper.onlyShowRightDivider(rightInsetTop, rightInsetBottom, rightDividerWidth, rightDividerColor); invalidate(); } - public void setDividerAlpha(int dividerAlpha) { - mLayoutHelper.setDividerAlpha(dividerAlpha); + @Override + public void setTopDividerAlpha(int dividerAlpha) { + mLayoutHelper.setTopDividerAlpha(dividerAlpha); + invalidate(); + } + + @Override + public void setBottomDividerAlpha(int dividerAlpha) { + mLayoutHelper.setBottomDividerAlpha(dividerAlpha); + invalidate(); + } + + @Override + public void setLeftDividerAlpha(int dividerAlpha) { + mLayoutHelper.setLeftDividerAlpha(dividerAlpha); + invalidate(); + } + + @Override + public void setRightDividerAlpha(int dividerAlpha) { + mLayoutHelper.setRightDividerAlpha(dividerAlpha); + invalidate(); + } + + @Override + public void setHideRadiusSide(int hideRadiusSide) { + mLayoutHelper.setHideRadiusSide(hideRadiusSide); invalidate(); } + @Override + public int getHideRadiusSide() { + return mLayoutHelper.getHideRadiusSide(); + } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { widthMeasureSpec = mLayoutHelper.getMeasuredWidthSpec(widthMeasureSpec); @@ -89,69 +126,108 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int minW = mLayoutHelper.handleMiniWidth(widthMeasureSpec, getMeasuredWidth()); int minH = mLayoutHelper.handleMiniHeight(heightMeasureSpec, getMeasuredHeight()); - if(widthMeasureSpec != minW || heightMeasureSpec != minH){ + if (widthMeasureSpec != minW || heightMeasureSpec != minH) { super.onMeasure(minW, minH); } } + @Override public void setRadiusAndShadow(int radius, int shadowElevation, final float shadowAlpha) { mLayoutHelper.setRadiusAndShadow(radius, shadowElevation, shadowAlpha); } + @Override public void setRadiusAndShadow(int radius, @QMUILayoutHelper.HideRadiusSide int hideRadiusSide, int shadowElevation, final float shadowAlpha) { mLayoutHelper.setRadiusAndShadow(radius, hideRadiusSide, shadowElevation, shadowAlpha); } + @Override public void setRadius(int radius) { - setRadius(radius, mLayoutHelper.getHideRadiusSide()); + mLayoutHelper.setRadius(radius); } + @Override public void setRadius(int radius, @QMUILayoutHelper.HideRadiusSide int hideRadiusSide) { - mLayoutHelper.setRadiusAndShadow(radius, hideRadiusSide, mLayoutHelper.getShadowElevation(), mLayoutHelper.getShadowAlpha()); + mLayoutHelper.setRadius(radius, hideRadiusSide); + } + + @Override + public int getRadius() { + return mLayoutHelper.getRadius(); + } + + @Override + public void setOutlineInset(int left, int top, int right, int bottom) { + mLayoutHelper.setOutlineInset(left, top, right, bottom); } + @Override public void setBorderColor(@ColorInt int borderColor) { mLayoutHelper.setBorderColor(borderColor); invalidate(); } + @Override public void setBorderWidth(int borderWidth) { mLayoutHelper.setBorderWidth(borderWidth); invalidate(); } + @Override public void setShowBorderOnlyBeforeL(boolean showBorderOnlyBeforeL) { mLayoutHelper.setShowBorderOnlyBeforeL(showBorderOnlyBeforeL); invalidate(); } - public void setWidthLimit(int widthLimit) { + @Override + public boolean setWidthLimit(int widthLimit) { if (mLayoutHelper.setWidthLimit(widthLimit)) { requestLayout(); invalidate(); } - + return true; } - public void setHeightLimit(int heightLimit) { + @Override + public boolean setHeightLimit(int heightLimit) { if (mLayoutHelper.setHeightLimit(heightLimit)) { requestLayout(); invalidate(); } + return true; } + @Override public void setUseThemeGeneralShadowElevation() { mLayoutHelper.setUseThemeGeneralShadowElevation(); } + @Override + public void setOutlineExcludePadding(boolean outlineExcludePadding) { + mLayoutHelper.setOutlineExcludePadding(outlineExcludePadding); + } + + @Override public void setShadowElevation(int elevation) { mLayoutHelper.setShadowElevation(elevation); } + @Override + public int getShadowElevation() { + return mLayoutHelper.getShadowElevation(); + } + + @Override public void setShadowAlpha(float shadowAlpha) { mLayoutHelper.setShadowAlpha(shadowAlpha); } + @Override + public float getShadowAlpha() { + return mLayoutHelper.getShadowAlpha(); + } + + @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); diff --git a/qmui/src/main/java/com/qmuiteam/qmui/layout/QMUIFrameLayout.java b/qmui/src/main/java/com/qmuiteam/qmui/layout/QMUIFrameLayout.java index ba6b5657c..8b08594a1 100644 --- a/qmui/src/main/java/com/qmuiteam/qmui/layout/QMUIFrameLayout.java +++ b/qmui/src/main/java/com/qmuiteam/qmui/layout/QMUIFrameLayout.java @@ -12,7 +12,7 @@ * @date 2017-03-10 */ -public class QMUIFrameLayout extends QMUIAlphaFrameLayout { +public class QMUIFrameLayout extends QMUIAlphaFrameLayout implements IQMUILayout { private QMUILayoutHelper mLayoutHelper; public QMUIFrameLayout(Context context) { @@ -43,7 +43,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int minW = mLayoutHelper.handleMiniWidth(widthMeasureSpec, getMeasuredWidth()); int minH = mLayoutHelper.handleMiniHeight(heightMeasureSpec, getMeasuredHeight()); - if(widthMeasureSpec != minW || heightMeasureSpec != minH){ + if (widthMeasureSpec != minW || heightMeasureSpec != minH) { super.onMeasure(minW, minH); } } @@ -91,8 +91,27 @@ public void onlyShowRightDivider(int rightInsetTop, int rightInsetBottom, int ri } - public void setDividerAlpha(int dividerAlpha) { - mLayoutHelper.setDividerAlpha(dividerAlpha); + @Override + public void setTopDividerAlpha(int dividerAlpha) { + mLayoutHelper.setTopDividerAlpha(dividerAlpha); + invalidate(); + } + + @Override + public void setBottomDividerAlpha(int dividerAlpha) { + mLayoutHelper.setBottomDividerAlpha(dividerAlpha); + invalidate(); + } + + @Override + public void setLeftDividerAlpha(int dividerAlpha) { + mLayoutHelper.setLeftDividerAlpha(dividerAlpha); + invalidate(); + } + + @Override + public void setRightDividerAlpha(int dividerAlpha) { + mLayoutHelper.setRightDividerAlpha(dividerAlpha); invalidate(); } @@ -104,50 +123,94 @@ public void setRadiusAndShadow(int topRadius, @QMUILayoutHelper.HideRadiusSide i mLayoutHelper.setRadiusAndShadow(topRadius, hideRadiusSide, shadowElevation, shadowAlpha); } - public void setRadius(int radius){ - setRadius(radius, mLayoutHelper.getHideRadiusSide()); + @Override + public void setRadius(int radius) { + mLayoutHelper.setRadius(radius); } public void setRadius(int radius, @QMUILayoutHelper.HideRadiusSide int hideRadiusSide) { - mLayoutHelper.setRadiusAndShadow(radius, hideRadiusSide, mLayoutHelper.getShadowElevation(), mLayoutHelper.getShadowAlpha()); + mLayoutHelper.setRadius(radius, hideRadiusSide); + } + + @Override + public int getRadius() { + return mLayoutHelper.getRadius(); } + + @Override + public void setOutlineInset(int left, int top, int right, int bottom) { + mLayoutHelper.setOutlineInset(left, top, right, bottom); + } + + @Override + public void setHideRadiusSide(int hideRadiusSide) { + mLayoutHelper.setHideRadiusSide(hideRadiusSide); + } + + @Override + public int getHideRadiusSide() { + return mLayoutHelper.getHideRadiusSide(); + } + public void setBorderColor(@ColorInt int borderColor) { mLayoutHelper.setBorderColor(borderColor); invalidate(); } + @Override + public void setBorderWidth(int borderWidth) { + mLayoutHelper.setBorderWidth(borderWidth); + invalidate(); + } + public void setShowBorderOnlyBeforeL(boolean showBorderOnlyBeforeL) { mLayoutHelper.setShowBorderOnlyBeforeL(showBorderOnlyBeforeL); invalidate(); } - public void setWidthLimit(int widthLimit) { - if(mLayoutHelper.setWidthLimit(widthLimit)){ + public boolean setWidthLimit(int widthLimit) { + if (mLayoutHelper.setWidthLimit(widthLimit)) { requestLayout(); invalidate(); } - + return true; } - public void setHeightLimit(int heightLimit) { - if(mLayoutHelper.setHeightLimit(heightLimit)){ + public boolean setHeightLimit(int heightLimit) { + if (mLayoutHelper.setHeightLimit(heightLimit)) { requestLayout(); invalidate(); } + return true; } public void setUseThemeGeneralShadowElevation() { mLayoutHelper.setUseThemeGeneralShadowElevation(); } + @Override + public void setOutlineExcludePadding(boolean outlineExcludePadding) { + mLayoutHelper.setOutlineExcludePadding(outlineExcludePadding); + } + public void setShadowElevation(int elevation) { mLayoutHelper.setShadowElevation(elevation); } + @Override + public int getShadowElevation() { + return mLayoutHelper.getShadowElevation(); + } + public void setShadowAlpha(float shadowAlpha) { mLayoutHelper.setShadowAlpha(shadowAlpha); } + @Override + public float getShadowAlpha() { + return mLayoutHelper.getShadowAlpha(); + } + @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); diff --git a/qmui/src/main/java/com/qmuiteam/qmui/layout/QMUILayoutHelper.java b/qmui/src/main/java/com/qmuiteam/qmui/layout/QMUILayoutHelper.java index 6e6f822ce..6039d34d9 100644 --- a/qmui/src/main/java/com/qmuiteam/qmui/layout/QMUILayoutHelper.java +++ b/qmui/src/main/java/com/qmuiteam/qmui/layout/QMUILayoutHelper.java @@ -12,7 +12,6 @@ import android.graphics.RectF; import android.os.Build; import android.support.annotation.ColorInt; -import android.support.annotation.IntDef; import android.support.v4.content.ContextCompat; import android.util.AttributeSet; import android.view.View; @@ -21,8 +20,6 @@ import com.qmuiteam.qmui.R; import com.qmuiteam.qmui.util.QMUIResHelper; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; /** @@ -30,19 +27,7 @@ * @date 2017-03-10 */ -public class QMUILayoutHelper { - public static final int HIDE_RADIUS_SIDE_NONE = 0; - public static final int HIDE_RADIUS_SIDE_TOP = 1; - public static final int HIDE_RADIUS_SIDE_RIGHT = 2; - public static final int HIDE_RADIUS_SIDE_BOTTOM = 3; - public static final int HIDE_RADIUS_SIDE_LEFT = 4; - - @IntDef(value = {HIDE_RADIUS_SIDE_NONE, HIDE_RADIUS_SIDE_TOP, HIDE_RADIUS_SIDE_RIGHT, - HIDE_RADIUS_SIDE_BOTTOM, HIDE_RADIUS_SIDE_LEFT}) - @Retention(RetentionPolicy.SOURCE) - public @interface HideRadiusSide { - } - +public class QMUILayoutHelper implements IQMUILayout { private Context mContext; // size private int mWidthLimit = 0; @@ -81,7 +66,7 @@ public class QMUILayoutHelper { private Paint mClipPaint; private PorterDuffXfermode mMode; private int mRadius; - private @HideRadiusSide int mHideRadiusSide = HIDE_RADIUS_SIDE_NONE; + private @IQMUILayout.HideRadiusSide int mHideRadiusSide = HIDE_RADIUS_SIDE_NONE; private float[] mRadiusArray; private RectF mBorderRect; private int mBorderColor = 0; @@ -199,11 +184,13 @@ public QMUILayoutHelper(Context context, AttributeSet attrs, int defAttr, View o setRadiusAndShadow(radius, mHideRadiusSide, shadow, mShadowAlpha); } + @Override public void setUseThemeGeneralShadowElevation() { mShadowElevation = QMUIResHelper.getAttrDimen(mContext, R.attr.qmui_general_shadow_elevation); setRadiusAndShadow(mRadius, mHideRadiusSide, mShadowElevation, mShadowAlpha); } + @Override public void setOutlineExcludePadding(boolean outlineExcludePadding) { if (useFeature()) { View owner = mOwner.get(); @@ -216,6 +203,7 @@ public void setOutlineExcludePadding(boolean outlineExcludePadding) { } + @Override public boolean setWidthLimit(int widthLimit) { if (mWidthLimit != widthLimit) { mWidthLimit = widthLimit; @@ -224,6 +212,7 @@ public boolean setWidthLimit(int widthLimit) { return false; } + @Override public boolean setHeightLimit(int heightLimit) { if (mHeightLimit != heightLimit) { mHeightLimit = heightLimit; @@ -232,14 +221,17 @@ public boolean setHeightLimit(int heightLimit) { return false; } + @Override public int getShadowElevation() { return mShadowElevation; } + @Override public float getShadowAlpha() { return mShadowAlpha; } + @Override public void setOutlineInset(int left, int top, int right, int bottom) { if (useFeature()) { View owner = mOwner.get(); @@ -255,10 +247,13 @@ public void setOutlineInset(int left, int top, int right, int bottom) { } + @Override public void setShowBorderOnlyBeforeL(boolean showBorderOnlyBeforeL) { mIsShowBorderOnlyBeforeL = showBorderOnlyBeforeL; + invalidate(); } + @Override public void setShadowElevation(int elevation) { if (mShadowElevation == elevation) { return; @@ -267,6 +262,7 @@ public void setShadowElevation(int elevation) { invalidate(); } + @Override public void setShadowAlpha(float shadowAlpha) { if (mShadowAlpha == shadowAlpha) { return; @@ -290,15 +286,46 @@ private void invalidate() { } } + @Override + public void setHideRadiusSide(@HideRadiusSide int hideRadiusSide) { + if (mHideRadiusSide == hideRadiusSide) { + return; + } + setRadiusAndShadow(mRadius, hideRadiusSide, mShadowElevation, mShadowAlpha); + } + + @Override public int getHideRadiusSide() { return mHideRadiusSide; } + @Override + public void setRadius(int radius) { + if (mRadius != radius) { + setRadiusAndShadow(radius, mShadowElevation, mShadowAlpha); + } + } + + @Override + public void setRadius(int radius, @IQMUILayout.HideRadiusSide int hideRadiusSide) { + if (mRadius == radius && hideRadiusSide == mHideRadiusSide) { + return; + } + setRadiusAndShadow(radius, hideRadiusSide, mShadowElevation, mShadowAlpha); + } + + @Override + public int getRadius() { + return mRadius; + } + + @Override public void setRadiusAndShadow(int radius, int shadowElevation, float shadowAlpha) { setRadiusAndShadow(radius, mHideRadiusSide, shadowElevation, shadowAlpha); } - public void setRadiusAndShadow(int radius, @HideRadiusSide int hideRadiusSide, int shadowElevation, float shadowAlpha) { + @Override + public void setRadiusAndShadow(int radius, @IQMUILayout.HideRadiusSide int hideRadiusSide, int shadowElevation, float shadowAlpha) { View owner = mOwner.get(); if (owner == null) { return; @@ -388,6 +415,7 @@ public boolean isRadiusWithSideHidden() { return mRadius > 0 && mHideRadiusSide != HIDE_RADIUS_SIDE_NONE; } + @Override public void updateTopDivider(int topInsetLeft, int topInsetRight, int topDividerHeight, int topDividerColor) { mTopDividerInsetLeft = topInsetLeft; mTopDividerInsetRight = topInsetRight; @@ -395,6 +423,7 @@ public void updateTopDivider(int topInsetLeft, int topInsetRight, int topDivider mTopDividerColor = topDividerColor; } + @Override public void updateBottomDivider(int bottomInsetLeft, int bottomInsetRight, int bottomDividerHeight, int bottomDividerColor) { mBottomDividerInsetLeft = bottomInsetLeft; mBottomDividerInsetRight = bottomInsetRight; @@ -402,6 +431,7 @@ public void updateBottomDivider(int bottomInsetLeft, int bottomInsetRight, int b mBottomDividerHeight = bottomDividerHeight; } + @Override public void updateLeftDivider(int leftInsetTop, int leftInsetBottom, int leftDividerWidth, int leftDividerColor) { mLeftDividerInsetTop = leftInsetTop; mLeftDividerInsetBottom = leftInsetBottom; @@ -409,6 +439,7 @@ public void updateLeftDivider(int leftInsetTop, int leftInsetBottom, int leftDiv mLeftDividerColor = leftDividerColor; } + @Override public void updateRightDivider(int rightInsetTop, int rightInsetBottom, int rightDividerWidth, int rightDividerColor) { mRightDividerInsetTop = rightInsetTop; mRightDividerInsetBottom = rightInsetBottom; @@ -416,6 +447,7 @@ public void updateRightDivider(int rightInsetTop, int rightInsetBottom, int righ mRightDividerColor = rightDividerColor; } + @Override public void onlyShowTopDivider(int topInsetLeft, int topInsetRight, int topDividerHeight, int topDividerColor) { updateTopDivider(topInsetLeft, topInsetRight, topDividerHeight, topDividerColor); @@ -424,6 +456,7 @@ public void onlyShowTopDivider(int topInsetLeft, int topInsetRight, mBottomDividerHeight = 0; } + @Override public void onlyShowBottomDivider(int bottomInsetLeft, int bottomInsetRight, int bottomDividerHeight, int bottomDividerColor) { updateBottomDivider(bottomInsetLeft, bottomInsetRight, bottomDividerHeight, bottomDividerColor); @@ -432,6 +465,7 @@ public void onlyShowBottomDivider(int bottomInsetLeft, int bottomInsetRight, mTopDividerHeight = 0; } + @Override public void onlyShowLeftDivider(int leftInsetTop, int leftInsetBottom, int leftDividerWidth, int leftDividerColor) { updateLeftDivider(leftInsetTop, leftInsetBottom, leftDividerWidth, leftDividerColor); mRightDividerWidth = 0; @@ -439,6 +473,7 @@ public void onlyShowLeftDivider(int leftInsetTop, int leftInsetBottom, int leftD mBottomDividerHeight = 0; } + @Override public void onlyShowRightDivider(int rightInsetTop, int rightInsetBottom, int rightDividerWidth, int rightDividerColor) { updateRightDivider(rightInsetTop, rightInsetBottom, rightDividerWidth, rightDividerColor); mLeftDividerWidth = 0; @@ -446,28 +481,38 @@ public void onlyShowRightDivider(int rightInsetTop, int rightInsetBottom, int ri mBottomDividerHeight = 0; } - /** - * 设置上下分割线的透明度 - *

由于设置透明度的场景(通常是滚动列表时不断设置)与设置颜色的场景(通常是在View初始化时设置一次)通常都不重合, 所以拆开两个方法分别设置

- *

上下分割线的alpha一起设置, 如果有需要再拆开两个方法

- * - * @param dividerAlpha [0, 255] - */ - public void setDividerAlpha(int dividerAlpha) { - mTopDividerAlpha = mBottomDividerAlpha = dividerAlpha; + @Override + public void setTopDividerAlpha(int dividerAlpha) { + mTopDividerAlpha = dividerAlpha; } + @Override + public void setBottomDividerAlpha(int dividerAlpha) { + mBottomDividerAlpha = dividerAlpha; + } + + @Override + public void setLeftDividerAlpha(int dividerAlpha) { + mLeftDividerAlpha = dividerAlpha; + } + + @Override + public void setRightDividerAlpha(int dividerAlpha) { + mRightDividerAlpha = dividerAlpha; + } + + public int handleMiniWidth(int widthMeasureSpec, int measuredWidth) { - if(View.MeasureSpec.getMode(widthMeasureSpec) != View.MeasureSpec.EXACTLY - && measuredWidth < mWidthMini){ + if (View.MeasureSpec.getMode(widthMeasureSpec) != View.MeasureSpec.EXACTLY + && measuredWidth < mWidthMini) { return View.MeasureSpec.makeMeasureSpec(mWidthMini, View.MeasureSpec.EXACTLY); } return widthMeasureSpec; } public int handleMiniHeight(int heightMeasureSpec, int measuredHeight) { - if(View.MeasureSpec.getMode(heightMeasureSpec) != View.MeasureSpec.EXACTLY - && measuredHeight < mHeightMini){ + if (View.MeasureSpec.getMode(heightMeasureSpec) != View.MeasureSpec.EXACTLY + && measuredHeight < mHeightMini) { return View.MeasureSpec.makeMeasureSpec(mHeightMini, View.MeasureSpec.EXACTLY); } return heightMeasureSpec; @@ -504,10 +549,12 @@ public int getMeasuredHeightSpec(int heightMeasureSpec) { return heightMeasureSpec; } + @Override public void setBorderColor(@ColorInt int borderColor) { mBorderColor = borderColor; } + @Override public void setBorderWidth(int borderWidth) { mBorderWidth = borderWidth; } diff --git a/qmui/src/main/java/com/qmuiteam/qmui/layout/QMUILinearLayout.java b/qmui/src/main/java/com/qmuiteam/qmui/layout/QMUILinearLayout.java index 6644fe6be..18b96ef2d 100644 --- a/qmui/src/main/java/com/qmuiteam/qmui/layout/QMUILinearLayout.java +++ b/qmui/src/main/java/com/qmuiteam/qmui/layout/QMUILinearLayout.java @@ -12,7 +12,7 @@ * @date 2017-03-10 */ -public class QMUILinearLayout extends QMUIAlphaLinearLayout { +public class QMUILinearLayout extends QMUIAlphaLinearLayout implements IQMUILayout { private QMUILayoutHelper mLayoutHelper; public QMUILinearLayout(Context context) { @@ -78,8 +78,27 @@ public void onlyShowRightDivider(int rightInsetTop, int rightInsetBottom, int ri invalidate(); } - public void setDividerAlpha(int dividerAlpha) { - mLayoutHelper.setDividerAlpha(dividerAlpha); + @Override + public void setTopDividerAlpha(int dividerAlpha) { + mLayoutHelper.setTopDividerAlpha(dividerAlpha); + invalidate(); + } + + @Override + public void setBottomDividerAlpha(int dividerAlpha) { + mLayoutHelper.setBottomDividerAlpha(dividerAlpha); + invalidate(); + } + + @Override + public void setLeftDividerAlpha(int dividerAlpha) { + mLayoutHelper.setLeftDividerAlpha(dividerAlpha); + invalidate(); + } + + @Override + public void setRightDividerAlpha(int dividerAlpha) { + mLayoutHelper.setRightDividerAlpha(dividerAlpha); invalidate(); } @@ -90,7 +109,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int minW = mLayoutHelper.handleMiniWidth(widthMeasureSpec, getMeasuredWidth()); int minH = mLayoutHelper.handleMiniHeight(heightMeasureSpec, getMeasuredHeight()); - if(widthMeasureSpec != minW || heightMeasureSpec != minH){ + if (widthMeasureSpec != minW || heightMeasureSpec != minH) { super.onMeasure(minW, minH); } } @@ -104,11 +123,21 @@ public void setRadiusAndShadow(int radius, @QMUILayoutHelper.HideRadiusSide int } public void setRadius(int radius) { - setRadius(radius, mLayoutHelper.getHideRadiusSide()); + mLayoutHelper.setRadius(radius); } public void setRadius(int radius, @QMUILayoutHelper.HideRadiusSide int hideRadiusSide) { - mLayoutHelper.setRadiusAndShadow(radius, hideRadiusSide, mLayoutHelper.getShadowElevation(), mLayoutHelper.getShadowAlpha()); + mLayoutHelper.setRadius(radius, hideRadiusSide); + } + + @Override + public int getRadius() { + return mLayoutHelper.getRadius(); + } + + @Override + public void setOutlineInset(int left, int top, int right, int bottom) { + mLayoutHelper.setOutlineInset(left, top, right, bottom); } public void setBorderColor(@ColorInt int borderColor) { @@ -126,33 +155,59 @@ public void setShowBorderOnlyBeforeL(boolean showBorderOnlyBeforeL) { invalidate(); } - public void setWidthLimit(int widthLimit) { + @Override + public void setHideRadiusSide(int hideRadiusSide) { + mLayoutHelper.setHideRadiusSide(hideRadiusSide); + } + + @Override + public int getHideRadiusSide() { + return mLayoutHelper.getHideRadiusSide(); + } + + public boolean setWidthLimit(int widthLimit) { if (mLayoutHelper.setWidthLimit(widthLimit)) { requestLayout(); invalidate(); } - + return true; } - public void setHeightLimit(int heightLimit) { + public boolean setHeightLimit(int heightLimit) { if (mLayoutHelper.setHeightLimit(heightLimit)) { requestLayout(); invalidate(); } + return true; } public void setUseThemeGeneralShadowElevation() { mLayoutHelper.setUseThemeGeneralShadowElevation(); } + @Override + public void setOutlineExcludePadding(boolean outlineExcludePadding) { + mLayoutHelper.setOutlineExcludePadding(outlineExcludePadding); + } + public void setShadowElevation(int elevation) { mLayoutHelper.setShadowElevation(elevation); } + @Override + public int getShadowElevation() { + return mLayoutHelper.getShadowElevation(); + } + public void setShadowAlpha(float shadowAlpha) { mLayoutHelper.setShadowAlpha(shadowAlpha); } + @Override + public float getShadowAlpha() { + return mLayoutHelper.getShadowAlpha(); + } + @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); diff --git a/qmui/src/main/java/com/qmuiteam/qmui/layout/QMUIRelativeLayout.java b/qmui/src/main/java/com/qmuiteam/qmui/layout/QMUIRelativeLayout.java index cb1f9a81e..c4da92bd7 100644 --- a/qmui/src/main/java/com/qmuiteam/qmui/layout/QMUIRelativeLayout.java +++ b/qmui/src/main/java/com/qmuiteam/qmui/layout/QMUIRelativeLayout.java @@ -12,7 +12,7 @@ * @date 2017-03-10 */ -public class QMUIRelativeLayout extends QMUIAlphaRelativeLayout { +public class QMUIRelativeLayout extends QMUIAlphaRelativeLayout implements IQMUILayout { private QMUILayoutHelper mLayoutHelper; public QMUIRelativeLayout(Context context) { @@ -78,8 +78,27 @@ public void onlyShowRightDivider(int rightInsetTop, int rightInsetBottom, int ri invalidate(); } - public void setDividerAlpha(int dividerAlpha) { - mLayoutHelper.setDividerAlpha(dividerAlpha); + @Override + public void setTopDividerAlpha(int dividerAlpha) { + mLayoutHelper.setTopDividerAlpha(dividerAlpha); + invalidate(); + } + + @Override + public void setBottomDividerAlpha(int dividerAlpha) { + mLayoutHelper.setBottomDividerAlpha(dividerAlpha); + invalidate(); + } + + @Override + public void setLeftDividerAlpha(int dividerAlpha) { + mLayoutHelper.setLeftDividerAlpha(dividerAlpha); + invalidate(); + } + + @Override + public void setRightDividerAlpha(int dividerAlpha) { + mLayoutHelper.setRightDividerAlpha(dividerAlpha); invalidate(); } @@ -90,7 +109,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int minW = mLayoutHelper.handleMiniWidth(widthMeasureSpec, getMeasuredWidth()); int minH = mLayoutHelper.handleMiniHeight(heightMeasureSpec, getMeasuredHeight()); - if(widthMeasureSpec != minW || heightMeasureSpec != minH){ + if (widthMeasureSpec != minW || heightMeasureSpec != minH) { super.onMeasure(minW, minH); } } @@ -103,12 +122,33 @@ public void setRadiusAndShadow(int topRadius, @QMUILayoutHelper.HideRadiusSide i mLayoutHelper.setRadiusAndShadow(topRadius, hideRadiusSide, shadowElevation, shadowAlpha); } + @Override public void setRadius(int radius) { - setRadius(radius, mLayoutHelper.getHideRadiusSide()); + mLayoutHelper.setRadius(radius); } public void setRadius(int radius, @QMUILayoutHelper.HideRadiusSide int hideRadiusSide) { - mLayoutHelper.setRadiusAndShadow(radius, hideRadiusSide, mLayoutHelper.getShadowElevation(), mLayoutHelper.getShadowAlpha()); + mLayoutHelper.setRadius(radius, hideRadiusSide); + } + + @Override + public int getRadius() { + return mLayoutHelper.getRadius(); + } + + @Override + public void setOutlineInset(int left, int top, int right, int bottom) { + mLayoutHelper.setOutlineInset(left, top, right, bottom); + } + + @Override + public void setHideRadiusSide(int hideRadiusSide) { + mLayoutHelper.setHideRadiusSide(hideRadiusSide); + } + + @Override + public int getHideRadiusSide() { + return mLayoutHelper.getHideRadiusSide(); } public void setBorderColor(@ColorInt int borderColor) { @@ -116,30 +156,42 @@ public void setBorderColor(@ColorInt int borderColor) { invalidate(); } + @Override + public void setBorderWidth(int borderWidth) { + mLayoutHelper.setBorderWidth(borderWidth); + invalidate(); + } + public void setShowBorderOnlyBeforeL(boolean showBorderOnlyBeforeL) { mLayoutHelper.setShowBorderOnlyBeforeL(showBorderOnlyBeforeL); invalidate(); } - public void setWidthLimit(int widthLimit) { + public boolean setWidthLimit(int widthLimit) { if (mLayoutHelper.setWidthLimit(widthLimit)) { requestLayout(); invalidate(); } - + return true; } - public void setHeightLimit(int heightLimit) { + public boolean setHeightLimit(int heightLimit) { if (mLayoutHelper.setHeightLimit(heightLimit)) { requestLayout(); invalidate(); } + return true; } public void setUseThemeGeneralShadowElevation() { mLayoutHelper.setUseThemeGeneralShadowElevation(); } + @Override + public void setOutlineExcludePadding(boolean outlineExcludePadding) { + mLayoutHelper.setOutlineExcludePadding(outlineExcludePadding); + } + public void setShadowElevation(int elevation) { mLayoutHelper.setShadowElevation(elevation); } @@ -152,6 +204,11 @@ public void setShadowAlpha(float shadowAlpha) { mLayoutHelper.setShadowAlpha(shadowAlpha); } + @Override + public float getShadowAlpha() { + return mLayoutHelper.getShadowAlpha(); + } + @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); From 537a7079cce65cea1b51414b505f5271a31a3fb0 Mon Sep 17 00:00:00 2001 From: cgspine Date: Fri, 23 Mar 2018 16:07:30 +0800 Subject: [PATCH 043/887] change the icon --- .../fragment/components/QDLayoutFragment.java | 2 +- .../main/res/mipmap-xhdpi/icon_grid_layout.png | Bin 0 -> 1396 bytes .../main/res/mipmap-xxhdpi/icon_grid_layout.png | Bin 0 -> 2359 bytes 3 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 qmuidemo/src/main/res/mipmap-xhdpi/icon_grid_layout.png create mode 100644 qmuidemo/src/main/res/mipmap-xxhdpi/icon_grid_layout.png diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDLayoutFragment.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDLayoutFragment.java index a3ac2e18c..a22a2ac9b 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDLayoutFragment.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDLayoutFragment.java @@ -23,7 +23,7 @@ * Created by cgspine on 2018/3/22. */ -@Widget(name = "QMUILayout", iconRes = R.mipmap.icon_grid_dialog) +@Widget(name = "QMUILayout", iconRes = R.mipmap.icon_grid_layout) public class QDLayoutFragment extends BaseFragment { @BindView(R.id.topbar) QMUITopBarLayout mTopBar; diff --git a/qmuidemo/src/main/res/mipmap-xhdpi/icon_grid_layout.png b/qmuidemo/src/main/res/mipmap-xhdpi/icon_grid_layout.png new file mode 100644 index 0000000000000000000000000000000000000000..2146cfb7205caf1b321c70b1e12de5858537e973 GIT binary patch literal 1396 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q4M;wBd$a>cF%}28J29*~C-ahlfmP4b#WAFU z@$Gcme35jK*7vcCbszP&9pbfUbxob9#8rPFaDvDCCOuZ)DN9cN_t08oB2uC`N3K)j zAG3yL(;b$b2Lv=lOl~Z@apZSe-0Y3vN3vIKHkPr!eCEx$1C{5C=g*aN-{8o=B+$UX zqQJn&;Xop@qMkG5{nAgnRA76jnW|QBOo%>A0rNi3_a}x!ox9=_3W9*~v zt~&2cfAZ&_8gl!sY@*!%F1)(C^z*~l=fu9L?fCriO8LBc?|&EVw&lgk9ut@6n|)n= zn#@OZw)FFk98 z1x{4$`BlWRBt2(tgTuAQSEoBG*e1VbVc8_NexJ;!(Ss;JcAjHB)w6fov(tf@{5Sm- z4NhiEx;y3c)A(||0L_nUa(|}O-;vui-|4~my}@p(MdhbbjeqYdZZ!Ioc)JXks&}w& zHTk!HeNNrK?2;lS?>|MK7A|f+$2#kDk-k!YU06RbS^r(`Q8JA?bRIap7S)`2w`O(v z_tJ^t#AN6Ipd?_V#U_bX$4`Sak)S@UCf z-u?Uc@{hT3{DtVoy)(`oE0cV;$D$&@E3!Vjw#KH}A?@ER@6X%oeyjYqeEh{{|EoWO zVYlGe_BjG{X8ZQri(dEe6v%rjdZ zoq2DSxZ3&n9glndwjIp-o4k16XPc<_JNpWFGmdKI;Vst03TU&xBvhE literal 0 HcmV?d00001 diff --git a/qmuidemo/src/main/res/mipmap-xxhdpi/icon_grid_layout.png b/qmuidemo/src/main/res/mipmap-xxhdpi/icon_grid_layout.png new file mode 100644 index 0000000000000000000000000000000000000000..9e7e7c41f2e37c5c59e3e22268a7a436eb5f701e GIT binary patch literal 2359 zcmeHJ=~og65Jz6N=CQ4tcBm~rUGrX#a?K-jTl2osP%IBJp1L7gTC3uL$9t8lq~sZ> zxp}k+;elx=YF2oIrGS#*u_TCuw-PG4^cU>MzVu;c-uummnKy6dH@{qeUpF;nEoA@z zpyuK35+IM0Urgzs+~?|=i{(KfF~IFSfW*)d0su;@9xlIKN>&iR?}>-p*6CXvm4qw5 zKd&07j={~&MlD93`93?x_3;8R*Pf8unX?TlUx?YoF66`9Z~5!w-=Qr=h90;4he<0O zQ+eJc5lMq`1yzxH^&3Ko<1+aMN<~&NDiS6xi;dNFlyoxzz^~(8`f9j4tUhjA#4S0U z>qs~6>tFl%Bxc~Q9<6tvIf>8>ju4=gYF{wnD_$=4_=8fWx2j)-onz`AI<3xR&%;8c zZG|<|3$3JL^|}i64-?#9ZRp|i`+QuNX;r<5yu)-GnrPx(XEs+dKXk&~Vm)0A2wN9h%pSIZ2%FSx!RB|}KXKbo zDG8+X_9l6&v;6pmjIPT)jU-V=8R=uPaOWMBZi|%a&6GtmN?Y-cwk7gx-E)v9?x$jZ@-Hrh&h; zDd%}X#W+t~fN*T=hGEya$j=Gwh1yz3tUbdk%AoUUO_7)>Fp*YoXWJxI#38SMV&Z6t zOyjq75*~@U0@>$IcBLjK3Ot(n{6iZl_%Pckt*{0QC}ts)TmVp9AH?}60yVrd8SWqj zWqy$jUipAgIiL~?25O8LB7W6W^0!p5*H4#&e(YG2AF5%%Tdv!3@DY)7N!Pjez(W3p zdNm9jLVoI;nSJQ(38B7oZ(2)KU=~2}NcHJ4x6EuQoL&!9P(I}xUHh%zw~>BZn*TeC ztVNa50JC;phhrT2O^OeY`>BJ&ZXISJo^`|Q`Wu7GjM3rH%2ub3RJ|+&T;g@13{Cfv z=hTIP*M4vVOeByIo53j1t$tJ9g@CJ(fW+0@krl zBXgW}>{=&sHxFSKE}Ki(ZSx#_|BJ&awU_{hSmW(+-aRQdwggZ6O?Kt9q`6K_T|r6i zkNeelP(O2xe8ZrE=$4b8F(Daz6ApDlX5<+pFA!plbP5usG;F@=oakDi4HaS6SL@^O zRcH8jjE`;|zLqhn8+Dh99_*how!A()Vquen8dk$BjfSGb+;Fv5QHxV|1z-+C)NzrF z3Ty(lu1MF0>0vb6Mo5dc;=lygGmA+ro)10>;z-y*8IbvjMM$qQJjKAvO4=lqO@a-~ z$c=t5p7|bZ#XBOLLW=7VikU1w=C Date: Fri, 23 Mar 2018 17:32:37 +0800 Subject: [PATCH 044/887] add method startFragmentForResult --- .../com/qmuiteam/qmui/arch/QMUIFragment.java | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java index b9b931cd6..a1064f7d1 100644 --- a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java +++ b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java @@ -1,5 +1,7 @@ package com.qmuiteam.qmui.arch; +import android.app.Activity; +import android.content.Intent; import android.content.res.Resources; import android.os.Bundle; import android.support.annotation.NonNull; @@ -15,6 +17,7 @@ import android.view.animation.Animation; import android.view.animation.AnimationUtils; +import com.qmuiteam.qmui.QMUILog; import com.qmuiteam.qmui.util.QMUIViewHelper; import java.lang.reflect.Field; @@ -55,6 +58,17 @@ public abstract class QMUIFragment extends Fragment { R.anim.scale_enter, R.anim.slide_still, R.anim.slide_still, R.anim.scale_exit); + + public static final int RESULT_CANCELED = Activity.RESULT_CANCELED; + public static final int RESULT_OK = Activity.RESULT_CANCELED; + public static final int RESULT_FIRST_USER = Activity.RESULT_FIRST_USER; + + private static final int NO_REQUEST_CODE = 0; + private int mSourceRequestCode = NO_REQUEST_CODE; + private Intent mResultData = null; + private int mResultCode = RESULT_CANCELED; + + private View mBaseView; private SwipeBackLayout mCacheView; private boolean isCreateForSwipeBack = false; @@ -95,6 +109,43 @@ protected void startFragment(QMUIFragment fragment) { } } + /** + * 模拟 startActivityForResult/onActivityResult + * fragment1 通过 startActivityForResult(fragment2, requestCode) 启动 fragment2 + * fragment2 处理完之后,通过 fragment2.setFragmentResult(RESULT_OK, data) 回调数据给 fragment1 + * fragment1,通过 onFragmentResult(requestCode, RESULT_OK, data) 取得回调的数据 + * + * @param fragment resultCode + * @param requestCode data + */ + public void startFragmentForResult(QMUIFragment fragment, int requestCode) { + if (requestCode == NO_REQUEST_CODE) { + throw new RuntimeException("requestCode can not be " + NO_REQUEST_CODE); + } + fragment.setTargetFragment(this, requestCode); + mSourceRequestCode = requestCode; + startFragment(fragment); + } + + + public void setFragmentResult(int resultCode, Intent data) { + int targetRequestCode = getTargetRequestCode(); + if (targetRequestCode == 0) { + QMUILog.w(TAG, "call setFragmentResult, but not requestCode exists"); + return; + } + Fragment fragment = getTargetFragment(); + if (fragment == null || !(fragment instanceof QMUIFragment)) { + return; + } + QMUIFragment targetFragment = (QMUIFragment) fragment; + + if (targetFragment.mSourceRequestCode == targetRequestCode) { + targetFragment.mResultCode = resultCode; + targetFragment.mResultData = data; + } + } + //============================= 生命周期 ================================ @@ -115,6 +166,22 @@ public void onCreate(@Nullable Bundle savedInstanceState) { } } + @Override + public void onStart() { + super.onStart(); + int requestCode = mSourceRequestCode; + int resultCode = mResultCode; + Intent data = mResultData; + + mSourceRequestCode = NO_REQUEST_CODE; + mResultCode = RESULT_CANCELED; + mResultData = null; + + if (requestCode != NO_REQUEST_CODE) { + onFragmentResult(requestCode, resultCode, data); + } + } + private SwipeBackLayout newSwipeBackLayout() { View rootView = onCreateView(); if (translucentFull()) { @@ -417,6 +484,16 @@ private void checkAndCallOnEnterAnimationEnd(@Nullable Animation animation) { */ protected abstract View onCreateView(); + /** + * 将在 onStart 中执行 + * @param requestCode + * @param resultCode + * @param data + */ + protected void onFragmentResult(int requestCode, int resultCode, Intent data) { + + } + /** * disable or enable drag back * From 8b9824953a6caeebc086138ba5d4f83b699bb957 Mon Sep 17 00:00:00 2001 From: cgspine Date: Fri, 23 Mar 2018 19:56:21 +0800 Subject: [PATCH 045/887] update qr url --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 522a19571..69df559bb 100644 --- a/README.md +++ b/README.md @@ -35,4 +35,4 @@ QMUI Android 支持 API Level 14+。 或扫二维码至官网下载: -![QMUI Website](http://qmuiteam.com/android/public/style/images/independent/DownloadQRCode.png?v=website) +![QMUI Website](http://qmuiteam.com/themes/qmui/public/style/images/independent/AndroidDownloadQRCode_2x.png) From 25d28081c7c9f06b37702740a216a9181e730745 Mon Sep 17 00:00:00 2001 From: cgspine Date: Mon, 26 Mar 2018 15:15:56 +0800 Subject: [PATCH 046/887] bugfix: prevent back event when transition animation. #184 #213 --- .../com/qmuiteam/qmui/arch/QMUIFragment.java | 50 ++++++++++++++----- .../qmui/arch/QMUIFragmentActivity.java | 2 +- .../qmui/widget/dialog/QMUIDialog.java | 2 + 3 files changed, 41 insertions(+), 13 deletions(-) diff --git a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java index a1064f7d1..b04aa088c 100644 --- a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java +++ b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java @@ -63,6 +63,11 @@ public abstract class QMUIFragment extends Fragment { public static final int RESULT_OK = Activity.RESULT_CANCELED; public static final int RESULT_FIRST_USER = Activity.RESULT_FIRST_USER; + public static final int ANIMATION_ENTER_STATUS_NOT_START = -1; + public static final int ANIMATION_ENTER_STATUS_STARTED = 0; + public static final int ANIMATION_ENTER_STATUS_END = 1; + + private static final int NO_REQUEST_CODE = 0; private int mSourceRequestCode = NO_REQUEST_CODE; private Intent mResultData = null; @@ -74,7 +79,7 @@ public abstract class QMUIFragment extends Fragment { private boolean isCreateForSwipeBack = false; private int mBackStackIndex = 0; - private boolean mIsEnterAnimationEnd = true; + private int mEnterAnimationStatus = ANIMATION_ENTER_STATUS_NOT_START; private boolean mCalled = true; private ArrayList mDelayRenderRunnableList = new ArrayList<>(); @@ -189,8 +194,16 @@ private SwipeBackLayout newSwipeBackLayout() { } else { rootView.setFitsSystemWindows(true); } - SwipeBackLayout swipeBackLayout = SwipeBackLayout.wrap(rootView, dragBackEdge()); - swipeBackLayout.setEnableGesture(canDragBack()); + final SwipeBackLayout swipeBackLayout = SwipeBackLayout.wrap(rootView, dragBackEdge()); + swipeBackLayout.setEnableGesture(false); + if(canDragBack()){ + runAfterAnimation(new Runnable() { + @Override + public void run() { + swipeBackLayout.setEnableGesture(true); + } + }, true); + } swipeBackLayout.addSwipeListener(new SwipeBackLayout.SwipeListener() { @Override public void onScrollStateChange(int state, float scrollPercent) { @@ -353,7 +366,7 @@ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, swipeBackLayout = newSwipeBackLayout(); mCacheView = swipeBackLayout; } else if (isCreateForSwipeBack) { - // in swipe back, must not in animation + // in swipe back, exactly not in animation swipeBackLayout = mCacheView; } else { boolean isInRemoving = false; @@ -418,6 +431,9 @@ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, } protected void popBackStack() { + if(mEnterAnimationStatus != ANIMATION_ENTER_STATUS_END){ + return; + } getBaseFragmentActivity().popBackStack(); } @@ -432,8 +448,8 @@ public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) { doNothingAnim.setDuration(duration); return doNothingAnim; } + Animation animation = null; if (enter) { - Animation animation = null; try { animation = AnimationUtils.loadAnimation(getContext(), nextAnim); @@ -442,7 +458,6 @@ public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) { } catch (RuntimeException ignored) { } - if (animation != null) { animation.setAnimationListener(new Animation.AnimationListener() { @Override @@ -464,9 +479,8 @@ public void onAnimationRepeat(Animation animation) { onEnterAnimationStart(null); checkAndCallOnEnterAnimationEnd(null); } - return animation; } - return null; + return animation; } @@ -516,15 +530,27 @@ protected int dragBackEdge() { return EDGE_LEFT; } + /** + * 在动画开始前或动画结束后都会被直接执行 + * + * @param runnable + */ + public void runAfterAnimation(Runnable runnable) { + runAfterAnimation(runnable, false); + } + /** * 异步数据渲染时,调用这个方法可以保证数据是在转场动画结束后进行渲染。 * 转场动画过程中进行数据渲染时,会造成卡顿,从而影响用户体验 * * @param runnable + * @param onlyEnd */ - public void runAfterAnimation(Runnable runnable) { + public void runAfterAnimation(Runnable runnable, boolean onlyEnd){ Utils.assertInMainThread(); - if (mIsEnterAnimationEnd) { + boolean ok = onlyEnd ? mEnterAnimationStatus == ANIMATION_ENTER_STATUS_END : + mEnterAnimationStatus != ANIMATION_ENTER_STATUS_STARTED; + if (ok) { runnable.run(); } else { mDelayRenderRunnableList.add(runnable); @@ -534,7 +560,7 @@ public void runAfterAnimation(Runnable runnable) { //============================= 新流程 ================================ protected void onEnterAnimationStart(@Nullable Animation animation) { - mIsEnterAnimationEnd = false; + mEnterAnimationStatus = ANIMATION_ENTER_STATUS_STARTED; } protected void onEnterAnimationEnd(@Nullable Animation animation) { @@ -542,7 +568,7 @@ protected void onEnterAnimationEnd(@Nullable Animation animation) { throw new IllegalAccessError("don't call #onEnterAnimationEnd() directly"); } mCalled = true; - mIsEnterAnimationEnd = true; + mEnterAnimationStatus = ANIMATION_ENTER_STATUS_END; if (mDelayRenderRunnableList.size() > 0) { for (int i = 0; i < mDelayRenderRunnableList.size(); i++) { mDelayRenderRunnableList.get(i).run(); diff --git a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragmentActivity.java b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragmentActivity.java index 65ee4a217..a63b37bc6 100644 --- a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragmentActivity.java +++ b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragmentActivity.java @@ -38,7 +38,7 @@ public FrameLayout getFragmentContainer() { public void onBackPressed() { QMUIFragment fragment = getCurrentFragment(); if (fragment != null) { - popBackStack(); + fragment.popBackStack(); } } diff --git a/qmui/src/main/java/com/qmuiteam/qmui/widget/dialog/QMUIDialog.java b/qmui/src/main/java/com/qmuiteam/qmui/widget/dialog/QMUIDialog.java index 28ed6acb6..1ac6112b9 100644 --- a/qmui/src/main/java/com/qmuiteam/qmui/widget/dialog/QMUIDialog.java +++ b/qmui/src/main/java/com/qmuiteam/qmui/widget/dialog/QMUIDialog.java @@ -190,6 +190,7 @@ protected void onCreateContent(QMUIDialog dialog, ViewGroup parent, Context cont mTextView = new QMUISpanTouchFixTextView(context); assignMessageTvWithAttr(mTextView, hasTitle(), R.attr.qmui_dialog_message_content_style); mTextView.setText(mMessage); + mTextView.setMovementMethodDefault(); mScrollContainer = new QMUIWrapContentScrollView(context); @@ -306,6 +307,7 @@ protected void onCreateContent(QMUIDialog dialog, ViewGroup parent, Context cont if (mMessage != null && mMessage.length() != 0) { mScrollContainer = new QMUIWrapContentScrollView(context); mTextView = new QMUISpanTouchFixTextView(context); + mTextView.setMovementMethodDefault(); MessageDialogBuilder.assignMessageTvWithAttr(mTextView, hasTitle(), R.attr.qmui_dialog_message_content_style); ScrollView.LayoutParams lp = new ScrollView.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); From 047b6d04348046540343070ce7d864ff32851364 Mon Sep 17 00:00:00 2001 From: cgspine Date: Mon, 26 Mar 2018 16:40:40 +0800 Subject: [PATCH 047/887] release to 1.1.0 --- arch/build.gradle | 2 +- qmui/build.gradle | 2 +- qmuidemo/build.gradle | 2 +- .../qmuiteam/qmuidemo/base/BaseFragment.java | 12 +-- .../qmuidemo/manager/QDPreferenceManager.java | 14 +-- .../qmuidemo/manager/QDUpgradeManager.java | 91 ++++++++++++++++--- qmuidemo/src/main/res/values/strings.xml | 2 +- qmuidemo/src/main/res/values/styles.xml | 11 +++ 8 files changed, 103 insertions(+), 33 deletions(-) diff --git a/arch/build.gradle b/arch/build.gradle index 3b849f046..4fdc4fc2e 100644 --- a/arch/build.gradle +++ b/arch/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'com.android.library' group = 'com.qmuiteam' -version = "0.0.2" +version = "0.0.3" android { diff --git a/qmui/build.gradle b/qmui/build.gradle index 834a45161..05941bf8d 100644 --- a/qmui/build.gradle +++ b/qmui/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'com.android.library' group = 'com.qmuiteam' -version = "1.0.8" // QMUI 发布到 bintray 的版本号 +version = "1.1.0" // QMUI 发布到 bintray 的版本号 //noinspection GroovyMissingReturnStatement android { diff --git a/qmuidemo/build.gradle b/qmuidemo/build.gradle index 582f30110..828096e98 100644 --- a/qmuidemo/build.gradle +++ b/qmuidemo/build.gradle @@ -25,7 +25,7 @@ android { minSdkVersion parent.ext.minSdkVersion targetSdkVersion parent.ext.targetSdkVersion versionCode gitVersion - versionName "1.0.7" + versionName "1.1.0" } buildTypes { debug { diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/base/BaseFragment.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/base/BaseFragment.java index 53828eb38..de3ddf1f7 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/base/BaseFragment.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/base/BaseFragment.java @@ -7,6 +7,7 @@ import com.qmuiteam.qmui.widget.dialog.QMUIDialogAction; import com.qmuiteam.qmuidemo.R; import com.qmuiteam.qmuidemo.manager.QDPreferenceManager; +import com.qmuiteam.qmuidemo.manager.QDUpgradeManager; /** * Created by cgspine on 2018/1/7. @@ -35,18 +36,11 @@ private void checkAndShowUpgradeTip() { if (preferenceManager.isNeedShowUpgradeTip()) { preferenceManager.setNeedShowUpgradeTip(false); String title = String.format(getString(R.string.app_upgrade_tip_title), QMUIPackageHelper.getAppVersion(getContext())); - String message = "1. 分离出 arch 模块,用于 fragment 管理,支持手势返回\n" + - "2. 整理 QMUITopbar 的 theme,能够对 QMUITopbar 做更多的差异化处理\n" + - "3. 其它 bugfix: #125、#127、#132、#141"; + CharSequence message = QDUpgradeManager.getInstance(getContext()).getUpgradeWord(getActivity()); new QMUIDialog.MessageDialogBuilder(getContext()) .setTitle(title) .setMessage(message) - .addAction(R.string.ok, new QMUIDialogAction.ActionListener() { - @Override - public void onClick(QMUIDialog qmuiDialog, int i) { - qmuiDialog.dismiss(); - } - }) + .create(R.style.ReleaseDialogTheme) .show(); } } diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/manager/QDPreferenceManager.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/manager/QDPreferenceManager.java index 0021c4b1b..01d1cf5c8 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/manager/QDPreferenceManager.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/manager/QDPreferenceManager.java @@ -10,20 +10,20 @@ public class QDPreferenceManager { private static SharedPreferences sPreferences; - private static QDPreferenceManager sQDPerferenceManager = null; + private static QDPreferenceManager sQDPreferenceManager = null; private static final String APP_VERSION_CODE = "app_version_code"; - private static final String APP_NNED_SHOW_UPGRADE_TIP = "app_has_show_upgrade_tip"; + private static final String APP_NEED_SHOW_UPGRADE_TIP = "app_has_show_upgrade_tip"; private QDPreferenceManager(Context context) { sPreferences = PreferenceManager.getDefaultSharedPreferences(context.getApplicationContext()); } public static final QDPreferenceManager getInstance(Context context) { - if (sQDPerferenceManager == null) { - sQDPerferenceManager = new QDPreferenceManager(context); + if (sQDPreferenceManager == null) { + sQDPreferenceManager = new QDPreferenceManager(context); } - return sQDPerferenceManager; + return sQDPreferenceManager; } public void setAppVersionCode(int code) { @@ -38,11 +38,11 @@ public int getVersionCode() { public void setNeedShowUpgradeTip(boolean needShowUpgradeTip) { final SharedPreferences.Editor editor = sPreferences.edit(); - editor.putBoolean(APP_NNED_SHOW_UPGRADE_TIP, needShowUpgradeTip); + editor.putBoolean(APP_NEED_SHOW_UPGRADE_TIP, needShowUpgradeTip); editor.apply(); } public boolean isNeedShowUpgradeTip() { - return sPreferences.getBoolean(APP_NNED_SHOW_UPGRADE_TIP, false); + return sPreferences.getBoolean(APP_NEED_SHOW_UPGRADE_TIP, false); } } diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/manager/QDUpgradeManager.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/manager/QDUpgradeManager.java index 04c19afcf..e90054b84 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/manager/QDUpgradeManager.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/manager/QDUpgradeManager.java @@ -1,6 +1,18 @@ package com.qmuiteam.qmuidemo.manager; +import android.app.Activity; import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.support.v4.content.ContextCompat; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.view.View; + +import com.qmuiteam.qmui.span.QMUIBlockSpaceSpan; +import com.qmuiteam.qmui.span.QMUITouchableSpan; +import com.qmuiteam.qmui.util.QMUIDisplayHelper; +import com.qmuiteam.qmuidemo.R; /** * Created by cgspine on 2018/1/14. @@ -9,43 +21,96 @@ public class QDUpgradeManager { public static final int INVALIDATE_VERSION_CODE = -1; - private static final int VERSION_1_0_7 = 107; - - private static final int sCurrentVersion = VERSION_1_0_7; + private static final int VERSION_1_1_0 = 110; + private static final int sCurrentVersion = VERSION_1_1_0; private static QDUpgradeManager sQDUpgradeManager = null; private Context mContext; - private QDUpgradeManager(Context context){ + private QDUpgradeManager(Context context) { mContext = context.getApplicationContext(); } - public static final QDUpgradeManager getInstance(Context context){ - if(sQDUpgradeManager == null){ + public static final QDUpgradeManager getInstance(Context context) { + if (sQDUpgradeManager == null) { sQDUpgradeManager = new QDUpgradeManager(context); } return sQDUpgradeManager; } - public void check(){ + public void check() { int oldVersion = QDPreferenceManager.getInstance(mContext).getVersionCode(); int currentVersion = sCurrentVersion; - if(currentVersion > oldVersion){ - if(oldVersion == INVALIDATE_VERSION_CODE){ + if (currentVersion > oldVersion) { + if (oldVersion == INVALIDATE_VERSION_CODE) { onNewInstall(currentVersion); - }else{ + } else { onUpgrade(oldVersion, currentVersion); } QDPreferenceManager.getInstance(mContext).setAppVersionCode(currentVersion); } } - private void onUpgrade(int oldVersion, int currentVersion){ + private void onUpgrade(int oldVersion, int currentVersion) { QDPreferenceManager.getInstance(mContext).setNeedShowUpgradeTip(true); } - private void onNewInstall(int currentVersion){ - // 并无法判断是 1.0.7 版本之前升级上来的,还是新装的 + private void onNewInstall(int currentVersion) { QDPreferenceManager.getInstance(mContext).setNeedShowUpgradeTip(true); } + + private void appendBlockSpace(Context context, SpannableStringBuilder builder) { + int start = builder.length(); + builder.append("[space]"); + QMUIBlockSpaceSpan blockSpaceSpan = new QMUIBlockSpaceSpan(QMUIDisplayHelper.dp2px(context, 6)); + builder.setSpan(blockSpaceSpan, start, builder.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + } + + public CharSequence getUpgradeWord(final Activity activity) { + switch (sCurrentVersion) { + case VERSION_1_1_0: + SpannableStringBuilder text = new SpannableStringBuilder(); + text.append("1. Added QMUILayout, making it easy to implement shadows, radii, and separators.\n"); + appendBlockSpace(activity, text); + text.append("2. Refactored the theme usage of QMUITopbar.\n"); + appendBlockSpace(activity, text); + text.append("3. Refactored QMUIDialog for more flexible configuration.\n"); + appendBlockSpace(activity, text); + text.append("4. Updated arch library to 0.0.3 to provide methods runAfterAnimation and startFragmentForResult.\n"); + appendBlockSpace(activity, text); + text.append("5. Bug fixes: "); + final String[] issues = new String[]{ + "125", "127", "132", "141", "177", "184", "198", "200", "209", "213" + }; + final String issueBaseUrl = "https://github.com/QMUI/QMUI_Android/issues/"; + int start, end; + for (int i = 0; i < issues.length; i++) { + if(i == issues.length - 1){ + text.append("and "); + } + final String issue = issues[i]; + start = text.length(); + text.append("#"); + text.append(issue); + end = text.length(); + int normalColor = ContextCompat.getColor(activity, R.color.app_color_blue); + int pressedColor = ContextCompat.getColor(activity, R.color.app_color_blue_pressed); + text.setSpan(new QMUITouchableSpan(normalColor, pressedColor, 0, 0) { + @Override + public void onSpanClick(View widget) { + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setData(Uri.parse(issueBaseUrl + issue)); + activity.startActivity(intent); + } + }, start, end, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); + if (i < issues.length - 1) { + text.append(", "); + }else{ + text.append("."); + } + } + return text; + } + return "欢迎体验新版本!"; + } } diff --git a/qmuidemo/src/main/res/values/strings.xml b/qmuidemo/src/main/res/values/strings.xml index 07ce9bca2..dec56b47e 100644 --- a/qmuidemo/src/main/res/values/strings.xml +++ b/qmuidemo/src/main/res/values/strings.xml @@ -3,7 +3,7 @@ QMUI 示例图片 - 更新提示(%1$s) + Release Notes (%1$s) 确 定 取 消 diff --git a/qmuidemo/src/main/res/values/styles.xml b/qmuidemo/src/main/res/values/styles.xml index 3a11fdc29..901372b23 100644 --- a/qmuidemo/src/main/res/values/styles.xml +++ b/qmuidemo/src/main/res/values/styles.xml @@ -93,6 +93,12 @@ @style/DialogTheme2MenuItemStyle + + + + - - - \ No newline at end of file diff --git a/qmui/src/main/res/values-v21/qmui_themes_compat.xml b/qmui/src/main/res/values-v21/qmui_themes_compat.xml deleted file mode 100644 index d5b436950..000000000 --- a/qmui/src/main/res/values-v21/qmui_themes_compat.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/qmui/src/main/res/values/qmui_style_widget.xml b/qmui/src/main/res/values/qmui_style_widget.xml index b10f3ee2e..b51fcfe62 100644 --- a/qmui/src/main/res/values/qmui_style_widget.xml +++ b/qmui/src/main/res/values/qmui_style_widget.xml @@ -26,7 +26,7 @@ - - - - --> + + - - - - - - - + \ No newline at end of file diff --git a/qmui/src/main/res/values/qmui_themes_compat.xml b/qmui/src/main/res/values/qmui_themes_compat.xml deleted file mode 100644 index 0b95e94a5..000000000 --- a/qmui/src/main/res/values/qmui_themes_compat.xml +++ /dev/null @@ -1,357 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/home/HomeFragment.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/home/HomeFragment.java index 855d26052..0102e9eaf 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/home/HomeFragment.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/home/HomeFragment.java @@ -16,9 +16,6 @@ package com.qmuiteam.qmuidemo.fragment.home; -import androidx.core.content.ContextCompat; -import androidx.viewpager.widget.PagerAdapter; -import androidx.viewpager.widget.ViewPager; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -31,6 +28,9 @@ import java.util.HashMap; +import androidx.core.content.ContextCompat; +import androidx.viewpager.widget.PagerAdapter; +import androidx.viewpager.widget.ViewPager; import butterknife.BindView; import butterknife.ButterKnife; diff --git a/qmuidemo/src/main/res/values/styles.xml b/qmuidemo/src/main/res/values/styles.xml index dbc37927c..e18358912 100644 --- a/qmuidemo/src/main/res/values/styles.xml +++ b/qmuidemo/src/main/res/values/styles.xml @@ -81,7 +81,7 @@ 48dp - diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDTabSegmentFixModeFragment.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDTabSegmentFixModeFragment.java index fee8e70b6..992fd16cd 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDTabSegmentFixModeFragment.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDTabSegmentFixModeFragment.java @@ -16,9 +16,7 @@ package com.qmuiteam.qmuidemo.fragment.components; -import androidx.core.content.ContextCompat; -import androidx.viewpager.widget.PagerAdapter; -import androidx.viewpager.widget.ViewPager; +import android.content.Context; import android.util.TypedValue; import android.view.Gravity; import android.view.LayoutInflater; @@ -28,9 +26,12 @@ import com.qmuiteam.qmui.util.QMUIDisplayHelper; import com.qmuiteam.qmui.util.QMUIResHelper; -import com.qmuiteam.qmui.widget.QMUITabSegment; import com.qmuiteam.qmui.widget.QMUITopBarLayout; import com.qmuiteam.qmui.widget.dialog.QMUIBottomSheet; +import com.qmuiteam.qmui.widget.tab.QMUITab; +import com.qmuiteam.qmui.widget.tab.QMUITabBuilder; +import com.qmuiteam.qmui.widget.tab.QMUITabIndicator; +import com.qmuiteam.qmui.widget.tab.QMUITabSegment; import com.qmuiteam.qmuidemo.R; import com.qmuiteam.qmuidemo.base.BaseFragment; import com.qmuiteam.qmuidemo.lib.Group; @@ -41,6 +42,9 @@ import java.util.HashMap; import java.util.Map; +import androidx.core.content.ContextCompat; +import androidx.viewpager.widget.PagerAdapter; +import androidx.viewpager.widget.ViewPager; import butterknife.BindView; import butterknife.ButterKnife; @@ -76,7 +80,8 @@ public int getCount() { public Object instantiateItem(final ViewGroup container, int position) { ContentPage page = ContentPage.getPage(position); View view = getPageView(page); - ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + ViewGroup.LayoutParams params = new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); container.addView(view, params); return view; } @@ -130,107 +135,177 @@ private void showBottomSheetList() { .addItem(getResources().getString(R.string.tabSegment_mode_muti_color)) .addItem(getResources().getString(R.string.tabSegment_mode_change_content_by_index)) .addItem(getResources().getString(R.string.tabSegment_mode_replace_tab_by_index)) + .addItem(getResources().getString(R.string.tabSegment_mode_scale_selected)) + .addItem(getResources().getString(R.string.tabSegment_mode_change_gravity)) .setOnSheetItemClickListener(new QMUIBottomSheet.BottomListSheetBuilder.OnSheetItemClickListener() { @Override public void onClick(QMUIBottomSheet dialog, View itemView, int position, String tag) { dialog.dismiss(); + Context context = getContext(); + QMUITabBuilder tabBuilder = mTabSegment.tabBuilder() + .setGravity(Gravity.CENTER); + int indicatorHeight = QMUIDisplayHelper.dp2px(context, 2); switch (position) { case 0: mTabSegment.reset(); - mTabSegment.setHasIndicator(false); - mTabSegment.addTab(new QMUITabSegment.Tab(getString(R.string.tabSegment_item_1_title))); - mTabSegment.addTab(new QMUITabSegment.Tab(getString(R.string.tabSegment_item_2_title))); + mTabSegment.setIndicator(null); + mTabSegment.addTab(tabBuilder.setText(getString(R.string.tabSegment_item_1_title)).build()); + mTabSegment.addTab(tabBuilder.setText(getString(R.string.tabSegment_item_2_title)).build()); break; case 1: mTabSegment.reset(); - mTabSegment.setHasIndicator(true); - mTabSegment.setIndicatorPosition(false); - mTabSegment.setIndicatorWidthAdjustContent(true); - mTabSegment.addTab(new QMUITabSegment.Tab(getString(R.string.tabSegment_item_1_title))); - mTabSegment.addTab(new QMUITabSegment.Tab(getString(R.string.tabSegment_item_2_title))); + mTabSegment.setIndicator(new QMUITabIndicator( + indicatorHeight, false, true)); + mTabSegment.addTab(tabBuilder.setText(getString(R.string.tabSegment_item_1_title)).build()); + mTabSegment.addTab(tabBuilder.setText(getString(R.string.tabSegment_item_2_title)).build()); break; case 2: mTabSegment.reset(); - mTabSegment.setHasIndicator(true); - mTabSegment.setIndicatorPosition(true); - mTabSegment.setIndicatorWidthAdjustContent(true); - mTabSegment.addTab(new QMUITabSegment.Tab(getString(R.string.tabSegment_item_1_title))); - mTabSegment.addTab(new QMUITabSegment.Tab(getString(R.string.tabSegment_item_2_title))); + mTabSegment.setIndicator(new QMUITabIndicator( + indicatorHeight, true, true)); + mTabSegment.addTab(tabBuilder.setText(getString(R.string.tabSegment_item_1_title)).build()); + mTabSegment.addTab(tabBuilder.setText(getString(R.string.tabSegment_item_2_title)).build()); break; case 3: mTabSegment.reset(); - mTabSegment.setHasIndicator(true); - mTabSegment.setIndicatorPosition(false); - mTabSegment.setIndicatorWidthAdjustContent(false); - mTabSegment.addTab(new QMUITabSegment.Tab(getString(R.string.tabSegment_item_1_title))); - mTabSegment.addTab(new QMUITabSegment.Tab(getString(R.string.tabSegment_item_2_title))); + mTabSegment.setIndicator(new QMUITabIndicator( + indicatorHeight, false, false)); + mTabSegment.addTab(tabBuilder.setText(getString(R.string.tabSegment_item_1_title)).build()); + mTabSegment.addTab(tabBuilder.setText(getString(R.string.tabSegment_item_2_title)).build()); break; - case 4: + case 4: { mTabSegment.reset(); - mTabSegment.setHasIndicator(false); - QMUITabSegment.Tab component = new QMUITabSegment.TabBuilder("Components") - .setNormalDrawable(ContextCompat.getDrawable(getContext(), R.mipmap.icon_tabbar_component)) - .setDynamicChangeIconColor(true) + mTabSegment.setIndicator(null); + tabBuilder.setDynamicChangeIconColor(true); + QMUITab component = tabBuilder + .setNormalDrawable(ContextCompat.getDrawable(context, R.mipmap.icon_tabbar_component)) + .setSelectedDrawable(ContextCompat.getDrawable(context, R.mipmap.icon_tabbar_component_selected)) + .setText("Components") .build(); - QMUITabSegment.Tab util = new QMUITabSegment.TabBuilder("Helper") - .setNormalDrawable(ContextCompat.getDrawable(getContext(), R.mipmap.icon_tabbar_util)) - .setDynamicChangeIconColor(true) + QMUITab util = tabBuilder + .setNormalDrawable(ContextCompat.getDrawable(context, R.mipmap.icon_tabbar_util)) + .setSelectedDrawable(ContextCompat.getDrawable(context, R.mipmap.icon_tabbar_util_selected)) + .setText("Helper") .build(); mTabSegment.addTab(component); mTabSegment.addTab(util); break; + } case 5: - QMUITabSegment.Tab tab = mTabSegment.getTab(0); - tab.setSignCountMargin(0, -QMUIDisplayHelper.dp2px(getContext(), 4)); - tab.showSignCountView(getContext(), 1); +// mTabSegment.showSignCountView(getContext(), 0, 20); // 也可以直接调用这个 + QMUITab tab = mTabSegment.getTab(0); + tab.setSignCount(20); + + QMUITab tab1 = mTabSegment.getTab(1); + tab1.setRedPoint(); break; - case 6: + case 6: { mTabSegment.reset(); - mTabSegment.setHasIndicator(false); - QMUITabSegment.Tab component2 = new QMUITabSegment.TabBuilder("Components") - .setNormalDrawable(ContextCompat.getDrawable(getContext(), R.mipmap.icon_tabbar_component)) - .setSelectedDrawable(ContextCompat.getDrawable(getContext(), R.mipmap.icon_tabbar_component_selected)) + mTabSegment.setIndicator(null); + tabBuilder.setDynamicChangeIconColor(false); + QMUITab component = tabBuilder + .setNormalDrawable(ContextCompat.getDrawable(context, R.mipmap.icon_tabbar_component)) + .setSelectedDrawable(ContextCompat.getDrawable(context, R.mipmap.icon_tabbar_component_selected)) + .setText("Components") .build(); - - - QMUITabSegment.Tab util2 = new QMUITabSegment.TabBuilder("Helper") - .setNormalDrawable(ContextCompat.getDrawable(getContext(), R.mipmap.icon_tabbar_util)) - .setSelectedDrawable(ContextCompat.getDrawable(getContext(), R.mipmap.icon_tabbar_util_selected)) + QMUITab util = tabBuilder + .setNormalDrawable(ContextCompat.getDrawable(context, R.mipmap.icon_tabbar_util)) + .setSelectedDrawable(ContextCompat.getDrawable(context, R.mipmap.icon_tabbar_util_selected)) + .setText("Helper") .build(); - mTabSegment.addTab(component2); - mTabSegment.addTab(util2); + mTabSegment.addTab(component); + mTabSegment.addTab(util); break; - case 7: + } + case 7: { mTabSegment.reset(); - mTabSegment.setHasIndicator(true); - mTabSegment.setIndicatorWidthAdjustContent(true); - mTabSegment.setIndicatorPosition(false); - QMUITabSegment.Tab component3 = new QMUITabSegment.TabBuilder("Components") - .setNormalDrawable(ContextCompat.getDrawable(getContext(), R.mipmap.icon_tabbar_component)) - .setDynamicChangeIconColor(true) - .setColor(QMUIResHelper.getAttrColor(getContext(), R.attr.qmui_config_color_blue), - QMUIResHelper.getAttrColor(getContext(), R.attr.qmui_config_color_red)) + mTabSegment.setIndicator(new QMUITabIndicator( + indicatorHeight, false, true)); + tabBuilder.setDynamicChangeIconColor(true); + QMUITab component = tabBuilder + .setNormalDrawable(ContextCompat.getDrawable(context, R.mipmap.icon_tabbar_component)) + .setSelectedDrawable(ContextCompat.getDrawable(context, R.mipmap.icon_tabbar_component_selected)) + .setText("Components") + .setColor(QMUIResHelper.getAttrColor(context, R.attr.qmui_config_color_gray_1), + QMUIResHelper.getAttrColor(context, R.attr.qmui_config_color_blue)) .build(); - QMUITabSegment.Tab util3 = new QMUITabSegment.TabBuilder("Helper") - .setNormalDrawable(ContextCompat.getDrawable(getContext(), R.mipmap.icon_tabbar_util)) - .setDynamicChangeIconColor(true) - .setColor(QMUIResHelper.getAttrColor(getContext(), R.attr.qmui_config_color_gray_1), - QMUIResHelper.getAttrColor(getContext(), R.attr.qmui_config_color_red)) + QMUITab util = tabBuilder + .setNormalDrawable(ContextCompat.getDrawable(context, R.mipmap.icon_tabbar_util)) + .setSelectedDrawable(ContextCompat.getDrawable(context, R.mipmap.icon_tabbar_util_selected)) + .setText("Helper") + .setColor(QMUIResHelper.getAttrColor(context, R.attr.qmui_config_color_gray_1), + QMUIResHelper.getAttrColor(context, R.attr.qmui_config_color_red)) .build(); - mTabSegment.addTab(component3); - mTabSegment.addTab(util3); + mTabSegment.addTab(component); + mTabSegment.addTab(util); break; + } case 8: mTabSegment.updateTabText(0, "动态更新文案"); break; - case 9: - QMUITabSegment.Tab component4 = new QMUITabSegment.TabBuilder("动态更新") + case 9: { + QMUITab newTab = tabBuilder.setText("动态更新") .setNormalDrawable(ContextCompat.getDrawable(getContext(), R.mipmap.icon_tabbar_component)) .setDynamicChangeIconColor(true) .build(); - mTabSegment.replaceTab(0, component4); + mTabSegment.replaceTab(0, newTab); break; - + } + case 10: { + mTabSegment.reset(); + mTabSegment.setIndicator(new QMUITabIndicator( + indicatorHeight, false, true)); + tabBuilder.setDynamicChangeIconColor(true) + .setTextSize( + QMUIDisplayHelper.sp2px(context, 13), + QMUIDisplayHelper.sp2px(context, 15)) + .setSelectedIconScale(1.5f); + QMUITab component = tabBuilder + .setNormalDrawable(ContextCompat.getDrawable(context, R.mipmap.icon_tabbar_component)) + .setSelectedDrawable(ContextCompat.getDrawable(context, R.mipmap.icon_tabbar_component_selected)) + .setText("Components") + .setColor(QMUIResHelper.getAttrColor(context, R.attr.qmui_config_color_blue), + QMUIResHelper.getAttrColor(context, R.attr.qmui_config_color_red)) + .build(); + QMUITab util = tabBuilder + .setNormalDrawable(ContextCompat.getDrawable(context, R.mipmap.icon_tabbar_util)) + .setSelectedDrawable(ContextCompat.getDrawable(context, R.mipmap.icon_tabbar_util_selected)) + .setText("Helper") + .setColor(QMUIResHelper.getAttrColor(context, R.attr.qmui_config_color_gray_1), + QMUIResHelper.getAttrColor(context, R.attr.qmui_config_color_red)) + .build(); + mTabSegment.addTab(component); + mTabSegment.addTab(util); + break; + } + case 11: { + mTabSegment.reset(); + mTabSegment.setIndicator(new QMUITabIndicator( + indicatorHeight, false, true)); + tabBuilder.setDynamicChangeIconColor(true) + .setTextSize( + QMUIDisplayHelper.sp2px(context, 13), + QMUIDisplayHelper.sp2px(context, 15)) + .setSelectedIconScale(1.5f) + .setGravity(Gravity.LEFT | Gravity.BOTTOM); + QMUITab component = tabBuilder + .setNormalDrawable(ContextCompat.getDrawable(context, R.mipmap.icon_tabbar_component)) + .setSelectedDrawable(ContextCompat.getDrawable(context, R.mipmap.icon_tabbar_component_selected)) + .setText("Components") + .setColor(QMUIResHelper.getAttrColor(context, R.attr.qmui_config_color_blue), + QMUIResHelper.getAttrColor(context, R.attr.qmui_config_color_red)) + .build(); + QMUITab util = tabBuilder + .setNormalDrawable(ContextCompat.getDrawable(context, R.mipmap.icon_tabbar_util)) + .setSelectedDrawable(ContextCompat.getDrawable(context, R.mipmap.icon_tabbar_util_selected)) + .setText("Helper") + .setColor(QMUIResHelper.getAttrColor(context, R.attr.qmui_config_color_gray_1), + QMUIResHelper.getAttrColor(context, R.attr.qmui_config_color_red)) + .build(); + mTabSegment.addTab(component); + mTabSegment.addTab(util); + break; + } default: break; } @@ -244,14 +319,15 @@ public void onClick(QMUIBottomSheet dialog, View itemView, int position, String private void initTabAndPager() { mContentViewPager.setAdapter(mPagerAdapter); mContentViewPager.setCurrentItem(mDestPage.getPosition(), false); - mTabSegment.addTab(new QMUITabSegment.Tab(getString(R.string.tabSegment_item_1_title))); - mTabSegment.addTab(new QMUITabSegment.Tab(getString(R.string.tabSegment_item_2_title))); + QMUITabBuilder builder = mTabSegment.tabBuilder(); + mTabSegment.addTab(builder.setText(getString(R.string.tabSegment_item_1_title)).build()); + mTabSegment.addTab(builder.setText(getString(R.string.tabSegment_item_2_title)).build()); mTabSegment.setupWithViewPager(mContentViewPager, false); mTabSegment.setMode(QMUITabSegment.MODE_FIXED); mTabSegment.addOnTabSelectedListener(new QMUITabSegment.OnTabSelectedListener() { @Override public void onTabSelected(int index) { - mTabSegment.hideSignCountView(index); + } @Override @@ -261,12 +337,11 @@ public void onTabUnselected(int index) { @Override public void onTabReselected(int index) { - mTabSegment.hideSignCountView(index); } @Override public void onDoubleTap(int index) { - + mTabSegment.clearSignCountView(index); } }); } diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDTabSegmentFragment.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDTabSegmentFragment.java index 5821dfe0d..d473e9ef8 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDTabSegmentFragment.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDTabSegmentFragment.java @@ -19,7 +19,7 @@ import android.view.LayoutInflater; import android.view.View; -import com.qmuiteam.qmui.widget.QMUITabSegment; +import com.qmuiteam.qmui.widget.tab.QMUITabSegment; import com.qmuiteam.qmui.widget.QMUITopBarLayout; import com.qmuiteam.qmui.widget.grouplist.QMUIGroupListView; import com.qmuiteam.qmuidemo.R; diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDTabSegmentScrollableModeFragment.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDTabSegmentScrollableModeFragment.java index 37e5ac61c..bc1528694 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDTabSegmentScrollableModeFragment.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDTabSegmentScrollableModeFragment.java @@ -30,7 +30,9 @@ import com.qmuiteam.qmui.util.QMUIDisplayHelper; import com.qmuiteam.qmui.util.QMUIViewHelper; -import com.qmuiteam.qmui.widget.QMUITabSegment; +import com.qmuiteam.qmui.widget.tab.QMUITabBuilder; +import com.qmuiteam.qmui.widget.tab.QMUITabIndicator; +import com.qmuiteam.qmui.widget.tab.QMUITabSegment; import com.qmuiteam.qmui.widget.QMUITopBarLayout; import com.qmuiteam.qmuidemo.R; import com.qmuiteam.qmuidemo.base.BaseFragment; @@ -78,7 +80,8 @@ public Object instantiateItem(final ViewGroup container, int position) { ContentPage page = ContentPage.getPage(position); View view = getPageView(page); view.setTag(page); - ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + ViewGroup.LayoutParams params = new ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); container.addView(view, params); return view; } @@ -136,11 +139,13 @@ public void onClick(View v) { private void initTabAndPager() { mContentViewPager.setAdapter(mPagerAdapter); mContentViewPager.setCurrentItem(mDestPage.getPosition(), false); + QMUITabBuilder tabBuilder = mTabSegment.tabBuilder(); for (int i = 0; i < mCurrentItemCount; i++) { - mTabSegment.addTab(new QMUITabSegment.Tab("Item " + (i + 1))); + mTabSegment.addTab(tabBuilder.setText("Item " + (i + 1)).build()); } int space = QMUIDisplayHelper.dp2px(getContext(), 16); - mTabSegment.setHasIndicator(true); + mTabSegment.setIndicator(new QMUITabIndicator( + QMUIDisplayHelper.dp2px(getContext(), 2), false, true)); mTabSegment.setMode(QMUITabSegment.MODE_SCROLLABLE); mTabSegment.setItemSpaceInScrollMode(space); mTabSegment.setupWithViewPager(mContentViewPager, false); @@ -170,14 +175,16 @@ public void onDoubleTap(int index) { private void reduceTabCount() { if (mCurrentItemCount <= 1) { - Toast.makeText(getContext(), "Only the last one, don't reduce it anymore!!!", Toast.LENGTH_SHORT).show(); + Toast.makeText(getContext(), "Only the last one, don't reduce it anymore!!!", + Toast.LENGTH_SHORT).show(); return; } mCurrentItemCount--; mPagerAdapter.notifyDataSetChanged(); mTabSegment.reset(); + QMUITabBuilder tabBuilder = mTabSegment.tabBuilder(); for (int i = 0; i < mCurrentItemCount; i++) { - mTabSegment.addTab(new QMUITabSegment.Tab("Item " + (i + 1))); + mTabSegment.addTab(tabBuilder.setText("Item " + (i + 1)).build()); } mTabSegment.notifyDataChanged(); } diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/qqface/QDQQFacePerformanceTestFragment.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/qqface/QDQQFacePerformanceTestFragment.java index b0e03866c..6393cba8e 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/qqface/QDQQFacePerformanceTestFragment.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/qqface/QDQQFacePerformanceTestFragment.java @@ -22,7 +22,7 @@ import android.view.View; import android.view.ViewGroup; -import com.qmuiteam.qmui.widget.QMUITabSegment; +import com.qmuiteam.qmui.widget.tab.QMUITabSegment; import com.qmuiteam.qmui.widget.QMUITopBarLayout; import com.qmuiteam.qmuidemo.manager.QDDataManager; import com.qmuiteam.qmuidemo.base.BaseFragment; diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/viewpager/QDFitSystemWindowViewPagerFragment.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/viewpager/QDFitSystemWindowViewPagerFragment.java index fe66c4825..324156c84 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/viewpager/QDFitSystemWindowViewPagerFragment.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/viewpager/QDFitSystemWindowViewPagerFragment.java @@ -17,17 +17,14 @@ package com.qmuiteam.qmuidemo.fragment.components.viewpager; import android.annotation.SuppressLint; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentTransaction; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; -import com.qmuiteam.qmui.util.QMUIResHelper; import com.qmuiteam.qmui.widget.QMUIPagerAdapter; -import com.qmuiteam.qmui.widget.QMUITabSegment; import com.qmuiteam.qmui.widget.QMUIViewPager; +import com.qmuiteam.qmui.widget.tab.QMUITabSegment; import com.qmuiteam.qmuidemo.R; import com.qmuiteam.qmuidemo.base.BaseFragment; import com.qmuiteam.qmuidemo.fragment.QDAboutFragment; @@ -35,6 +32,8 @@ import com.qmuiteam.qmuidemo.fragment.components.QDTabSegmentScrollableModeFragment; import com.qmuiteam.qmuidemo.lib.annotation.Widget; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentTransaction; import butterknife.BindView; import butterknife.ButterKnife; @@ -54,18 +53,10 @@ public class QDFitSystemWindowViewPagerFragment extends BaseFragment { protected View onCreateView() { FrameLayout layout = (FrameLayout) LayoutInflater.from(getActivity()).inflate(R.layout.fragment_fsw_viewpager, null); ButterKnife.bind(this, layout); - initTabs(); initPagers(); return layout; } - private void initTabs() { - int normalColor = QMUIResHelper.getAttrColor(getActivity(), R.attr.qmui_config_color_gray_6); - int selectColor = QMUIResHelper.getAttrColor(getActivity(), R.attr.qmui_config_color_blue); - mTabSegment.setDefaultNormalColor(normalColor); - mTabSegment.setDefaultSelectedColor(selectColor); - } - private void initPagers() { QMUIPagerAdapter pagerAdapter = new QMUIPagerAdapter() { private FragmentTransaction mCurrentTransaction; @@ -105,7 +96,7 @@ protected Object hydrate(ViewGroup container, int position) { .beginTransaction(); } Fragment fragment = getChildFragmentManager().findFragmentByTag(name); - if(fragment != null){ + if (fragment != null) { return fragment; } switch (position) { @@ -132,7 +123,7 @@ protected void populate(ViewGroup container, Object item, int position) { Fragment fragment = getChildFragmentManager().findFragmentByTag(name); if (fragment != null) { mCurrentTransaction.attach(fragment); - if(fragment.getView() != null && fragment.getView().getWidth() == 0){ + if (fragment.getView() != null && fragment.getView().getWidth() == 0) { fragment.getView().requestLayout(); } } else { diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/home/HomeFragment.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/home/HomeFragment.java index 0102e9eaf..bb0469f2b 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/home/HomeFragment.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/home/HomeFragment.java @@ -21,8 +21,11 @@ import android.view.ViewGroup; import android.widget.FrameLayout; +import com.qmuiteam.qmui.util.QMUIDisplayHelper; import com.qmuiteam.qmui.util.QMUIResHelper; -import com.qmuiteam.qmui.widget.QMUITabSegment; +import com.qmuiteam.qmui.widget.tab.QMUITab; +import com.qmuiteam.qmui.widget.tab.QMUITabBuilder; +import com.qmuiteam.qmui.widget.tab.QMUITabSegment; import com.qmuiteam.qmuidemo.R; import com.qmuiteam.qmuidemo.base.BaseFragment; @@ -98,34 +101,27 @@ protected View onCreateView() { } private void initTabs() { - int normalColor = QMUIResHelper.getAttrColor(getActivity(), R.attr.qmui_config_color_gray_6); - int selectColor = QMUIResHelper.getAttrColor(getActivity(), R.attr.qmui_config_color_blue); - mTabSegment.setDefaultNormalColor(normalColor); - mTabSegment.setDefaultSelectedColor(selectColor); -// mTabSegment.setDefaultTabIconPosition(QMUITabSegment.ICON_POSITION_BOTTOM); - - - QMUITabSegment.Tab component = new QMUITabSegment.TabBuilder("Components") + int normalColor = QMUIResHelper.getAttrColor(getContext(), R.attr.qmui_config_color_gray_6); + int selectColor = QMUIResHelper.getAttrColor(getContext(), R.attr.qmui_config_color_blue); + QMUITabBuilder builder = mTabSegment.tabBuilder(); + builder.setColor(normalColor, selectColor) + .setSelectedIconScale(1.6f) + .setTextSize(QMUIDisplayHelper.sp2px(getContext(), 13), QMUIDisplayHelper.sp2px(getContext(), 15)) + .setDynamicChangeIconColor(false); + QMUITab component = builder .setNormalDrawable(ContextCompat.getDrawable(getContext(), R.mipmap.icon_tabbar_component)) .setSelectedDrawable(ContextCompat.getDrawable(getContext(), R.mipmap.icon_tabbar_component_selected)) - .setDynamicChangeIconColor(false) + .setText("Components") .build(); - - // 如果你的 icon 显示大小和实际大小不吻合: - // 通过 tab.setTabIconBounds 重新设置 bounds -// int iconShowSize = QMUIDisplayHelper.dp2px(getContext(), 20); -// component.setTabIconBounds(0, 0, iconShowSize, iconShowSize); - - QMUITabSegment.Tab util = new QMUITabSegment.TabBuilder("Helper") + QMUITab util = builder .setNormalDrawable(ContextCompat.getDrawable(getContext(), R.mipmap.icon_tabbar_util)) .setSelectedDrawable(ContextCompat.getDrawable(getContext(), R.mipmap.icon_tabbar_util_selected)) - .setDynamicChangeIconColor(false) + .setText("Helper") .build(); - - QMUITabSegment.Tab lab = new QMUITabSegment.TabBuilder("Lab") + QMUITab lab = builder .setNormalDrawable(ContextCompat.getDrawable(getContext(), R.mipmap.icon_tabbar_lab)) .setSelectedDrawable(ContextCompat.getDrawable(getContext(), R.mipmap.icon_tabbar_lab_selected)) - .setDynamicChangeIconColor(false) + .setText("Lab") .build(); mTabSegment.addTab(component) diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/util/QDNotchHelperFragment.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/util/QDNotchHelperFragment.java index be4cdf735..2dadc0156 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/util/QDNotchHelperFragment.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/util/QDNotchHelperFragment.java @@ -19,9 +19,6 @@ import android.app.Activity; import android.os.Build; import android.os.Bundle; -import androidx.annotation.Nullable; -import androidx.core.content.ContextCompat; -import androidx.core.view.ViewCompat; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -30,15 +27,21 @@ import android.widget.TextView; import com.qmuiteam.qmui.util.QMUIDisplayHelper; +import com.qmuiteam.qmui.util.QMUIResHelper; import com.qmuiteam.qmui.util.QMUIViewHelper; -import com.qmuiteam.qmui.widget.QMUITabSegment; import com.qmuiteam.qmui.widget.QMUITopBarLayout; +import com.qmuiteam.qmui.widget.tab.QMUITab; +import com.qmuiteam.qmui.widget.tab.QMUITabBuilder; +import com.qmuiteam.qmui.widget.tab.QMUITabSegment; import com.qmuiteam.qmuidemo.R; import com.qmuiteam.qmuidemo.base.BaseFragment; import com.qmuiteam.qmuidemo.lib.Group; import com.qmuiteam.qmuidemo.lib.annotation.Widget; import com.qmuiteam.qmuidemo.manager.QDDataManager; +import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; +import androidx.core.view.ViewCompat; import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; @@ -107,23 +110,29 @@ public void onClick(View v) { } private void initTabs() { - QMUITabSegment.Tab component = new QMUITabSegment.TabBuilder("Components") + int normalColor = QMUIResHelper.getAttrColor(getContext(), R.attr.qmui_config_color_gray_6); + int selectColor = QMUIResHelper.getAttrColor(getContext(), R.attr.qmui_config_color_blue); + QMUITabBuilder builder = mTabSegment.tabBuilder(); + builder.setColor(normalColor, selectColor) + .setSelectedIconScale(2f) + .setTextSize(QMUIDisplayHelper.sp2px(getContext(), 14), QMUIDisplayHelper.sp2px(getContext(), 16)) + .setDynamicChangeIconColor(false); + QMUITab component = builder .setNormalDrawable(ContextCompat.getDrawable(getContext(), R.mipmap.icon_tabbar_component)) .setSelectedDrawable(ContextCompat.getDrawable(getContext(), R.mipmap.icon_tabbar_component_selected)) - .setDynamicChangeIconColor(false) + .setText("Components") .build(); - - QMUITabSegment.Tab util = new QMUITabSegment.TabBuilder("Helper") + QMUITab util = builder .setNormalDrawable(ContextCompat.getDrawable(getContext(), R.mipmap.icon_tabbar_util)) .setSelectedDrawable(ContextCompat.getDrawable(getContext(), R.mipmap.icon_tabbar_util_selected)) - .setDynamicChangeIconColor(false) + .setText("Helper") .build(); - - QMUITabSegment.Tab lab = new QMUITabSegment.TabBuilder("Lab") + QMUITab lab = builder .setNormalDrawable(ContextCompat.getDrawable(getContext(), R.mipmap.icon_tabbar_lab)) .setSelectedDrawable(ContextCompat.getDrawable(getContext(), R.mipmap.icon_tabbar_lab_selected)) - .setDynamicChangeIconColor(false) + .setText("Lab") .build(); + mTabSegment.addTab(component) .addTab(util) .addTab(lab); diff --git a/qmuidemo/src/main/res/layout/fragment_fsw_viewpager.xml b/qmuidemo/src/main/res/layout/fragment_fsw_viewpager.xml index c5a0d8dd6..cee9d02e4 100644 --- a/qmuidemo/src/main/res/layout/fragment_fsw_viewpager.xml +++ b/qmuidemo/src/main/res/layout/fragment_fsw_viewpager.xml @@ -27,12 +27,16 @@ android:layout_height="match_parent" android:layout_marginBottom="@dimen/home_tab_height" android:fitsSystemWindows="true"/> - \ No newline at end of file diff --git a/qmuidemo/src/main/res/layout/fragment_home.xml b/qmuidemo/src/main/res/layout/fragment_home.xml index 0fbf21066..d3a31c783 100644 --- a/qmuidemo/src/main/res/layout/fragment_home.xml +++ b/qmuidemo/src/main/res/layout/fragment_home.xml @@ -16,21 +16,24 @@ --> + xmlns:app="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:clipChildren="false"> + - + + + app:qmui_tab_icon_position="top"/> \ No newline at end of file diff --git a/qmuidemo/src/main/res/layout/fragment_notch.xml b/qmuidemo/src/main/res/layout/fragment_notch.xml index ee16490a7..59fb9c3b6 100644 --- a/qmuidemo/src/main/res/layout/fragment_notch.xml +++ b/qmuidemo/src/main/res/layout/fragment_notch.xml @@ -52,7 +52,7 @@ android:layout_gravity="bottom" android:fitsSystemWindows="true"> - - 不同 item,不同文字(icon)颜色 根据 index 更新 tab 文案 根据 index 完全替换 tab + 放大选中态 + 修改 Gravity 点击开始 From 5ce4c4abfac3ba57f4cceca5c77c5b6babb16a16 Mon Sep 17 00:00:00 2001 From: cgspine Date: Thu, 21 Feb 2019 15:37:05 +0800 Subject: [PATCH 218/887] lazyViewLifecycleOwner for QMUIFragment.(androidx) #512 --- .../com/qmuiteam/qmui/arch/QMUIFragment.java | 73 +++++++++- .../arch/QMUIFragmentLazyLifecycleOwner.java | 131 +++++++++++++++++ .../qmui/arch/QMUIFragmentPagerAdapter.java | 127 +++++++++++++++++ .../qmui/widget/QMUIPagerAdapter.java | 16 ++- .../qmuiteam/qmui/widget/QMUIViewPager.java | 22 +-- .../QDCollapsingTopBarLayoutFragment.java | 12 ++ .../QDTabSegmentScrollableModeFragment.java | 10 ++ .../components/viewpager/CardTransformer.java | 3 +- .../QDFitSystemWindowViewPagerFragment.java | 134 ++++-------------- .../viewpager/QDLazyTestObserver.java | 63 ++++++++ .../viewpager/QDLoopViewPagerFragment.java | 16 ++- .../viewpager/QDViewPagerFragment.java | 9 ++ 12 files changed, 476 insertions(+), 140 deletions(-) create mode 100644 arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragmentLazyLifecycleOwner.java create mode 100644 arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragmentPagerAdapter.java create mode 100644 qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/viewpager/QDLazyTestObserver.java diff --git a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java index 82822c63b..dfebc7a01 100644 --- a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java +++ b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java @@ -18,15 +18,9 @@ import android.annotation.SuppressLint; import android.app.Activity; -import androidx.arch.core.util.Function; import android.content.Intent; import android.content.res.Resources; import android.os.Bundle; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentManager; -import androidx.core.view.ViewCompat; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -44,6 +38,14 @@ import java.util.ArrayList; import java.util.List; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.arch.core.util.Function; +import androidx.core.view.ViewCompat; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.lifecycle.LifecycleOwner; + import static com.qmuiteam.qmui.arch.SwipeBackLayout.EDGE_LEFT; /** @@ -52,7 +54,7 @@ *

* Created by cgspine on 15/9/14. */ -public abstract class QMUIFragment extends Fragment { +public abstract class QMUIFragment extends Fragment implements QMUIFragmentLazyLifecycleOwner.Callback { private static final String SWIPE_BACK_VIEW = "swipe_back_view"; private static final String TAG = QMUIFragment.class.getSimpleName(); @@ -93,6 +95,7 @@ public abstract class QMUIFragment extends Fragment { private int mEnterAnimationStatus = ANIMATION_ENTER_STATUS_NOT_START; private boolean mCalled = true; private ArrayList mDelayRenderRunnableList = new ArrayList<>(); + private QMUIFragmentLazyLifecycleOwner mLazyViewLifecycleOwner; public QMUIFragment() { super(); @@ -233,6 +236,14 @@ public void onCreate(@Nullable Bundle savedInstanceState) { } } + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + mLazyViewLifecycleOwner = new QMUIFragmentLazyLifecycleOwner(this); + mLazyViewLifecycleOwner.setViewVisible(getUserVisibleHint()); + getViewLifecycleOwner().getLifecycle().addObserver(mLazyViewLifecycleOwner); + } + @Override public void onStart() { super.onStart(); @@ -771,6 +782,54 @@ public void onDestroy() { } } + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); + notifyFragmentVisibleToUserChanged(isParentVisibleToUser() && isVisibleToUser); + } + + @Override + public boolean isVisibleToUser() { + return getUserVisibleHint() && isParentVisibleToUser(); + } + + /** + * @return true if parentFragments is visible to user + */ + private boolean isParentVisibleToUser() { + Fragment parentFragment = getParentFragment(); + while (parentFragment != null) { + if (!parentFragment.getUserVisibleHint()) { + return false; + } + parentFragment = parentFragment.getParentFragment(); + } + return true; + } + + private void notifyFragmentVisibleToUserChanged(boolean isVisibleToUser) { + if (mLazyViewLifecycleOwner != null) { + mLazyViewLifecycleOwner.setViewVisible(isVisibleToUser); + } + if (isAdded()) { + List childFragments = getChildFragmentManager().getFragments(); + for (Fragment fragment : childFragments) { + if (fragment instanceof QMUIFragment) { + ((QMUIFragment) fragment).notifyFragmentVisibleToUserChanged( + isVisibleToUser && fragment.getUserVisibleHint()); + } + } + } + } + + public LifecycleOwner getLazyViewLifecycleOwner() { + if (mLazyViewLifecycleOwner == null) { + throw new IllegalStateException("Can't access the QMUIFragment View's LifecycleOwner when " + + "getView() is null i.e., before onViewCreated() or after onDestroyView()"); + } + return mLazyViewLifecycleOwner; + } + /** * Immersive processing * diff --git a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragmentLazyLifecycleOwner.java b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragmentLazyLifecycleOwner.java new file mode 100644 index 000000000..bbc9d0191 --- /dev/null +++ b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragmentLazyLifecycleOwner.java @@ -0,0 +1,131 @@ +/* + * 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.qmuiteam.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 diff --git a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragmentPagerAdapter.java b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragmentPagerAdapter.java new file mode 100644 index 000000000..bde97c445 --- /dev/null +++ b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragmentPagerAdapter.java @@ -0,0 +1,127 @@ +/* + * 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.qmuiteam.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 QMUIFragment 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 diff --git a/qmui/src/main/java/com/qmuiteam/qmui/widget/QMUIPagerAdapter.java b/qmui/src/main/java/com/qmuiteam/qmui/widget/QMUIPagerAdapter.java index ed1efb921..06a1775d4 100644 --- a/qmui/src/main/java/com/qmuiteam/qmui/widget/QMUIPagerAdapter.java +++ b/qmui/src/main/java/com/qmuiteam/qmui/widget/QMUIPagerAdapter.java @@ -16,10 +16,12 @@ package com.qmuiteam.qmui.widget; -import androidx.viewpager.widget.PagerAdapter; import android.util.SparseArray; import android.view.ViewGroup; +import androidx.annotation.NonNull; +import androidx.viewpager.widget.PagerAdapter; + /** * @author cginechen * @date 2017-09-13 @@ -37,14 +39,16 @@ public QMUIPagerAdapter() { * that doesn't yet contain any domain data ("real" data), * and then populating it with domain data. */ - protected abstract Object hydrate(ViewGroup container, int position); + @NonNull + protected abstract Object hydrate(@NonNull ViewGroup container, int position); - protected abstract void populate(ViewGroup container, Object item, int position); + protected abstract void populate(@NonNull ViewGroup container, @NonNull Object item, int position); - protected abstract void destroy(ViewGroup container, int position, Object object); + protected abstract void destroy(@NonNull ViewGroup container, int position, @NonNull Object object); @Override - public final Object instantiateItem(ViewGroup container, int position) { + @NonNull + public final Object instantiateItem(@NonNull ViewGroup container, int position) { Object item = mScrapItems.get(position); if (item == null) { item = hydrate(container, position); @@ -56,7 +60,7 @@ public final Object instantiateItem(ViewGroup container, int position) { } @Override - public final void destroyItem(ViewGroup container, int position, Object object) { + public final void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { destroy(container, position, object); mScrapItems.put(position, object); } diff --git a/qmui/src/main/java/com/qmuiteam/qmui/widget/QMUIViewPager.java b/qmui/src/main/java/com/qmuiteam/qmui/widget/QMUIViewPager.java index 10188d65a..1df86d9bc 100644 --- a/qmui/src/main/java/com/qmuiteam/qmui/widget/QMUIViewPager.java +++ b/qmui/src/main/java/com/qmuiteam/qmui/widget/QMUIViewPager.java @@ -21,10 +21,6 @@ import android.graphics.Rect; import android.os.Build; import android.os.Parcelable; -import androidx.annotation.NonNull; -import androidx.viewpager.widget.PagerAdapter; -import androidx.core.view.ViewCompat; -import androidx.viewpager.widget.ViewPager; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; @@ -32,6 +28,11 @@ import com.qmuiteam.qmui.util.QMUIWindowInsetHelper; +import androidx.annotation.NonNull; +import androidx.core.view.ViewCompat; +import androidx.viewpager.widget.PagerAdapter; +import androidx.viewpager.widget.ViewPager; + /** * @author cginechen * @date 2017-09-13 @@ -161,7 +162,8 @@ public int getCount() { } @Override - public Object instantiateItem(ViewGroup container, int position) { + @NonNull + public Object instantiateItem(@NonNull ViewGroup container, int position) { int realPosition = position; if (mEnableLoop && mAdapter.getCount() != 0) { realPosition = position % mAdapter.getCount(); @@ -170,7 +172,7 @@ public Object instantiateItem(ViewGroup container, int position) { } @Override - public void destroyItem(ViewGroup container, int position, Object object) { + public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { int realPosition = position; if (mEnableLoop && mAdapter.getCount() != 0) { realPosition = position % mAdapter.getCount(); @@ -179,7 +181,7 @@ public void destroyItem(ViewGroup container, int position, Object object) { } @Override - public boolean isViewFromObject(View view, Object object) { + public boolean isViewFromObject(@NonNull View view, @NonNull Object object) { return mAdapter.isViewFromObject(view, object); } @@ -195,12 +197,12 @@ public Parcelable saveState() { } @Override - public void startUpdate(ViewGroup container) { + public void startUpdate(@NonNull ViewGroup container) { mAdapter.startUpdate(container); } @Override - public void finishUpdate(ViewGroup container) { + public void finishUpdate(@NonNull ViewGroup container) { mAdapter.finishUpdate(container); } @@ -237,7 +239,7 @@ public void notifyDataSetChanged() { } @Override - public int getItemPosition(Object object) { + public int getItemPosition(@NonNull Object object) { return mAdapter.getItemPosition(object); } } diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDCollapsingTopBarLayoutFragment.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDCollapsingTopBarLayoutFragment.java index 1484b0e1c..1108ffd52 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDCollapsingTopBarLayoutFragment.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDCollapsingTopBarLayoutFragment.java @@ -17,14 +17,19 @@ package com.qmuiteam.qmuidemo.fragment.components; import android.animation.ValueAnimator; + +import androidx.annotation.Nullable; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; + +import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import com.qmuiteam.qmui.widget.QMUICollapsingTopBarLayout; import com.qmuiteam.qmui.widget.QMUITopBar; +import com.qmuiteam.qmuidemo.fragment.components.viewpager.QDLazyTestObserver; import com.qmuiteam.qmuidemo.manager.QDDataManager; import com.qmuiteam.qmuidemo.R; import com.qmuiteam.qmuidemo.adaptor.QDRecyclerViewAdapter; @@ -72,6 +77,13 @@ public void onAnimationUpdate(ValueAnimator animation) { return rootView; } + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + getLazyViewLifecycleOwner().getLifecycle().addObserver( + new QDLazyTestObserver("QDCollapsingTopBar")); + } + @Override protected boolean translucentFull() { return true; diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDTabSegmentScrollableModeFragment.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDTabSegmentScrollableModeFragment.java index bc1528694..72de1cba6 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDTabSegmentScrollableModeFragment.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDTabSegmentScrollableModeFragment.java @@ -17,9 +17,12 @@ package com.qmuiteam.qmuidemo.fragment.components; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import androidx.viewpager.widget.PagerAdapter; import androidx.viewpager.widget.ViewPager; + +import android.os.Bundle; import android.util.TypedValue; import android.view.Gravity; import android.view.LayoutInflater; @@ -36,6 +39,7 @@ import com.qmuiteam.qmui.widget.QMUITopBarLayout; import com.qmuiteam.qmuidemo.R; import com.qmuiteam.qmuidemo.base.BaseFragment; +import com.qmuiteam.qmuidemo.fragment.components.viewpager.QDLazyTestObserver; import com.qmuiteam.qmuidemo.lib.Group; import com.qmuiteam.qmuidemo.lib.annotation.Widget; import com.qmuiteam.qmuidemo.manager.QDDataManager; @@ -118,6 +122,12 @@ protected View onCreateView() { return rootView; } + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + getLazyViewLifecycleOwner().getLifecycle().addObserver(new QDLazyTestObserver("QDTabSegment")); + } + private void initTopBar() { mTopBar.addLeftBackImageButton().setOnClickListener(new View.OnClickListener() { @Override diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/viewpager/CardTransformer.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/viewpager/CardTransformer.java index 67c93c785..30444a894 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/viewpager/CardTransformer.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/viewpager/CardTransformer.java @@ -16,9 +16,10 @@ package com.qmuiteam.qmuidemo.fragment.components.viewpager; -import androidx.viewpager.widget.ViewPager; import android.view.View; +import androidx.viewpager.widget.ViewPager; + /** * @author cginechen * @date 2017-09-13 diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/viewpager/QDFitSystemWindowViewPagerFragment.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/viewpager/QDFitSystemWindowViewPagerFragment.java index 324156c84..3b3348342 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/viewpager/QDFitSystemWindowViewPagerFragment.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/viewpager/QDFitSystemWindowViewPagerFragment.java @@ -16,24 +16,22 @@ package com.qmuiteam.qmuidemo.fragment.components.viewpager; -import android.annotation.SuppressLint; +import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; -import android.view.ViewGroup; import android.widget.FrameLayout; -import com.qmuiteam.qmui.widget.QMUIPagerAdapter; +import com.qmuiteam.qmui.arch.QMUIFragment; +import com.qmuiteam.qmui.arch.QMUIFragmentPagerAdapter; import com.qmuiteam.qmui.widget.QMUIViewPager; import com.qmuiteam.qmui.widget.tab.QMUITabSegment; import com.qmuiteam.qmuidemo.R; import com.qmuiteam.qmuidemo.base.BaseFragment; -import com.qmuiteam.qmuidemo.fragment.QDAboutFragment; import com.qmuiteam.qmuidemo.fragment.components.QDCollapsingTopBarLayoutFragment; import com.qmuiteam.qmuidemo.fragment.components.QDTabSegmentScrollableModeFragment; import com.qmuiteam.qmuidemo.lib.annotation.Widget; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentTransaction; +import androidx.annotation.Nullable; import butterknife.BindView; import butterknife.ButterKnife; @@ -57,14 +55,27 @@ protected View onCreateView() { return layout; } - private void initPagers() { - QMUIPagerAdapter pagerAdapter = new QMUIPagerAdapter() { - private FragmentTransaction mCurrentTransaction; - private Fragment mCurrentPrimaryItem = null; + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + getLazyViewLifecycleOwner().getLifecycle().addObserver(new QDLazyTestObserver("QDfSWViewPager")); + } + private void initPagers() { + QMUIFragmentPagerAdapter pagerAdapter = new QMUIFragmentPagerAdapter(getChildFragmentManager()) { @Override - public boolean isViewFromObject(View view, Object object) { - return view == ((Fragment) object).getView(); + public QMUIFragment createFragment(int position) { + switch (position) { + case 0: + return new QDTabSegmentScrollableModeFragment(); + case 1: + return new QDCollapsingTopBarLayoutFragment(); + case 2: + return new QDFitSystemWindowViewPagerFragment(); + case 3: + default: + return new QDViewPagerFragment(); + } } @Override @@ -78,109 +89,14 @@ public CharSequence getPageTitle(int position) { case 0: return "TabSegment"; case 1: - return "CollapsingTopBar"; + return "CTopBar"; case 2: - return "About"; + return "IViewPager"; case 3: default: return "ViewPager"; } } - - @SuppressLint("CommitTransaction") - @Override - protected Object hydrate(ViewGroup container, int position) { - String name = makeFragmentName(container.getId(), position); - if (mCurrentTransaction == null) { - mCurrentTransaction = getChildFragmentManager() - .beginTransaction(); - } - Fragment fragment = getChildFragmentManager().findFragmentByTag(name); - if (fragment != null) { - return fragment; - } - switch (position) { - case 0: - return new QDTabSegmentScrollableModeFragment(); - case 1: - return new QDCollapsingTopBarLayoutFragment(); - case 2: - return new QDAboutFragment(); - case 3: - default: - return new QDViewPagerFragment(); - } - } - - @SuppressLint("CommitTransaction") - @Override - protected void populate(ViewGroup container, Object item, int position) { - String name = makeFragmentName(container.getId(), position); - if (mCurrentTransaction == null) { - mCurrentTransaction = getChildFragmentManager() - .beginTransaction(); - } - Fragment fragment = getChildFragmentManager().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(ViewGroup container, int position, Object object) { - if (mCurrentTransaction == null) { - mCurrentTransaction = getChildFragmentManager() - .beginTransaction(); - } - mCurrentTransaction.detach((Fragment) object); - } - - @Override - public void startUpdate(ViewGroup container) { - if (container.getId() == View.NO_ID) { - throw new IllegalStateException("ViewPager with adapter " + this - + " requires a view id"); - } - } - - @Override - public void finishUpdate(ViewGroup container) { - if (mCurrentTransaction != null) { - mCurrentTransaction.commitNowAllowingStateLoss(); - mCurrentTransaction = null; - } - } - - @Override - public void setPrimaryItem(ViewGroup container, int position, Object object) { - Fragment fragment = (Fragment) object; - if (fragment != mCurrentPrimaryItem) { - if (mCurrentPrimaryItem != null) { - mCurrentPrimaryItem.setMenuVisibility(false); - mCurrentPrimaryItem.setUserVisibleHint(false); - } - if (fragment != null) { - fragment.setMenuVisibility(true); - fragment.setUserVisibleHint(true); - } - mCurrentPrimaryItem = fragment; - } - } - - private String makeFragmentName(int viewId, long id) { - return "QDFitSystemWindowViewPagerFragment:" + viewId + ":" + id; - } }; mViewPager.setAdapter(pagerAdapter); mTabSegment.setupWithViewPager(mViewPager); diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/viewpager/QDLazyTestObserver.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/viewpager/QDLazyTestObserver.java new file mode 100644 index 000000000..7f5e194d7 --- /dev/null +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/viewpager/QDLazyTestObserver.java @@ -0,0 +1,63 @@ +/* + * 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.qmuiteam.qmuidemo.fragment.components.viewpager; + +import android.util.Log; + +import androidx.lifecycle.Lifecycle; +import androidx.lifecycle.LifecycleObserver; +import androidx.lifecycle.LifecycleOwner; +import androidx.lifecycle.OnLifecycleEvent; + +public class QDLazyTestObserver implements LifecycleObserver { + private static final String TAG = "QDLazyTestObserver"; + private final String mPrefix; + + public QDLazyTestObserver(String prefix) { + mPrefix = prefix; + } + + @OnLifecycleEvent(Lifecycle.Event.ON_CREATE) + void onCreate(LifecycleOwner owner) { + Log.i(TAG, mPrefix + ": onCreate"); + } + + @OnLifecycleEvent(Lifecycle.Event.ON_START) + void onStart(LifecycleOwner owner) { + Log.i(TAG, mPrefix + ": onStart"); + } + + @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) + void onResume(LifecycleOwner owner) { + Log.i(TAG, mPrefix + ": onResume"); + } + + @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) + void onPause(LifecycleOwner owner) { + Log.i(TAG, mPrefix + ": onPause"); + } + + @OnLifecycleEvent(Lifecycle.Event.ON_STOP) + void onStop(LifecycleOwner owner) { + Log.i(TAG, mPrefix + ": onStop"); + } + + @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) + void onDestroy(LifecycleOwner owner) { + Log.i(TAG, mPrefix + ": onDestroy"); + } +} diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/viewpager/QDLoopViewPagerFragment.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/viewpager/QDLoopViewPagerFragment.java index 1860bbb58..b62b98816 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/viewpager/QDLoopViewPagerFragment.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/viewpager/QDLoopViewPagerFragment.java @@ -18,8 +18,6 @@ import android.content.Context; import android.os.Build; -import androidx.core.content.ContextCompat; -import androidx.core.view.ViewCompat; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; @@ -31,14 +29,17 @@ import com.qmuiteam.qmui.widget.QMUIPagerAdapter; import com.qmuiteam.qmui.widget.QMUITopBar; import com.qmuiteam.qmui.widget.QMUIViewPager; -import com.qmuiteam.qmuidemo.manager.QDDataManager; import com.qmuiteam.qmuidemo.R; import com.qmuiteam.qmuidemo.base.BaseFragment; import com.qmuiteam.qmuidemo.lib.annotation.Widget; +import com.qmuiteam.qmuidemo.manager.QDDataManager; import java.util.ArrayList; import java.util.List; +import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; +import androidx.core.view.ViewCompat; import butterknife.BindView; import butterknife.ButterKnife; @@ -86,7 +87,7 @@ private void initPagers() { QMUIPagerAdapter pagerAdapter = new QMUIPagerAdapter() { @Override - public boolean isViewFromObject(View view, Object object) { + public boolean isViewFromObject(@NonNull View view, @NonNull Object object) { return view == object; } @@ -101,19 +102,20 @@ public CharSequence getPageTitle(int position) { } @Override - protected Object hydrate(ViewGroup container, int position) { + @NonNull + protected Object hydrate(@NonNull ViewGroup container, int position) { return new ItemView(getContext()); } @Override - protected void populate(ViewGroup container, Object item, int position) { + protected void populate(@NonNull ViewGroup container, @NonNull Object item, int position) { ItemView itemView = (ItemView) item; itemView.setText(mItems.get(position)); container.addView(itemView); } @Override - protected void destroy(ViewGroup container, int position, Object object) { + protected void destroy(@NonNull ViewGroup container, int position, @NonNull Object object) { container.removeView((View) object); } }; diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/viewpager/QDViewPagerFragment.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/viewpager/QDViewPagerFragment.java index ac8ac1dd3..3c835a36c 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/viewpager/QDViewPagerFragment.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/viewpager/QDViewPagerFragment.java @@ -16,6 +16,7 @@ package com.qmuiteam.qmuidemo.fragment.components.viewpager; +import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; @@ -28,6 +29,8 @@ import com.qmuiteam.qmuidemo.manager.QDDataManager; import com.qmuiteam.qmuidemo.model.QDItemDescription; +import androidx.annotation.Nullable; +import androidx.lifecycle.LifecycleObserver; import butterknife.BindView; import butterknife.ButterKnife; @@ -60,6 +63,12 @@ protected View onCreateView() { return root; } + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + getLazyViewLifecycleOwner().getLifecycle().addObserver(new QDLazyTestObserver("QDViewPager")); + } + private void initTopBar() { mTopBar.addLeftBackImageButton().setOnClickListener(new View.OnClickListener() { @Override From 2a035a13a80322103e5af1e457ecb8d999b1c010 Mon Sep 17 00:00:00 2001 From: cgspine Date: Thu, 21 Feb 2019 16:03:11 +0800 Subject: [PATCH 219/887] prevent drag back in QMUIFragment if it in ViewPager. #513 --- .../com/qmuiteam/qmui/arch/QMUIFragment.java | 21 +++++ qmuidemo/src/main/AndroidManifest.xml | 9 +- .../activity/TestArchInViewPagerActivity.java | 92 +++++++++++++++++++ .../QDFitSystemWindowViewPagerFragment.java | 1 - .../fragment/lab/QDArchTestFragment.java | 9 +- 5 files changed, 128 insertions(+), 4 deletions(-) create mode 100644 qmuidemo/src/main/java/com/qmuiteam/qmuidemo/activity/TestArchInViewPagerActivity.java diff --git a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java index dfebc7a01..7d4cbfc87 100644 --- a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java +++ b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java @@ -25,6 +25,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.ViewParent; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.view.animation.AnimationUtils; @@ -45,6 +46,7 @@ import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.lifecycle.LifecycleOwner; +import androidx.viewpager.widget.ViewPager; import static com.qmuiteam.qmui.arch.SwipeBackLayout.EDGE_LEFT; @@ -290,6 +292,25 @@ public boolean canSwipeBack() { if (!canDragBack()) { return false; } + + if (getParentFragment() != null) { + return false; + } + + View view = getView(); + if (view == null) { + return false; + } + + // if the Fragment is in ViewPager, then stop drag back + ViewParent parent = view.getParent(); + while (parent != null) { + if (parent instanceof ViewPager) { + return false; + } + parent = parent.getParent(); + } + FragmentManager fragmentManager = getFragmentManager(); if (fragmentManager == null || fragmentManager.getBackStackEntryCount() <= 1) { return QMUISwipeBackActivityManager.getInstance().canSwipeBack(); diff --git a/qmuidemo/src/main/AndroidManifest.xml b/qmuidemo/src/main/AndroidManifest.xml index 6afbbeb5e..6ec53ae24 100644 --- a/qmuidemo/src/main/AndroidManifest.xml +++ b/qmuidemo/src/main/AndroidManifest.xml @@ -12,8 +12,8 @@ android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" - android:theme="@style/AppTheme" android:networkSecurityConfig="@xml/network_security_config" + android:theme="@style/AppTheme" tools:ignore="AllowBackup,GoogleAppIndexingWarning" tools:targetApi="n"> @@ -57,6 +57,13 @@ android:windowSoftInputMode="stateAlwaysHidden|adjustResize"> + + + diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/activity/TestArchInViewPagerActivity.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/activity/TestArchInViewPagerActivity.java new file mode 100644 index 000000000..02469ca3a --- /dev/null +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/activity/TestArchInViewPagerActivity.java @@ -0,0 +1,92 @@ +/* + * 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.qmuiteam.qmuidemo.activity; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; + +import com.qmuiteam.qmui.arch.QMUIFragment; +import com.qmuiteam.qmui.arch.QMUIFragmentPagerAdapter; +import com.qmuiteam.qmui.widget.QMUIViewPager; +import com.qmuiteam.qmui.widget.tab.QMUITabSegment; +import com.qmuiteam.qmuidemo.R; +import com.qmuiteam.qmuidemo.base.BaseActivity; +import com.qmuiteam.qmuidemo.fragment.components.QDCollapsingTopBarLayoutFragment; +import com.qmuiteam.qmuidemo.fragment.components.QDTabSegmentScrollableModeFragment; +import com.qmuiteam.qmuidemo.fragment.components.viewpager.QDFitSystemWindowViewPagerFragment; +import com.qmuiteam.qmuidemo.fragment.components.viewpager.QDViewPagerFragment; + +import androidx.annotation.Nullable; +import butterknife.BindView; +import butterknife.ButterKnife; + +public class TestArchInViewPagerActivity extends BaseActivity { + + @BindView(R.id.pager) QMUIViewPager mViewPager; + @BindView(R.id.tabs) QMUITabSegment mTabSegment; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + View root = LayoutInflater.from(this).inflate(R.layout.fragment_fsw_viewpager, null); + ButterKnife.bind(this, root); + setContentView(root); + initPagers(); + } + + private void initPagers() { + QMUIFragmentPagerAdapter pagerAdapter = new QMUIFragmentPagerAdapter(getSupportFragmentManager()) { + @Override + public QMUIFragment createFragment(int position) { + switch (position) { + case 0: + return new QDTabSegmentScrollableModeFragment(); + case 1: + return new QDCollapsingTopBarLayoutFragment(); + case 2: + return new QDFitSystemWindowViewPagerFragment(); + case 3: + default: + return new QDViewPagerFragment(); + } + } + + @Override + public int getCount() { + return 4; + } + + @Override + public CharSequence getPageTitle(int position) { + switch (position) { + case 0: + return "TabSegment"; + case 1: + return "CTopBar"; + case 2: + return "IViewPager"; + case 3: + default: + return "ViewPager"; + } + } + }; + mViewPager.setAdapter(pagerAdapter); + mTabSegment.setupWithViewPager(mViewPager); + } +} diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/viewpager/QDFitSystemWindowViewPagerFragment.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/viewpager/QDFitSystemWindowViewPagerFragment.java index 3b3348342..73369fc08 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/viewpager/QDFitSystemWindowViewPagerFragment.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/viewpager/QDFitSystemWindowViewPagerFragment.java @@ -46,7 +46,6 @@ public class QDFitSystemWindowViewPagerFragment extends BaseFragment { @BindView(R.id.pager) QMUIViewPager mViewPager; @BindView(R.id.tabs) QMUITabSegment mTabSegment; - @Override protected View onCreateView() { FrameLayout layout = (FrameLayout) LayoutInflater.from(getActivity()).inflate(R.layout.fragment_fsw_viewpager, null); diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/lab/QDArchTestFragment.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/lab/QDArchTestFragment.java index 7feb01b2a..32a2b1234 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/lab/QDArchTestFragment.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/lab/QDArchTestFragment.java @@ -19,7 +19,6 @@ import android.content.Context; import android.content.Intent; import android.os.Bundle; -import androidx.annotation.Nullable; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -35,9 +34,11 @@ import com.qmuiteam.qmuidemo.QDMainActivity; import com.qmuiteam.qmuidemo.R; import com.qmuiteam.qmuidemo.activity.ArchTestActivity; +import com.qmuiteam.qmuidemo.activity.TestArchInViewPagerActivity; import com.qmuiteam.qmuidemo.base.BaseFragment; import com.qmuiteam.qmuidemo.lib.annotation.Widget; +import androidx.annotation.Nullable; import butterknife.BindView; import butterknife.ButterKnife; @@ -140,10 +141,11 @@ public static void showBottomSheetList(final Context context) { .addItem("Directly Activity") .addItem("Directly Activity And Keep Bottom Sheet shown") .addItem("Show a Dialog") + .addItem("QMUIFragment in QMUIActivity") .setOnSheetItemClickListener(new QMUIBottomSheet.BottomListSheetBuilder.OnSheetItemClickListener() { @Override public void onClick(QMUIBottomSheet dialog, View itemView, int position, String tag) { - if(position != 4){ + if (position != 4) { dialog.dismiss(); } @@ -182,6 +184,9 @@ public void onClick(QMUIDialog dialog, int index) { } }) .show(); + } else if (position == 6) { + Intent intent = new Intent(context, TestArchInViewPagerActivity.class); + context.startActivity(intent); } } }) From 8630d3c3da11c489a7104b9f208258b1fb0f77c0 Mon Sep 17 00:00:00 2001 From: chanthuang Date: Thu, 21 Feb 2019 19:27:10 +0800 Subject: [PATCH 220/887] feature: use onClickListener when adding QMUICommonListItemView with ACCESSORY_TYPE_SWITCH to QMUIGroupListItemView. #514 --- .../qmui/widget/grouplist/QMUICommonListItemView.java | 10 +++------- .../qmui/widget/grouplist/QMUIGroupListView.java | 10 +--------- .../fragment/components/QDGroupListViewFragment.java | 3 +++ 3 files changed, 7 insertions(+), 16 deletions(-) diff --git a/qmui/src/main/java/com/qmuiteam/qmui/widget/grouplist/QMUICommonListItemView.java b/qmui/src/main/java/com/qmuiteam/qmui/widget/grouplist/QMUICommonListItemView.java index a811cb129..90048035a 100644 --- a/qmui/src/main/java/com/qmuiteam/qmui/widget/grouplist/QMUICommonListItemView.java +++ b/qmui/src/main/java/com/qmuiteam/qmui/widget/grouplist/QMUICommonListItemView.java @@ -19,9 +19,6 @@ import android.content.Context; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; -import androidx.annotation.IntDef; -import androidx.legacy.widget.Space; - import android.util.AttributeSet; import android.util.TypedValue; import android.view.Gravity; @@ -30,7 +27,6 @@ import android.view.ViewGroup; import android.view.ViewStub; import android.widget.CheckBox; -import android.widget.CompoundButton; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; @@ -45,6 +41,9 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import androidx.annotation.IntDef; +import androidx.legacy.widget.Space; + /** * 作为通用列表 {@link QMUIGroupListView} 里的 item 使用,也可以单独使用。 * 支持以下样式: @@ -301,9 +300,6 @@ public int getAccessoryType() { /** * 设置右侧 View 的类型。 - *

- * 注意如果 type 为 {@link #ACCESSORY_TYPE_SWITCH}, 那么 switch 的切换事件应该 {@link #getSwitch()} 后用 {@link CheckBox#setOnCheckedChangeListener(CompoundButton.OnCheckedChangeListener)} 来监听 - *

* * @param type 见 {@link QMUICommonListItemAccessoryType} */ diff --git a/qmui/src/main/java/com/qmuiteam/qmui/widget/grouplist/QMUIGroupListView.java b/qmui/src/main/java/com/qmuiteam/qmui/widget/grouplist/QMUIGroupListView.java index f9a1de8c0..a39bfa829 100644 --- a/qmui/src/main/java/com/qmuiteam/qmui/widget/grouplist/QMUIGroupListView.java +++ b/qmui/src/main/java/com/qmuiteam/qmui/widget/grouplist/QMUIGroupListView.java @@ -258,15 +258,7 @@ public Section addItemView(QMUICommonListItemView itemView, OnClickListener onCl * @return Section 本身, 支持链式调用 */ public Section addItemView(final QMUICommonListItemView itemView, OnClickListener onClickListener, OnLongClickListener onLongClickListener) { - // 如果本身带有开关控件,点击item时要改变开关控件的状态(开关控件本身已经disable掉) - if (itemView.getAccessoryType() == QMUICommonListItemView.ACCESSORY_TYPE_SWITCH) { - itemView.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - itemView.getSwitch().toggle(); - } - }); - } else if (onClickListener != null) { + if (onClickListener != null) { itemView.setOnClickListener(onClickListener); } diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDGroupListViewFragment.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDGroupListViewFragment.java index a2e186729..288e39c6b 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDGroupListViewFragment.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDGroupListViewFragment.java @@ -120,6 +120,9 @@ public void onClick(View v) { if (v instanceof QMUICommonListItemView) { CharSequence text = ((QMUICommonListItemView) v).getText(); Toast.makeText(getActivity(), text + " is Clicked", Toast.LENGTH_SHORT).show(); + if (((QMUICommonListItemView) v).getAccessoryType() == QMUICommonListItemView.ACCESSORY_TYPE_SWITCH) { + ((QMUICommonListItemView) v).getSwitch().toggle(); + } } } }; From a5fea5b87eb0e39e99b16848b6fff517162409de Mon Sep 17 00:00:00 2001 From: cgspine Date: Fri, 22 Feb 2019 14:34:31 +0800 Subject: [PATCH 221/887] feature: add some hook api such as onKeyUp, onDragStart --- .../com/qmuiteam/qmui/arch/QMUIActivity.java | 14 ++++++++-- .../com/qmuiteam/qmui/arch/QMUIFragment.java | 21 ++++++++++++++ .../qmui/arch/QMUIFragmentActivity.java | 28 ++++++++++++++++--- 3 files changed, 57 insertions(+), 6 deletions(-) diff --git a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIActivity.java b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIActivity.java index a868f4489..093efe690 100644 --- a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIActivity.java +++ b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIActivity.java @@ -18,7 +18,6 @@ import android.app.Activity; import android.os.Bundle; -import androidx.annotation.Nullable; import android.util.Log; import android.view.View; import android.view.ViewGroup; @@ -26,6 +25,8 @@ import com.qmuiteam.qmui.util.QMUIStatusBarHelper; +import androidx.annotation.Nullable; + import static com.qmuiteam.qmui.arch.SwipeBackLayout.EDGE_LEFT; public class QMUIActivity extends InnerBaseActivity { @@ -68,6 +69,7 @@ public void onScroll(int edgeFlag, float scrollPercent) { @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() @@ -185,6 +187,13 @@ protected int backViewInitOffset() { return 0; } + /** + * called when drag back started. + */ + protected void onDragStart() { + + } + protected int dragBackEdge() { return EDGE_LEFT; @@ -201,9 +210,10 @@ protected boolean translucentFull() { /** * restore sub window(e.g dialog) when drag back to previous activity + * * @return */ - protected boolean restoreSubWindowWhenDragBack(){ + protected boolean restoreSubWindowWhenDragBack() { return true; } } diff --git a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java index 7d4cbfc87..b1e40f6aa 100644 --- a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java +++ b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragment.java @@ -22,6 +22,7 @@ import android.content.res.Resources; import android.os.Bundle; import android.util.Log; +import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -420,6 +421,7 @@ public void onEdgeTouch(int edgeFlag) { return; } QMUIKeyboardHelper.hideKeyboard(mBaseView); + onDragStart(); int backStackCount = fragmentManager.getBackStackEntryCount(); if (backStackCount > 1) { try { @@ -642,6 +644,10 @@ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, return swipeBackLayout; } + protected void onBackPressed() { + popBackStack(); + } + protected void popBackStack() { if (mEnterAnimationStatus != ANIMATION_ENTER_STATUS_END) { return; @@ -649,6 +655,14 @@ protected void popBackStack() { getBaseFragmentActivity().popBackStack(); } + public boolean onKeyDown(int keyCode, KeyEvent event) { + return false; + } + + public boolean onKeyUp(int keyCode, KeyEvent event) { + return false; + } + @Override public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) { if (!enter && getParentFragment() != null && getParentFragment().isRemoving()) { @@ -739,6 +753,13 @@ protected int backViewInitOffset() { return 0; } + /** + * called when drag back started. + */ + protected void onDragStart() { + + } + protected int dragBackEdge() { return EDGE_LEFT; } diff --git a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragmentActivity.java b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragmentActivity.java index 2714fbfc2..90e4a7df8 100644 --- a/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragmentActivity.java +++ b/arch/src/main/java/com/qmuiteam/qmui/arch/QMUIFragmentActivity.java @@ -18,10 +18,8 @@ import android.content.Intent; import android.os.Bundle; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentManager; -import androidx.fragment.app.FragmentTransaction; import android.util.Log; +import android.view.KeyEvent; import android.widget.FrameLayout; import com.qmuiteam.qmui.util.QMUIStatusBarHelper; @@ -29,6 +27,10 @@ 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. @@ -57,8 +59,26 @@ public FrameLayout getFragmentContainer() { public void onBackPressed() { QMUIFragment fragment = getCurrentFragment(); if (fragment != null && !fragment.isInSwipeBack()) { - fragment.popBackStack(); + 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); } /** From 1f5f3289d4229b33bf0dba3168015e82b20d4818 Mon Sep 17 00:00:00 2001 From: cgspine Date: Mon, 25 Feb 2019 13:52:55 +0800 Subject: [PATCH 222/887] no android prefix items for compat theme --- qmui/src/main/res/values/qmui_themes.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/qmui/src/main/res/values/qmui_themes.xml b/qmui/src/main/res/values/qmui_themes.xml index 04cb37552..40c864b6c 100644 --- a/qmui/src/main/res/values/qmui_themes.xml +++ b/qmui/src/main/res/values/qmui_themes.xml @@ -54,6 +54,12 @@ @style/AutoCompleteTextView.Compat @style/DropDownListView.Compat @style/TextView.Compat + + @style/ImageButton.Compat + @style/Button.Compat + @style/EditText.Compat + @style/AutoCompleteTextView.Compat + @style/DropDownListView.Compat From 0a52717885e2644c38dfd511a46405494cd642f6 Mon Sep 17 00:00:00 2001 From: chanthuang Date: Mon, 25 Feb 2019 16:03:10 +0800 Subject: [PATCH 223/887] =?UTF-8?q?feature:=20=E6=B7=BB=E5=8A=A0=20setChan?= =?UTF-8?q?geAlphaWhenPressed(boolean=20changeAlphaWhenPress)=20=E7=9A=84?= =?UTF-8?q?=E5=B1=95=E7=A4=BA=EF=BC=9B=E4=BD=BF=E7=94=A8=20@style/QDRadius?= =?UTF-8?q?Button=20=E7=9A=84=20Button=20=E6=94=B9=E7=94=A8=20QMUIRoundBut?= =?UTF-8?q?ton?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fragment/components/QDButtonFragment.java | 6 +++ .../fragment/components/QDPopupFragment.java | 15 +++---- .../components/QDProgressBarFragment.java | 6 +-- .../util/QDDrawableHelperFragment.java | 8 ++-- .../src/main/res/color/s_app_color_blue_2.xml | 1 + .../s_app_color_blue_3.xml} | 21 +++------- .../s_app_color_blue_to_red.xml} | 7 ++-- .../common_bg_with_radius_and_border.xml | 33 --------------- .../res/drawable/radius_button_bg_pressed.xml | 33 --------------- .../src/main/res/layout/fragment_button.xml | 41 +++++++++++++++---- .../res/layout/fragment_drawablehelper.xml | 4 +- .../src/main/res/layout/fragment_popup.xml | 12 +++--- .../main/res/layout/fragment_progressbar.xml | 16 ++++---- qmuidemo/src/main/res/values/colors.xml | 4 ++ qmuidemo/src/main/res/values/styles.xml | 5 ++- 15 files changed, 87 insertions(+), 125 deletions(-) rename qmuidemo/src/main/res/{drawable/radius_button_bg.xml => color/s_app_color_blue_3.xml} (62%) rename qmuidemo/src/main/res/{drawable/s_radius_button_bg.xml => color/s_app_color_blue_to_red.xml} (77%) delete mode 100644 qmuidemo/src/main/res/drawable/common_bg_with_radius_and_border.xml delete mode 100644 qmuidemo/src/main/res/drawable/radius_button_bg_pressed.xml diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDButtonFragment.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDButtonFragment.java index 8d02e59b0..d67e5f61c 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDButtonFragment.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDButtonFragment.java @@ -21,6 +21,7 @@ import com.qmuiteam.qmui.widget.QMUITopBar; import com.qmuiteam.qmui.widget.QMUITopBarLayout; +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton; import com.qmuiteam.qmuidemo.manager.QDDataManager; import com.qmuiteam.qmuidemo.R; import com.qmuiteam.qmuidemo.base.BaseFragment; @@ -36,6 +37,9 @@ public class QDButtonFragment extends BaseFragment { @BindView(R.id.topbar) QMUITopBarLayout mTopBar; + @BindView(R.id.alpha_button) + QMUIRoundButton alphaButton; + private QDItemDescription mQDItemDescription; @Override @@ -44,6 +48,8 @@ protected View onCreateView() { ButterKnife.bind(this, view); mQDItemDescription = QDDataManager.getInstance().getDescription(this.getClass()); + alphaButton.setChangeAlphaWhenPress(true); + initTopBar(); return view; diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDPopupFragment.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDPopupFragment.java index 2d3013a71..3ae115797 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDPopupFragment.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDPopupFragment.java @@ -26,6 +26,7 @@ import android.widget.TextView; import android.widget.Toast; +import com.qmuiteam.qmui.alpha.QMUIAlphaButton; import com.qmuiteam.qmui.util.QMUIDisplayHelper; import com.qmuiteam.qmui.widget.QMUITopBarLayout; import com.qmuiteam.qmui.widget.popup.QMUIListPopup; @@ -55,25 +56,25 @@ public class QDPopupFragment extends BaseFragment { @BindView(R.id.topbar) QMUITopBarLayout mTopBar; - @BindView(R.id.actiontBtn1) - Button mActionButton1; - @BindView(R.id.actiontBtn2) - Button mActionButton2; + @BindView(R.id.actionBtn1) + QMUIAlphaButton mActionButton1; + @BindView(R.id.actionBtn2) + QMUIAlphaButton mActionButton2; private QMUIPopup mNormalPopup; private QMUIListPopup mListPopup; - @OnClick({R.id.actiontBtn1, R.id.actiontBtn2}) + @OnClick({R.id.actionBtn1, R.id.actionBtn2}) void onClick(View v) { switch (v.getId()) { - case R.id.actiontBtn1: + case R.id.actionBtn1: initNormalPopupIfNeed(); mNormalPopup.setAnimStyle(QMUIPopup.ANIM_GROW_FROM_CENTER); mNormalPopup.setPreferredDirection(QMUIPopup.DIRECTION_TOP); mNormalPopup.show(v); mActionButton1.setText(getContext().getResources().getString(R.string.popup_normal_action_button_text_hide)); break; - case R.id.actiontBtn2: + case R.id.actionBtn2: initListPopupIfNeed(); mListPopup.setAnimStyle(QMUIPopup.ANIM_GROW_FROM_CENTER); mListPopup.setPreferredDirection(QMUIPopup.DIRECTION_TOP); diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDProgressBarFragment.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDProgressBarFragment.java index 4175f40e8..ca1adb79c 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDProgressBarFragment.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/components/QDProgressBarFragment.java @@ -20,10 +20,10 @@ import android.os.Message; import android.view.LayoutInflater; import android.view.View; -import android.widget.Button; import com.qmuiteam.qmui.widget.QMUIProgressBar; import com.qmuiteam.qmui.widget.QMUITopBarLayout; +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton; import com.qmuiteam.qmuidemo.R; import com.qmuiteam.qmuidemo.base.BaseFragment; import com.qmuiteam.qmuidemo.lib.annotation.Widget; @@ -51,9 +51,9 @@ public class QDProgressBarFragment extends BaseFragment { @BindView(R.id.circleProgressBar) QMUIProgressBar mCircleProgressBar; @BindView(R.id.startBtn) - Button mStartBtn; + QMUIRoundButton mStartBtn; @BindView(R.id.backBtn) - Button mBackBtn; + QMUIRoundButton mBackBtn; int count; private QDItemDescription mQDItemDescription; diff --git a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/util/QDDrawableHelperFragment.java b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/util/QDDrawableHelperFragment.java index 09c666e94..1f3e5ef27 100644 --- a/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/util/QDDrawableHelperFragment.java +++ b/qmuidemo/src/main/java/com/qmuiteam/qmuidemo/fragment/util/QDDrawableHelperFragment.java @@ -20,10 +20,8 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.LayerDrawable; -import androidx.core.content.ContextCompat; import android.view.LayoutInflater; import android.view.View; -import android.widget.Button; import android.widget.ImageView; import com.qmuiteam.qmui.util.QMUIDisplayHelper; @@ -31,13 +29,15 @@ import com.qmuiteam.qmui.util.QMUIViewHelper; import com.qmuiteam.qmui.widget.QMUITopBar; import com.qmuiteam.qmui.widget.dialog.QMUIDialog; -import com.qmuiteam.qmuidemo.manager.QDDataManager; +import com.qmuiteam.qmui.widget.roundwidget.QMUIRoundButton; import com.qmuiteam.qmuidemo.R; import com.qmuiteam.qmuidemo.base.BaseFragment; import com.qmuiteam.qmuidemo.lib.Group; import com.qmuiteam.qmuidemo.lib.annotation.Widget; +import com.qmuiteam.qmuidemo.manager.QDDataManager; import com.qmuiteam.qmuidemo.model.QDItemDescription; +import androidx.core.content.ContextCompat; import butterknife.BindView; import butterknife.ButterKnife; @@ -50,7 +50,7 @@ public class QDDrawableHelperFragment extends BaseFragment { @BindView(R.id.topbar) QMUITopBar mTopBar; - @BindView(R.id.createFromView) Button mCreateFromViewButton; + @BindView(R.id.createFromView) QMUIRoundButton mCreateFromViewButton; @BindView(R.id.solidImage) ImageView mSolidImageView; @BindView(R.id.circleGradient) ImageView mCircleGradientView; @BindView(R.id.tintColor) ImageView mTintColorImageView; diff --git a/qmuidemo/src/main/res/color/s_app_color_blue_2.xml b/qmuidemo/src/main/res/color/s_app_color_blue_2.xml index 045c7096b..cdcf7da46 100644 --- a/qmuidemo/src/main/res/color/s_app_color_blue_2.xml +++ b/qmuidemo/src/main/res/color/s_app_color_blue_2.xml @@ -16,6 +16,7 @@ --> + \ No newline at end of file diff --git a/qmuidemo/src/main/res/drawable/radius_button_bg.xml b/qmuidemo/src/main/res/color/s_app_color_blue_3.xml similarity index 62% rename from qmuidemo/src/main/res/drawable/radius_button_bg.xml rename to qmuidemo/src/main/res/color/s_app_color_blue_3.xml index 872a13074..cb4ed3fda 100644 --- a/qmuidemo/src/main/res/drawable/radius_button_bg.xml +++ b/qmuidemo/src/main/res/color/s_app_color_blue_3.xml @@ -15,19 +15,8 @@ limitations under the License. --> - - - - - - - - - - - - - \ No newline at end of file + + + + + \ No newline at end of file diff --git a/qmuidemo/src/main/res/drawable/s_radius_button_bg.xml b/qmuidemo/src/main/res/color/s_app_color_blue_to_red.xml similarity index 77% rename from qmuidemo/src/main/res/drawable/s_radius_button_bg.xml rename to qmuidemo/src/main/res/color/s_app_color_blue_to_red.xml index 4007e5f82..e2d4dcd46 100644 --- a/qmuidemo/src/main/res/drawable/s_radius_button_bg.xml +++ b/qmuidemo/src/main/res/color/s_app_color_blue_to_red.xml @@ -16,6 +16,7 @@ --> - - - + + + + \ No newline at end of file diff --git a/qmuidemo/src/main/res/drawable/common_bg_with_radius_and_border.xml b/qmuidemo/src/main/res/drawable/common_bg_with_radius_and_border.xml deleted file mode 100644 index bfbecaa81..000000000 --- a/qmuidemo/src/main/res/drawable/common_bg_with_radius_and_border.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/qmuidemo/src/main/res/drawable/radius_button_bg_pressed.xml b/qmuidemo/src/main/res/drawable/radius_button_bg_pressed.xml deleted file mode 100644 index 5661fb8ea..000000000 --- a/qmuidemo/src/main/res/drawable/radius_button_bg_pressed.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/qmuidemo/src/main/res/layout/fragment_button.xml b/qmuidemo/src/main/res/layout/fragment_button.xml index 10b63c1a5..d847d5f19 100644 --- a/qmuidemo/src/main/res/layout/fragment_button.xml +++ b/qmuidemo/src/main/res/layout/fragment_button.xml @@ -38,7 +38,6 @@ @@ -108,22 +107,46 @@ - + + + + android:text="更改文字颜色、边框颜色和背景颜色" + android:textColor="@color/s_app_color_blue_to_red" + app:qmui_backgroundColor="@color/s_app_color_blue_3" + app:qmui_borderColor="@color/s_app_color_blue_to_red" + app:qmui_borderWidth="1px" /> + - + + + + + diff --git a/qmuidemo/src/main/res/layout/fragment_drawablehelper.xml b/qmuidemo/src/main/res/layout/fragment_drawablehelper.xml index 8d89bd43b..b58166858 100644 --- a/qmuidemo/src/main/res/layout/fragment_drawablehelper.xml +++ b/qmuidemo/src/main/res/layout/fragment_drawablehelper.xml @@ -112,9 +112,9 @@ style="@style/QDCommonTitle" android:text="@string/drawableHelper_create_from_view_title"/> -