From 643f8e3c7f4a7a1f7a6bea225b61274367ca6a75 Mon Sep 17 00:00:00 2001 From: xuexiangjys Date: Thu, 31 Oct 2019 09:15:06 +0800 Subject: [PATCH 01/27] =?UTF-8?q?=E5=88=87=E5=88=86=E5=87=BA1.1.1=E7=89=88?= =?UTF-8?q?=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 4 ++-- app/src/main/AndroidManifest.xml | 18 +++++++++--------- .../base/webview/MiddlewareWebViewClient.java | 16 +++------------- ...Dialog.java => WebViewInterceptDialog.java} | 16 ++++++++++------ app/src/main/res/values/strings.xml | 1 + .../xui/widget/flowlayout/BaseTagAdapter.java | 1 - .../xui/widget/flowlayout/FlowTagLayout.java | 2 +- .../xui/widget/tabbar/MultiTabControlView.java | 13 +++++++++++++ .../xui/widget/tabbar/TabControlView.java | 14 ++++++++++++++ xui_lib/src/main/res/values/xui_attrs.xml | 6 +++++- 10 files changed, 58 insertions(+), 33 deletions(-) rename app/src/main/java/com/xuexiang/xuidemo/base/webview/{WebViewTipDialog.java => WebViewInterceptDialog.java} (88%) diff --git a/app/build.gradle b/app/build.gradle index d8d026b2..3662082f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -101,8 +101,8 @@ dependencies { implementation 'com.github.bumptech.glide:glide:4.8.0' //XUI框架 -// implementation project(':xui_lib') - implementation 'com.github.xuexiangjys:XUI:1.1.0' + implementation project(':xui_lib') +// implementation 'com.github.xuexiangjys:XUI:1.1.0' // implementation 'com.qmuiteam:qmui:1.2.0' //工具类 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e5b6cc86..fc63c95f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -78,7 +78,7 @@ android:name=".base.webview.AgentWebActivity" android:configChanges="screenSize|keyboardHidden|orientation|keyboard" android:hardwareAccelerated="true" - android:label="XUI浏览器" + android:label="@string/app_browser_name" android:theme="@style/AppTheme"> @@ -117,21 +117,21 @@ android:scheme="https"/> + + - - - - + + diff --git a/app/src/main/java/com/xuexiang/xuidemo/base/webview/MiddlewareWebViewClient.java b/app/src/main/java/com/xuexiang/xuidemo/base/webview/MiddlewareWebViewClient.java index 1b6dbfa6..4a254bd9 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/base/webview/MiddlewareWebViewClient.java +++ b/app/src/main/java/com/xuexiang/xuidemo/base/webview/MiddlewareWebViewClient.java @@ -16,9 +16,6 @@ package com.xuexiang.xuidemo.base.webview; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; import android.net.Uri; import android.os.Build; import android.util.Log; @@ -30,12 +27,9 @@ import com.just.agentweb.core.client.MiddlewareWebClientBase; import com.xuexiang.xui.utils.ResUtils; -import com.xuexiang.xui.widget.dialog.DialogLoader; import com.xuexiang.xuidemo.R; -import com.xuexiang.xuidemo.utils.XToastUtils; -import com.xuexiang.xutil.XUtil; -import java.net.URISyntaxException; +import static com.xuexiang.xuidemo.base.webview.WebViewInterceptDialog.APP_LINK_HOST; /** * 【网络请求、加载】 @@ -60,7 +54,7 @@ *

*

* 中断中间件的执行, 删除super.methodName(...) 这行即可 - * + *

* 这里主要是做去广告的工作 */ public class MiddlewareWebViewClient extends MiddlewareWebClientBase { @@ -131,10 +125,6 @@ public static boolean hasAd(String url) { return false; } - public static final String APP_LINK_HOST = "xuexiangjys.club"; - public static final String APP_LINK_ACTION = "com.xuexiang.xui.applink"; - - /** * 根据url的scheme处理跳转第三方app的业务 */ @@ -149,7 +139,7 @@ private boolean shouldOverrideUrlLoadingByApp(WebView webView, final String url) } } - WebViewTipDialog.show(url); + WebViewInterceptDialog.show(url); return true; } diff --git a/app/src/main/java/com/xuexiang/xuidemo/base/webview/WebViewTipDialog.java b/app/src/main/java/com/xuexiang/xuidemo/base/webview/WebViewInterceptDialog.java similarity index 88% rename from app/src/main/java/com/xuexiang/xuidemo/base/webview/WebViewTipDialog.java rename to app/src/main/java/com/xuexiang/xuidemo/base/webview/WebViewInterceptDialog.java index 189de67c..720d230c 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/base/webview/WebViewTipDialog.java +++ b/app/src/main/java/com/xuexiang/xuidemo/base/webview/WebViewInterceptDialog.java @@ -35,21 +35,25 @@ import java.net.URISyntaxException; -import static com.xuexiang.xuidemo.base.webview.MiddlewareWebViewClient.APP_LINK_ACTION; -import static com.xuexiang.xuidemo.base.webview.MiddlewareWebViewClient.APP_LINK_HOST; - /** * WebView拦截提示 * * @author xuexiang * @since 2019-10-21 9:51 */ -public class WebViewTipDialog extends AppCompatActivity implements DialogInterface.OnDismissListener { +public class WebViewInterceptDialog extends AppCompatActivity implements DialogInterface.OnDismissListener { - private static final String KEY_INTERCEPT_URL = "KEY_INTERCEPT_URL"; + private static final String KEY_INTERCEPT_URL = "key_intercept_url"; + public static final String APP_LINK_HOST = "xuexiangjys.club"; + public static final String APP_LINK_ACTION = "com.xuexiang.xui.applink"; + /** + * 显示WebView拦截提示 + * + * @param url + */ public static void show(String url) { - ActivityUtils.startActivity(WebViewTipDialog.class, KEY_INTERCEPT_URL, url); + ActivityUtils.startActivity(WebViewInterceptDialog.class, KEY_INTERCEPT_URL, url); } @Override diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9bf3724a..fc6dc2af 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,5 +1,6 @@ XUIDemo + XUI浏览器 diff --git a/xui_lib/src/main/java/com/xuexiang/xui/widget/flowlayout/BaseTagAdapter.java b/xui_lib/src/main/java/com/xuexiang/xui/widget/flowlayout/BaseTagAdapter.java index 4274bb94..873eba0d 100644 --- a/xui_lib/src/main/java/com/xuexiang/xui/widget/flowlayout/BaseTagAdapter.java +++ b/xui_lib/src/main/java/com/xuexiang/xui/widget/flowlayout/BaseTagAdapter.java @@ -19,7 +19,6 @@ public abstract class BaseTagAdapter extends BaseListAdapter impleme * 初始化选中的位置 */ private List mPositions = new ArrayList<>(); - /** * 当前选中的索引集合 */ diff --git a/xui_lib/src/main/java/com/xuexiang/xui/widget/flowlayout/FlowTagLayout.java b/xui_lib/src/main/java/com/xuexiang/xui/widget/flowlayout/FlowTagLayout.java index ff7a5a80..bfe934df 100644 --- a/xui_lib/src/main/java/com/xuexiang/xui/widget/flowlayout/FlowTagLayout.java +++ b/xui_lib/src/main/java/com/xuexiang/xui/widget/flowlayout/FlowTagLayout.java @@ -391,7 +391,7 @@ public void onClick(View v) { //更新点击状态 mCheckedTagArray.put(index, false); childView.setSelected(false); - setSelectedIndexs(null); + setSelectedIndexs(new ArrayList()); if (mOnTagSelectListener != null) { mOnTagSelectListener.onItemSelect(FlowTagLayout.this, index, new ArrayList()); } diff --git a/xui_lib/src/main/java/com/xuexiang/xui/widget/tabbar/MultiTabControlView.java b/xui_lib/src/main/java/com/xuexiang/xui/widget/tabbar/MultiTabControlView.java index 4ccdb51a..521c8e99 100644 --- a/xui_lib/src/main/java/com/xuexiang/xui/widget/tabbar/MultiTabControlView.java +++ b/xui_lib/src/main/java/com/xuexiang/xui/widget/tabbar/MultiTabControlView.java @@ -76,6 +76,14 @@ public class MultiTabControlView extends LinearLayout implements HasTypeface { * 选项间距 */ private int mItemPadding; + /** + * 选项水平间距 + */ + private int mItemPaddingHorizontal; + /** + * 选项垂直间距 + */ + private int mItemPaddingVertical; /** * 选中背景的颜色 */ @@ -164,6 +172,8 @@ private void initAttrs(Context context, AttributeSet attrs) throws Exception { mUnselectedTextColor = attributes.getColor(R.styleable.TabControlView_tcv_unselectedTextColor, ThemeUtils.resolveColor(context, R.attr.colorAccent)); mStrokeWidth = attributes.getDimensionPixelSize(R.styleable.TabControlView_tcv_strokeWidth, ResUtils.getDimensionPixelSize(R.dimen.default_tcv_stroke_width)); mItemPadding = attributes.getDimensionPixelSize(R.styleable.TabControlView_tcv_item_padding, -1); + mItemPaddingHorizontal = attributes.getDimensionPixelSize(R.styleable.TabControlView_tcv_item_padding_horizontal, -1); + mItemPaddingVertical = attributes.getDimensionPixelSize(R.styleable.TabControlView_tcv_item_padding_vertical, -1); //Set text mSelectedColor state list mTextColorStateList = new ColorStateList(new int[][]{ @@ -243,6 +253,9 @@ private void update() { if (mItemPadding != -1) { cb.setPadding(mItemPadding, mItemPadding, mItemPadding, mItemPadding); } + if (mItemPaddingHorizontal != -1 && mItemPaddingVertical != -1) { + cb.setPadding(mItemPaddingHorizontal, mItemPaddingVertical, mItemPaddingHorizontal, mItemPaddingVertical); + } cb.setMinWidth(mStrokeWidth * 10); cb.setGravity(Gravity.CENTER); cb.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSize); diff --git a/xui_lib/src/main/java/com/xuexiang/xui/widget/tabbar/TabControlView.java b/xui_lib/src/main/java/com/xuexiang/xui/widget/tabbar/TabControlView.java index 50d19157..bf9a6719 100644 --- a/xui_lib/src/main/java/com/xuexiang/xui/widget/tabbar/TabControlView.java +++ b/xui_lib/src/main/java/com/xuexiang/xui/widget/tabbar/TabControlView.java @@ -73,6 +73,14 @@ public class TabControlView extends RadioGroup implements HasTypeface { * 选项间距 */ private int mItemPadding; + /** + * 选项水平间距 + */ + private int mItemPaddingHorizontal; + /** + * 选项垂直间距 + */ + private int mItemPaddingVertical; /** * 选中背景的颜色 */ @@ -104,6 +112,7 @@ public class TabControlView extends RadioGroup implements HasTypeface { private ColorStateList mTextColorStateList; //Item organization + private LinkedHashMap mItemMap = new LinkedHashMap<>(); private List mOptions; /** @@ -155,6 +164,8 @@ private void initAttrs(Context context, AttributeSet attrs) throws Exception { mUnselectedTextColor = attributes.getColor(R.styleable.TabControlView_tcv_unselectedTextColor, ThemeUtils.resolveColor(context, R.attr.colorAccent)); mStrokeWidth = attributes.getDimensionPixelSize(R.styleable.TabControlView_tcv_strokeWidth, ResUtils.getDimensionPixelSize(R.dimen.default_tcv_stroke_width)); mItemPadding = attributes.getDimensionPixelSize(R.styleable.TabControlView_tcv_item_padding, -1); + mItemPaddingHorizontal = attributes.getDimensionPixelSize(R.styleable.TabControlView_tcv_item_padding_horizontal, -1); + mItemPaddingVertical = attributes.getDimensionPixelSize(R.styleable.TabControlView_tcv_item_padding_vertical, -1); //Set text mSelectedColor state list mTextColorStateList = new ColorStateList(new int[][]{ @@ -232,6 +243,9 @@ private void update() { if (mItemPadding != -1) { rb.setPadding(mItemPadding, mItemPadding, mItemPadding, mItemPadding); } + if (mItemPaddingHorizontal != -1 && mItemPaddingVertical != -1) { + rb.setPadding(mItemPaddingHorizontal, mItemPaddingVertical, mItemPaddingHorizontal, mItemPaddingVertical); + } rb.setMinWidth(mStrokeWidth * 10); rb.setGravity(Gravity.CENTER); rb.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSize); diff --git a/xui_lib/src/main/res/values/xui_attrs.xml b/xui_lib/src/main/res/values/xui_attrs.xml index cd6be9fd..0a0581f8 100755 --- a/xui_lib/src/main/res/values/xui_attrs.xml +++ b/xui_lib/src/main/res/values/xui_attrs.xml @@ -1288,8 +1288,12 @@ - + + + + + From 53b5e0df1ea524ac9c5de66eac079e4ba4c10e4c Mon Sep 17 00:00:00 2001 From: xuexiangjys Date: Thu, 31 Oct 2019 15:38:51 +0800 Subject: [PATCH 02/27] =?UTF-8?q?=E5=8D=87=E7=BA=A7=E7=85=A7=E7=9B=B8?= =?UTF-8?q?=E6=9C=BA=E5=BA=93=E7=9A=84=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 2 +- .../fragment/expands/qrcode/CustomCaptureActivity.java | 4 ++-- app/src/main/res/layout/activity_camera.xml | 6 +++--- app/src/main/res/layout/activity_camera_view.xml | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 3662082f..595e302d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -185,7 +185,7 @@ dependencies { //图标库控件(可选) implementation "com.mikepenz:iconics-views:4.0.1-b02" //相机拍摄 - implementation 'com.github.xuexiangjys:CameraView:1.0.0' + implementation 'com.github.xuexiangjys:CameraView:1.0.2' //版本更新 implementation 'com.github.xuexiangjys:XUpdate:1.1.1' diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/qrcode/CustomCaptureActivity.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/qrcode/CustomCaptureActivity.java index ffe0a7be..d427d303 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/qrcode/CustomCaptureActivity.java +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/qrcode/CustomCaptureActivity.java @@ -33,8 +33,8 @@ import com.xuexiang.xuidemo.R; import com.xuexiang.xuidemo.utils.XToastUtils; -import static com.xuexiang.xuidemo.base.webview.MiddlewareWebViewClient.APP_LINK_ACTION; -import static com.xuexiang.xuidemo.base.webview.MiddlewareWebViewClient.APP_LINK_HOST; +import static com.xuexiang.xuidemo.base.webview.WebViewInterceptDialog.APP_LINK_ACTION; +import static com.xuexiang.xuidemo.base.webview.WebViewInterceptDialog.APP_LINK_HOST; /** * 自定义二维码扫描界面 diff --git a/app/src/main/res/layout/activity_camera.xml b/app/src/main/res/layout/activity_camera.xml index 59087b41..639a7a8f 100644 --- a/app/src/main/res/layout/activity_camera.xml +++ b/app/src/main/res/layout/activity_camera.xml @@ -1,5 +1,4 @@ - - + + + + + + + diff --git a/app/src/main/res/layout/fragment_qrcode.xml b/app/src/main/res/layout/fragment_qrcode.xml index 8cbe1779..64f8d21d 100644 --- a/app/src/main/res/layout/fragment_qrcode.xml +++ b/app/src/main/res/layout/fragment_qrcode.xml @@ -19,44 +19,44 @@ android:layout_height="match_parent" android:orientation="vertical"> - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_supertextview_common_use.xml b/app/src/main/res/layout/fragment_supertextview_common_use.xml index 8699b4dc..2531fb56 100755 --- a/app/src/main/res/layout/fragment_supertextview_common_use.xml +++ b/app/src/main/res/layout/fragment_supertextview_common_use.xml @@ -5,15 +5,9 @@ android:layout_height="match_parent" android:orientation="vertical"> - + - + - - - - - diff --git a/app/src/main/res/values/styles_widget.xml b/app/src/main/res/values/styles_widget.xml index c532ceaa..eb5b4d8b 100644 --- a/app/src/main/res/values/styles_widget.xml +++ b/app/src/main/res/values/styles_widget.xml @@ -165,4 +165,17 @@ @layout/sv_layout_custom + + + + \ No newline at end of file From 07190db27a1be4b8950e354980318b084b8fe824 Mon Sep 17 00:00:00 2001 From: xuexiangjys Date: Sat, 9 Nov 2019 17:22:14 +0800 Subject: [PATCH 06/27] =?UTF-8?q?=E5=AE=8C=E5=96=84=E6=A1=88=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/ImageViewFragment.java | 6 +- .../imageview/ImageLoadStrategyFragment.java | 86 +++++++++++++++++++ .../imageview/edit/PhotoEditFragment.java | 40 ++++++++- .../com/xuexiang/xuidemo/utils/Utils.java | 8 ++ .../xuexiang/xuidemo/utils/XToastUtils.java | 5 ++ .../layout/fragment_imageload_strategy.xml | 54 ++++++++++++ .../main/res/layout/fragment_photo_edit.xml | 7 ++ 7 files changed, 199 insertions(+), 7 deletions(-) create mode 100644 app/src/main/java/com/xuexiang/xuidemo/fragment/components/imageview/ImageLoadStrategyFragment.java create mode 100644 app/src/main/res/layout/fragment_imageload_strategy.xml diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/ImageViewFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/ImageViewFragment.java index 4658d9c9..e2edca8b 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/ImageViewFragment.java +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/ImageViewFragment.java @@ -4,8 +4,7 @@ import com.xuexiang.xuidemo.R; import com.xuexiang.xuidemo.base.ComponentContainerFragment; import com.xuexiang.xuidemo.fragment.components.imageview.ImageEditFragment; -import com.xuexiang.xuidemo.fragment.components.imageview.edit.ImageCropFragment; -import com.xuexiang.xuidemo.fragment.components.imageview.edit.ImageEnhanceFragment; +import com.xuexiang.xuidemo.fragment.components.imageview.ImageLoadStrategyFragment; import com.xuexiang.xuidemo.fragment.components.imageview.PreviewFragment; import com.xuexiang.xuidemo.fragment.components.imageview.RadiusImageViewFragment; import com.xuexiang.xuidemo.fragment.components.imageview.pictureselector.PictureSelectorFragment; @@ -27,7 +26,8 @@ protected Class[] getPagesClasses() { RadiusImageViewFragment.class, PictureSelectorFragment.class, PreviewFragment.class, - ImageEditFragment.class + ImageEditFragment.class, + ImageLoadStrategyFragment.class }; } } diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/imageview/ImageLoadStrategyFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/imageview/ImageLoadStrategyFragment.java new file mode 100644 index 00000000..6a4d1cf1 --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/imageview/ImageLoadStrategyFragment.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.xuexiang.xuidemo.fragment.components.imageview; + +import androidx.appcompat.widget.AppCompatImageView; + +import com.xuexiang.xpage.annotation.Page; +import com.xuexiang.xui.utils.DensityUtils; +import com.xuexiang.xui.utils.ResUtils; +import com.xuexiang.xui.widget.imageview.ImageLoader; +import com.xuexiang.xui.widget.imageview.strategy.DiskCacheStrategyEnum; +import com.xuexiang.xui.widget.imageview.strategy.ILoadListener; +import com.xuexiang.xui.widget.imageview.strategy.LoadOption; +import com.xuexiang.xuidemo.R; +import com.xuexiang.xuidemo.base.BaseFragment; + +import butterknife.BindView; + +/** + * @author xuexiang + * @since 2019-11-09 16:20 + */ +@Page(name = "图片加载策略") +public class ImageLoadStrategyFragment extends BaseFragment { + + private static final String PICTURE_URL = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1573298332486&di=57555a4ffbd9c2c09f12042f0f2b8ba6&imgtype=0&src=http%3A%2F%2Fimg.pconline.com.cn%2Fimages%2Fupload%2Fupc%2Ftx%2Fwallpaper%2F1212%2F10%2Fc1%2F16491245_1355126013759.jpg"; + private static final String PICTURE_URL1 = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1573298947875&di=a2d6f04cd74ad2a7db74eb5d2395f2c6&imgtype=0&src=http%3A%2F%2Fupload.17u.net%2Fuploadpicbase%2Fimage%2F201306150338029631.jpg"; + private static final String PICTURE_URL2 = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1573298976039&di=ba80603c68dc64a4efc55e19065eacf1&imgtype=0&src=http%3A%2F%2Fpic1.win4000.com%2Fwallpaper%2Fc%2F59bcd50cb8281.jpg"; + + @BindView(R.id.iv_content) + AppCompatImageView ivContent; + @BindView(R.id.iv_content1) + AppCompatImageView ivContent1; + @BindView(R.id.iv_content2) + AppCompatImageView ivContent2; + + /** + * 布局的资源id + * + * @return + */ + @Override + protected int getLayoutId() { + return R.layout.fragment_imageload_strategy; + } + + /** + * 初始化控件 + */ + @Override + protected void initViews() { + getMessageLoader("加载中..."); + ImageLoader.get().loadImage(ivContent, PICTURE_URL, DiskCacheStrategyEnum.NONE, new ILoadListener() { + @Override + public void onLoadSuccess() { + getMessageLoader().dismiss(); + } + @Override + public void onLoadFailed(Throwable error) { + getMessageLoader().dismiss(); + } + }); + LoadOption option = LoadOption.of(DiskCacheStrategyEnum.ALL) + .setPlaceholder(ResUtils.getDrawable(R.drawable.xui_ic_default_img)) + .setSize(DensityUtils.dp2px(200), DensityUtils.dp2px(100)); + ImageLoader.get().loadImage(ivContent1, PICTURE_URL1, option); + + ImageLoader.get().loadImage(ivContent2, PICTURE_URL2, ResUtils.getDrawable(R.drawable.xui_ic_default_img), DiskCacheStrategyEnum.AUTOMATIC); + + } +} diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/imageview/edit/PhotoEditFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/imageview/edit/PhotoEditFragment.java index 98a3127c..94b6e91d 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/imageview/edit/PhotoEditFragment.java +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/imageview/edit/PhotoEditFragment.java @@ -17,11 +17,14 @@ package com.xuexiang.xuidemo.fragment.components.imageview.edit; +import android.annotation.SuppressLint; import android.content.Intent; import android.graphics.Bitmap; import android.net.Uri; import android.view.View; +import androidx.annotation.NonNull; + import com.xuexiang.xaop.annotation.Permission; import com.xuexiang.xaop.annotation.SingleClick; import com.xuexiang.xpage.annotation.Page; @@ -35,6 +38,8 @@ import com.xuexiang.xui.widget.imageview.edit.ViewType; import com.xuexiang.xuidemo.R; import com.xuexiang.xuidemo.base.BaseFragment; +import com.xuexiang.xuidemo.utils.Utils; +import com.xuexiang.xuidemo.utils.XToastUtils; import com.xuexiang.xutil.app.IntentUtils; import com.xuexiang.xutil.app.PathUtils; import com.xuexiang.xutil.display.ImageUtils; @@ -50,7 +55,7 @@ * @author xuexiang * @since 2019-10-28 10:56 */ -@Page(name = "图片编辑\n画笔、橡皮檫、文字、滤镜") +@Page(name = "图片编辑\n画笔、橡皮檫、文字、滤镜、保存") public class PhotoEditFragment extends BaseFragment implements OnPhotoEditorListener { @BindView(R.id.photo_editor_view) @@ -81,7 +86,7 @@ protected void initViews() { } @SingleClick - @OnClick({R.id.btn_select, R.id.btn_brush, R.id.btn_text, R.id.btn_rubber, R.id.iv_undo, R.id.iv_redo, R.id.btn_filter}) + @OnClick({R.id.btn_select, R.id.btn_brush, R.id.btn_text, R.id.btn_rubber, R.id.iv_undo, R.id.iv_redo, R.id.btn_filter, R.id.btn_save}) public void onViewClicked(View view) { switch (view.getId()) { case R.id.btn_select: @@ -95,8 +100,8 @@ public void onViewClicked(View view) { break; case R.id.btn_brush: mPhotoEditor.setBrushColor(ResUtils.getColor(R.color.xui_config_color_white)) - .setBrushSize(DensityUtils.dp2px(5)) - .setBrushDrawingMode(true); + .setBrushSize(DensityUtils.dp2px(5)) + .setBrushDrawingMode(true); break; case R.id.btn_text: final TextStyleBuilder styleBuilder = new TextStyleBuilder(); @@ -109,11 +114,37 @@ public void onViewClicked(View view) { case R.id.btn_filter: mPhotoEditor.setFilterEffect(PhotoFilter.GRAY_SCALE); break; + case R.id.btn_save: + saveImage(); + break; default: break; } } + /** + * 保存图片 + */ + @SuppressLint("MissingPermission") + @Permission(STORAGE) + private void saveImage() { + getMessageLoader("保存中...").show(); + mPhotoEditor.saveAsFile(Utils.getImageSavePath(), new PhotoEditor.OnSaveListener() { + @Override + public void onSuccess(@NonNull String imagePath) { + getMessageLoader().dismiss(); + if (photoEditorView != null) { + photoEditorView.getSource().setImageBitmap(ImageUtils.getBitmap(imagePath)); + } + } + @Override + public void onFailure(@NonNull Exception exception) { + getMessageLoader().dismiss(); + XToastUtils.error(exception); + } + }); + } + @Permission(STORAGE) private void selectImage() { startActivityForResult(IntentUtils.getDocumentPickerIntent(IntentUtils.DocumentType.IMAGE), REQUEST_IMAGE); @@ -128,6 +159,7 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { Uri uri = data.getData(); if (uri != null) { mPhotoEditor.clearAllViews(); + @SuppressLint("MissingPermission") Bitmap bitmap = ImageUtils.getBitmap(PathUtils.getFilePathByUri(uri)); photoEditorView.getSource().setImageBitmap(bitmap); } diff --git a/app/src/main/java/com/xuexiang/xuidemo/utils/Utils.java b/app/src/main/java/com/xuexiang/xuidemo/utils/Utils.java index e3e95d53..a80394f5 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/utils/Utils.java +++ b/app/src/main/java/com/xuexiang/xuidemo/utils/Utils.java @@ -35,6 +35,8 @@ import com.xuexiang.xutil.file.FileIOUtils; import com.xuexiang.xutil.file.FileUtils; +import java.io.File; + import static com.xuexiang.xuidemo.base.webview.AgentWebFragment.KEY_URL; /** @@ -142,12 +144,14 @@ public static PictureSelectionModel getPictureSelector(Activity activity) { /** * 处理拍照的回调 + * * @param data * @return */ public static String handleOnPictureTaken(byte[] data) { return handleOnPictureTaken(data, JPEG); } + /** * 处理拍照的回调 * @@ -160,6 +164,10 @@ public static String handleOnPictureTaken(byte[] data, String fileSuffix) { return result ? picPath : ""; } + public static String getImageSavePath() { + return FileUtils.getDiskCacheDir("images") + File.separator + DateUtils.getNowMills() + JPEG; + } + //==========截图===========// /** diff --git a/app/src/main/java/com/xuexiang/xuidemo/utils/XToastUtils.java b/app/src/main/java/com/xuexiang/xuidemo/utils/XToastUtils.java index a1cf18d5..51173576 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/utils/XToastUtils.java +++ b/app/src/main/java/com/xuexiang/xuidemo/utils/XToastUtils.java @@ -70,6 +70,11 @@ public static void error(@NonNull CharSequence message) { XToast.error(XUI.getContext(), message).show(); } + @MainThread + public static void error(@NonNull Exception error) { + XToast.error(XUI.getContext(), error.getMessage()).show(); + } + @MainThread public static void error(@StringRes int message) { XToast.error(XUI.getContext(), message).show(); diff --git a/app/src/main/res/layout/fragment_imageload_strategy.xml b/app/src/main/res/layout/fragment_imageload_strategy.xml new file mode 100644 index 00000000..c404cd77 --- /dev/null +++ b/app/src/main/res/layout/fragment_imageload_strategy.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_photo_edit.xml b/app/src/main/res/layout/fragment_photo_edit.xml index 2abba014..40b6e21c 100644 --- a/app/src/main/res/layout/fragment_photo_edit.xml +++ b/app/src/main/res/layout/fragment_photo_edit.xml @@ -61,6 +61,13 @@ android:layout_marginTop="8dp" android:text="滤镜" /> + + Date: Sat, 9 Nov 2019 18:08:11 +0800 Subject: [PATCH 07/27] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=B8=83=E5=B1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dialog/materialdialog/DialogInit.java | 20 +++++------ .../dialog/materialdialog/MaterialDialog.java | 6 ++-- .../materialdialog/internal/MDRootLayout.java | 2 +- .../simplelist/MaterialSimpleListAdapter.java | 2 +- .../widget/imageview/edit/PhotoEditor.java | 6 ++-- .../popup/XUIExpandableListPopup.java | 33 +++++++++++++++++++ .../editspinner/EditSpinnerAdapter.java | 2 +- .../MaterialSpinnerBaseAdapter.java | 2 +- .../statelayout/MultipleStatusView.java | 8 ++--- .../com/xuexiang/xui/widget/toast/XToast.java | 2 +- ...toast_layout.xml => xui_layout_xtoast.xml} | 0 ...toast_layout.xml => xui_layout_xtoast.xml} | 0 ...g_basic.xml => md_layout_dialog_basic.xml} | 4 +-- ...k.xml => md_layout_dialog_basic_check.xml} | 4 +-- ...custom.xml => md_layout_dialog_custom.xml} | 4 +-- ...g_input.xml => md_layout_dialog_input.xml} | 4 +-- ...k.xml => md_layout_dialog_input_check.xml} | 4 +-- ...log_list.xml => md_layout_dialog_list.xml} | 4 +-- ...ck.xml => md_layout_dialog_list_check.xml} | 4 +-- ...ress.xml => md_layout_dialog_progress.xml} | 6 ++-- ..._layout_dialog_progress_indeterminate.xml} | 6 ++-- ...log_progress_indeterminate_horizontal.xml} | 6 ++-- ...md_listitem.xml => md_layout_listitem.xml} | 0 ...xml => md_layout_listitem_multichoice.xml} | 0 ...ml => md_layout_listitem_singlechoice.xml} | 0 ...om.xml => md_layout_preference_custom.xml} | 0 ...item.xml => md_layout_simplelist_item.xml} | 0 ...s.xml => md_layout_stub_actionbuttons.xml} | 0 ...tpref.xml => md_layout_stub_inputpref.xml} | 0 ...ogress.xml => md_layout_stub_progress.xml} | 0 ...md_layout_stub_progress_indeterminate.xml} | 0 ...tub_progress_indeterminate_horizontal.xml} | 0 ...rame.xml => md_layout_stub_titleframe.xml} | 0 ...md_layout_stub_titleframe_lesspadding.xml} | 0 ..._list_item.xml => ms_layout_list_item.xml} | 0 ...pty_view.xml => msv_layout_empty_view.xml} | 0 ...ror_view.xml => msv_layout_error_view.xml} | 0 ...g_view.xml => msv_layout_loading_view.xml} | 0 ...iew.xml => msv_layout_no_network_view.xml} | 0 .../res/layout/xui_layout_expand_list_pop.xml | 22 +++++++++++++ ....xml => xui_layout_photo_editor_image.xml} | 0 ...t.xml => xui_layout_photo_editor_text.xml} | 0 ...toast_layout.xml => xui_layout_xtoast.xml} | 0 xui_lib/src/main/res/values/xui_public.xml | 9 +++-- .../src/main/res/values/xui_styles_widget.xml | 8 ++--- 45 files changed, 111 insertions(+), 57 deletions(-) create mode 100644 xui_lib/src/main/java/com/xuexiang/xui/widget/popupwindow/popup/XUIExpandableListPopup.java rename xui_lib/src/main/res/layout-large/{xtoast_layout.xml => xui_layout_xtoast.xml} (100%) rename xui_lib/src/main/res/layout-xlarge/{xtoast_layout.xml => xui_layout_xtoast.xml} (100%) rename xui_lib/src/main/res/layout/{md_dialog_basic.xml => md_layout_dialog_basic.xml} (93%) mode change 100755 => 100644 rename xui_lib/src/main/res/layout/{md_dialog_basic_check.xml => md_layout_dialog_basic_check.xml} (95%) mode change 100755 => 100644 rename xui_lib/src/main/res/layout/{md_dialog_custom.xml => md_layout_dialog_custom.xml} (90%) mode change 100755 => 100644 rename xui_lib/src/main/res/layout/{md_dialog_input.xml => md_layout_dialog_input.xml} (96%) mode change 100755 => 100644 rename xui_lib/src/main/res/layout/{md_dialog_input_check.xml => md_layout_dialog_input_check.xml} (96%) mode change 100755 => 100644 rename xui_lib/src/main/res/layout/{md_dialog_list.xml => md_layout_dialog_list.xml} (95%) mode change 100755 => 100644 rename xui_lib/src/main/res/layout/{md_dialog_list_check.xml => md_layout_dialog_list_check.xml} (96%) mode change 100755 => 100644 rename xui_lib/src/main/res/layout/{md_dialog_progress.xml => md_layout_dialog_progress.xml} (89%) mode change 100755 => 100644 rename xui_lib/src/main/res/layout/{md_dialog_progress_indeterminate.xml => md_layout_dialog_progress_indeterminate.xml} (85%) mode change 100755 => 100644 rename xui_lib/src/main/res/layout/{md_dialog_progress_indeterminate_horizontal.xml => md_layout_dialog_progress_indeterminate_horizontal.xml} (88%) mode change 100755 => 100644 rename xui_lib/src/main/res/layout/{md_listitem.xml => md_layout_listitem.xml} (100%) mode change 100755 => 100644 rename xui_lib/src/main/res/layout/{md_listitem_multichoice.xml => md_layout_listitem_multichoice.xml} (100%) mode change 100755 => 100644 rename xui_lib/src/main/res/layout/{md_listitem_singlechoice.xml => md_layout_listitem_singlechoice.xml} (100%) mode change 100755 => 100644 rename xui_lib/src/main/res/layout/{md_preference_custom.xml => md_layout_preference_custom.xml} (100%) rename xui_lib/src/main/res/layout/{md_simplelist_item.xml => md_layout_simplelist_item.xml} (100%) mode change 100755 => 100644 rename xui_lib/src/main/res/layout/{md_stub_actionbuttons.xml => md_layout_stub_actionbuttons.xml} (100%) mode change 100755 => 100644 rename xui_lib/src/main/res/layout/{md_stub_inputpref.xml => md_layout_stub_inputpref.xml} (100%) rename xui_lib/src/main/res/layout/{md_stub_progress.xml => md_layout_stub_progress.xml} (100%) mode change 100755 => 100644 rename xui_lib/src/main/res/layout/{md_stub_progress_indeterminate.xml => md_layout_stub_progress_indeterminate.xml} (100%) mode change 100755 => 100644 rename xui_lib/src/main/res/layout/{md_stub_progress_indeterminate_horizontal.xml => md_layout_stub_progress_indeterminate_horizontal.xml} (100%) mode change 100755 => 100644 rename xui_lib/src/main/res/layout/{md_stub_titleframe.xml => md_layout_stub_titleframe.xml} (100%) mode change 100755 => 100644 rename xui_lib/src/main/res/layout/{md_stub_titleframe_lesspadding.xml => md_layout_stub_titleframe_lesspadding.xml} (100%) mode change 100755 => 100644 rename xui_lib/src/main/res/layout/{ms_list_item.xml => ms_layout_list_item.xml} (100%) mode change 100755 => 100644 rename xui_lib/src/main/res/layout/{msv_empty_view.xml => msv_layout_empty_view.xml} (100%) rename xui_lib/src/main/res/layout/{msv_error_view.xml => msv_layout_error_view.xml} (100%) rename xui_lib/src/main/res/layout/{msv_loading_view.xml => msv_layout_loading_view.xml} (100%) rename xui_lib/src/main/res/layout/{msv_no_network_view.xml => msv_layout_no_network_view.xml} (100%) create mode 100644 xui_lib/src/main/res/layout/xui_layout_expand_list_pop.xml rename xui_lib/src/main/res/layout/{layout_photo_editor_image.xml => xui_layout_photo_editor_image.xml} (100%) rename xui_lib/src/main/res/layout/{layout_photo_editor_text.xml => xui_layout_photo_editor_text.xml} (100%) rename xui_lib/src/main/res/layout/{xtoast_layout.xml => xui_layout_xtoast.xml} (100%) diff --git a/xui_lib/src/main/java/com/xuexiang/xui/widget/dialog/materialdialog/DialogInit.java b/xui_lib/src/main/java/com/xuexiang/xui/widget/dialog/materialdialog/DialogInit.java index 832e9365..e01ca836 100755 --- a/xui_lib/src/main/java/com/xuexiang/xui/widget/dialog/materialdialog/DialogInit.java +++ b/xui_lib/src/main/java/com/xuexiang/xui/widget/dialog/materialdialog/DialogInit.java @@ -80,28 +80,28 @@ static int getTheme(@NonNull MaterialDialog.Builder builder) { @LayoutRes static int getInflateLayout(MaterialDialog.Builder builder) { if (builder.customView != null) { - return R.layout.md_dialog_custom; + return R.layout.md_layout_dialog_custom; } else if (builder.items != null || builder.adapter != null) { if (builder.checkBoxPrompt != null) { - return R.layout.md_dialog_list_check; + return R.layout.md_layout_dialog_list_check; } - return R.layout.md_dialog_list; + return R.layout.md_layout_dialog_list; } else if (builder.progress > -2) { - return R.layout.md_dialog_progress; + return R.layout.md_layout_dialog_progress; } else if (builder.indeterminateProgress) { if (builder.indeterminateIsHorizontalProgress) { - return R.layout.md_dialog_progress_indeterminate_horizontal; + return R.layout.md_layout_dialog_progress_indeterminate_horizontal; } - return R.layout.md_dialog_progress_indeterminate; + return R.layout.md_layout_dialog_progress_indeterminate; } else if (builder.inputCallback != null) { if (builder.checkBoxPrompt != null) { - return R.layout.md_dialog_input_check; + return R.layout.md_layout_dialog_input_check; } - return R.layout.md_dialog_input; + return R.layout.md_layout_dialog_input; } else if (builder.checkBoxPrompt != null) { - return R.layout.md_dialog_basic_check; + return R.layout.md_layout_dialog_basic_check; } else { - return R.layout.md_dialog_basic; + return R.layout.md_layout_dialog_basic; } } diff --git a/xui_lib/src/main/java/com/xuexiang/xui/widget/dialog/materialdialog/MaterialDialog.java b/xui_lib/src/main/java/com/xuexiang/xui/widget/dialog/materialdialog/MaterialDialog.java index b4cd6fc4..345a8766 100755 --- a/xui_lib/src/main/java/com/xuexiang/xui/widget/dialog/materialdialog/MaterialDialog.java +++ b/xui_lib/src/main/java/com/xuexiang/xui/widget/dialog/materialdialog/MaterialDialog.java @@ -1035,11 +1035,11 @@ enum ListType { public static int getLayoutForType(ListType type) { switch (type) { case REGULAR: - return R.layout.md_listitem; + return R.layout.md_layout_listitem; case SINGLE: - return R.layout.md_listitem_singlechoice; + return R.layout.md_layout_listitem_singlechoice; case MULTI: - return R.layout.md_listitem_multichoice; + return R.layout.md_layout_listitem_multichoice; default: throw new IllegalArgumentException("Not a valid list type"); } diff --git a/xui_lib/src/main/java/com/xuexiang/xui/widget/dialog/materialdialog/internal/MDRootLayout.java b/xui_lib/src/main/java/com/xuexiang/xui/widget/dialog/materialdialog/internal/MDRootLayout.java index b31f6e83..0d8e5246 100755 --- a/xui_lib/src/main/java/com/xuexiang/xui/widget/dialog/materialdialog/internal/MDRootLayout.java +++ b/xui_lib/src/main/java/com/xuexiang/xui/widget/dialog/materialdialog/internal/MDRootLayout.java @@ -42,7 +42,7 @@ /** * @author Kevin Barry (teslacoil) 4/02/2015 This is the top level view for all MaterialDialogs It - * handles the layout of: titleFrame (md_stub_titleframe) content (text, custom view, listview, + * handles the layout of: titleFrame (md_layout_stub_titleframe) content (text, custom view, listview, * etc) buttonDefault... (either stacked or horizontal) */ public class MDRootLayout extends ViewGroup { diff --git a/xui_lib/src/main/java/com/xuexiang/xui/widget/dialog/materialdialog/simplelist/MaterialSimpleListAdapter.java b/xui_lib/src/main/java/com/xuexiang/xui/widget/dialog/materialdialog/simplelist/MaterialSimpleListAdapter.java index 2b4db4de..ea809f5e 100755 --- a/xui_lib/src/main/java/com/xuexiang/xui/widget/dialog/materialdialog/simplelist/MaterialSimpleListAdapter.java +++ b/xui_lib/src/main/java/com/xuexiang/xui/widget/dialog/materialdialog/simplelist/MaterialSimpleListAdapter.java @@ -91,7 +91,7 @@ public MaterialDialog getMaterialDialog() { public SimpleListVH onCreateViewHolder(ViewGroup parent, int viewType) { final View view = LayoutInflater.from(parent.getContext()) - .inflate(R.layout.md_simplelist_item, parent, false); + .inflate(R.layout.md_layout_simplelist_item, parent, false); return new SimpleListVH(view, this); } diff --git a/xui_lib/src/main/java/com/xuexiang/xui/widget/imageview/edit/PhotoEditor.java b/xui_lib/src/main/java/com/xuexiang/xui/widget/imageview/edit/PhotoEditor.java index 6235f69a..9076722b 100644 --- a/xui_lib/src/main/java/com/xuexiang/xui/widget/imageview/edit/PhotoEditor.java +++ b/xui_lib/src/main/java/com/xuexiang/xui/widget/imageview/edit/PhotoEditor.java @@ -339,7 +339,7 @@ private View getLayout(final ViewType viewType) { View rootView = null; switch (viewType) { case TEXT: - rootView = mLayoutInflater.inflate(R.layout.layout_photo_editor_text, null); + rootView = mLayoutInflater.inflate(R.layout.xui_layout_photo_editor_text, null); TextView txtText = rootView.findViewById(R.id.tv_editor_text); if (txtText != null && mDefaultTextTypeface != null) { txtText.setGravity(Gravity.CENTER); @@ -349,10 +349,10 @@ private View getLayout(final ViewType viewType) { } break; case IMAGE: - rootView = mLayoutInflater.inflate(R.layout.layout_photo_editor_image, null); + rootView = mLayoutInflater.inflate(R.layout.xui_layout_photo_editor_image, null); break; case EMOJI: - rootView = mLayoutInflater.inflate(R.layout.layout_photo_editor_text, null); + rootView = mLayoutInflater.inflate(R.layout.xui_layout_photo_editor_text, null); TextView txtTextEmoji = rootView.findViewById(R.id.tv_editor_text); if (txtTextEmoji != null) { if (mDefaultEmojiTypeface != null) { diff --git a/xui_lib/src/main/java/com/xuexiang/xui/widget/popupwindow/popup/XUIExpandableListPopup.java b/xui_lib/src/main/java/com/xuexiang/xui/widget/popupwindow/popup/XUIExpandableListPopup.java new file mode 100644 index 00000000..cc47ab3d --- /dev/null +++ b/xui_lib/src/main/java/com/xuexiang/xui/widget/popupwindow/popup/XUIExpandableListPopup.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.xuexiang.xui.widget.popupwindow.popup; + +import android.content.Context; + +/** + * 继承自 {@link XUIPopup},在 {@link XUIPopup} 的基础上,支持显示一个可伸缩的列表。 + * + * @author xuexiang + * @since 2019-11-09 18:05 + */ +public class XUIExpandableListPopup extends XUIPopup { + + public XUIExpandableListPopup(Context context) { + super(context); + } +} diff --git a/xui_lib/src/main/java/com/xuexiang/xui/widget/spinner/editspinner/EditSpinnerAdapter.java b/xui_lib/src/main/java/com/xuexiang/xui/widget/spinner/editspinner/EditSpinnerAdapter.java index b74c52f9..8640d1c8 100755 --- a/xui_lib/src/main/java/com/xuexiang/xui/widget/spinner/editspinner/EditSpinnerAdapter.java +++ b/xui_lib/src/main/java/com/xuexiang/xui/widget/spinner/editspinner/EditSpinnerAdapter.java @@ -89,7 +89,7 @@ public View getView(int position, View convertView, ViewGroup parent) { final TextView textView; if (convertView == null) { LayoutInflater inflater = LayoutInflater.from(mContext); - convertView = inflater.inflate(R.layout.ms_list_item, parent, false); + convertView = inflater.inflate(R.layout.ms_layout_list_item, parent, false); textView = convertView.findViewById(R.id.tv_tinted_spinner); textView.setTextColor(textColor); textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize); diff --git a/xui_lib/src/main/java/com/xuexiang/xui/widget/spinner/materialspinner/MaterialSpinnerBaseAdapter.java b/xui_lib/src/main/java/com/xuexiang/xui/widget/spinner/materialspinner/MaterialSpinnerBaseAdapter.java index 0c04b374..e16716fd 100755 --- a/xui_lib/src/main/java/com/xuexiang/xui/widget/spinner/materialspinner/MaterialSpinnerBaseAdapter.java +++ b/xui_lib/src/main/java/com/xuexiang/xui/widget/spinner/materialspinner/MaterialSpinnerBaseAdapter.java @@ -39,7 +39,7 @@ public View getView(int position, View convertView, ViewGroup parent) { final TextView textView; if (convertView == null) { LayoutInflater inflater = LayoutInflater.from(context); - convertView = inflater.inflate(R.layout.ms_list_item, parent, false); + convertView = inflater.inflate(R.layout.ms_layout_list_item, parent, false); textView = convertView.findViewById(R.id.tv_tinted_spinner); textView.setTextColor(textColor); textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize); diff --git a/xui_lib/src/main/java/com/xuexiang/xui/widget/statelayout/MultipleStatusView.java b/xui_lib/src/main/java/com/xuexiang/xui/widget/statelayout/MultipleStatusView.java index d20b2c46..7cad6a98 100644 --- a/xui_lib/src/main/java/com/xuexiang/xui/widget/statelayout/MultipleStatusView.java +++ b/xui_lib/src/main/java/com/xuexiang/xui/widget/statelayout/MultipleStatusView.java @@ -99,10 +99,10 @@ public MultipleStatusView(Context context, AttributeSet attrs, int defStyleAttr) private void initAttrs(Context context, AttributeSet attrs, int defStyleAttr) { final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MultipleStatusView, defStyleAttr, 0); - mEmptyViewResId = a.getResourceId(R.styleable.MultipleStatusView_msv_emptyView, R.layout.msv_empty_view); - mErrorViewResId = a.getResourceId(R.styleable.MultipleStatusView_msv_errorView, R.layout.msv_error_view); - mLoadingViewResId = a.getResourceId(R.styleable.MultipleStatusView_msv_loadingView, R.layout.msv_loading_view); - mNoNetworkViewResId = a.getResourceId(R.styleable.MultipleStatusView_msv_noNetworkView, R.layout.msv_no_network_view); + mEmptyViewResId = a.getResourceId(R.styleable.MultipleStatusView_msv_emptyView, R.layout.msv_layout_empty_view); + mErrorViewResId = a.getResourceId(R.styleable.MultipleStatusView_msv_errorView, R.layout.msv_layout_error_view); + mLoadingViewResId = a.getResourceId(R.styleable.MultipleStatusView_msv_loadingView, R.layout.msv_layout_loading_view); + mNoNetworkViewResId = a.getResourceId(R.styleable.MultipleStatusView_msv_noNetworkView, R.layout.msv_layout_no_network_view); mContentViewResId = a.getResourceId(R.styleable.MultipleStatusView_msv_contentView, NULL_RESOURCE_ID); a.recycle(); mInflater = LayoutInflater.from(getContext()); diff --git a/xui_lib/src/main/java/com/xuexiang/xui/widget/toast/XToast.java b/xui_lib/src/main/java/com/xuexiang/xui/widget/toast/XToast.java index 341eedb8..f0dcecc4 100644 --- a/xui_lib/src/main/java/com/xuexiang/xui/widget/toast/XToast.java +++ b/xui_lib/src/main/java/com/xuexiang/xui/widget/toast/XToast.java @@ -296,7 +296,7 @@ public static Toast custom(@NonNull Context context, @NonNull CharSequence messa @ColorInt int tintColor, @ColorInt int textColor, int duration, boolean withIcon, boolean shouldTint) { final Toast currentToast = Toast.makeText(context, "", duration); - final View toastLayout = ((LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.xtoast_layout, null); + final View toastLayout = ((LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.xui_layout_xtoast, null); final ImageView toastIcon = toastLayout.findViewById(R.id.toast_icon); final TextView toastTextView = toastLayout.findViewById(R.id.toast_text); Drawable drawableFrame; diff --git a/xui_lib/src/main/res/layout-large/xtoast_layout.xml b/xui_lib/src/main/res/layout-large/xui_layout_xtoast.xml similarity index 100% rename from xui_lib/src/main/res/layout-large/xtoast_layout.xml rename to xui_lib/src/main/res/layout-large/xui_layout_xtoast.xml diff --git a/xui_lib/src/main/res/layout-xlarge/xtoast_layout.xml b/xui_lib/src/main/res/layout-xlarge/xui_layout_xtoast.xml similarity index 100% rename from xui_lib/src/main/res/layout-xlarge/xtoast_layout.xml rename to xui_lib/src/main/res/layout-xlarge/xui_layout_xtoast.xml diff --git a/xui_lib/src/main/res/layout/md_dialog_basic.xml b/xui_lib/src/main/res/layout/md_layout_dialog_basic.xml old mode 100755 new mode 100644 similarity index 93% rename from xui_lib/src/main/res/layout/md_dialog_basic.xml rename to xui_lib/src/main/res/layout/md_layout_dialog_basic.xml index d35447e6..3e45f19c --- a/xui_lib/src/main/res/layout/md_dialog_basic.xml +++ b/xui_lib/src/main/res/layout/md_layout_dialog_basic.xml @@ -23,7 +23,7 @@ android:orientation="vertical" app:md_reduce_padding_no_title_no_buttons="false"> - + - + \ No newline at end of file diff --git a/xui_lib/src/main/res/layout/md_dialog_basic_check.xml b/xui_lib/src/main/res/layout/md_layout_dialog_basic_check.xml old mode 100755 new mode 100644 similarity index 95% rename from xui_lib/src/main/res/layout/md_dialog_basic_check.xml rename to xui_lib/src/main/res/layout/md_layout_dialog_basic_check.xml index b5594944..871805a5 --- a/xui_lib/src/main/res/layout/md_dialog_basic_check.xml +++ b/xui_lib/src/main/res/layout/md_layout_dialog_basic_check.xml @@ -23,7 +23,7 @@ android:orientation="vertical" app:md_reduce_padding_no_title_no_buttons="false"> - + - + \ No newline at end of file diff --git a/xui_lib/src/main/res/layout/md_dialog_custom.xml b/xui_lib/src/main/res/layout/md_layout_dialog_custom.xml old mode 100755 new mode 100644 similarity index 90% rename from xui_lib/src/main/res/layout/md_dialog_custom.xml rename to xui_lib/src/main/res/layout/md_layout_dialog_custom.xml index 74119e98..81a50466 --- a/xui_lib/src/main/res/layout/md_dialog_custom.xml +++ b/xui_lib/src/main/res/layout/md_layout_dialog_custom.xml @@ -22,13 +22,13 @@ android:layout_height="wrap_content" android:orientation="vertical"> - + - + \ No newline at end of file diff --git a/xui_lib/src/main/res/layout/md_dialog_input.xml b/xui_lib/src/main/res/layout/md_layout_dialog_input.xml old mode 100755 new mode 100644 similarity index 96% rename from xui_lib/src/main/res/layout/md_dialog_input.xml rename to xui_lib/src/main/res/layout/md_layout_dialog_input.xml index 86ffad10..fb9c9d57 --- a/xui_lib/src/main/res/layout/md_dialog_input.xml +++ b/xui_lib/src/main/res/layout/md_layout_dialog_input.xml @@ -24,7 +24,7 @@ android:orientation="vertical" app:md_reduce_padding_no_title_no_buttons="false"> - + - + \ No newline at end of file diff --git a/xui_lib/src/main/res/layout/md_dialog_input_check.xml b/xui_lib/src/main/res/layout/md_layout_dialog_input_check.xml old mode 100755 new mode 100644 similarity index 96% rename from xui_lib/src/main/res/layout/md_dialog_input_check.xml rename to xui_lib/src/main/res/layout/md_layout_dialog_input_check.xml index a15a9def..41926a32 --- a/xui_lib/src/main/res/layout/md_dialog_input_check.xml +++ b/xui_lib/src/main/res/layout/md_layout_dialog_input_check.xml @@ -24,7 +24,7 @@ android:orientation="vertical" app:md_reduce_padding_no_title_no_buttons="false"> - + - + \ No newline at end of file diff --git a/xui_lib/src/main/res/layout/md_dialog_list.xml b/xui_lib/src/main/res/layout/md_layout_dialog_list.xml old mode 100755 new mode 100644 similarity index 95% rename from xui_lib/src/main/res/layout/md_dialog_list.xml rename to xui_lib/src/main/res/layout/md_layout_dialog_list.xml index d9972db7..906ab0fe --- a/xui_lib/src/main/res/layout/md_dialog_list.xml +++ b/xui_lib/src/main/res/layout/md_layout_dialog_list.xml @@ -21,7 +21,7 @@ android:layout_height="wrap_content" android:orientation="vertical"> - + - + \ No newline at end of file diff --git a/xui_lib/src/main/res/layout/md_dialog_list_check.xml b/xui_lib/src/main/res/layout/md_layout_dialog_list_check.xml old mode 100755 new mode 100644 similarity index 96% rename from xui_lib/src/main/res/layout/md_dialog_list_check.xml rename to xui_lib/src/main/res/layout/md_layout_dialog_list_check.xml index 3c9e30c4..60bc5745 --- a/xui_lib/src/main/res/layout/md_dialog_list_check.xml +++ b/xui_lib/src/main/res/layout/md_layout_dialog_list_check.xml @@ -21,7 +21,7 @@ android:layout_height="wrap_content" android:orientation="vertical"> - + - + \ No newline at end of file diff --git a/xui_lib/src/main/res/layout/md_dialog_progress.xml b/xui_lib/src/main/res/layout/md_layout_dialog_progress.xml old mode 100755 new mode 100644 similarity index 89% rename from xui_lib/src/main/res/layout/md_dialog_progress.xml rename to xui_lib/src/main/res/layout/md_layout_dialog_progress.xml index 8a19a156..d02ca5e8 --- a/xui_lib/src/main/res/layout/md_dialog_progress.xml +++ b/xui_lib/src/main/res/layout/md_layout_dialog_progress.xml @@ -23,7 +23,7 @@ android:orientation="vertical" app:md_reduce_padding_no_title_no_buttons="false"> - + - + - + \ No newline at end of file diff --git a/xui_lib/src/main/res/layout/md_dialog_progress_indeterminate.xml b/xui_lib/src/main/res/layout/md_layout_dialog_progress_indeterminate.xml old mode 100755 new mode 100644 similarity index 85% rename from xui_lib/src/main/res/layout/md_dialog_progress_indeterminate.xml rename to xui_lib/src/main/res/layout/md_layout_dialog_progress_indeterminate.xml index f2843c08..f949c18f --- a/xui_lib/src/main/res/layout/md_dialog_progress_indeterminate.xml +++ b/xui_lib/src/main/res/layout/md_layout_dialog_progress_indeterminate.xml @@ -23,10 +23,10 @@ android:orientation="vertical" app:md_reduce_padding_no_title_no_buttons="false"> - + - + - + \ No newline at end of file diff --git a/xui_lib/src/main/res/layout/md_dialog_progress_indeterminate_horizontal.xml b/xui_lib/src/main/res/layout/md_layout_dialog_progress_indeterminate_horizontal.xml old mode 100755 new mode 100644 similarity index 88% rename from xui_lib/src/main/res/layout/md_dialog_progress_indeterminate_horizontal.xml rename to xui_lib/src/main/res/layout/md_layout_dialog_progress_indeterminate_horizontal.xml index e143c4ab..7a0ab2a9 --- a/xui_lib/src/main/res/layout/md_dialog_progress_indeterminate_horizontal.xml +++ b/xui_lib/src/main/res/layout/md_layout_dialog_progress_indeterminate_horizontal.xml @@ -23,7 +23,7 @@ android:orientation="vertical" app:md_reduce_padding_no_title_no_buttons="false"> - + - + - + \ No newline at end of file diff --git a/xui_lib/src/main/res/layout/md_listitem.xml b/xui_lib/src/main/res/layout/md_layout_listitem.xml old mode 100755 new mode 100644 similarity index 100% rename from xui_lib/src/main/res/layout/md_listitem.xml rename to xui_lib/src/main/res/layout/md_layout_listitem.xml diff --git a/xui_lib/src/main/res/layout/md_listitem_multichoice.xml b/xui_lib/src/main/res/layout/md_layout_listitem_multichoice.xml old mode 100755 new mode 100644 similarity index 100% rename from xui_lib/src/main/res/layout/md_listitem_multichoice.xml rename to xui_lib/src/main/res/layout/md_layout_listitem_multichoice.xml diff --git a/xui_lib/src/main/res/layout/md_listitem_singlechoice.xml b/xui_lib/src/main/res/layout/md_layout_listitem_singlechoice.xml old mode 100755 new mode 100644 similarity index 100% rename from xui_lib/src/main/res/layout/md_listitem_singlechoice.xml rename to xui_lib/src/main/res/layout/md_layout_listitem_singlechoice.xml diff --git a/xui_lib/src/main/res/layout/md_preference_custom.xml b/xui_lib/src/main/res/layout/md_layout_preference_custom.xml similarity index 100% rename from xui_lib/src/main/res/layout/md_preference_custom.xml rename to xui_lib/src/main/res/layout/md_layout_preference_custom.xml diff --git a/xui_lib/src/main/res/layout/md_simplelist_item.xml b/xui_lib/src/main/res/layout/md_layout_simplelist_item.xml old mode 100755 new mode 100644 similarity index 100% rename from xui_lib/src/main/res/layout/md_simplelist_item.xml rename to xui_lib/src/main/res/layout/md_layout_simplelist_item.xml diff --git a/xui_lib/src/main/res/layout/md_stub_actionbuttons.xml b/xui_lib/src/main/res/layout/md_layout_stub_actionbuttons.xml old mode 100755 new mode 100644 similarity index 100% rename from xui_lib/src/main/res/layout/md_stub_actionbuttons.xml rename to xui_lib/src/main/res/layout/md_layout_stub_actionbuttons.xml diff --git a/xui_lib/src/main/res/layout/md_stub_inputpref.xml b/xui_lib/src/main/res/layout/md_layout_stub_inputpref.xml similarity index 100% rename from xui_lib/src/main/res/layout/md_stub_inputpref.xml rename to xui_lib/src/main/res/layout/md_layout_stub_inputpref.xml diff --git a/xui_lib/src/main/res/layout/md_stub_progress.xml b/xui_lib/src/main/res/layout/md_layout_stub_progress.xml old mode 100755 new mode 100644 similarity index 100% rename from xui_lib/src/main/res/layout/md_stub_progress.xml rename to xui_lib/src/main/res/layout/md_layout_stub_progress.xml diff --git a/xui_lib/src/main/res/layout/md_stub_progress_indeterminate.xml b/xui_lib/src/main/res/layout/md_layout_stub_progress_indeterminate.xml old mode 100755 new mode 100644 similarity index 100% rename from xui_lib/src/main/res/layout/md_stub_progress_indeterminate.xml rename to xui_lib/src/main/res/layout/md_layout_stub_progress_indeterminate.xml diff --git a/xui_lib/src/main/res/layout/md_stub_progress_indeterminate_horizontal.xml b/xui_lib/src/main/res/layout/md_layout_stub_progress_indeterminate_horizontal.xml old mode 100755 new mode 100644 similarity index 100% rename from xui_lib/src/main/res/layout/md_stub_progress_indeterminate_horizontal.xml rename to xui_lib/src/main/res/layout/md_layout_stub_progress_indeterminate_horizontal.xml diff --git a/xui_lib/src/main/res/layout/md_stub_titleframe.xml b/xui_lib/src/main/res/layout/md_layout_stub_titleframe.xml old mode 100755 new mode 100644 similarity index 100% rename from xui_lib/src/main/res/layout/md_stub_titleframe.xml rename to xui_lib/src/main/res/layout/md_layout_stub_titleframe.xml diff --git a/xui_lib/src/main/res/layout/md_stub_titleframe_lesspadding.xml b/xui_lib/src/main/res/layout/md_layout_stub_titleframe_lesspadding.xml old mode 100755 new mode 100644 similarity index 100% rename from xui_lib/src/main/res/layout/md_stub_titleframe_lesspadding.xml rename to xui_lib/src/main/res/layout/md_layout_stub_titleframe_lesspadding.xml diff --git a/xui_lib/src/main/res/layout/ms_list_item.xml b/xui_lib/src/main/res/layout/ms_layout_list_item.xml old mode 100755 new mode 100644 similarity index 100% rename from xui_lib/src/main/res/layout/ms_list_item.xml rename to xui_lib/src/main/res/layout/ms_layout_list_item.xml diff --git a/xui_lib/src/main/res/layout/msv_empty_view.xml b/xui_lib/src/main/res/layout/msv_layout_empty_view.xml similarity index 100% rename from xui_lib/src/main/res/layout/msv_empty_view.xml rename to xui_lib/src/main/res/layout/msv_layout_empty_view.xml diff --git a/xui_lib/src/main/res/layout/msv_error_view.xml b/xui_lib/src/main/res/layout/msv_layout_error_view.xml similarity index 100% rename from xui_lib/src/main/res/layout/msv_error_view.xml rename to xui_lib/src/main/res/layout/msv_layout_error_view.xml diff --git a/xui_lib/src/main/res/layout/msv_loading_view.xml b/xui_lib/src/main/res/layout/msv_layout_loading_view.xml similarity index 100% rename from xui_lib/src/main/res/layout/msv_loading_view.xml rename to xui_lib/src/main/res/layout/msv_layout_loading_view.xml diff --git a/xui_lib/src/main/res/layout/msv_no_network_view.xml b/xui_lib/src/main/res/layout/msv_layout_no_network_view.xml similarity index 100% rename from xui_lib/src/main/res/layout/msv_no_network_view.xml rename to xui_lib/src/main/res/layout/msv_layout_no_network_view.xml diff --git a/xui_lib/src/main/res/layout/xui_layout_expand_list_pop.xml b/xui_lib/src/main/res/layout/xui_layout_expand_list_pop.xml new file mode 100644 index 00000000..4418ba78 --- /dev/null +++ b/xui_lib/src/main/res/layout/xui_layout_expand_list_pop.xml @@ -0,0 +1,22 @@ + + + + diff --git a/xui_lib/src/main/res/layout/layout_photo_editor_image.xml b/xui_lib/src/main/res/layout/xui_layout_photo_editor_image.xml similarity index 100% rename from xui_lib/src/main/res/layout/layout_photo_editor_image.xml rename to xui_lib/src/main/res/layout/xui_layout_photo_editor_image.xml diff --git a/xui_lib/src/main/res/layout/layout_photo_editor_text.xml b/xui_lib/src/main/res/layout/xui_layout_photo_editor_text.xml similarity index 100% rename from xui_lib/src/main/res/layout/layout_photo_editor_text.xml rename to xui_lib/src/main/res/layout/xui_layout_photo_editor_text.xml diff --git a/xui_lib/src/main/res/layout/xtoast_layout.xml b/xui_lib/src/main/res/layout/xui_layout_xtoast.xml similarity index 100% rename from xui_lib/src/main/res/layout/xtoast_layout.xml rename to xui_lib/src/main/res/layout/xui_layout_xtoast.xml diff --git a/xui_lib/src/main/res/values/xui_public.xml b/xui_lib/src/main/res/values/xui_public.xml index b750f96f..62cf99d3 100644 --- a/xui_lib/src/main/res/values/xui_public.xml +++ b/xui_lib/src/main/res/values/xui_public.xml @@ -162,13 +162,12 @@ - - - - - + + + + diff --git a/xui_lib/src/main/res/values/xui_styles_widget.xml b/xui_lib/src/main/res/values/xui_styles_widget.xml index 8f0d048e..0b3e7648 100644 --- a/xui_lib/src/main/res/values/xui_styles_widget.xml +++ b/xui_lib/src/main/res/values/xui_styles_widget.xml @@ -444,10 +444,10 @@ + + + \ No newline at end of file diff --git a/xui_lib/src/main/java/com/xuexiang/xui/utils/CountDownButtonHelper.java b/xui_lib/src/main/java/com/xuexiang/xui/utils/CountDownButtonHelper.java index 15628ba0..6252166b 100644 --- a/xui_lib/src/main/java/com/xuexiang/xui/utils/CountDownButtonHelper.java +++ b/xui_lib/src/main/java/com/xuexiang/xui/utils/CountDownButtonHelper.java @@ -89,6 +89,7 @@ public void onFinish() { * 开始倒计时 */ public void start() { + initCountDownTimer(); mButton.setEnabled(false); mCountDownTimer.start(); } @@ -130,6 +131,16 @@ public interface OnCountDownListener { public void cancel() { if (mCountDownTimer != null) { mCountDownTimer.cancel(); + mCountDownTimer = null; } } + + /** + * 资源回收 + */ + public void recycle() { + cancel(); + mListener = null; + mButton = null; + } } diff --git a/xui_lib/src/main/java/com/xuexiang/xui/utils/StatusBarUtils.java b/xui_lib/src/main/java/com/xuexiang/xui/utils/StatusBarUtils.java index 841bd0d9..fc41e018 100644 --- a/xui_lib/src/main/java/com/xuexiang/xui/utils/StatusBarUtils.java +++ b/xui_lib/src/main/java/com/xuexiang/xui/utils/StatusBarUtils.java @@ -5,9 +5,11 @@ import android.content.Context; import android.graphics.Color; import android.os.Build; + import androidx.annotation.ColorInt; import androidx.annotation.IntDef; import androidx.core.view.ViewCompat; + import android.view.Gravity; import android.view.View; import android.view.ViewGroup; @@ -61,6 +63,24 @@ private StatusBarUtils() { throw new UnsupportedOperationException("u can't instantiate me..."); } + /** + * 设置沉浸式状态栏样式 + * + * @param activity + * @param isDark 是否是深色的状态栏 + * @param colorOn5x 颜色 + */ + public static void initStatusBarStyle(Activity activity, boolean isDark, @ColorInt int colorOn5x) { + //设置沉浸式状态栏的颜色 + translucent(activity, colorOn5x); + //修改状态栏的字体颜色 + if (isDark) { + setStatusBarDarkMode(activity); + } else { + setStatusBarLightMode(activity); + } + } + /** * 沉浸式状态栏。 * 支持 4.4 以上版本的 MIUI 和 Flyme,以及 5.0 以上版本的其他 Android。 @@ -512,7 +532,7 @@ public static void fullScreen(Window window) { * @param navigationBarColor 导航栏的颜色 */ public static void cancelFullScreen(Activity activity, @ColorInt int statusBarColor, @ColorInt int navigationBarColor) { - cancelFullScreen(activity, statusBarColor, navigationBarColor); + cancelFullScreen(activity.getWindow(), statusBarColor, navigationBarColor); } /** From 9093bad02661dbb8aef1723c0f7fb537b848afd2 Mon Sep 17 00:00:00 2001 From: xuexiangjys Date: Mon, 18 Nov 2019 00:31:32 +0800 Subject: [PATCH 11/27] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=AE=80=E6=98=93?= =?UTF-8?q?=E7=9A=84=E7=99=BB=E5=BD=95=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/xuexiang/xuidemo/fragment/LoginFragment.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/LoginFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/LoginFragment.java index f006f5d8..37786add 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/fragment/LoginFragment.java +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/LoginFragment.java @@ -22,8 +22,7 @@ import com.xuexiang.xaop.annotation.SingleClick; import com.xuexiang.xpage.annotation.Page; -import com - .xuexiang.xpage.enums.CoreAnim; +import com.xuexiang.xpage.enums.CoreAnim; import com.xuexiang.xui.utils.CountDownButtonHelper; import com.xuexiang.xui.utils.ResUtils; import com.xuexiang.xui.widget.actionbar.TitleBar; From 8b37f6af01288ce132682aea82a5159349d43074 Mon Sep 17 00:00:00 2001 From: xuexiangjys Date: Mon, 18 Nov 2019 14:29:07 +0800 Subject: [PATCH 12/27] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=B8=8B=E6=8B=89?= =?UTF-8?q?=E5=88=B7=E6=96=B0=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../refresh/swipe/SwipeRefreshFragment.java | 69 ++++++++++++++++--- 1 file changed, 59 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/refresh/swipe/SwipeRefreshFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/refresh/swipe/SwipeRefreshFragment.java index e3aa7a5b..1ad9b0f6 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/refresh/swipe/SwipeRefreshFragment.java +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/refresh/swipe/SwipeRefreshFragment.java @@ -1,15 +1,19 @@ package com.xuexiang.xuidemo.fragment.components.refresh.swipe; import android.os.Handler; +import android.view.View; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; import com.xuexiang.xpage.annotation.Page; import com.xuexiang.xui.utils.WidgetUtils; +import com.xuexiang.xui.widget.banner.widget.banner.SimpleImageBanner; +import com.xuexiang.xui.widget.banner.widget.banner.base.BaseBanner; import com.xuexiang.xuidemo.DemoDataProvider; import com.xuexiang.xuidemo.R; import com.xuexiang.xuidemo.adapter.SimpleRecyclerAdapter; import com.xuexiang.xuidemo.base.BaseFragment; +import com.xuexiang.xuidemo.utils.XToastUtils; import com.xuexiang.xuidemo.widget.MaterialLoadMoreView; import com.yanzhenjie.recyclerview.SwipeRecyclerView; @@ -23,6 +27,7 @@ public class SwipeRefreshFragment extends BaseFragment { private SimpleRecyclerAdapter mAdapter; + private SimpleImageBanner banner; @BindView(R.id.recycler_view) SwipeRecyclerView recyclerView; @@ -32,6 +37,9 @@ public class SwipeRefreshFragment extends BaseFragment { private Handler mHandler = new Handler(); private boolean mEnableLoadMore; + + private int mIndex = 0; + MaterialLoadMoreView mLoadMoreView; /** * 布局的资源id * @@ -49,6 +57,19 @@ protected int getLayoutId() { protected void initViews() { WidgetUtils.initRecyclerView(recyclerView); + // HeaderView,必须在setAdapter之前调用 + View headerView = getLayoutInflater().inflate(R.layout.include_head_view_banner, recyclerView, false); + + banner = headerView.findViewById(R.id.sib_simple_usage); + banner.setSource(DemoDataProvider.getBannerList()) + .setOnItemClickL(new BaseBanner.OnItemClickL() { + @Override + public void onItemClick(int position) { + XToastUtils.toast("headBanner position--->" + position); + } + }).startScroll(); + recyclerView.addHeaderView(headerView); + recyclerView.setAdapter(mAdapter = new SimpleRecyclerAdapter()); swipeRefreshLayout.setColorSchemeColors(0xff0099cc, 0xffff4444, 0xff669900, 0xffaa66cc, 0xffff8800); @@ -60,7 +81,7 @@ protected void initListeners() { // 刷新监听。 swipeRefreshLayout.setOnRefreshListener(mRefreshListener); - refresh(); + autoRefresh(); } /** @@ -69,16 +90,17 @@ protected void initListeners() { private SwipeRefreshLayout.OnRefreshListener mRefreshListener = new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { - loadData(); + refreshData(); } }; - private void refresh() { + private void autoRefresh() { swipeRefreshLayout.setRefreshing(true); - loadData(); + refreshData(); } - private void loadData() { + private void refreshData() { + mIndex = 0; mHandler.postDelayed(new Runnable() { @Override public void run() { @@ -97,8 +119,6 @@ public void run() { private void enableLoadMore() { if (recyclerView != null && !mEnableLoadMore) { mEnableLoadMore = true; - //SwipeRefreshLayout不支持加载更多 -// recyclerView.useDefaultLoadMore(); useMaterialLoadMore(); // 加载更多的监听。 recyclerView.setLoadMoreListener(mLoadMoreListener); @@ -107,9 +127,32 @@ private void enableLoadMore() { } private void useMaterialLoadMore() { - MaterialLoadMoreView loadMoreView = new MaterialLoadMoreView(getContext()); - recyclerView.addFooterView(loadMoreView); - recyclerView.setLoadMoreView(loadMoreView); + if (mLoadMoreView == null) { + mLoadMoreView = new MaterialLoadMoreView(getContext()); + } + recyclerView.addFooterView(mLoadMoreView); + recyclerView.setLoadMoreView(mLoadMoreView); + } + + /** + * 确保有数据加载了才开启加载更多 + */ + private void disEnableLoadMore() { + if (recyclerView != null && mEnableLoadMore) { + mEnableLoadMore = false; + disableMaterialLoadMore(); + // 加载更多的监听。 + recyclerView.setLoadMoreListener(null); + recyclerView.loadMoreFinish(false, false); + } + } + + private void disableMaterialLoadMore() { + if (mLoadMoreView == null) { + mLoadMoreView = new MaterialLoadMoreView(getContext()); + } + recyclerView.removeFooterView(mLoadMoreView); + recyclerView.setLoadMoreView(null); } /** @@ -118,6 +161,7 @@ private void useMaterialLoadMore() { private SwipeRecyclerView.LoadMoreListener mLoadMoreListener = new SwipeRecyclerView.LoadMoreListener() { @Override public void onLoadMore() { + mIndex ++; mHandler.postDelayed(new Runnable() { @Override public void run() { @@ -128,6 +172,9 @@ public void run() { if (recyclerView != null) { recyclerView.loadMoreFinish(false, true); } + if (mIndex >= 2) { + disEnableLoadMore(); + } // 如果加载失败调用下面的方法,传入errorCode和errorMessage。 // errorCode随便传,你自定义LoadMoreView时可以根据errorCode判断错误类型。 // errorMessage是会显示到loadMoreView上的,用户可以看到。 @@ -140,9 +187,11 @@ public void run() { @Override public void onDestroyView() { + banner.recycle(); mHandler.removeCallbacksAndMessages(null); super.onDestroyView(); } + } From a73f9d3ceefb7bc894d6b2148e75c0a671190a30 Mon Sep 17 00:00:00 2001 From: xuexiangjys Date: Mon, 18 Nov 2019 23:00:31 +0800 Subject: [PATCH 13/27] =?UTF-8?q?=E5=AE=8C=E5=96=84=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xuidemo/fragment/AboutFragment.java | 1 + .../xuidemo/fragment/LoginFragment.java | 17 ++++- .../xuexiang/xuidemo/utils/TokenUtils.java | 4 +- app/src/main/res/layout/fragment_login.xml | 72 ++++++++++++++++++- app/src/main/res/values/strings.xml | 2 + 5 files changed, 91 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/AboutFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/AboutFragment.java index 5bd370d1..2ec3e9b2 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/fragment/AboutFragment.java +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/AboutFragment.java @@ -79,6 +79,7 @@ public void onClick(View v) { Utils.checkUpdate(getContext(), true); } }) + .addItemView(mAboutGroupListView.createItemView(getResources().getString(R.string.about_item_add_qq_group)), v -> Utils.goWeb(getContext(), getString(R.string.url_add_qq_group))) .addTo(mAboutGroupListView); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy", Locale.CHINA); diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/LoginFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/LoginFragment.java index 37786add..42d77943 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/fragment/LoginFragment.java +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/LoginFragment.java @@ -32,6 +32,7 @@ import com.xuexiang.xuidemo.activity.MainActivity; import com.xuexiang.xuidemo.base.BaseFragment; import com.xuexiang.xuidemo.utils.TokenUtils; +import com.xuexiang.xuidemo.utils.XToastUtils; import com.xuexiang.xutil.app.ActivityUtils; import com.xuexiang.xutil.common.RandomUtils; @@ -79,7 +80,7 @@ protected void initViews() { } @SingleClick - @OnClick({R.id.btn_get_verify_code, R.id.btn_login}) + @OnClick({R.id.btn_get_verify_code, R.id.btn_login, R.id.tv_other_login, R.id.tv_forget_password, R.id.tv_user_protocol, R.id.tv_privacy_protocol}) public void onViewClicked(View view) { switch (view.getId()) { case R.id.btn_get_verify_code: @@ -94,6 +95,18 @@ public void onViewClicked(View view) { } } break; + case R.id.tv_other_login: + XToastUtils.info("其他登录方式"); + break; + case R.id.tv_forget_password: + XToastUtils.info("忘记密码"); + break; + case R.id.tv_user_protocol: + XToastUtils.info("用户协议"); + break; + case R.id.tv_privacy_protocol: + XToastUtils.info("隐私政策"); + break; default: break; } @@ -117,8 +130,8 @@ private void loginByVerifyCode(String phoneNumber, String verifyCode) { // TODO: 2019-11-18 这里只是界面演示而已 String token = RandomUtils.getRandomNumbersAndLetters(16); if (TokenUtils.handleLoginSuccess(token)) { - ActivityUtils.startActivity(MainActivity.class); popToBack(); + ActivityUtils.startActivity(MainActivity.class); } } diff --git a/app/src/main/java/com/xuexiang/xuidemo/utils/TokenUtils.java b/app/src/main/java/com/xuexiang/xuidemo/utils/TokenUtils.java index ffb6e0c6..eff55e31 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/utils/TokenUtils.java +++ b/app/src/main/java/com/xuexiang/xuidemo/utils/TokenUtils.java @@ -37,7 +37,6 @@ public final class TokenUtils { private static final String KEY_TOKEN = "com.xuexiang.xuidemo.utils.KEY_TOKEN"; - private TokenUtils() { throw new UnsupportedOperationException("u can't instantiate me..."); } @@ -52,6 +51,7 @@ public static void init(Context context) { public static void setToken(String token) { sToken = token; + MMKV.defaultMMKV().putString(KEY_TOKEN, token); } public static void clearToken() { @@ -60,7 +60,7 @@ public static void clearToken() { } public static boolean hasToken() { - return !StringUtils.isEmpty(sToken); + return MMKV.defaultMMKV().containsKey(KEY_TOKEN); } /** diff --git a/app/src/main/res/layout/fragment_login.xml b/app/src/main/res/layout/fragment_login.xml index d5456b10..9bc85069 100644 --- a/app/src/main/res/layout/fragment_login.xml +++ b/app/src/main/res/layout/fragment_login.xml @@ -118,13 +118,83 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0903dc7b..009e098b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -17,6 +17,7 @@ 版本更新 GitHub主页 © %1$s xuexiangjys All rights reserved. + 加入QQ官方交流群 Far far away, behind the word mountains, far from the countries Vokalia and Consonantia, there live the blind texts. Separated they live in Bookmarksgrove right at the coast of the Semantics, a large language ocean. A small river named Duden flows by their place and supplies it with the necessary regelialia. It is a paradisematic country, in which roasted parts of sentences fly into your mouth. Even the all-powerful Pointing has no control about the blind texts it is an almost unorthographic life One day however a small line of blind text by the name of Lorem Ipsum decided to leave for the far World of Grammar. @@ -412,5 +413,6 @@ 重置密码 点击注册即表示同意 ]]> + From a122c7574bf0fe3a8f8184ebad2a5005d67f1e73 Mon Sep 17 00:00:00 2001 From: xuexiangjys Date: Tue, 19 Nov 2019 11:16:02 +0800 Subject: [PATCH 14/27] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=AD=97=E4=BD=93?= =?UTF-8?q?=E5=9B=BE=E6=A0=87=E5=BA=93=E7=9A=84=E8=AF=B4=E6=98=8E=E9=93=BE?= =?UTF-8?q?=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fragment/expands/IconFontFragment.java | 22 +++++++++++++++++++ .../xuidemo/widget/iconfont/XUIIconFont.java | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/IconFontFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/IconFontFragment.java index ef137584..c584f0fb 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/IconFontFragment.java +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/IconFontFragment.java @@ -17,12 +17,16 @@ package com.xuexiang.xuidemo.fragment.expands; +import android.view.View; + import com.xuexiang.xpage.annotation.Page; import com.xuexiang.xpage.core.PageOption; +import com.xuexiang.xui.widget.actionbar.TitleBar; import com.xuexiang.xuidemo.R; import com.xuexiang.xuidemo.base.BaseSimpleListFragment; import com.xuexiang.xuidemo.fragment.expands.iconfont.SimpleIconFontFragment; import com.xuexiang.xuidemo.fragment.expands.iconfont.XUIIconFontDisplayFragment; +import com.xuexiang.xuidemo.utils.Utils; import com.xuexiang.xuidemo.widget.iconfont.IconFontActivity; import java.util.List; @@ -56,4 +60,22 @@ protected void onItemClick(int position) { break; } } + + @Override + protected TitleBar initTitle() { + TitleBar titleBar = super.initTitle(); + titleBar.addAction(new TitleBar.TextAction("图标库") { + @Override + public void performAction(View view) { + Utils.goWeb(getContext(), "https://www.iconfont.cn/"); + } + }); + titleBar.addAction(new TitleBar.TextAction("Github") { + @Override + public void performAction(View view) { + Utils.goWeb(getContext(), "https://github.com/mikepenz/Android-Iconics"); + } + }); + return titleBar; + } } diff --git a/app/src/main/java/com/xuexiang/xuidemo/widget/iconfont/XUIIconFont.java b/app/src/main/java/com/xuexiang/xuidemo/widget/iconfont/XUIIconFont.java index 09b81f1a..bcaa11c1 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/widget/iconfont/XUIIconFont.java +++ b/app/src/main/java/com/xuexiang/xuidemo/widget/iconfont/XUIIconFont.java @@ -36,7 +36,7 @@ import java.util.Map; /** - * XUI字体图标库 + * XUI字体图标库,是使用 平台自动生成的 * * @author xuexiang * @since 2019-10-13 16:29 From 7a5f96d2bd6f882c24a2c623097cb8b716d72fad Mon Sep 17 00:00:00 2001 From: xuexiangjys Date: Thu, 21 Nov 2019 16:12:10 +0800 Subject: [PATCH 15/27] =?UTF-8?q?=E4=B8=BAVerifyCodeEditText=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E6=9B=B4=E4=B8=B0=E5=AF=8C=E7=9A=84=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E6=A1=88=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edittext/VerifyCodeEditTextFragment.java | 4 +++ .../drawable/custom_vcet_shape_bg_focus.xml | 28 +++++++++++++++++++ .../drawable/custom_vcet_shape_bg_normal.xml | 27 ++++++++++++++++++ .../layout/fragment_verify_code_edittext.xml | 15 +++++++++- 4 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 app/src/main/res/drawable/custom_vcet_shape_bg_focus.xml create mode 100644 app/src/main/res/drawable/custom_vcet_shape_bg_normal.xml diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/edittext/VerifyCodeEditTextFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/edittext/VerifyCodeEditTextFragment.java index 4a303254..a0706d65 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/edittext/VerifyCodeEditTextFragment.java +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/edittext/VerifyCodeEditTextFragment.java @@ -22,6 +22,8 @@ public class VerifyCodeEditTextFragment extends BaseFragment implements VerifyCo VerifyCodeEditText vcet2; @BindView(R.id.vcet_3) VerifyCodeEditText vcet3; + @BindView(R.id.vcet_4) + VerifyCodeEditText vcet4; @Override protected int getLayoutId() { @@ -38,6 +40,7 @@ protected void initListeners() { vcet1.setOnInputListener(this); vcet2.setOnInputListener(this); vcet3.setOnInputListener(this); + vcet4.setOnInputListener(this); } @Override @@ -60,5 +63,6 @@ public void onViewClicked() { vcet1.clearInputValue(); vcet2.clearInputValue(); vcet3.clearInputValue(); + vcet4.clearInputValue(); } } diff --git a/app/src/main/res/drawable/custom_vcet_shape_bg_focus.xml b/app/src/main/res/drawable/custom_vcet_shape_bg_focus.xml new file mode 100644 index 00000000..f93a979b --- /dev/null +++ b/app/src/main/res/drawable/custom_vcet_shape_bg_focus.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + diff --git a/app/src/main/res/drawable/custom_vcet_shape_bg_normal.xml b/app/src/main/res/drawable/custom_vcet_shape_bg_normal.xml new file mode 100644 index 00000000..cb6f615e --- /dev/null +++ b/app/src/main/res/drawable/custom_vcet_shape_bg_normal.xml @@ -0,0 +1,27 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_verify_code_edittext.xml b/app/src/main/res/layout/fragment_verify_code_edittext.xml index bd0a94d8..d096b7af 100644 --- a/app/src/main/res/layout/fragment_verify_code_edittext.xml +++ b/app/src/main/res/layout/fragment_verify_code_edittext.xml @@ -30,10 +30,23 @@ android:layout_height="wrap_content" app:vcet_is_pwd="true" /> + + + android:layout_marginTop="?attr/xui_config_content_spacing_vertical" + android:text="清空" /> \ No newline at end of file From 6c07b72403da55c7206bbc5933b0c11d21386443 Mon Sep 17 00:00:00 2001 From: xuexiangjys Date: Fri, 22 Nov 2019 16:32:44 +0800 Subject: [PATCH 16/27] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=8F=AF=E4=BC=B8?= =?UTF-8?q?=E7=BC=A9=E5=B8=83=E5=B1=80=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 2 +- .../adapter/ExpandableListAdapter.java | 110 +++++ .../fragment/components/LayoutFragment.java | 4 +- .../layout/ExpandableLayoutFragment.java | 45 ++ .../ExpandableHorizontalFragment.java | 68 +++ .../ExpandableRecycleViewFragment.java | 59 +++ .../expandable/ExpandableSimpleFragment.java | 91 ++++ .../ic_chevron_right_black_48dp.png | Bin 0 -> 660 bytes .../layout/adapter_expandable_list_item.xml | 51 +++ .../layout/fragment_expandable_horizontal.xml | 64 +++ .../res/layout/fragment_expandable_simple.xml | 72 ++++ .../res/layout/layout_common_recycleview.xml | 29 ++ .../recyclerview/BaseRecyclerAdapter.java | 4 +- .../recyclerview/XRecyclerAdapter.java | 4 +- .../xui/widget/layout/ExpandableLayout.java | 389 ++++++++++++++++++ .../FastOutSlowInInterpolator.java | 71 ++++ .../interpolator/LookupTableInterpolator.java | 58 +++ .../widget/textview/ExpandableTextView.java | 18 +- .../xui_config_list_item_selector.xml | 1 + .../xui_config_list_item_selector.xml | 1 + xui_lib/src/main/res/values/xui_attrs.xml | 27 +- 21 files changed, 1148 insertions(+), 20 deletions(-) create mode 100644 app/src/main/java/com/xuexiang/xuidemo/adapter/ExpandableListAdapter.java create mode 100644 app/src/main/java/com/xuexiang/xuidemo/fragment/components/layout/ExpandableLayoutFragment.java create mode 100644 app/src/main/java/com/xuexiang/xuidemo/fragment/components/layout/expandable/ExpandableHorizontalFragment.java create mode 100644 app/src/main/java/com/xuexiang/xuidemo/fragment/components/layout/expandable/ExpandableRecycleViewFragment.java create mode 100644 app/src/main/java/com/xuexiang/xuidemo/fragment/components/layout/expandable/ExpandableSimpleFragment.java create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_chevron_right_black_48dp.png create mode 100644 app/src/main/res/layout/adapter_expandable_list_item.xml create mode 100644 app/src/main/res/layout/fragment_expandable_horizontal.xml create mode 100644 app/src/main/res/layout/fragment_expandable_simple.xml create mode 100644 app/src/main/res/layout/layout_common_recycleview.xml create mode 100644 xui_lib/src/main/java/com/xuexiang/xui/widget/layout/ExpandableLayout.java create mode 100644 xui_lib/src/main/java/com/xuexiang/xui/widget/layout/interpolator/FastOutSlowInInterpolator.java create mode 100644 xui_lib/src/main/java/com/xuexiang/xui/widget/layout/interpolator/LookupTableInterpolator.java diff --git a/app/build.gradle b/app/build.gradle index dfecccf2..4cbe6bc0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -184,7 +184,7 @@ dependencies { //图标库控件(可选) implementation "com.mikepenz:iconics-views:4.0.1-b02" //相机拍摄 - implementation 'com.github.xuexiangjys:CameraView:1.0.2' + implementation 'com.github.xuexiangjys:CameraView:1.0.3' //版本更新 implementation 'com.github.xuexiangjys:XUpdate:1.1.1' diff --git a/app/src/main/java/com/xuexiang/xuidemo/adapter/ExpandableListAdapter.java b/app/src/main/java/com/xuexiang/xuidemo/adapter/ExpandableListAdapter.java new file mode 100644 index 00000000..9f96ffc6 --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/adapter/ExpandableListAdapter.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.xuexiang.xuidemo.adapter; + +import android.view.View; +import android.view.animation.OvershootInterpolator; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.xuexiang.xaop.annotation.SingleClick; +import com.xuexiang.xui.adapter.recyclerview.BaseRecyclerAdapter; +import com.xuexiang.xui.adapter.recyclerview.RecyclerViewHolder; +import com.xuexiang.xui.utils.ResUtils; +import com.xuexiang.xui.widget.layout.ExpandableLayout; +import com.xuexiang.xuidemo.R; + +import java.util.Collection; + +/** + * 可伸缩布局适配器 + * + * @author xuexiang + * @since 2019-11-22 15:38 + */ +public class ExpandableListAdapter extends BaseRecyclerAdapter { + + private RecyclerView mRecyclerView; + + public ExpandableListAdapter(RecyclerView recyclerView, Collection data) { + super(data); + mRecyclerView = recyclerView; + } + + /** + * 适配的布局 + * + * @param viewType + * @return + */ + @Override + protected int getItemLayoutId(int viewType) { + return R.layout.adapter_expandable_list_item; + } + + /** + * 绑定数据 + * + * @param holder + * @param position 索引 + * @param item 列表项 + */ + @Override + protected void bindData(@NonNull RecyclerViewHolder holder, int position, String item) { + ExpandableLayout expandableLayout = holder.findViewById(R.id.expandable_layout); + expandableLayout.setInterpolator(new OvershootInterpolator()); + expandableLayout.setOnExpansionChangedListener(new ExpandableLayout.OnExpansionChangedListener() { + @Override + public void onExpansionChanged(float expansion, int state) { + if (state == ExpandableLayout.State.EXPANDING) { + mRecyclerView.smoothScrollToPosition(position); + } + } + }); + + boolean isSelected = position == mSelectPosition; + expandableLayout.setExpanded(isSelected, false); + + holder.select(R.id.tv_content, isSelected); + holder.text(R.id.tv_content, ResUtils.getResources().getString(R.string.item_example_number_title, position)); + holder.click(R.id.tv_content, new View.OnClickListener() { + @SingleClick + @Override + public void onClick(View v) { + onClickItem(v, expandableLayout, position); + } + }); + } + + private void onClickItem(View view, final ExpandableLayout expandableLayout, final int position) { + RecyclerViewHolder holder = (RecyclerViewHolder) mRecyclerView.findViewHolderForAdapterPosition(mSelectPosition); + if (holder != null) { + holder.select(R.id.tv_content, false); + ((ExpandableLayout) holder.findViewById(R.id.expandable_layout)).collapse(); + } + + if (position == mSelectPosition) { + mSelectPosition = -1; + } else { + view.setSelected(true); + expandableLayout.expand(); + mSelectPosition = position; + } + } +} diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/LayoutFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/LayoutFragment.java index e1dab7a7..b6ba9bf9 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/LayoutFragment.java +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/LayoutFragment.java @@ -21,6 +21,7 @@ import com.xuexiang.xuidemo.R; import com.xuexiang.xuidemo.base.ComponentContainerFragment; import com.xuexiang.xuidemo.fragment.components.layout.AlphaViewFragment; +import com.xuexiang.xuidemo.fragment.components.layout.ExpandableLayoutFragment; import com.xuexiang.xuidemo.fragment.components.layout.XUILayoutFragment; /** @@ -38,7 +39,8 @@ public class LayoutFragment extends ComponentContainerFragment { protected Class[] getPagesClasses() { return new Class[]{ AlphaViewFragment.class, - XUILayoutFragment.class + XUILayoutFragment.class, + ExpandableLayoutFragment.class }; } } diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/layout/ExpandableLayoutFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/layout/ExpandableLayoutFragment.java new file mode 100644 index 00000000..23f3e037 --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/layout/ExpandableLayoutFragment.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.xuexiang.xuidemo.fragment.components.layout; + +import com.xuexiang.xpage.annotation.Page; +import com.xuexiang.xuidemo.base.ComponentContainerFragment; +import com.xuexiang.xuidemo.fragment.components.layout.expandable.ExpandableHorizontalFragment; +import com.xuexiang.xuidemo.fragment.components.layout.expandable.ExpandableRecycleViewFragment; +import com.xuexiang.xuidemo.fragment.components.layout.expandable.ExpandableSimpleFragment; + +/** + * @author xuexiang + * @since 2019-11-22 14:18 + */ +@Page(name = "可伸缩布局\n可水平、垂直伸缩") +public class ExpandableLayoutFragment extends ComponentContainerFragment { + /** + * 获取页面的类集合[使用@Page注解进行注册的页面] + * + * @return + */ + @Override + protected Class[] getPagesClasses() { + return new Class[]{ + ExpandableSimpleFragment.class, + ExpandableHorizontalFragment.class, + ExpandableRecycleViewFragment.class + }; + } +} diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/layout/expandable/ExpandableHorizontalFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/layout/expandable/ExpandableHorizontalFragment.java new file mode 100644 index 00000000..f201f443 --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/layout/expandable/ExpandableHorizontalFragment.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.xuexiang.xuidemo.fragment.components.layout.expandable; + +import androidx.appcompat.widget.AppCompatImageView; + +import com.xuexiang.xpage.annotation.Page; +import com.xuexiang.xui.widget.layout.ExpandableLayout; +import com.xuexiang.xuidemo.R; +import com.xuexiang.xuidemo.base.BaseFragment; + +import butterknife.BindView; +import butterknife.OnClick; + +/** + * @author xuexiang + * @since 2019-11-22 14:42 + */ +@Page(name = "水平伸缩使用") +public class ExpandableHorizontalFragment extends BaseFragment { + @BindView(R.id.expandable_layout) + ExpandableLayout expandableLayout; + @BindView(R.id.expand_button) + AppCompatImageView expandButton; + + /** + * 布局的资源id + * + * @return + */ + @Override + protected int getLayoutId() { + return R.layout.fragment_expandable_horizontal; + } + + /** + * 初始化控件 + */ + @Override + protected void initViews() { + expandableLayout.setOnExpansionChangedListener(new ExpandableLayout.OnExpansionChangedListener() { + @Override + public void onExpansionChanged(float expansion, int state) { + expandButton.setRotation(expansion * 180); + } + }); + } + + @OnClick(R.id.expand_button) + public void onViewClicked() { + expandableLayout.toggle(); + } +} diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/layout/expandable/ExpandableRecycleViewFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/layout/expandable/ExpandableRecycleViewFragment.java new file mode 100644 index 00000000..4a9adf4c --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/layout/expandable/ExpandableRecycleViewFragment.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.xuexiang.xuidemo.fragment.components.layout.expandable; + +import androidx.recyclerview.widget.RecyclerView; + +import com.xuexiang.xpage.annotation.Page; +import com.xuexiang.xui.utils.WidgetUtils; +import com.xuexiang.xuidemo.DemoDataProvider; +import com.xuexiang.xuidemo.R; +import com.xuexiang.xuidemo.adapter.ExpandableListAdapter; +import com.xuexiang.xuidemo.base.BaseFragment; + +import butterknife.BindView; + +/** + * @author xuexiang + * @since 2019-11-22 15:33 + */ +@Page(name = "在RecycleView中使用") +public class ExpandableRecycleViewFragment extends BaseFragment { + @BindView(R.id.recycler_view) + RecyclerView recyclerView; + + /** + * 布局的资源id + * + * @return + */ + @Override + protected int getLayoutId() { + return R.layout.layout_common_recycleview; + } + + /** + * 初始化控件 + */ + @Override + protected void initViews() { + WidgetUtils.initRecyclerView(recyclerView, 0); + + recyclerView.setAdapter(new ExpandableListAdapter(recyclerView, DemoDataProvider.getDemoData1())); + } +} diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/layout/expandable/ExpandableSimpleFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/layout/expandable/ExpandableSimpleFragment.java new file mode 100644 index 00000000..01ff9869 --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/layout/expandable/ExpandableSimpleFragment.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.xuexiang.xuidemo.fragment.components.layout.expandable; + +import android.util.Log; + +import com.xuexiang.xpage.annotation.Page; +import com.xuexiang.xui.widget.layout.ExpandableLayout; +import com.xuexiang.xuidemo.R; +import com.xuexiang.xuidemo.base.BaseFragment; +import com.xuexiang.xuidemo.utils.XToastUtils; + +import butterknife.BindView; +import butterknife.OnClick; + +import static com.xuexiang.xui.widget.layout.ExpandableLayout.State.COLLAPSED; +import static com.xuexiang.xui.widget.layout.ExpandableLayout.State.EXPANDED; + +/** + * @author xuexiang + * @since 2019-11-22 14:21 + */ +@Page(name = "可伸缩布局简单使用") +public class ExpandableSimpleFragment extends BaseFragment { + + @BindView(R.id.expandable_layout_1) + ExpandableLayout expandableLayout1; + @BindView(R.id.expandable_layout_2) + ExpandableLayout expandableLayout2; + + /** + * 布局的资源id + * + * @return + */ + @Override + protected int getLayoutId() { + return R.layout.fragment_expandable_simple; + } + + /** + * 初始化控件 + */ + @Override + protected void initViews() { + expandableLayout1.setOnExpansionChangedListener(new ExpandableLayout.OnExpansionChangedListener() { + @Override + public void onExpansionChanged(float expansion, int state) { + Log.d("expandableLayout1", "State: " + state); + } + }); + + expandableLayout2.setOnExpansionChangedListener(new ExpandableLayout.OnExpansionChangedListener() { + @Override + public void onExpansionChanged(float expansion, int state) { + if (state == COLLAPSED) { + XToastUtils.toast("已收起"); + } else if (state == EXPANDED) { + XToastUtils.toast("已展开"); + } + } + }); + } + + @OnClick(R.id.expand_button) + public void onViewClicked() { + if (expandableLayout1.isExpanded()) { + expandableLayout1.collapse(); + } else if (expandableLayout2.isExpanded()) { + expandableLayout2.collapse(); + } else { + expandableLayout1.expand(); + expandableLayout2.expand(); + } + } +} diff --git a/app/src/main/res/drawable-xxxhdpi/ic_chevron_right_black_48dp.png b/app/src/main/res/drawable-xxxhdpi/ic_chevron_right_black_48dp.png new file mode 100644 index 0000000000000000000000000000000000000000..2ba0db98e438363ac9a05c240e8356b3c9126f21 GIT binary patch literal 660 zcmeAS@N?(olHy`uVBq!ia0vp^2SAvE4M+yv$zcalY)RhkE(}DB>Fg|~vUlf0*kV@SoVw|Bk$t`;yHeYiNU(UoIGjNEM{ z4<5r~67R0181G4CKk$T4M&ilE*~@J2PdAxs`d5Ab9azFExL?q~)A?9F zi_a;yNuPP_8I%)@?2d70q_bSP-6I%~XMEDNry$!Sgsf|y~;h# zp|O4L6D>CfL*)hcmIGyb8mfTm&KokFs_hgEILEPKyRhQ*r~ zWa`pQVwrNg7ihlu$y~7cwm?JTfYQ~T|BisIxZMwwwLcjPm5o^ZJ$XOF|F3zA&bOIc zpZK-!-|3C~?EZrGTaWnbehl{hb47^i%(cC1-plU=*>k>d#uK|o%Wnj>NgphFbNE1Z zP45rQa+#08@1l?R@0{E*zv#Yl-KoDFKQzA^KU#igeMkK#yPm&H!e!fb{qJKW6m=kZ a<4+u#DRHZQKWIt-aXnrAT-G@yGywp=%Kn)E literal 0 HcmV?d00001 diff --git a/app/src/main/res/layout/adapter_expandable_list_item.xml b/app/src/main/res/layout/adapter_expandable_list_item.xml new file mode 100644 index 00000000..d7f92869 --- /dev/null +++ b/app/src/main/res/layout/adapter_expandable_list_item.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_expandable_horizontal.xml b/app/src/main/res/layout/fragment_expandable_horizontal.xml new file mode 100644 index 00000000..a474e5d9 --- /dev/null +++ b/app/src/main/res/layout/fragment_expandable_horizontal.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_expandable_simple.xml b/app/src/main/res/layout/fragment_expandable_simple.xml new file mode 100644 index 00000000..ab34720d --- /dev/null +++ b/app/src/main/res/layout/fragment_expandable_simple.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_common_recycleview.xml b/app/src/main/res/layout/layout_common_recycleview.xml new file mode 100644 index 00000000..5c9d64d5 --- /dev/null +++ b/app/src/main/res/layout/layout_common_recycleview.xml @@ -0,0 +1,29 @@ + + + + + + + \ No newline at end of file diff --git a/xui_lib/src/main/java/com/xuexiang/xui/adapter/recyclerview/BaseRecyclerAdapter.java b/xui_lib/src/main/java/com/xuexiang/xui/adapter/recyclerview/BaseRecyclerAdapter.java index 881cdef8..f1de33ed 100755 --- a/xui_lib/src/main/java/com/xuexiang/xui/adapter/recyclerview/BaseRecyclerAdapter.java +++ b/xui_lib/src/main/java/com/xuexiang/xui/adapter/recyclerview/BaseRecyclerAdapter.java @@ -21,7 +21,7 @@ import androidx.annotation.NonNull; -import java.util.List; +import java.util.Collection; /** * 通用的RecyclerView适配器 @@ -35,7 +35,7 @@ public BaseRecyclerAdapter() { super(); } - public BaseRecyclerAdapter(List list) { + public BaseRecyclerAdapter(Collection list) { super(list); } diff --git a/xui_lib/src/main/java/com/xuexiang/xui/adapter/recyclerview/XRecyclerAdapter.java b/xui_lib/src/main/java/com/xuexiang/xui/adapter/recyclerview/XRecyclerAdapter.java index a6307ac7..a46d1678 100644 --- a/xui_lib/src/main/java/com/xuexiang/xui/adapter/recyclerview/XRecyclerAdapter.java +++ b/xui_lib/src/main/java/com/xuexiang/xui/adapter/recyclerview/XRecyclerAdapter.java @@ -54,13 +54,13 @@ public abstract class XRecyclerAdapter ext /** * 当前点击的条目 */ - private int mSelectPosition = -1; + protected int mSelectPosition = -1; public XRecyclerAdapter() { } - public XRecyclerAdapter(List list) { + public XRecyclerAdapter(Collection list) { if (list != null) { mData.addAll(list); } diff --git a/xui_lib/src/main/java/com/xuexiang/xui/widget/layout/ExpandableLayout.java b/xui_lib/src/main/java/com/xuexiang/xui/widget/layout/ExpandableLayout.java new file mode 100644 index 00000000..7cd764c0 --- /dev/null +++ b/xui_lib/src/main/java/com/xuexiang/xui/widget/layout/ExpandableLayout.java @@ -0,0 +1,389 @@ +/* + * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.xuexiang.xui.widget.layout; + +import android.animation.Animator; +import android.animation.ValueAnimator; +import android.content.Context; +import android.content.res.Configuration; +import android.content.res.TypedArray; +import android.os.Bundle; +import android.os.Parcelable; +import android.util.AttributeSet; +import android.view.View; +import android.view.animation.Interpolator; +import android.widget.FrameLayout; +import android.widget.LinearLayout; + +import com.xuexiang.xui.R; +import com.xuexiang.xui.widget.layout.interpolator.FastOutSlowInInterpolator; + +import static com.xuexiang.xui.widget.layout.ExpandableLayout.State.COLLAPSED; +import static com.xuexiang.xui.widget.layout.ExpandableLayout.State.COLLAPSING; +import static com.xuexiang.xui.widget.layout.ExpandableLayout.State.EXPANDED; +import static com.xuexiang.xui.widget.layout.ExpandableLayout.State.EXPANDING; + +/** + * 可伸缩的布局 + * + * @author xuexiang + * @since 2019-11-22 13:41 + */ +public class ExpandableLayout extends FrameLayout { + + public interface State { + /** + * 已收缩 + */ + int COLLAPSED = 0; + /** + * 收缩中 + */ + int COLLAPSING = 1; + /** + * 伸展中 + */ + int EXPANDING = 2; + /** + * 已伸展 + */ + int EXPANDED = 3; + } + + public static final String KEY_SUPER_STATE = "key_super_state"; + public static final String KEY_EXPANSION = "key_expansion"; + + public static final int HORIZONTAL = 0; + public static final int VERTICAL = 1; + + /** + * 默认伸缩动画持续的时间 + */ + private static final int DEFAULT_DURATION = 300; + + /** + * 伸缩动画持续的时间 + */ + private int mDuration = DEFAULT_DURATION; + /** + * 视差效果 + */ + private float mParallax; + /** + * 伸缩比率【Value between 0 (收缩) and 1 (伸展) 】 + */ + private float mExpansion; + /** + * 伸缩方向 + */ + private int mOrientation; + /** + * 伸缩状态 + */ + private int mState; + + private Interpolator mInterpolator = new FastOutSlowInInterpolator(); + private ValueAnimator mAnimator; + private OnExpansionChangedListener mListener; + + public ExpandableLayout(Context context) { + this(context, null); + } + + public ExpandableLayout(Context context, AttributeSet attrs) { + super(context, attrs); + if (attrs != null) { + TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.ExpandableLayout); + mDuration = a.getInt(R.styleable.ExpandableLayout_el_duration, DEFAULT_DURATION); + mExpansion = a.getBoolean(R.styleable.ExpandableLayout_el_expanded, false) ? 1 : 0; + mOrientation = a.getInt(R.styleable.ExpandableLayout_android_orientation, VERTICAL); + mParallax = a.getFloat(R.styleable.ExpandableLayout_el_parallax, 1); + a.recycle(); + mState = mExpansion == 0 ? COLLAPSED : EXPANDED; + setParallax(mParallax); + } + } + + @Override + protected Parcelable onSaveInstanceState() { + Parcelable superState = super.onSaveInstanceState(); + Bundle bundle = new Bundle(); + mExpansion = isExpanded() ? 1 : 0; + bundle.putFloat(KEY_EXPANSION, mExpansion); + bundle.putParcelable(KEY_SUPER_STATE, superState); + return bundle; + } + + @Override + protected void onRestoreInstanceState(Parcelable parcelable) { + Bundle bundle = (Bundle) parcelable; + mExpansion = bundle.getFloat(KEY_EXPANSION); + mState = mExpansion == 1 ? EXPANDED : COLLAPSED; + Parcelable superState = bundle.getParcelable(KEY_SUPER_STATE); + super.onRestoreInstanceState(superState); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + int width = getMeasuredWidth(); + int height = getMeasuredHeight(); + int size = mOrientation == LinearLayout.HORIZONTAL ? width : height; + setVisibility(mExpansion == 0 && size == 0 ? GONE : VISIBLE); + int expansionDelta = size - Math.round(size * mExpansion); + if (mParallax > 0) { + float parallaxDelta = expansionDelta * mParallax; + for (int i = 0; i < getChildCount(); i++) { + View child = getChildAt(i); + if (mOrientation == HORIZONTAL) { + int direction = -1; + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1 && getLayoutDirection() == LAYOUT_DIRECTION_RTL) { + direction = 1; + } + child.setTranslationX(direction * parallaxDelta); + } else { + child.setTranslationY(-parallaxDelta); + } + } + } + + if (mOrientation == HORIZONTAL) { + setMeasuredDimension(width - expansionDelta, height); + } else { + setMeasuredDimension(width, height - expansionDelta); + } + } + + @Override + protected void onConfigurationChanged(Configuration newConfig) { + if (mAnimator != null) { + mAnimator.cancel(); + } + super.onConfigurationChanged(newConfig); + } + + /** + * Get mExpansion mState + * + * @return one of {@link State} + */ + public int getState() { + return mState; + } + + public boolean isExpanded() { + return mState == EXPANDING || mState == EXPANDED; + } + + /** + * 切换 + */ + public void toggle() { + toggle(true); + } + + public void toggle(boolean animate) { + if (isExpanded()) { + collapse(animate); + } else { + expand(animate); + } + } + + /** + * 伸展 + */ + public void expand() { + expand(true); + } + + public void expand(boolean animate) { + setExpanded(true, animate); + } + + /** + * 收缩 + */ + public void collapse() { + collapse(true); + } + + public void collapse(boolean animate) { + setExpanded(false, animate); + } + + /** + * Convenience method - same as calling setExpanded(expanded, true) + */ + public void setExpanded(boolean expand) { + setExpanded(expand, true); + } + + public void setExpanded(boolean expand, boolean animate) { + if (expand == isExpanded()) { + return; + } + + int targetExpansion = expand ? 1 : 0; + if (animate) { + animateSize(targetExpansion); + } else { + setExpansion(targetExpansion); + } + } + + public int getDuration() { + return mDuration; + } + + public ExpandableLayout setInterpolator(Interpolator interpolator) { + mInterpolator = interpolator; + return this; + } + + public ExpandableLayout setDuration(int duration) { + mDuration = duration; + return this; + } + + public float getExpansion() { + return mExpansion; + } + + public void setExpansion(float expansion) { + if (mExpansion == expansion) { + return; + } + // Infer mState from previous value + float delta = expansion - this.mExpansion; + if (expansion == 0) { + mState = COLLAPSED; + } else if (expansion == 1) { + mState = EXPANDED; + } else if (delta < 0) { + mState = COLLAPSING; + } else if (delta > 0) { + mState = EXPANDING; + } + setVisibility(mState == COLLAPSED ? GONE : VISIBLE); + mExpansion = expansion; + requestLayout(); + + if (mListener != null) { + mListener.onExpansionChanged(expansion, mState); + } + } + + public float getParallax() { + return mParallax; + } + + public ExpandableLayout setParallax(float parallax) { + parallax = Math.min(1, Math.max(0, parallax)); + mParallax = parallax; + return this; + } + + public int getOrientation() { + return mOrientation; + } + + public ExpandableLayout setOrientation(int orientation) { + if (orientation < 0 || orientation > 1) { + throw new IllegalArgumentException("Orientation must be either 0 (horizontal) or 1 (vertical)"); + } + mOrientation = orientation; + return this; + } + + /** + * 设置伸缩比率变化监听 + * @param listener + * @return + */ + public ExpandableLayout setOnExpansionChangedListener(OnExpansionChangedListener listener) { + mListener = listener; + return this; + } + + private void animateSize(int targetExpansion) { + if (mAnimator != null) { + mAnimator.cancel(); + mAnimator = null; + } + + mAnimator = ValueAnimator.ofFloat(mExpansion, targetExpansion); + mAnimator.setInterpolator(mInterpolator); + mAnimator.setDuration(mDuration); + + mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator valueAnimator) { + setExpansion((float) valueAnimator.getAnimatedValue()); + } + }); + + mAnimator.addListener(new ExpansionListener(targetExpansion)); + + mAnimator.start(); + } + + /** + * 伸缩比率变化监听 + */ + public interface OnExpansionChangedListener { + /** + * 伸缩比率变化 + * + * @param expansion 伸缩比率【Value between 0 (收缩) and 1 (伸展) 】 + * @param state 伸缩状态 + */ + void onExpansionChanged(float expansion, int state); + } + + private class ExpansionListener implements Animator.AnimatorListener { + private int targetExpansion; + private boolean canceled; + + public ExpansionListener(int targetExpansion) { + this.targetExpansion = targetExpansion; + } + + @Override + public void onAnimationStart(Animator animation) { + mState = targetExpansion == 0 ? COLLAPSING : EXPANDING; + } + + @Override + public void onAnimationEnd(Animator animation) { + if (!canceled) { + mState = targetExpansion == 0 ? COLLAPSED : EXPANDED; + setExpansion(targetExpansion); + } + } + + @Override + public void onAnimationCancel(Animator animation) { + canceled = true; + } + + @Override + public void onAnimationRepeat(Animator animation) { + } + } +} diff --git a/xui_lib/src/main/java/com/xuexiang/xui/widget/layout/interpolator/FastOutSlowInInterpolator.java b/xui_lib/src/main/java/com/xuexiang/xui/widget/layout/interpolator/FastOutSlowInInterpolator.java new file mode 100644 index 00000000..5329a766 --- /dev/null +++ b/xui_lib/src/main/java/com/xuexiang/xui/widget/layout/interpolator/FastOutSlowInInterpolator.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.xuexiang.xui.widget.layout.interpolator; + +/** + * Interpolator corresponding to {@link android.R.interpolator#fast_out_slow_in}. + * + * Uses a lookup table for the Bezier curve from (0,0) to (1,1) with control points: + * P0 (0, 0) + * P1 (0.4, 0) + * P2 (0.2, 1.0) + * P3 (1.0, 1.0) + */ +public class FastOutSlowInInterpolator extends LookupTableInterpolator { + + /** + * Lookup table values sampled with x at regular intervals between 0 and 1 for a total of + * 201 points. + */ + private static final float[] VALUES = new float[] { + 0.0000f, 0.0001f, 0.0002f, 0.0005f, 0.0009f, 0.0014f, 0.0020f, + 0.0027f, 0.0036f, 0.0046f, 0.0058f, 0.0071f, 0.0085f, 0.0101f, + 0.0118f, 0.0137f, 0.0158f, 0.0180f, 0.0205f, 0.0231f, 0.0259f, + 0.0289f, 0.0321f, 0.0355f, 0.0391f, 0.0430f, 0.0471f, 0.0514f, + 0.0560f, 0.0608f, 0.0660f, 0.0714f, 0.0771f, 0.0830f, 0.0893f, + 0.0959f, 0.1029f, 0.1101f, 0.1177f, 0.1257f, 0.1339f, 0.1426f, + 0.1516f, 0.1610f, 0.1707f, 0.1808f, 0.1913f, 0.2021f, 0.2133f, + 0.2248f, 0.2366f, 0.2487f, 0.2611f, 0.2738f, 0.2867f, 0.2998f, + 0.3131f, 0.3265f, 0.3400f, 0.3536f, 0.3673f, 0.3810f, 0.3946f, + 0.4082f, 0.4217f, 0.4352f, 0.4485f, 0.4616f, 0.4746f, 0.4874f, + 0.5000f, 0.5124f, 0.5246f, 0.5365f, 0.5482f, 0.5597f, 0.5710f, + 0.5820f, 0.5928f, 0.6033f, 0.6136f, 0.6237f, 0.6335f, 0.6431f, + 0.6525f, 0.6616f, 0.6706f, 0.6793f, 0.6878f, 0.6961f, 0.7043f, + 0.7122f, 0.7199f, 0.7275f, 0.7349f, 0.7421f, 0.7491f, 0.7559f, + 0.7626f, 0.7692f, 0.7756f, 0.7818f, 0.7879f, 0.7938f, 0.7996f, + 0.8053f, 0.8108f, 0.8162f, 0.8215f, 0.8266f, 0.8317f, 0.8366f, + 0.8414f, 0.8461f, 0.8507f, 0.8551f, 0.8595f, 0.8638f, 0.8679f, + 0.8720f, 0.8760f, 0.8798f, 0.8836f, 0.8873f, 0.8909f, 0.8945f, + 0.8979f, 0.9013f, 0.9046f, 0.9078f, 0.9109f, 0.9139f, 0.9169f, + 0.9198f, 0.9227f, 0.9254f, 0.9281f, 0.9307f, 0.9333f, 0.9358f, + 0.9382f, 0.9406f, 0.9429f, 0.9452f, 0.9474f, 0.9495f, 0.9516f, + 0.9536f, 0.9556f, 0.9575f, 0.9594f, 0.9612f, 0.9629f, 0.9646f, + 0.9663f, 0.9679f, 0.9695f, 0.9710f, 0.9725f, 0.9739f, 0.9753f, + 0.9766f, 0.9779f, 0.9791f, 0.9803f, 0.9815f, 0.9826f, 0.9837f, + 0.9848f, 0.9858f, 0.9867f, 0.9877f, 0.9885f, 0.9894f, 0.9902f, + 0.9910f, 0.9917f, 0.9924f, 0.9931f, 0.9937f, 0.9944f, 0.9949f, + 0.9955f, 0.9960f, 0.9964f, 0.9969f, 0.9973f, 0.9977f, 0.9980f, + 0.9984f, 0.9986f, 0.9989f, 0.9991f, 0.9993f, 0.9995f, 0.9997f, + 0.9998f, 0.9999f, 0.9999f, 1.0000f, 1.0000f + }; + + public FastOutSlowInInterpolator() { + super(VALUES); + } + +} diff --git a/xui_lib/src/main/java/com/xuexiang/xui/widget/layout/interpolator/LookupTableInterpolator.java b/xui_lib/src/main/java/com/xuexiang/xui/widget/layout/interpolator/LookupTableInterpolator.java new file mode 100644 index 00000000..f1f65e85 --- /dev/null +++ b/xui_lib/src/main/java/com/xuexiang/xui/widget/layout/interpolator/LookupTableInterpolator.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.xuexiang.xui.widget.layout.interpolator; + +import android.view.animation.Interpolator; + +/** + * An {@link Interpolator} that uses a lookup table to compute an interpolation based on a + * given input. + */ +abstract class LookupTableInterpolator implements Interpolator { + + private final float[] mValues; + private final float mStepSize; + + public LookupTableInterpolator(float[] values) { + mValues = values; + mStepSize = 1f / (mValues.length - 1); + } + + @Override + public float getInterpolation(float input) { + if (input >= 1.0f) { + return 1.0f; + } + if (input <= 0f) { + return 0f; + } + + // Calculate index - We use min with length - 2 to avoid IndexOutOfBoundsException when + // we lerp (linearly interpolate) in the return statement + int position = Math.min((int) (input * (mValues.length - 1)), mValues.length - 2); + + // Calculate values to account for small offsets as the lookup table has discrete values + float quantized = position * mStepSize; + float diff = input - quantized; + float weight = diff / mStepSize; + + // Linearly interpolate between the table values + return mValues[position] + weight * (mValues[position + 1] - mValues[position]); + } + +} diff --git a/xui_lib/src/main/java/com/xuexiang/xui/widget/textview/ExpandableTextView.java b/xui_lib/src/main/java/com/xuexiang/xui/widget/textview/ExpandableTextView.java index bd9eae14..e35c95b1 100755 --- a/xui_lib/src/main/java/com/xuexiang/xui/widget/textview/ExpandableTextView.java +++ b/xui_lib/src/main/java/com/xuexiang/xui/widget/textview/ExpandableTextView.java @@ -93,8 +93,8 @@ public ExpandableTextView(Context context, AttributeSet attrs, int defStyle) { } @Override - public void setOrientation(int orientation){ - if(LinearLayout.HORIZONTAL == orientation){ + public void setOrientation(int orientation) { + if (LinearLayout.HORIZONTAL == orientation) { throw new IllegalArgumentException("ExpandableTextView only supports Vertical Orientation."); } super.setOrientation(orientation); @@ -130,6 +130,7 @@ public void onClick(View view) { public void onAnimationStart(Animation animation) { applyAlphaAnimation(mTv, mAnimAlphaStart); } + @Override public void onAnimationEnd(Animation animation) { // clear animation here to avoid repeated applyTransformation() calls @@ -142,8 +143,10 @@ public void onAnimationEnd(Animation animation) { mListener.onExpandStateChanged(mTv, !mCollapsed); } } + @Override - public void onAnimationRepeat(Animation animation) { } + public void onAnimationRepeat(Animation animation) { + } }); clearAnimation(); @@ -213,6 +216,7 @@ public void run() { /** * 设置伸展状态监听 + * * @param listener */ public void setOnExpandStateChangeListener(@Nullable OnExpandStateChangeListener listener) { @@ -336,7 +340,7 @@ public ExpandCollapseAnimation(View view, int startHeight, int endHeight) { @Override protected void applyTransformation(float interpolatedTime, Transformation t) { - final int newHeight = (int)((mEndHeight - mStartHeight) * interpolatedTime + mStartHeight); + final int newHeight = (int) ((mEndHeight - mStartHeight) * interpolatedTime + mStartHeight); mTv.setMaxHeight(newHeight - mMarginBetweenTxtAndBottom); if (Float.compare(mAnimAlphaStart, 1.0f) != 0) { applyAlphaAnimation(mTv, mAnimAlphaStart + interpolatedTime * (1.0f - mAnimAlphaStart)); @@ -346,12 +350,12 @@ protected void applyTransformation(float interpolatedTime, Transformation t) { } @Override - public void initialize( int width, int height, int parentWidth, int parentHeight ) { + public void initialize(int width, int height, int parentWidth, int parentHeight) { super.initialize(width, height, parentWidth, parentHeight); } @Override - public boolean willChangeBounds( ) { + public boolean willChangeBounds() { return true; } } @@ -360,7 +364,7 @@ public interface OnExpandStateChangeListener { /** * Called when the expand/collapse animation has been finished * - * @param textView - TextView being expanded/collapsed + * @param textView - TextView being expanded/collapsed * @param isExpanded - true if the TextView has been expanded */ void onExpandStateChanged(TextView textView, boolean isExpanded); diff --git a/xui_lib/src/main/res/drawable-v17/xui_config_list_item_selector.xml b/xui_lib/src/main/res/drawable-v17/xui_config_list_item_selector.xml index 9296c89e..ff6d61af 100644 --- a/xui_lib/src/main/res/drawable-v17/xui_config_list_item_selector.xml +++ b/xui_lib/src/main/res/drawable-v17/xui_config_list_item_selector.xml @@ -1,5 +1,6 @@ + \ No newline at end of file diff --git a/xui_lib/src/main/res/drawable/xui_config_list_item_selector.xml b/xui_lib/src/main/res/drawable/xui_config_list_item_selector.xml index 469a9b1c..1608777e 100755 --- a/xui_lib/src/main/res/drawable/xui_config_list_item_selector.xml +++ b/xui_lib/src/main/res/drawable/xui_config_list_item_selector.xml @@ -1,5 +1,6 @@ + \ No newline at end of file diff --git a/xui_lib/src/main/res/values/xui_attrs.xml b/xui_lib/src/main/res/values/xui_attrs.xml index a41fcbd7..7a06f17e 100755 --- a/xui_lib/src/main/res/values/xui_attrs.xml +++ b/xui_lib/src/main/res/values/xui_attrs.xml @@ -123,6 +123,19 @@ + + + + + + + + + + + + + @@ -1137,18 +1150,18 @@ - - - + + + - + - + - + - + From d74060c8512c7f88e50f202391af88214a0a395d Mon Sep 17 00:00:00 2001 From: xuexiangjys Date: Sat, 23 Nov 2019 02:18:03 +0800 Subject: [PATCH 17/27] =?UTF-8?q?=E5=A2=9E=E5=8A=A0FlexboxLayoutManager?= =?UTF-8?q?=E7=9A=84=E4=BD=BF=E7=94=A8=E6=A1=88=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xuidemo/adapter/FlexboxLayoutAdapter.java | 78 +++++++++++ .../components/FlowLayoutFragment.java | 4 +- .../flowlayout/FlexboxLayoutFragment.java | 122 ++++++++++++++++++ .../ExpandableHorizontalFragment.java | 4 +- .../layout/adapter_flexbox_layout_item.xml | 36 ++++++ app/src/main/res/layout/adapter_item_tag.xml | 2 +- .../res/layout/fragment_flexbox_layout.xml | 73 +++++++++++ .../res/layout/fragment_flowtaglayout.xml | 17 +++ 8 files changed, 333 insertions(+), 3 deletions(-) create mode 100644 app/src/main/java/com/xuexiang/xuidemo/adapter/FlexboxLayoutAdapter.java create mode 100644 app/src/main/java/com/xuexiang/xuidemo/fragment/components/flowlayout/FlexboxLayoutFragment.java create mode 100644 app/src/main/res/layout/adapter_flexbox_layout_item.xml create mode 100644 app/src/main/res/layout/fragment_flexbox_layout.xml diff --git a/app/src/main/java/com/xuexiang/xuidemo/adapter/FlexboxLayoutAdapter.java b/app/src/main/java/com/xuexiang/xuidemo/adapter/FlexboxLayoutAdapter.java new file mode 100644 index 00000000..d0910e1f --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/adapter/FlexboxLayoutAdapter.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.xuexiang.xuidemo.adapter; + +import androidx.annotation.NonNull; + +import com.xuexiang.xui.adapter.recyclerview.BaseRecyclerAdapter; +import com.xuexiang.xui.adapter.recyclerview.RecyclerViewHolder; +import com.xuexiang.xuidemo.R; + +/** + * @author xuexiang + * @since 2019-11-23 01:32 + */ +public class FlexboxLayoutAdapter extends BaseRecyclerAdapter { + + public FlexboxLayoutAdapter(String[] data) { + super(data); + } + + @Override + protected int getItemLayoutId(int viewType) { + return R.layout.adapter_flexbox_layout_item; + } + + @Override + protected void bindData(@NonNull RecyclerViewHolder holder, int position, String item) { + holder.text(R.id.tv_tag, item); + holder.select(R.id.tv_tag, getSelectPosition() == position); + } + + + /** + * 单选 + * + * @param position + * @param cancelable + */ + public boolean singleSelect(int position, boolean cancelable) { + if (position == getSelectPosition()) { + if (cancelable) { + setSelectPosition(-1); + return true; + } + } else { + setSelectPosition(position); + return true; + } + return false; + } + + + /** + * @return 获取选中的内容 + */ + public String getSelectContent() { + String value = getSelectItem(); + if (value == null) { + return ""; + } + return value; + } +} diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/FlowLayoutFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/FlowLayoutFragment.java index 52638935..5e596225 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/FlowLayoutFragment.java +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/FlowLayoutFragment.java @@ -3,6 +3,7 @@ import com.xuexiang.xpage.annotation.Page; import com.xuexiang.xuidemo.R; import com.xuexiang.xuidemo.base.ComponentContainerFragment; +import com.xuexiang.xuidemo.fragment.components.flowlayout.FlexboxLayoutFragment; import com.xuexiang.xuidemo.fragment.components.flowlayout.FlowTagLayoutFragment; import com.xuexiang.xuidemo.fragment.components.flowlayout.NormalFlowLayoutFragment; @@ -22,7 +23,8 @@ public class FlowLayoutFragment extends ComponentContainerFragment { protected Class[] getPagesClasses() { return new Class[]{ FlowTagLayoutFragment.class, - NormalFlowLayoutFragment.class + NormalFlowLayoutFragment.class, + FlexboxLayoutFragment.class }; } } diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/flowlayout/FlexboxLayoutFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/flowlayout/FlexboxLayoutFragment.java new file mode 100644 index 00000000..1da40e57 --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/flowlayout/FlexboxLayoutFragment.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.xuexiang.xuidemo.fragment.components.flowlayout; + +import android.view.View; + +import androidx.recyclerview.widget.RecyclerView; + +import com.google.android.flexbox.FlexDirection; +import com.google.android.flexbox.FlexWrap; +import com.google.android.flexbox.FlexboxLayoutManager; +import com.google.android.flexbox.JustifyContent; +import com.xuexiang.xpage.annotation.Page; +import com.xuexiang.xui.adapter.recyclerview.RecyclerViewHolder; +import com.xuexiang.xui.utils.ResUtils; +import com.xuexiang.xui.widget.toast.XToast; +import com.xuexiang.xuidemo.R; +import com.xuexiang.xuidemo.adapter.FlexboxLayoutAdapter; +import com.xuexiang.xuidemo.base.BaseFragment; +import com.xuexiang.xuidemo.utils.XToastUtils; + +import butterknife.BindView; + +/** + * @author xuexiang + * @since 2019-11-23 01:23 + */ +@Page(name = "FlexboxLayout + RecyclerView") +public class FlexboxLayoutFragment extends BaseFragment { + + + @BindView(R.id.recycler_view_1) + RecyclerView recyclerView1; + @BindView(R.id.recycler_view_2) + RecyclerView recyclerView2; + @BindView(R.id.recycler_view_3) + RecyclerView recyclerView3; + + private FlexboxLayoutAdapter mAdapter1; + private FlexboxLayoutAdapter mAdapter2; + private FlexboxLayoutAdapter mAdapter3; + + @Override + protected int getLayoutId() { + return R.layout.fragment_flexbox_layout; + } + + @Override + protected void initViews() { + String[] array = ResUtils.getStringArray(R.array.tags_values); + + recyclerView1.setLayoutManager(getFlexboxLayoutManager()); + recyclerView1.setAdapter(mAdapter1 = new FlexboxLayoutAdapter(array)); + + recyclerView2.setLayoutManager(getFlexboxLayoutManager()); + recyclerView2.setAdapter(mAdapter2 = new FlexboxLayoutAdapter(array)); + + recyclerView3.setLayoutManager(getFlexboxLayoutManager()); + recyclerView3.setAdapter(mAdapter3 = new FlexboxLayoutAdapter(array)); + + + } + + private FlexboxLayoutManager getFlexboxLayoutManager() { + //设置布局管理器 + FlexboxLayoutManager flexboxLayoutManager = new FlexboxLayoutManager(getContext()); + //flexDirection 属性决定主轴的方向(即项目的排列方向)。类似 LinearLayout 的 vertical 和 horizontal: + // 主轴为水平方向,起点在左端。 + flexboxLayoutManager.setFlexDirection(FlexDirection.ROW); + //flexWrap 默认情况下 Flex 跟 LinearLayout 一样,都是不带换行排列的,但是flexWrap属性可以支持换行排列: + // 按正常方向换行 + flexboxLayoutManager.setFlexWrap(FlexWrap.WRAP); + //justifyContent 属性定义了项目在主轴上的对齐方式: + // 交叉轴的起点对齐 + flexboxLayoutManager.setJustifyContent(JustifyContent.FLEX_START); + return flexboxLayoutManager; + } + + + @Override + protected void initListeners() { + mAdapter1.setOnItemClickListener(new RecyclerViewHolder.OnItemClickListener() { + @Override + public void onItemClick(View itemView, String item, int position) { + XToastUtils.toast("点击了:" + item); + } + }); + + mAdapter2.setOnItemClickListener(new RecyclerViewHolder.OnItemClickListener() { + @Override + public void onItemClick(View itemView, String item, int position) { + if (mAdapter2.singleSelect(position, false)) { + XToastUtils.toast("选中的内容:" + mAdapter2.getSelectContent()); + } + } + }); + + mAdapter3.setOnItemClickListener(new RecyclerViewHolder.OnItemClickListener() { + @Override + public void onItemClick(View itemView, String item, int position) { + if (mAdapter3.singleSelect(position, true)) { + XToastUtils.toast("选中的内容:" + mAdapter3.getSelectContent()); + } + } + }); + } +} diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/layout/expandable/ExpandableHorizontalFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/layout/expandable/ExpandableHorizontalFragment.java index f201f443..10f1c5e1 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/layout/expandable/ExpandableHorizontalFragment.java +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/layout/expandable/ExpandableHorizontalFragment.java @@ -56,7 +56,9 @@ protected void initViews() { expandableLayout.setOnExpansionChangedListener(new ExpandableLayout.OnExpansionChangedListener() { @Override public void onExpansionChanged(float expansion, int state) { - expandButton.setRotation(expansion * 180); + if (expandButton != null) { + expandButton.setRotation(expansion * 180); + } } }); } diff --git a/app/src/main/res/layout/adapter_flexbox_layout_item.xml b/app/src/main/res/layout/adapter_flexbox_layout_item.xml new file mode 100644 index 00000000..3101bde5 --- /dev/null +++ b/app/src/main/res/layout/adapter_flexbox_layout_item.xml @@ -0,0 +1,36 @@ + + + + + + + + diff --git a/app/src/main/res/layout/adapter_item_tag.xml b/app/src/main/res/layout/adapter_item_tag.xml index 41f4b99a..fe904eb1 100644 --- a/app/src/main/res/layout/adapter_item_tag.xml +++ b/app/src/main/res/layout/adapter_item_tag.xml @@ -7,7 +7,7 @@ android:id="@+id/tv_tag" style="@style/TextStyle.Explain" android:layout_height="32dp" - android:layout_marginLeft="?attr/xui_config_content_spacing_horizontal" + android:layout_marginStart="?attr/xui_config_content_spacing_horizontal" android:layout_marginTop="?attr/xui_config_content_spacing_horizontal" android:background="@drawable/bg_rect_round_tag_btn" android:paddingBottom="5dp" diff --git a/app/src/main/res/layout/fragment_flexbox_layout.xml b/app/src/main/res/layout/fragment_flexbox_layout.xml new file mode 100644 index 00000000..34348c97 --- /dev/null +++ b/app/src/main/res/layout/fragment_flexbox_layout.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_flowtaglayout.xml b/app/src/main/res/layout/fragment_flowtaglayout.xml index afbb876f..868c34d9 100644 --- a/app/src/main/res/layout/fragment_flowtaglayout.xml +++ b/app/src/main/res/layout/fragment_flowtaglayout.xml @@ -1,4 +1,21 @@ + + Date: Sat, 23 Nov 2019 15:14:13 +0800 Subject: [PATCH 18/27] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=A1=88=E4=BE=8B?= =?UTF-8?q?=E7=9A=84=E4=BD=BF=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adapter/ExpandableListAdapter.java | 16 +- .../xuidemo/adapter/FlexboxLayoutAdapter.java | 86 ++++++- .../flowlayout/FlexboxLayoutFragment.java | 28 ++- .../ExpandableRecycleViewFragment.java | 2 +- .../supertextview/SuperClickFragment.java | 25 +++ app/src/main/res/drawable/ic_arrow_right.xml | 9 + .../layout/adapter_expandable_list_item.xml | 35 ++- .../res/layout/fragment_flexbox_layout.xml | 11 + .../res/layout/fragment_grouplistview.xml | 17 +- .../main/res/layout/fragment_super_click.xml | 211 +++++++++++------- 10 files changed, 325 insertions(+), 115 deletions(-) create mode 100644 app/src/main/res/drawable/ic_arrow_right.xml diff --git a/app/src/main/java/com/xuexiang/xuidemo/adapter/ExpandableListAdapter.java b/app/src/main/java/com/xuexiang/xuidemo/adapter/ExpandableListAdapter.java index 9f96ffc6..a8d8f73c 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/adapter/ExpandableListAdapter.java +++ b/app/src/main/java/com/xuexiang/xuidemo/adapter/ExpandableListAdapter.java @@ -21,6 +21,7 @@ import android.view.animation.OvershootInterpolator; import androidx.annotation.NonNull; +import androidx.appcompat.widget.AppCompatImageView; import androidx.recyclerview.widget.RecyclerView; import com.xuexiang.xaop.annotation.SingleClick; @@ -68,22 +69,27 @@ protected int getItemLayoutId(int viewType) { @Override protected void bindData(@NonNull RecyclerViewHolder holder, int position, String item) { ExpandableLayout expandableLayout = holder.findViewById(R.id.expandable_layout); + AppCompatImageView ivIndicator = holder.findViewById(R.id.iv_indicator); expandableLayout.setInterpolator(new OvershootInterpolator()); expandableLayout.setOnExpansionChangedListener(new ExpandableLayout.OnExpansionChangedListener() { @Override public void onExpansionChanged(float expansion, int state) { - if (state == ExpandableLayout.State.EXPANDING) { + if (mRecyclerView != null && state == ExpandableLayout.State.EXPANDING) { mRecyclerView.smoothScrollToPosition(position); } + if (ivIndicator != null) { + ivIndicator.setRotation(expansion * 90); + } } }); boolean isSelected = position == mSelectPosition; expandableLayout.setExpanded(isSelected, false); - holder.select(R.id.tv_content, isSelected); - holder.text(R.id.tv_content, ResUtils.getResources().getString(R.string.item_example_number_title, position)); - holder.click(R.id.tv_content, new View.OnClickListener() { + holder.select(R.id.fl_title, isSelected); + holder.text(R.id.tv_title, ResUtils.getResources().getString(R.string.item_example_number_title, position + 1)); + holder.text(R.id.tv_content, ResUtils.getResources().getString(R.string.item_example_number_abstract, position + 1)); + holder.click(R.id.fl_title, new View.OnClickListener() { @SingleClick @Override public void onClick(View v) { @@ -95,7 +101,7 @@ public void onClick(View v) { private void onClickItem(View view, final ExpandableLayout expandableLayout, final int position) { RecyclerViewHolder holder = (RecyclerViewHolder) mRecyclerView.findViewHolderForAdapterPosition(mSelectPosition); if (holder != null) { - holder.select(R.id.tv_content, false); + holder.select(R.id.fl_title, false); ((ExpandableLayout) holder.findViewById(R.id.expandable_layout)).collapse(); } diff --git a/app/src/main/java/com/xuexiang/xuidemo/adapter/FlexboxLayoutAdapter.java b/app/src/main/java/com/xuexiang/xuidemo/adapter/FlexboxLayoutAdapter.java index d0910e1f..b2429f25 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/adapter/FlexboxLayoutAdapter.java +++ b/app/src/main/java/com/xuexiang/xuidemo/adapter/FlexboxLayoutAdapter.java @@ -17,22 +17,42 @@ package com.xuexiang.xuidemo.adapter; +import android.util.SparseBooleanArray; + import androidx.annotation.NonNull; import com.xuexiang.xui.adapter.recyclerview.BaseRecyclerAdapter; import com.xuexiang.xui.adapter.recyclerview.RecyclerViewHolder; import com.xuexiang.xuidemo.R; +import java.util.ArrayList; +import java.util.List; + /** * @author xuexiang * @since 2019-11-23 01:32 */ public class FlexboxLayoutAdapter extends BaseRecyclerAdapter { + private boolean mIsMultiSelectMode; + private boolean mCancelable; + + private SparseBooleanArray mSparseArray = new SparseBooleanArray(); + public FlexboxLayoutAdapter(String[] data) { super(data); } + public FlexboxLayoutAdapter setIsMultiSelectMode(boolean isMultiSelectMode) { + mIsMultiSelectMode = isMultiSelectMode; + return this; + } + + public FlexboxLayoutAdapter setCancelable(boolean cancelable) { + mCancelable = cancelable; + return this; + } + @Override protected int getItemLayoutId(int viewType) { return R.layout.adapter_flexbox_layout_item; @@ -41,9 +61,59 @@ protected int getItemLayoutId(int viewType) { @Override protected void bindData(@NonNull RecyclerViewHolder holder, int position, String item) { holder.text(R.id.tv_tag, item); - holder.select(R.id.tv_tag, getSelectPosition() == position); + if (mIsMultiSelectMode) { + holder.select(R.id.tv_tag, mSparseArray.get(position)); + } else { + holder.select(R.id.tv_tag, getSelectPosition() == position); + } + } + + /** + * 选择 + * + * @param position + * @return + */ + public boolean select(int position) { + return mIsMultiSelectMode ? multiSelect(position) : singleSelect(position); } + /** + * 多选 + * + * @param positions + */ + public void multiSelect(int... positions) { + if (!mIsMultiSelectMode) { + return; + } + for (int position : positions) { + multiSelect(position); + } + } + + /** + * 多选 + * + * @param position + */ + public boolean multiSelect(int position) { + if (!mIsMultiSelectMode) { + return false; + } + mSparseArray.append(position, !mSparseArray.get(position)); + notifyItemChanged(position); + return true; + } + + /** + * 单选 + * + * @param position + */ + public boolean singleSelect(int position) { + return singleSelect(position, mCancelable); + } /** * 单选 @@ -75,4 +145,18 @@ public String getSelectContent() { } return value; } + + + /** + * @return 获取多选的内容 + */ + public List getMultiContent() { + List list = new ArrayList<>(); + for (int i = 0; i < getItemCount(); i++) { + if (mSparseArray.get(i)) { + list.add(getItem(i)); + } + } + return list; + } } diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/flowlayout/FlexboxLayoutFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/flowlayout/FlexboxLayoutFragment.java index 1da40e57..ee84fc7d 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/flowlayout/FlexboxLayoutFragment.java +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/flowlayout/FlexboxLayoutFragment.java @@ -33,6 +33,7 @@ import com.xuexiang.xuidemo.adapter.FlexboxLayoutAdapter; import com.xuexiang.xuidemo.base.BaseFragment; import com.xuexiang.xuidemo.utils.XToastUtils; +import com.xuexiang.xutil.common.StringUtils; import butterknife.BindView; @@ -40,20 +41,22 @@ * @author xuexiang * @since 2019-11-23 01:23 */ -@Page(name = "FlexboxLayout + RecyclerView") +@Page(name = "FlexboxLayoutManager + RecyclerView\n流标签") public class FlexboxLayoutFragment extends BaseFragment { - @BindView(R.id.recycler_view_1) RecyclerView recyclerView1; @BindView(R.id.recycler_view_2) RecyclerView recyclerView2; @BindView(R.id.recycler_view_3) RecyclerView recyclerView3; + @BindView(R.id.recycler_view_4) + RecyclerView recyclerView4; private FlexboxLayoutAdapter mAdapter1; private FlexboxLayoutAdapter mAdapter2; private FlexboxLayoutAdapter mAdapter3; + private FlexboxLayoutAdapter mAdapter4; @Override protected int getLayoutId() { @@ -71,11 +74,18 @@ protected void initViews() { recyclerView2.setAdapter(mAdapter2 = new FlexboxLayoutAdapter(array)); recyclerView3.setLayoutManager(getFlexboxLayoutManager()); - recyclerView3.setAdapter(mAdapter3 = new FlexboxLayoutAdapter(array)); + recyclerView3.setAdapter(mAdapter3 = new FlexboxLayoutAdapter(array).setCancelable(true)); + recyclerView4.setLayoutManager(getFlexboxLayoutManager()); + recyclerView4.setItemAnimator(null); + recyclerView4.setAdapter(mAdapter4 = new FlexboxLayoutAdapter(array).setIsMultiSelectMode(true)); + mAdapter2.select(2); + mAdapter3.select(3); + mAdapter4.multiSelect(1, 2, 3); } + private FlexboxLayoutManager getFlexboxLayoutManager() { //设置布局管理器 FlexboxLayoutManager flexboxLayoutManager = new FlexboxLayoutManager(getContext()); @@ -104,7 +114,7 @@ public void onItemClick(View itemView, String item, int position) { mAdapter2.setOnItemClickListener(new RecyclerViewHolder.OnItemClickListener() { @Override public void onItemClick(View itemView, String item, int position) { - if (mAdapter2.singleSelect(position, false)) { + if (mAdapter2.select(position)) { XToastUtils.toast("选中的内容:" + mAdapter2.getSelectContent()); } } @@ -113,10 +123,18 @@ public void onItemClick(View itemView, String item, int position) { mAdapter3.setOnItemClickListener(new RecyclerViewHolder.OnItemClickListener() { @Override public void onItemClick(View itemView, String item, int position) { - if (mAdapter3.singleSelect(position, true)) { + if (mAdapter3.select(position)) { XToastUtils.toast("选中的内容:" + mAdapter3.getSelectContent()); } } }); + + mAdapter4.setOnItemClickListener(new RecyclerViewHolder.OnItemClickListener() { + @Override + public void onItemClick(View itemView, String item, int position) { + mAdapter4.select(position); + XToastUtils.toast("选中的内容:" + StringUtils.listToString(mAdapter4.getMultiContent(), ",")); + } + }); } } diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/layout/expandable/ExpandableRecycleViewFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/layout/expandable/ExpandableRecycleViewFragment.java index 4a9adf4c..9198ee48 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/layout/expandable/ExpandableRecycleViewFragment.java +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/layout/expandable/ExpandableRecycleViewFragment.java @@ -52,7 +52,7 @@ protected int getLayoutId() { */ @Override protected void initViews() { - WidgetUtils.initRecyclerView(recyclerView, 0); + WidgetUtils.initRecyclerView(recyclerView); recyclerView.setAdapter(new ExpandableListAdapter(recyclerView, DemoDataProvider.getDemoData1())); } diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/textview/supertextview/SuperClickFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/textview/supertextview/SuperClickFragment.java index e60b9d60..ffdaae08 100755 --- a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/textview/supertextview/SuperClickFragment.java +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/textview/supertextview/SuperClickFragment.java @@ -6,6 +6,7 @@ import android.widget.ImageView; import com.xuexiang.xpage.annotation.Page; +import com.xuexiang.xui.widget.layout.ExpandableLayout; import com.xuexiang.xui.widget.textview.badge.Badge; import com.xuexiang.xui.widget.textview.badge.BadgeView; import com.xuexiang.xui.widget.textview.supertextview.SuperTextView; @@ -25,6 +26,10 @@ public class SuperClickFragment extends BaseFragment { SuperTextView superTextView_switch; @BindView(R.id.super_message_tv) SuperTextView stvMessage; + @BindView(R.id.stv_expandable) + SuperTextView stvExpandable; + @BindView(R.id.expandable_layout) + ExpandableLayout mExpandableLayout; @BindView(R.id.stv_name) SuperTextView stvName; @BindView(R.id.stv_phone) @@ -159,6 +164,26 @@ public void onClick(View v) { XToastUtils.toast("点击监听"); } }); + + + mExpandableLayout.setOnExpansionChangedListener(new ExpandableLayout.OnExpansionChangedListener() { + @Override + public void onExpansionChanged(float expansion, int state) { + if (stvExpandable != null && stvExpandable.getRightIconIV() != null) { + stvExpandable.getRightIconIV().setRotation(expansion * 90); + } + } + }); + stvExpandable.setOnSuperTextViewClickListener(new SuperTextView.OnSuperTextViewClickListener() { + @Override + public void onClickListener(SuperTextView superTextView) { + if (mExpandableLayout != null) { + mExpandableLayout.toggle(); + } + } + }); + + } } diff --git a/app/src/main/res/drawable/ic_arrow_right.xml b/app/src/main/res/drawable/ic_arrow_right.xml new file mode 100644 index 00000000..86de623b --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_right.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/adapter_expandable_list_item.xml b/app/src/main/res/layout/adapter_expandable_list_item.xml index d7f92869..099f3033 100644 --- a/app/src/main/res/layout/adapter_expandable_list_item.xml +++ b/app/src/main/res/layout/adapter_expandable_list_item.xml @@ -17,17 +17,34 @@ - + android:orientation="horizontal"> + + + + + + + android:textColor="@color/xui_config_color_white" + tools:text="这里面是内容" /> diff --git a/app/src/main/res/layout/fragment_flexbox_layout.xml b/app/src/main/res/layout/fragment_flexbox_layout.xml index 34348c97..2e8c0f30 100644 --- a/app/src/main/res/layout/fragment_flexbox_layout.xml +++ b/app/src/main/res/layout/fragment_flexbox_layout.xml @@ -66,6 +66,17 @@ android:layout_height="wrap_content" android:overScrollMode="never" /> + + + + diff --git a/app/src/main/res/layout/fragment_grouplistview.xml b/app/src/main/res/layout/fragment_grouplistview.xml index 2444bc22..3e62f459 100644 --- a/app/src/main/res/layout/fragment_grouplistview.xml +++ b/app/src/main/res/layout/fragment_grouplistview.xml @@ -19,16 +19,17 @@ android:layout_height="match_parent" android:orientation="vertical"> - + - + - + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_super_click.xml b/app/src/main/res/layout/fragment_super_click.xml index 246afe42..abbf1ccd 100755 --- a/app/src/main/res/layout/fragment_super_click.xml +++ b/app/src/main/res/layout/fragment_super_click.xml @@ -1,95 +1,136 @@ - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From aa8221b61f21940ff70de5dcd7a2746943674042 Mon Sep 17 00:00:00 2001 From: xuexiangjys Date: Mon, 25 Nov 2019 17:49:00 +0800 Subject: [PATCH 19/27] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=8F=8C=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E8=81=94=E5=8A=A8=E4=BD=BF=E7=94=A8=E6=A1=88=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 14 +- app/build.gradle | 3 + .../xuexiang/xuidemo/DemoDataProvider.java | 28 ++++ .../expands/LinkageRecyclerViewFragment.java | 60 +++++++++ .../LinkageRecyclerViewCustomFragment.java | 93 +++++++++++++ .../LinkageRecyclerViewSimpleFragment.java | 111 ++++++++++++++++ .../linkage/custom/CustomGroupedItem.java | 82 ++++++++++++ .../CustomLinkagePrimaryAdapterConfig.java | 104 +++++++++++++++ .../CustomLinkageSecondaryAdapterConfig.java | 122 ++++++++++++++++++ .../drawable-hdpi/ic_expand_linkage_list.png | Bin 0 -> 882 bytes .../layout/fragment_linkage_recyclerview.xml | 28 ++++ 11 files changed, 641 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/com/xuexiang/xuidemo/fragment/expands/LinkageRecyclerViewFragment.java create mode 100644 app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/LinkageRecyclerViewCustomFragment.java create mode 100644 app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/LinkageRecyclerViewSimpleFragment.java create mode 100644 app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/custom/CustomGroupedItem.java create mode 100644 app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/custom/CustomLinkagePrimaryAdapterConfig.java create mode 100644 app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/custom/CustomLinkageSecondaryAdapterConfig.java create mode 100644 app/src/main/res/drawable-hdpi/ic_expand_linkage_list.png create mode 100644 app/src/main/res/layout/fragment_linkage_recyclerview.xml diff --git a/README.md b/README.md index d3d6a8ee..42429048 100644 --- a/README.md +++ b/README.md @@ -183,15 +183,19 @@ protected void attachBaseContext(Context newBase) { * [QMUI_Android](https://github.com/Tencent/QMUI_Android) * [AgentWeb](https://github.com/Justson/AgentWeb) -* [CityPicker](https://github.com/xuexiangjys/CityPicker) -* [SmartRefreshLayout](https://github.com/scwang90/SmartRefreshLayout) -* [PictureSelector](https://github.com/LuckSiege/PictureSelector) +* [Android-Iconics](https://github.com/mikepenz/Android-Iconics) * [Android-PickerView](https://github.com/Bigkoo/Android-PickerView) +* [CityPicker](https://github.com/xuexiangjys/CityPicker) +* [FlycoBanner_Master](https://github.com/H07000223/FlycoBanner_Master) +* [Linkage-RecyclerView](https://github.com/KunMinX/Linkage-RecyclerView) * [MaterialEditText](https://github.com/rengwuxian/MaterialEditText) * [MaterialSpinner](https://github.com/jaredrummler/MaterialSpinner) -* [FlycoBanner_Master](https://github.com/H07000223/FlycoBanner_Master) * [MaterialProgressBar](https://github.com/DreaminginCodeZH/MaterialProgressBar) +* [MPAndroidChart](https://github.com/PhilJay/MPAndroidChart) +* [PictureSelector](https://github.com/LuckSiege/PictureSelector) +* [SmartRefreshLayout](https://github.com/scwang90/SmartRefreshLayout) * [SlideBack](https://github.com/ParfoisMeng/SlideBack) +* [SwipeRecyclerView](https://github.com/yanzhenjie/SwipeRecyclerView) ## 如果觉得项目还不错,可以考虑打赏一波 @@ -210,6 +214,8 @@ C*y | 1¥ | 微信 *事 | 10¥ | 微信 优*1 | 168¥ | 微信 *、 | 20¥ | 微信 +*钰晗 | 6¥ | 支付宝 +*娜 | 3¥ | 微信 ## 联系方式 diff --git a/app/build.gradle b/app/build.gradle index 4cbe6bc0..88c9aae6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -192,6 +192,9 @@ dependencies { //腾讯的键值对存储mmkv implementation 'com.tencent:mmkv:1.0.22' + //双列表联动 + implementation 'com.kunminx.linkage:linkage-recyclerview:1.9.2' + //umeng统计 implementation 'com.umeng.umsdk:analytics:8.0.2' implementation 'com.umeng.umsdk:common:2.0.2' diff --git a/app/src/main/java/com/xuexiang/xuidemo/DemoDataProvider.java b/app/src/main/java/com/xuexiang/xuidemo/DemoDataProvider.java index 1e8b455b..ff10ca91 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/DemoDataProvider.java +++ b/app/src/main/java/com/xuexiang/xuidemo/DemoDataProvider.java @@ -2,6 +2,7 @@ import androidx.viewpager.widget.ViewPager; +import com.kunminx.linkage.bean.DefaultGroupedItem; import com.xuexiang.xaop.annotation.MemoryCache; import com.xuexiang.xui.adapter.simple.AdapterItem; import com.xuexiang.xui.adapter.simple.ExpandableItem; @@ -16,6 +17,7 @@ import com.xuexiang.xuidemo.adapter.entity.NewInfo; import com.xuexiang.xuidemo.fragment.components.imageview.preview.ImageViewInfo; import com.xuexiang.xuidemo.fragment.components.imageview.preview.NineGridInfo; +import com.xuexiang.xuidemo.fragment.expands.linkage.custom.CustomGroupedItem; import java.util.ArrayList; import java.util.Arrays; @@ -419,4 +421,30 @@ public static List getDemoNewInfos() { return list; } + @MemoryCache + public static List getGroupItems() { + List items = new ArrayList<>(); + for (int i = 0; i < 100; i++) { + if (i % 10 == 0) { + items.add(new DefaultGroupedItem(true, "菜单" + i / 10)); + } else { + items.add(new DefaultGroupedItem(new DefaultGroupedItem.ItemInfo("这是标题" + i, "菜单" + i / 10, "这是内容" + i))); + } + } + return items; + } + + @MemoryCache + public static List getCustomGroupItems() { + List items = new ArrayList<>(); + for (int i = 0; i < 100; i++) { + if (i % 10 == 0) { + items.add(new CustomGroupedItem(true, "菜单" + i / 10)); + } else { + items.add(new CustomGroupedItem(new CustomGroupedItem.ItemInfo("这是标题" + i, "菜单" + i / 10, "这是内容" + i))); + } + } + return items; + } + } diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/LinkageRecyclerViewFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/LinkageRecyclerViewFragment.java new file mode 100644 index 00000000..83443986 --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/LinkageRecyclerViewFragment.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.xuexiang.xuidemo.fragment.expands; + +import android.view.View; + +import com.xuexiang.xpage.annotation.Page; +import com.xuexiang.xui.widget.actionbar.TitleBar; +import com.xuexiang.xuidemo.R; +import com.xuexiang.xuidemo.base.ComponentContainerFragment; +import com.xuexiang.xuidemo.fragment.expands.linkage.LinkageRecyclerViewCustomFragment; +import com.xuexiang.xuidemo.fragment.expands.linkage.LinkageRecyclerViewSimpleFragment; +import com.xuexiang.xuidemo.utils.Utils; + +/** + * @author xuexiang + * @since 2019-11-25 11:24 + */ +@Page(name = "双列表联动", extra = R.drawable.ic_expand_linkage_list) +public class LinkageRecyclerViewFragment extends ComponentContainerFragment { + /** + * 获取页面的类集合[使用@Page注解进行注册的页面] + * + * @return + */ + @Override + protected Class[] getPagesClasses() { + return new Class[]{ + LinkageRecyclerViewSimpleFragment.class, + LinkageRecyclerViewCustomFragment.class + }; + } + + @Override + protected TitleBar initTitle() { + TitleBar titleBar = super.initTitle(); + titleBar.addAction(new TitleBar.TextAction("Github") { + @Override + public void performAction(View view) { + Utils.goWeb(getContext(), "https://github.com/KunMinX/Linkage-RecyclerView"); + } + }); + return titleBar; + } +} diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/LinkageRecyclerViewCustomFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/LinkageRecyclerViewCustomFragment.java new file mode 100644 index 00000000..2e510643 --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/LinkageRecyclerViewCustomFragment.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.xuexiang.xuidemo.fragment.expands.linkage; + +import android.view.View; +import android.view.ViewGroup; + +import com.kunminx.linkage.LinkageRecyclerView; +import com.kunminx.linkage.adapter.viewholder.LinkagePrimaryViewHolder; +import com.kunminx.linkage.adapter.viewholder.LinkageSecondaryViewHolder; +import com.kunminx.linkage.bean.BaseGroupedItem; +import com.xuexiang.xaop.annotation.SingleClick; +import com.xuexiang.xpage.annotation.Page; +import com.xuexiang.xui.utils.SnackbarUtils; +import com.xuexiang.xui.widget.actionbar.TitleBar; +import com.xuexiang.xuidemo.DemoDataProvider; +import com.xuexiang.xuidemo.R; +import com.xuexiang.xuidemo.base.BaseFragment; +import com.xuexiang.xuidemo.fragment.expands.linkage.custom.CustomGroupedItem; +import com.xuexiang.xuidemo.fragment.expands.linkage.custom.CustomLinkagePrimaryAdapterConfig; +import com.xuexiang.xuidemo.fragment.expands.linkage.custom.CustomLinkageSecondaryAdapterConfig; + +import butterknife.BindView; + +/** + * @author xuexiang + * @since 2019-11-25 16:52 + */ +@Page(name = "双列表自定义样式") +public class LinkageRecyclerViewCustomFragment extends BaseFragment implements CustomLinkagePrimaryAdapterConfig.OnPrimaryItemClickListener, CustomLinkageSecondaryAdapterConfig.OnSecondaryItemClickListener { + + @BindView(R.id.linkage) + LinkageRecyclerView linkage; + + /** + * 布局的资源id + * + * @return + */ + @Override + protected int getLayoutId() { + return R.layout.fragment_linkage_recyclerview; + } + + @Override + protected TitleBar initTitle() { + TitleBar titleBar = super.initTitle(); + titleBar.addAction(new TitleBar.TextAction("切换") { + @SingleClick + @Override + public void performAction(View view) { + if (linkage != null) { + linkage.setGridMode(!linkage.isGridMode()); + } + } + }); + return titleBar; + } + + /** + * 初始化控件 + */ + @Override + protected void initViews() { + linkage.init(DemoDataProvider.getCustomGroupItems(), new CustomLinkagePrimaryAdapterConfig(this), new CustomLinkageSecondaryAdapterConfig(this)); + + } + + @Override + public void onPrimaryItemClick(LinkagePrimaryViewHolder holder, View view, String title) { + SnackbarUtils.Short(view, title).show(); + } + + @Override + public void onSecondaryItemClick(LinkageSecondaryViewHolder holder, ViewGroup view, BaseGroupedItem item) { + SnackbarUtils.Short(view, item.info.getTitle()).show(); + } +} diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/LinkageRecyclerViewSimpleFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/LinkageRecyclerViewSimpleFragment.java new file mode 100644 index 00000000..90c24037 --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/LinkageRecyclerViewSimpleFragment.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.xuexiang.xuidemo.fragment.expands.linkage; + +import android.text.TextUtils; +import android.view.View; +import android.widget.TextView; + +import androidx.core.content.ContextCompat; + +import com.google.android.material.snackbar.Snackbar; +import com.kunminx.linkage.LinkageRecyclerView; +import com.kunminx.linkage.bean.DefaultGroupedItem; +import com.xuexiang.xaop.annotation.MemoryCache; +import com.xuexiang.xaop.annotation.SingleClick; +import com.xuexiang.xpage.annotation.Page; +import com.xuexiang.xui.utils.SnackbarUtils; +import com.xuexiang.xui.widget.actionbar.TitleBar; +import com.xuexiang.xuidemo.DemoDataProvider; +import com.xuexiang.xuidemo.R; +import com.xuexiang.xuidemo.base.BaseFragment; + +import java.util.ArrayList; +import java.util.List; + +import butterknife.BindView; + +/** + * @author xuexiang + * @since 2019-11-25 11:36 + */ +@Page(name = "双列表简单使用") +public class LinkageRecyclerViewSimpleFragment extends BaseFragment { + @BindView(R.id.linkage) + LinkageRecyclerView linkage; + + /** + * 布局的资源id + * + * @return + */ + @Override + protected int getLayoutId() { + return R.layout.fragment_linkage_recyclerview; + } + + @Override + protected TitleBar initTitle() { + TitleBar titleBar = super.initTitle(); + titleBar.addAction(new TitleBar.TextAction("切换") { + @SingleClick + @Override + public void performAction(View view) { + if (linkage != null) { + linkage.setGridMode(!linkage.isGridMode()); + } + } + }); + return titleBar; + } + + /** + * 初始化控件 + */ + @Override + protected void initViews() { + linkage.init(DemoDataProvider.getGroupItems()); + linkage.setScrollSmoothly(true); + linkage.setDefaultOnItemBindListener( + (primaryHolder, primaryClickView, title) -> { + //一级列表点击 + SnackbarUtils.Short(primaryClickView, title).show(); + }, + (primaryHolder, title) -> { + //一级列表样式设置 + //TODO + + }, + (secondaryHolder, item) -> { + //二级列表点击 + secondaryHolder.getView(R.id.level_2_item).setOnClickListener(v -> { + SnackbarUtils.Short(v, item.info.getTitle()).show(); + }); + }, + (headerHolder, item) -> { + //TODO + }, + (footerHolder, item) -> { + //TODO + } + ); + } + + + +} diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/custom/CustomGroupedItem.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/custom/CustomGroupedItem.java new file mode 100644 index 00000000..70ce336a --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/custom/CustomGroupedItem.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.xuexiang.xuidemo.fragment.expands.linkage.custom; + +import com.kunminx.linkage.bean.BaseGroupedItem; + +/** + * 自定义组 + * + * @author xuexiang + * @since 2019-11-25 17:15 + */ +public class CustomGroupedItem extends BaseGroupedItem { + + public CustomGroupedItem(boolean isHeader, String header) { + super(isHeader, header); + } + + public CustomGroupedItem(ItemInfo item) { + super(item); + } + + public static class ItemInfo extends BaseGroupedItem.ItemInfo { + private String content; + private String imgUrl; + private String cost; + + public ItemInfo(String title, String group, String content) { + super(title, group); + this.content = content; + } + + public ItemInfo(String title, String group, String content, String imgUrl) { + this(title, group, content); + this.imgUrl = imgUrl; + } + + public ItemInfo(String title, String group, String content, String imgUrl, String cost) { + this(title, group, content, imgUrl); + this.cost = cost; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public String getImgUrl() { + return imgUrl; + } + + public void setImgUrl(String imgUrl) { + this.imgUrl = imgUrl; + } + + public String getCost() { + return cost; + } + + public void setCost(String cost) { + this.cost = cost; + } + } +} diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/custom/CustomLinkagePrimaryAdapterConfig.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/custom/CustomLinkagePrimaryAdapterConfig.java new file mode 100644 index 00000000..f1b42cd4 --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/custom/CustomLinkagePrimaryAdapterConfig.java @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.xuexiang.xuidemo.fragment.expands.linkage.custom; + + +import android.content.Context; +import android.text.TextUtils; +import android.view.View; +import android.widget.TextView; + +import androidx.core.content.ContextCompat; + +import com.kunminx.linkage.adapter.viewholder.LinkagePrimaryViewHolder; +import com.kunminx.linkage.contract.ILinkagePrimaryAdapterConfig; +import com.xuexiang.xuidemo.R; + +/** + * 自定义主菜单适配器 + * + * @author xuexiang + * @since 2019-11-25 17:17 + */ +public class CustomLinkagePrimaryAdapterConfig implements ILinkagePrimaryAdapterConfig { + + private static final int MARQUEE_REPEAT_LOOP_MODE = -1; + private static final int MARQUEE_REPEAT_NONE_MODE = 0; + private Context mContext; + private OnPrimaryItemClickListener mItemClickListener; + + public CustomLinkagePrimaryAdapterConfig(OnPrimaryItemClickListener itemClickListener) { + mItemClickListener = itemClickListener; + } + + public CustomLinkagePrimaryAdapterConfig setOnItemClickListner(OnPrimaryItemClickListener itemClickListener) { + mItemClickListener = itemClickListener; + return this; + } + + @Override + public void setContext(Context context) { + mContext = context; + } + + @Override + public int getLayoutId() { + return R.layout.default_adapter_linkage_primary; + } + + @Override + public int getGroupTitleViewId() { + return R.id.tv_group; + } + + @Override + public int getRootViewId() { + return R.id.layout_group; + } + + @Override + public void onBindViewHolder(LinkagePrimaryViewHolder holder, boolean selected, String title) { + TextView tvTitle = ((TextView) holder.mGroupTitle); + tvTitle.setText(title); + + tvTitle.setBackgroundColor(mContext.getResources().getColor(selected ? R.color.colorAccent : R.color.colorWhite)); + tvTitle.setTextColor(ContextCompat.getColor(mContext, selected ? R.color.colorWhite : R.color.colorGray)); + tvTitle.setEllipsize(selected ? TextUtils.TruncateAt.MARQUEE : TextUtils.TruncateAt.END); + tvTitle.setFocusable(selected); + tvTitle.setFocusableInTouchMode(selected); + tvTitle.setMarqueeRepeatLimit(selected ? MARQUEE_REPEAT_LOOP_MODE : MARQUEE_REPEAT_NONE_MODE); + } + + @Override + public void onItemClick(LinkagePrimaryViewHolder holder, View view, String title) { + if (mItemClickListener != null) { + mItemClickListener.onPrimaryItemClick(holder, view, title); + } + } + + public interface OnPrimaryItemClickListener { + /** + * we suggest you get position by holder.getAdapterPosition + * + * @param holder primaryHolder + * @param view view + * @param title groupTitle + */ + void onPrimaryItemClick(LinkagePrimaryViewHolder holder, View view, String title); + } +} diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/custom/CustomLinkageSecondaryAdapterConfig.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/custom/CustomLinkageSecondaryAdapterConfig.java new file mode 100644 index 00000000..5cf43024 --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/custom/CustomLinkageSecondaryAdapterConfig.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.xuexiang.xuidemo.fragment.expands.linkage.custom; + + +import android.content.Context; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.kunminx.linkage.adapter.viewholder.LinkageSecondaryFooterViewHolder; +import com.kunminx.linkage.adapter.viewholder.LinkageSecondaryHeaderViewHolder; +import com.kunminx.linkage.adapter.viewholder.LinkageSecondaryViewHolder; +import com.kunminx.linkage.bean.BaseGroupedItem; +import com.kunminx.linkage.contract.ILinkageSecondaryAdapterConfig; +import com.xuexiang.xuidemo.R; + +/** + * @author xuexiang + * @since 2019-11-25 17:17 + */ +public class CustomLinkageSecondaryAdapterConfig implements ILinkageSecondaryAdapterConfig { + + private Context mContext; + private OnSecondaryItemClickListener mItemClickListener; + private static final int SPAN_COUNT = 2; + + public CustomLinkageSecondaryAdapterConfig(OnSecondaryItemClickListener itemClickListener) { + mItemClickListener = itemClickListener; + } + + public CustomLinkageSecondaryAdapterConfig setOnItemClickListner(OnSecondaryItemClickListener itemClickListener) { + mItemClickListener = itemClickListener; + return this; + } + + @Override + public void setContext(Context context) { + mContext = context; + } + + @Override + public int getGridLayoutId() { + return R.layout.default_adapter_linkage_secondary_grid; + } + + @Override + public int getLinearLayoutId() { + return R.layout.default_adapter_linkage_secondary_linear; + } + + @Override + public int getHeaderLayoutId() { + return R.layout.default_adapter_linkage_secondary_header; + } + + @Override + public int getFooterLayoutId() { + return 0; + } + + @Override + public int getHeaderTextViewId() { + return R.id.secondary_header; + } + + @Override + public int getSpanCountOfGridMode() { + return SPAN_COUNT; + } + + @Override + public void onBindViewHolder(final LinkageSecondaryViewHolder holder, + final BaseGroupedItem item) { + + ((TextView) holder.getView(R.id.level_2_title)).setText(item.info.getTitle()); + ((TextView) holder.getView(R.id.level_2_content)).setText(item.info.getContent()); + + ViewGroup viewGroup = holder.getView(R.id.level_2_item); + viewGroup.setOnClickListener(v -> { + if (mItemClickListener != null) { + mItemClickListener.onSecondaryItemClick(holder, viewGroup, item); + } + }); + + } + + @Override + public void onBindHeaderViewHolder(LinkageSecondaryHeaderViewHolder holder, + BaseGroupedItem item) { + ((TextView) holder.getView(R.id.secondary_header)).setText(item.header); + } + + @Override + public void onBindFooterViewHolder(LinkageSecondaryFooterViewHolder holder, + BaseGroupedItem item) { + } + + public interface OnSecondaryItemClickListener { + /** + * we suggest you get position by holder.getAdapterPosition + * + * @param holder primaryHolder + * @param item 内容 + */ + void onSecondaryItemClick(LinkageSecondaryViewHolder holder, ViewGroup view, BaseGroupedItem item); + } +} diff --git a/app/src/main/res/drawable-hdpi/ic_expand_linkage_list.png b/app/src/main/res/drawable-hdpi/ic_expand_linkage_list.png new file mode 100644 index 0000000000000000000000000000000000000000..97dd5f34e99700fb779ec4c6e316b241efeee3c4 GIT binary patch literal 882 zcmV-&1C9KNP)aLdL}7ZWBuhaf{sZ+Qw0A`j58W6G9twK#*n0CIdhlkOL{Jg*4=A4O zO%(A^(%o1JLRS&Nn_w*@`($m9bYW+9GB3+4nOyVU_uhQ-&5!qH8I1XljrsV&5?~cD z<_y>+Fy;bCw+WUToe35mIj=)j5lVi$e&UA?#wdKHOQ6yUmKefK063+a00Vg9xqLwv zhtgk2KxHMEVFh?g84wvPcjoy$N=zNB%n1O1b>HO|bdsj@RU!a;FjV3(6(tftx!nGd zgwQxtg8Q4-`F0X%$^>-kd|h=0oMwOnK8XZ4t)LAE)2jF)d&XeVo9B;nK|rMyJZA{k zC<%yEE1EQ;6i{t_Il2djmjJO!K>|Zq^=kZuP$8l}_0s;o?9uT_<+f7h%rc#^&<(1$J12{&p!F6~4yxU$py_cI~&}r^G1Yox*2EUKN zJ~6;sp3C3o;wBioFOcvct3Hi728~xhRLTxHEi-9~p~%MQJz&VeA9O=#_%(im1d9Mf z+7fe`!7Bi`L=X!QVWYr`S2x|09t9o+hLnIPNWW1rC}ZW=2=KAkD?Ko+F`9}1<i)##UhS!FTyxO$>5(sRAf3LQ(d<%cU{NM=1al zCgZfeT>%VVQYM6m^PSq{Q%X!7EO9ls|1!L+6Cmy@D^Dqlp){{pN(2lm-@!UxL;!s` zEPseKjDQ1gh$O<3^)U@2fVw4?GX+pLL~^$WkZ4{J#Hb~pm^+ENB|t=DzZ3NT9x&=- zkYq{~L97C-0t5_Xy#%J81yk6C*^uaMuzA2c}JuuB?VAOQ&tXB#8ANy6VTYX z$QXO00w}X(2y + + + + + + \ No newline at end of file From d51265ffcdae8e8de55e4aec7dd7e728cdbaba0a Mon Sep 17 00:00:00 2001 From: xuexiangjys Date: Mon, 25 Nov 2019 23:39:10 +0800 Subject: [PATCH 20/27] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=8F=8C=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E8=81=94=E5=8A=A8=E7=9A=84=E4=BD=BF=E7=94=A8=E6=A1=88?= =?UTF-8?q?=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 3 +- app/proguard-rules.pro | 1 + app/src/main/assets/eleme.json | 534 ++++++++++++++++++ .../xuexiang/xuidemo/DemoDataProvider.java | 11 + .../expands/LinkageRecyclerViewFragment.java | 4 +- .../LinkageRecyclerViewElemeFragment.java | 97 ++++ .../LinkageRecyclerViewSimpleFragment.java | 10 - .../linkage/eleme/ElemeGroupedItem.java | 82 +++ .../eleme/ElemeSecondaryAdapterConfig.java | 135 +++++ .../res/drawable-xxhdpi/bg_food_sample.png | Bin 0 -> 1406 bytes .../main/res/drawable-xxhdpi/btn_add_food.png | Bin 0 -> 1534 bytes .../main/res/drawable-xxhdpi/tag_new_good.png | Bin 0 -> 4154 bytes .../layout/adapter_eleme_secondary_grid.xml | 72 +++ .../layout/adapter_eleme_secondary_linear.xml | 94 +++ 14 files changed, 1031 insertions(+), 12 deletions(-) create mode 100644 app/src/main/assets/eleme.json create mode 100644 app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/LinkageRecyclerViewElemeFragment.java create mode 100644 app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/eleme/ElemeGroupedItem.java create mode 100644 app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/eleme/ElemeSecondaryAdapterConfig.java create mode 100644 app/src/main/res/drawable-xxhdpi/bg_food_sample.png create mode 100644 app/src/main/res/drawable-xxhdpi/btn_add_food.png create mode 100644 app/src/main/res/drawable-xxhdpi/tag_new_good.png create mode 100644 app/src/main/res/layout/adapter_eleme_secondary_grid.xml create mode 100644 app/src/main/res/layout/adapter_eleme_secondary_linear.xml diff --git a/app/build.gradle b/app/build.gradle index 88c9aae6..5528c659 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -89,6 +89,7 @@ android { dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') implementation deps.androidx.multidex + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' //下拉刷新、CityPicker、XUI框架需要 // implementation deps.androidx.appcompat @@ -96,7 +97,7 @@ dependencies { // implementation deps.androidx.design // implementation deps.glide implementation 'androidx.appcompat:appcompat:1.1.0' - implementation 'androidx.recyclerview:recyclerview:1.0.0' + implementation 'androidx.recyclerview:recyclerview:1.1.0' implementation 'com.google.android.material:material:1.1.0-beta01' implementation 'com.github.bumptech.glide:glide:4.8.0' diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 3b3f19e7..3fc317a9 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -244,6 +244,7 @@ } -keep public class com.xuexiang.xuidemo.fragment.components.pickerview.**{*;} +-keep public class com.xuexiang.xuidemo.fragment.expands.linkage.eleme.**{*;} # agentweb -keep class com.just.agentweb.** { diff --git a/app/src/main/assets/eleme.json b/app/src/main/assets/eleme.json new file mode 100644 index 00000000..eb691991 --- /dev/null +++ b/app/src/main/assets/eleme.json @@ -0,0 +1,534 @@ +[ + { + "header": "优惠", + "isHeader": true + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "优惠", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-7d50230a36c40a94.png", + "title": "全家桶" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "优惠", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-2c0645f9b1a588de.png", + "title": "可乐" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "优惠", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-4a6889ba228feb46.png", + "title": "小食四拼" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "优惠", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-636381a9f7a855d6.png", + "title": "烤全翅" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "优惠", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-203db4255e78922a.png", + "title": "奥尔良鸡腿汉堡" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "优惠", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-7d50230a36c40a94.png", + "title": "鳕鱼堡" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "优惠", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-2c0645f9b1a588de.png", + "title": "鸡腿" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "优惠", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-203db4255e78922a.png", + "title": "草莓派" + } + }, + { + "header": "套餐", + "isHeader": true + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "套餐", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-7d50230a36c40a94.png", + "title": "全家桶" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "套餐", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-2c0645f9b1a588de.png", + "title": "可乐" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "套餐", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-4a6889ba228feb46.png", + "title": "小食四拼" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "套餐", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-636381a9f7a855d6.png", + "title": "烤全翅" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "套餐", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-203db4255e78922a.png", + "title": "奥尔良鸡腿汉堡" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "套餐", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-7d50230a36c40a94.png", + "title": "鳕鱼堡" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "套餐", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-2c0645f9b1a588de.png", + "title": "鸡腿" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "套餐", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-203db4255e78922a.png", + "title": "草莓派" + } + }, + { + "header": "主食", + "isHeader": true + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "主食", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-7d50230a36c40a94.png", + "title": "全家桶" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "主食", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-2c0645f9b1a588de.png", + "title": "可乐" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "主食", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-4a6889ba228feb46.png", + "title": "小食四拼" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "主食", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-636381a9f7a855d6.png", + "title": "烤全翅" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "主食", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-203db4255e78922a.png", + "title": "奥尔良鸡腿汉堡" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "主食", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-7d50230a36c40a94.png", + "title": "鳕鱼堡" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "主食", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-2c0645f9b1a588de.png", + "title": "鸡腿" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "主食", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-203db4255e78922a.png", + "title": "草莓派" + } + }, + { + "header": "饮料", + "isHeader": true + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "饮料", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-7d50230a36c40a94.png", + "title": "全家桶" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "饮料", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-2c0645f9b1a588de.png", + "title": "可乐" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "饮料", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-4a6889ba228feb46.png", + "title": "小食四拼" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "饮料", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-636381a9f7a855d6.png", + "title": "烤全翅" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "饮料", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-203db4255e78922a.png", + "title": "奥尔良鸡腿汉堡" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "饮料", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-7d50230a36c40a94.png", + "title": "鳕鱼堡" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "饮料", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-2c0645f9b1a588de.png", + "title": "鸡腿" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "饮料", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-203db4255e78922a.png", + "title": "草莓派" + } + }, + { + "header": "套餐A", + "isHeader": true + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "套餐A", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-7d50230a36c40a94.png", + "title": "全家桶" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "套餐A", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-2c0645f9b1a588de.png", + "title": "可乐" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "套餐A", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-4a6889ba228feb46.png", + "title": "小食四拼" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "套餐A", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-636381a9f7a855d6.png", + "title": "烤全翅" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "套餐A", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-203db4255e78922a.png", + "title": "奥尔良鸡腿汉堡" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "套餐A", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-7d50230a36c40a94.png", + "title": "鳕鱼堡" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "套餐A", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-2c0645f9b1a588de.png", + "title": "鸡腿" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "套餐A", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-203db4255e78922a.png", + "title": "草莓派" + } + }, + { + "header": "套餐B", + "isHeader": true + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "套餐B", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-7d50230a36c40a94.png", + "title": "全家桶" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "套餐B", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-2c0645f9b1a588de.png", + "title": "可乐" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "套餐B", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-4a6889ba228feb46.png", + "title": "小食四拼" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "套餐B", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-636381a9f7a855d6.png", + "title": "烤全翅" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "套餐B", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-203db4255e78922a.png", + "title": "奥尔良鸡腿汉堡" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "套餐B", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-7d50230a36c40a94.png", + "title": "鳕鱼堡" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "套餐B", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-2c0645f9b1a588de.png", + "title": "鸡腿" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "套餐B", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-203db4255e78922a.png", + "title": "草莓派" + } + }, + { + "header": "套餐C", + "isHeader": true + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "套餐C", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-7d50230a36c40a94.png", + "title": "全家桶" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "套餐C", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-2c0645f9b1a588de.png", + "title": "可乐" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "套餐C", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-4a6889ba228feb46.png", + "title": "小食四拼" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "套餐C", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-636381a9f7a855d6.png", + "title": "烤全翅" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "套餐C", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-203db4255e78922a.png", + "title": "奥尔良鸡腿汉堡" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "套餐C", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-7d50230a36c40a94.png", + "title": "鳕鱼堡" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "套餐C", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-2c0645f9b1a588de.png", + "title": "鸡腿" + } + }, + { + "isHeader": false, + "info": { + "content": "好吃的食物,增肥神器,有求必应\\n月售10008 好评率100%", + "group": "套餐C", + "imgUrl": "https://upload-images.jianshu.io/upload_images/57036-203db4255e78922a.png", + "title": "草莓派" + } + } +] diff --git a/app/src/main/java/com/xuexiang/xuidemo/DemoDataProvider.java b/app/src/main/java/com/xuexiang/xuidemo/DemoDataProvider.java index ff10ca91..ce02babe 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/DemoDataProvider.java +++ b/app/src/main/java/com/xuexiang/xuidemo/DemoDataProvider.java @@ -2,6 +2,7 @@ import androidx.viewpager.widget.ViewPager; +import com.google.gson.reflect.TypeToken; import com.kunminx.linkage.bean.DefaultGroupedItem; import com.xuexiang.xaop.annotation.MemoryCache; import com.xuexiang.xui.adapter.simple.AdapterItem; @@ -17,7 +18,11 @@ import com.xuexiang.xuidemo.adapter.entity.NewInfo; import com.xuexiang.xuidemo.fragment.components.imageview.preview.ImageViewInfo; import com.xuexiang.xuidemo.fragment.components.imageview.preview.NineGridInfo; +import com.xuexiang.xuidemo.fragment.components.pickerview.ProvinceInfo; import com.xuexiang.xuidemo.fragment.expands.linkage.custom.CustomGroupedItem; +import com.xuexiang.xuidemo.fragment.expands.linkage.eleme.ElemeGroupedItem; +import com.xuexiang.xutil.net.JsonUtil; +import com.xuexiang.xutil.resource.ResourceUtils; import java.util.ArrayList; import java.util.Arrays; @@ -447,4 +452,10 @@ public static List getCustomGroupItems() { return items; } + @MemoryCache + public static List getElemeGroupItems() { + return JsonUtil.fromJson(ResourceUtils.readStringFromAssert("eleme.json"), new TypeToken>() { + }.getType()); + } + } diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/LinkageRecyclerViewFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/LinkageRecyclerViewFragment.java index 83443986..e0358522 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/LinkageRecyclerViewFragment.java +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/LinkageRecyclerViewFragment.java @@ -24,6 +24,7 @@ import com.xuexiang.xuidemo.R; import com.xuexiang.xuidemo.base.ComponentContainerFragment; import com.xuexiang.xuidemo.fragment.expands.linkage.LinkageRecyclerViewCustomFragment; +import com.xuexiang.xuidemo.fragment.expands.linkage.LinkageRecyclerViewElemeFragment; import com.xuexiang.xuidemo.fragment.expands.linkage.LinkageRecyclerViewSimpleFragment; import com.xuexiang.xuidemo.utils.Utils; @@ -42,7 +43,8 @@ public class LinkageRecyclerViewFragment extends ComponentContainerFragment { protected Class[] getPagesClasses() { return new Class[]{ LinkageRecyclerViewSimpleFragment.class, - LinkageRecyclerViewCustomFragment.class + LinkageRecyclerViewCustomFragment.class, + LinkageRecyclerViewElemeFragment.class }; } diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/LinkageRecyclerViewElemeFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/LinkageRecyclerViewElemeFragment.java new file mode 100644 index 00000000..964e8592 --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/LinkageRecyclerViewElemeFragment.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.xuexiang.xuidemo.fragment.expands.linkage; + +import android.view.View; +import android.view.ViewGroup; + +import com.kunminx.linkage.LinkageRecyclerView; +import com.kunminx.linkage.adapter.viewholder.LinkagePrimaryViewHolder; +import com.kunminx.linkage.adapter.viewholder.LinkageSecondaryViewHolder; +import com.kunminx.linkage.bean.BaseGroupedItem; +import com.xuexiang.xaop.annotation.SingleClick; +import com.xuexiang.xpage.annotation.Page; +import com.xuexiang.xui.utils.SnackbarUtils; +import com.xuexiang.xui.widget.actionbar.TitleBar; +import com.xuexiang.xuidemo.DemoDataProvider; +import com.xuexiang.xuidemo.R; +import com.xuexiang.xuidemo.base.BaseFragment; +import com.xuexiang.xuidemo.fragment.expands.linkage.custom.CustomLinkagePrimaryAdapterConfig; +import com.xuexiang.xuidemo.fragment.expands.linkage.eleme.ElemeGroupedItem; +import com.xuexiang.xuidemo.fragment.expands.linkage.eleme.ElemeSecondaryAdapterConfig; + +import butterknife.BindView; + +/** + * @author xuexiang + * @since 2019-11-25 23:20 + */ +@Page(name = "仿饿了么双列表联动菜单") +public class LinkageRecyclerViewElemeFragment extends BaseFragment implements CustomLinkagePrimaryAdapterConfig.OnPrimaryItemClickListener, ElemeSecondaryAdapterConfig.OnSecondaryItemClickListener { + + @BindView(R.id.linkage) + LinkageRecyclerView linkage; + + /** + * 布局的资源id + * + * @return + */ + @Override + protected int getLayoutId() { + return R.layout.fragment_linkage_recyclerview; + } + + @Override + protected TitleBar initTitle() { + TitleBar titleBar = super.initTitle(); + titleBar.addAction(new TitleBar.TextAction("切换") { + @SingleClick + @Override + public void performAction(View view) { + if (linkage != null) { + linkage.setGridMode(!linkage.isGridMode()); + } + } + }); + return titleBar; + } + + /** + * 初始化控件 + */ + @Override + protected void initViews() { + linkage.init(DemoDataProvider.getElemeGroupItems(), new CustomLinkagePrimaryAdapterConfig(this), new ElemeSecondaryAdapterConfig(this)); + } + + @Override + public void onPrimaryItemClick(LinkagePrimaryViewHolder holder, View view, String title) { + SnackbarUtils.Short(view, title).show(); + } + + @Override + public void onSecondaryItemClick(LinkageSecondaryViewHolder holder, ViewGroup view, BaseGroupedItem item) { + SnackbarUtils.Short(view, item.info.getTitle()).show(); + } + + @Override + public void onGoodAdd(View view, BaseGroupedItem item) { + SnackbarUtils.Short(view, "添加:" + item.info.getTitle()).show(); + } +} diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/LinkageRecyclerViewSimpleFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/LinkageRecyclerViewSimpleFragment.java index 90c24037..fb0fc0aa 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/LinkageRecyclerViewSimpleFragment.java +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/LinkageRecyclerViewSimpleFragment.java @@ -17,16 +17,9 @@ package com.xuexiang.xuidemo.fragment.expands.linkage; -import android.text.TextUtils; import android.view.View; -import android.widget.TextView; -import androidx.core.content.ContextCompat; - -import com.google.android.material.snackbar.Snackbar; import com.kunminx.linkage.LinkageRecyclerView; -import com.kunminx.linkage.bean.DefaultGroupedItem; -import com.xuexiang.xaop.annotation.MemoryCache; import com.xuexiang.xaop.annotation.SingleClick; import com.xuexiang.xpage.annotation.Page; import com.xuexiang.xui.utils.SnackbarUtils; @@ -35,9 +28,6 @@ import com.xuexiang.xuidemo.R; import com.xuexiang.xuidemo.base.BaseFragment; -import java.util.ArrayList; -import java.util.List; - import butterknife.BindView; /** diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/eleme/ElemeGroupedItem.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/eleme/ElemeGroupedItem.java new file mode 100644 index 00000000..1dbcb57b --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/eleme/ElemeGroupedItem.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.xuexiang.xuidemo.fragment.expands.linkage.eleme; + +import com.kunminx.linkage.bean.BaseGroupedItem; + +/** + * 饿了么列表简单演示 + * + * @author xuexiang + * @since 2019-11-25 22:52 + */ +public class ElemeGroupedItem extends BaseGroupedItem { + + public ElemeGroupedItem(boolean isHeader, String header) { + super(isHeader, header); + } + + public ElemeGroupedItem(ItemInfo item) { + super(item); + } + + public static class ItemInfo extends BaseGroupedItem.ItemInfo { + private String content; + private String imgUrl; + private String cost; + + public ItemInfo(String title, String group, String content) { + super(title, group); + this.content = content; + } + + public ItemInfo(String title, String group, String content, String imgUrl) { + this(title, group, content); + this.imgUrl = imgUrl; + } + + public ItemInfo(String title, String group, String content, String imgUrl, String cost) { + this(title, group, content, imgUrl); + this.cost = cost; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public String getImgUrl() { + return imgUrl; + } + + public void setImgUrl(String imgUrl) { + this.imgUrl = imgUrl; + } + + public String getCost() { + return cost; + } + + public void setCost(String cost) { + this.cost = cost; + } + } +} diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/eleme/ElemeSecondaryAdapterConfig.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/eleme/ElemeSecondaryAdapterConfig.java new file mode 100644 index 00000000..6930a7da --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/eleme/ElemeSecondaryAdapterConfig.java @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.xuexiang.xuidemo.fragment.expands.linkage.eleme; + +import android.content.Context; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.bumptech.glide.Glide; +import com.kunminx.linkage.adapter.viewholder.LinkageSecondaryFooterViewHolder; +import com.kunminx.linkage.adapter.viewholder.LinkageSecondaryHeaderViewHolder; +import com.kunminx.linkage.adapter.viewholder.LinkageSecondaryViewHolder; +import com.kunminx.linkage.bean.BaseGroupedItem; +import com.kunminx.linkage.contract.ILinkageSecondaryAdapterConfig; +import com.xuexiang.xuidemo.R; + +/** + * 饿了么列表适配器 + * + * @author xuexiang + * @since 2019-11-25 22:54 + */ +public class ElemeSecondaryAdapterConfig implements ILinkageSecondaryAdapterConfig { + + private static final int SPAN_COUNT = 2; + + private Context mContext; + + private OnSecondaryItemClickListener mItemClickListener; + + public ElemeSecondaryAdapterConfig(OnSecondaryItemClickListener itemClickListener) { + mItemClickListener = itemClickListener; + } + + public ElemeSecondaryAdapterConfig setOnItemClickListner(OnSecondaryItemClickListener itemClickListener) { + mItemClickListener = itemClickListener; + return this; + } + + @Override + public void setContext(Context context) { + mContext = context; + } + + @Override + public int getGridLayoutId() { + return R.layout.adapter_eleme_secondary_grid; + } + + @Override + public int getLinearLayoutId() { + return R.layout.adapter_eleme_secondary_linear; + } + + + @Override + public int getHeaderLayoutId() { + return R.layout.default_adapter_linkage_secondary_header; + } + + @Override + public int getFooterLayoutId() { + return 0; + } + + @Override + public int getHeaderTextViewId() { + return R.id.secondary_header; + } + + @Override + public int getSpanCountOfGridMode() { + return SPAN_COUNT; + } + + @Override + public void onBindViewHolder(final LinkageSecondaryViewHolder holder, + final BaseGroupedItem item) { + + ((TextView) holder.getView(R.id.iv_goods_name)).setText(item.info.getTitle()); + Glide.with(mContext).load(item.info.getImgUrl()).into((ImageView) holder.getView(R.id.iv_goods_img)); + + ViewGroup viewGroup = holder.getView(R.id.iv_goods_item); + viewGroup.setOnClickListener(v -> { + if (mItemClickListener != null) { + mItemClickListener.onSecondaryItemClick(holder, viewGroup, item); + } + }); + + holder.getView(R.id.iv_goods_add).setOnClickListener(v -> { + if (mItemClickListener != null) { + mItemClickListener.onGoodAdd(v, item); + } + }); + } + + @Override + public void onBindHeaderViewHolder(LinkageSecondaryHeaderViewHolder holder, + BaseGroupedItem item) { + + ((TextView) holder.getView(R.id.secondary_header)).setText(item.header); + } + + @Override + public void onBindFooterViewHolder(LinkageSecondaryFooterViewHolder holder, + BaseGroupedItem item) { + + } + + + public interface OnSecondaryItemClickListener { + + void onSecondaryItemClick(LinkageSecondaryViewHolder holder, ViewGroup view, BaseGroupedItem item); + + void onGoodAdd(View view, BaseGroupedItem item); + + } +} diff --git a/app/src/main/res/drawable-xxhdpi/bg_food_sample.png b/app/src/main/res/drawable-xxhdpi/bg_food_sample.png new file mode 100644 index 0000000000000000000000000000000000000000..3fbfc906f2748d03ad4db86b6a1d141ddbf99d8c GIT binary patch literal 1406 zcmeAS@N?(olHy`uVBq!ia0vp^^MQCZ2Q!fL*V~r~q;3cJgt!9fr=6Dn(~RkW)|_?) z+5#tm3^;<=4&g%7z@?BG4|=R1vVXFSHy(A_x!39VYWruc7W=n3-tV=#HO2aUmD%}4 zw%-a(Kb4uy7wicKde6Ef$S;_I={Mg;xylfZdsh~p`SR+-h7KLkTV85&{hsXW%RG|j zVzGU4N=&qyp)&i`qb0=-Pqt3a{Isf3a(ahlsLHLYz6=a3;+`&!Ar*{ouDUxNHV|OF za51vM-Wj=X1TL*MChpvH$$-yoiUJ1s`sG#y)%MK8XvzW$F*6 z-??|!<}q`Xk<^Yg0h9aub<|!o8lQ+*`0jb_F4f347YwuKes(Q4pZad!NA;&7vA2$| zSuo*V|DRS{j*FttPgu>*)3W_g{@DD*F}tL-?X$JMZ~wD6l;f|?{j|Nm)Bo4hi|{YJ z{lY=iJXG#ycqGH#b;_%DtUc$}I+e9oO>$~YsBXWGY)0{>o4fY;*SJ|VsjXl6YTK{d ztHr7>99q6>_kNY{6ZJdx=$#IJQU87Z$#vX!f*ikodirph=`rOwFDG$ng@6Cvzb3rJ z;`F^Vcms;STk~u$)z~2y?H^O?_$^U zP4ezr5_NA*myL?pY#!Kg%uVmNu|qOvb&CJR3#Qefix%>Vo^VY$G*2|+kk`%amQph| zmupHzY^t}O_+gdxi7$4gaw3+JsytWJ*LSqCnzE+)EI6`wg5;Dv%LL3th6zgEZ2u)X~sf4}?R`u93BfBrPszkkO4`Df?nKU>e=6BECd zCw_ijp!(7!J0JdDyz=Jn(`TIKa(JNZLBMK)JQ4LUT!(7Qdu~zRJA%KezB&0a{WE$xd%kzECSR8CR*N_k@o3*kxxatY1xIo z&`s>$;OCu+x+I)^_wzdSE*bM$F}^vKgG&UYJRqbe+Jcg;Py++zOMd9o+l0~Edq z>o2=-B%S@3+?JhNR^Coy>Am;liZMJd?YXY?nx*6J&mWAnKiclvsgZbcgOqn7q>r5 z@KG(ReCcpx>;5f2Hyza}P&je(XM4xgHzj43t(=DvAE>vNJlwV9?X!=|Z1(ZBiEa5I Zx9aYPx)xJg7oRCodHTs>?YMHu~N{Syk(Boz>#@C6g-Qcy&sNE!rHD4+ldBm^=FNE9F? z6|$(}A_Wpjus}$O1O*hNLZS%;w77#{<=lWH8sf$j*k^lq@5}CKZ@qiBzjL$atYqEp z?96=cy`8^r_FEfqaCE+~$ATSse$UDYn41?P$F0Z_W92Z;4=V&Ko7Tvt5!nzccaXLk z7`eSSEx&Z%G3!mkgx&g&MQej^mgUT@l~+*vSr9v3$%;{7ZcQ2a?zIK^Y0;RyO7*1_ zu2qP+uk7RIKY0&N`E_gMSc<*MNyf-Jg#Fq+Bv;nnGJjRBFsz^!A?Cic9n+HwsPjz- zFjE(}Vf8?e9`0YaGqSYyw&@Pbo9A97A)fu#KD>2L7V(5WK%bw^W3cW#Ah3fL`01ge zviRGp=HIgQmlk4f*`7mB{R}POv9iYNEQc0y*9P+b+Jd=RrryFrbbhdhJuG!}x!q06Hft(a8Fe~;PBuBQ0uq9B0BRT5xE(==524<+CIfloyrAiA`28SF-S3b}p z=ta_jif3r*d}c~+B{z?UyrJ5+n`P!50}rNCWZ zK=BQfABe_>f*J(jYq;^D@W3)P;21IQ0hVz?nCJT8;EoTG{Lo+;>+aIqaOyV0i=?wu zm!Gh99<>%YPAuC;db@B9jC_K1!EAw|{jAi$!1etHCrA6K1x~n!kZ`37l&&``cw7LF zQZ77r++)|cAD>VHmov9H2ewLBph2{t%3*4RhwGVzhPsQa5XMn7axzjt|UJE9@F~9NYEJ95moy zx#}M>=ZIDVhVVHz>zP4n5HOC>GhEK$P=i2&Iq%0YItSo|L2#!A(Squh7of%iLb&0BUK7Lqk5s)*v)2a%gvCRnUbqm7-Yv3Hkbw^`_Ft!;A^*n&* z1OmB|b7ZV9gvKP={cotFj1%~KJsyYI7lK6XtX#q-#f}Tobe58K($bQ7>bNFH2D8WO z8W2LG+!5d%&(PF)n%kU~)`)#@Oh)uWoWUcExc>t_V53np=%d?k_;kOM2vmd$`;LPw zvaewGE+YA#PDb+Y6M|Jd2qp`KWYn2Pxn~R8$~)wg7Ewns17pMhJB0e98LbSYwfI80 zfKwKQOdy!CI({3S}a9* zhy9jr5%Eg(lW4{^Bdixbij(MFknh1)xj~OP=|IJ?9j;U8)I55BSq=2%;}4*&oF07*qoM6N<$f;pkv#{d8T literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/tag_new_good.png b/app/src/main/res/drawable-xxhdpi/tag_new_good.png new file mode 100644 index 0000000000000000000000000000000000000000..ef42dec28bbfac5441e701a03d6d2a9962b13348 GIT binary patch literal 4154 zcmV-A5XJ9_P)Px^^hrcPRA>dQT4{`2#SyMIJ9~I{ZSR`3*K1?r0~-h!umuPQY-|TZ07VFhKqBxX zn4m-ofj>xGBEckz1WJfR4u}j=0zolH5LX}x7(%!L1TbJQN5Cic`q=fJ9?$N~b2 zV@#P~jdISpR<5Au7%MR@l?Oa^N@L;;XL$NBdu7_I(3kTt|K`heB3X(Hd;m0#VNT94 zT1k8zbIPEnHb>wS_?7E-FX<=^mhJ;?MXIa-Bq$IQHR6Vhum|DE)5JjEXZVm1)d|VM*nK*;94n_>U~(!e zlnkv0650_&hxia|Yi^u9MZqv;3a2d9HT+1q*$VjB2mQcahG%jzJsWc!vXBhwrW`Ra zJT;&fY&lQG1#XT}JQf&ZnRs0{eC~Q&R=Av2s4>du4Bz^R2&g=OSygO_I|{wo2zVGE z0e&ojA<5vZGBpqaO~)3H>$}^91<7kGVfk7)_lF$>N%7G{y zCz6-*CtV>Ob+e?krcG|yex)2J7a_On+sr!NoN2iuDPFo}*AiGObuy=Zu6$7VNGc#; z`E;E5C!Rb~PJtJBQqE601`{Si<u3oO& zbhE4<++c}-T~A7UxqNlPA~~`7Smj3F%1?WXm~--G8@*=ofAqXB&-HFdbxh9^hyYXn zK4y;unL$<7Eu=A1u1}g|YW-}T+YTo3?!arZxcLmko5iD19WLj$t&Cw` zdfZzo$g}(2gH6Q8N~3*{=A2iMC7ANC1{p3fO9)AMc`+Fr&#XT}e$erAOvY}r8s^E3 zGj1QXc<=5t@<#tZWo66Rqt;@<&SIy$HSi8T?@2z%%TT2R!X!%q@d1h{`21g*+Cc)i zoA9AYigKWHegzp46m|*&KVVrMe3-L2mA_o$-A$7mV7D6Z=z=9d)jBuWS!4ecxKl^6ORmxYa|$vLf; z$ke(Sa`k5y%0PKg*GZ^W#>ubetd*Wpw>;MMkUZ1#v=X0!WX8?OdlEe%MvC5|=NAn& z+=7+7@u{+>k%r*HIJQlZe^ML-u?~HEQmA9+QMl}=i*;V;+7yT#w3cPnog7*}2j@hs zoY1^9=v&s0YdT5la&p{~jpeOmxoz?857 z$2c?=+K5^dUy8@F`d76G7w|bdE3y*fT%EGle~G*~_!2Iy9cp6n_|vsQtn_iKZ$3rk zg>pe&=v`-J4+FFjH?s*j99s$dxj`)tnCA%n+Q-H`(W(PYIYTkM9MlFcHSj&~l) z0eUGOo@`8i;6QFw_zKUUuo#FbSt#=QJ-lIoOs|`xP$eBQzu_1;v-JWQDi5jA zYT89|S^GD93SDoO$ZRe$zNXO^Lm%t-nDNpl8)e}G|9S@L0w$heS66;m#4a)34{|oVJ}Y;^kg>}1Sxb5M*iZqv*p}FmIrOFSsTNIJhJy?xohXs>f{ecUL$S!3F^-=aj(e; zg8O#8D!=;tIh`?i3exH{1?t*e3|`GK$fe^PF0b+Ov)T8@_D79xn{~%1+2x;nNAfu} zt!sGagr0%hry4+?yvRZlwNLN^cY+*R-(IbHkXcJjbKsrGw7N;C&enryR*NU)8`ZB> zFa7%^Njk;&%rfO!)rKk>;df_ouM}`b z#o{_t@pQkNIp?g^d>! zLXw$+{BX+}`B(o(;heJHb4N8ECVxEgM$@9Q2A0|7Z?H4o`$>xN>R8#jK<=5pN^$O^ zdXu;W|3*ac%GHv>xqU(qm=y8viS7sRQmaYV2Fv^5Fu{wig=vDG=z2^B@f3Z;xTEwJ zdT(h!lQ1<-P>F}Q+2@mL-0WZtzNwSN7^!*blQ{9!Nv4Ei_Hk1=gN4wp1`j;ba$c_M zwr$P}Ep-N`IQ`konUSF4*IUk$-_ChRZk>6jwAW5k9sg>nX_ep4yI)q%{IM*XxJ<SJU;Mf8skGUTM)hvmd@tOTnDGK(6qAsH?;-HsLjkjr|Aa+8;AJA z90?-8K~{n^Od0!0`N=Y?VJ-#o_P`q&h)%*6RbT0QS!eU`TC@XaQyunhWVFhzgfNnf-x=xE)vM$6L8hQWAj`tIC(J1~8_@){(hbq?j=ctlRh0Un6!{ns#CrDjVZ;SYTwCgX>2|LK(b(}8ioSTx8gwDuz z)})hVLGxUYCf?Sk)cUR3v^9AVwy~yOzSnWO2I?60^T%apBat49ZXVWkuGPter+?M3 zGV`)BWs#K=&(Xg~(9pV`zsg`~KStH>XY|^J?7_Vc<2#4HlMTrYGp->--s*o>{$1Dv zh&^;!_1TR;74W6IrG!kvx%+pW3)+_YaLnF<3^4?a=9&h%c1HF}WK1B0>L1J*S6aQ4 z>l%K|yKz&5G*UjZ^;`<@&^0W7-uEcp=`6u4Cv(TmQ+WvwW5x0?#)-Vp^OElFk7nMW zYy5g}&*Lid#HiDB)duPAV$rxj9wlsq`a!2-**>UpSa9E(7|7H=e5aL)vA*tzFE4`J z*-y9KAeXmag|~^jgny#Be)?)W#%H(r^#kjrfQLylY*q5?zQ4<&rsHJOfvxg-KmPI% z5^m2w&{1;SEpH?QX+(_ExUJrDuWT6DthW5e@a+1ja@(A5o0<{OYGANzd{F$>hj*C_ z73`PL;_-83^{lM2G~NiWKWKrsf=S;8*%?%&45iND9dgUI>!bk>ifr%ie_s>CfIcpK zEPv{H1X4?=odG#{9+lLXYsS-c0WmXpt{Z8K8{;?wI?WDHPPT=h;S1V|?n@K@4F`1QUAZ~wZ6d#VU?-9IFy z?`#QS6Y5y@VOOkZ zm_+P8UZ}BGUkEJLN%6p`9R?0%>T}NCUrp#ZmP6o|GQ|vDd&sGq;(Z*;b!_pIj{=g) z27L}PLv-$B0}&YF4ya-DHU^f)T#i*6)20PwyT-X=%wBAZyRUZ1CAAgs!6xMzFq0hH z!h&&S#oL+(@4Z$R@xbW@C>{deuvAVw{Hl-8Lyi8VQggT7#aKBWoRL*Dh?8(o=I=BG z8X@Yb5fU6RCP^of;whu9ehjO4R!HgtawWihGrNjWMduRqp%-&jmDG0ZpLWbQDVQ&_ zZ5aAAx%)DC&AQ@}o7U)WF?~)+Nd^MJnSppMlThYB0|+~7c*EIF1g8W9ow%xu0QCcg zJ%kpB-3@I%5^wrkOF6p_#Y4_>lw*ukFZfXYs$;&4S3EXM;JdD_vGx+&WGZ@_PYngb zo=Nr|n949`&*lV11*xkR2!k-Z;fSfmGwF6?P+}T@>8LJ}o8mE6r|v)Ks(&hTBPgR1 z{Ax^!Hy>O#e6Y{TrGCI6vHh5Cz$V>2wB+VBOb#{w15t1&Sf1nruK)l507*qoM6N<$ Eg289_fdBvi literal 0 HcmV?d00001 diff --git a/app/src/main/res/layout/adapter_eleme_secondary_grid.xml b/app/src/main/res/layout/adapter_eleme_secondary_grid.xml new file mode 100644 index 00000000..c85a661c --- /dev/null +++ b/app/src/main/res/layout/adapter_eleme_secondary_grid.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/adapter_eleme_secondary_linear.xml b/app/src/main/res/layout/adapter_eleme_secondary_linear.xml new file mode 100644 index 00000000..0204cc45 --- /dev/null +++ b/app/src/main/res/layout/adapter_eleme_secondary_linear.xml @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 66498b7b5970d4616e8c59df45fe142eca8dc2cd Mon Sep 17 00:00:00 2001 From: xuexiangjys Date: Tue, 26 Nov 2019 10:38:41 +0800 Subject: [PATCH 21/27] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tabbar/TabControlViewFragment.java | 2 +- .../CustomLinkageSecondaryAdapterConfig.java | 2 +- .../eleme/ElemeSecondaryAdapterConfig.java | 2 +- .../layout/adapter_linkage_empty_footer.xml | 25 ++++++ .../widget/tabbar/MultiTabControlView.java | 86 ++++++++++++++----- .../xui/widget/tabbar/TabControlView.java | 68 ++++++++++++--- 6 files changed, 152 insertions(+), 33 deletions(-) create mode 100644 app/src/main/res/layout/adapter_linkage_empty_footer.xml diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/tabbar/TabControlViewFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/tabbar/TabControlViewFragment.java index 62970f01..46f93536 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/tabbar/TabControlViewFragment.java +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/tabbar/TabControlViewFragment.java @@ -75,7 +75,7 @@ private void initMultiTabControlView() { mMultiTabControlView.setOnMultiTabSelectionChangedListener(new MultiTabControlView.OnMultiTabSelectionChangedListener() { @Override public void newSelection(String title, String value, boolean isChecked) { - XToastUtils.toast("选中了:" + title + ", 选中的值为:" + value + ", isChecked:" + isChecked); + XToastUtils.toast((isChecked ? "选中了:" : "取消了:") + title + ", 值为:" + value); } }); } diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/custom/CustomLinkageSecondaryAdapterConfig.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/custom/CustomLinkageSecondaryAdapterConfig.java index 5cf43024..ab741341 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/custom/CustomLinkageSecondaryAdapterConfig.java +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/custom/CustomLinkageSecondaryAdapterConfig.java @@ -70,7 +70,7 @@ public int getHeaderLayoutId() { @Override public int getFooterLayoutId() { - return 0; + return R.layout.adapter_linkage_empty_footer; } @Override diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/eleme/ElemeSecondaryAdapterConfig.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/eleme/ElemeSecondaryAdapterConfig.java index 6930a7da..e2ea7079 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/eleme/ElemeSecondaryAdapterConfig.java +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/eleme/ElemeSecondaryAdapterConfig.java @@ -77,7 +77,7 @@ public int getHeaderLayoutId() { @Override public int getFooterLayoutId() { - return 0; + return R.layout.adapter_linkage_empty_footer; } @Override diff --git a/app/src/main/res/layout/adapter_linkage_empty_footer.xml b/app/src/main/res/layout/adapter_linkage_empty_footer.xml new file mode 100644 index 00000000..073b6e22 --- /dev/null +++ b/app/src/main/res/layout/adapter_linkage_empty_footer.xml @@ -0,0 +1,25 @@ + + + + + + + \ No newline at end of file diff --git a/xui_lib/src/main/java/com/xuexiang/xui/widget/tabbar/MultiTabControlView.java b/xui_lib/src/main/java/com/xuexiang/xui/widget/tabbar/MultiTabControlView.java index 521c8e99..473fd9a8 100644 --- a/xui_lib/src/main/java/com/xuexiang/xui/widget/tabbar/MultiTabControlView.java +++ b/xui_lib/src/main/java/com/xuexiang/xui/widget/tabbar/MultiTabControlView.java @@ -114,7 +114,6 @@ public class MultiTabControlView extends LinearLayout implements HasTypeface { private boolean mEqualWidth = false; private ColorStateList mTextColorStateList; - //Item organization private LinkedHashMap mItemMap = new LinkedHashMap<>(); private List mOptions; @@ -125,19 +124,21 @@ public class MultiTabControlView extends LinearLayout implements HasTypeface { */ private void addOnCheckedChangeListener(CheckBox cb) { if (cb != null) { - cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { - @Override - public void onCheckedChanged(CompoundButton checkBox, boolean b) { - if (mListener != null) { - String identifier = checkBox.getText().toString(); - String value = mItemMap.get(identifier); - mListener.newSelection(identifier, value, checkBox.isChecked()); - } - } - }); + cb.setOnCheckedChangeListener(mCheckBoxListener); } } + private CompoundButton.OnCheckedChangeListener mCheckBoxListener = new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton checkBox, boolean isChecked) { + if (mListener != null) { + String identifier = checkBox.getText().toString(); + String value = mItemMap.get(identifier); + mListener.newSelection(identifier, value, checkBox.isChecked()); + } + } + }; + public MultiTabControlView(Context context) { super(context, null); //Initialize @@ -456,20 +457,65 @@ public MultiTabControlView setSelection(String... values) { * @param value */ public MultiTabControlView setSelection(String value) { - String buttonText = ""; - if (mItemMap.containsValue(value)) { - for (String entry : mItemMap.keySet()) { - if (mItemMap.get(entry).equalsIgnoreCase(value)) { - buttonText = entry; + setSelectionStatus(value, true); + return this; + } + + /** + * 通过值 设置tab的选中状态 + * + * @param value + */ + public MultiTabControlView setSelectionStatus(String value, boolean isChecked) { + String title = getTitleByValue(value); + setSelectionStatusByTitle(title, isChecked); + return this; + } + + /** + * 静默通过标题设置tab的选中状态 + * + * @param title + * @param isChecked + * @return + */ + public MultiTabControlView setSelectionStatusByTitle(String title, boolean isChecked) { + setSelectionStatusByTitle(title, isChecked, true); + return this; + } + + /** + * 通过标题设置tab的选中状态 + * + * @param title + * @param isChecked 是否选中 + * @param isSilent 是否静默设置 + * @return + */ + public MultiTabControlView setSelectionStatusByTitle(String title, boolean isChecked, boolean isSilent) { + for (CheckBox option : mOptions) { + if (option.getText().toString().equalsIgnoreCase(title)) { + if (isSilent) { + option.setOnCheckedChangeListener(null); + option.setChecked(isChecked); + addOnCheckedChangeListener(option); + } else { + option.setChecked(isChecked); } } } - for (CheckBox option : mOptions) { - if (option.getText().toString().equalsIgnoreCase(buttonText)) { - option.setChecked(true); + return this; + } + + private String getTitleByValue(String value) { + if (mItemMap.containsValue(value)) { + for (String key : mItemMap.keySet()) { + if (mItemMap.get(key).equalsIgnoreCase(value)) { + return key; + } } } - return this; + return ""; } /** diff --git a/xui_lib/src/main/java/com/xuexiang/xui/widget/tabbar/TabControlView.java b/xui_lib/src/main/java/com/xuexiang/xui/widget/tabbar/TabControlView.java index bf9a6719..b1b30901 100644 --- a/xui_lib/src/main/java/com/xuexiang/xui/widget/tabbar/TabControlView.java +++ b/xui_lib/src/main/java/com/xuexiang/xui/widget/tabbar/TabControlView.java @@ -360,6 +360,12 @@ public TabControlView setItems(String[] itemArray, String[] valueArray) throws E return this; } + /** + * 为每一个选项设置 items and values + * + * @param itemArray + * @param valueArray + */ private void setItems(CharSequence[] itemArray, CharSequence[] valueArray) throws Exception { if (itemArray != null && valueArray != null) { if (itemArray.length != valueArray.length) { @@ -418,22 +424,64 @@ public TabControlView setDefaultSelection(int defaultSelection) throws Exception * @param value */ public TabControlView setSelection(String value) { - String buttonText = ""; - if (mItemMap.containsValue(value)) { - for (String entry : mItemMap.keySet()) { - if (mItemMap.get(entry).equalsIgnoreCase(value)) { - buttonText = entry; - } - } - } + setSelection(value, true); + return this; + } + + /** + * 通过值 设置选中的Tab + * + * @param value + */ + public TabControlView setSelection(String value, boolean isSilent) { + String title = getTitleByValue(value); + setSelectionTitle(title, isSilent); + return this; + } + + /** + * 通过标题设置选中的Tab + * + * @param title + * @return + */ + public TabControlView setSelectionTitle(String title) { + setSelectionTitle(title, true); + return this; + } + + /** + * 通过标题设置选中的Tab + * + * @param title + * @param isSilent 是否静默设置 + * @return + */ + public TabControlView setSelectionTitle(String title, boolean isSilent) { for (RadioButton option : mOptions) { - if (option.getText().toString().equalsIgnoreCase(buttonText)) { - this.check(option.getId()); + if (option.getText().toString().equalsIgnoreCase(title)) { + if (isSilent) { + setOnCheckedChangeListener(null); + this.check(option.getId()); + setOnCheckedChangeListener(mSelectionChangedListener); + } else { + this.check(option.getId()); + } } } return this; } + private String getTitleByValue(String value) { + if (mItemMap.containsValue(value)) { + for (String key : mItemMap.keySet()) { + if (mItemMap.get(key).equalsIgnoreCase(value)) { + return key; + } + } + } + return ""; + } /** * Sets the colors used when drawing the view. The primary color will be used for selected color From b134a91ad5b967240b1652d5abf28b79a4411e55 Mon Sep 17 00:00:00 2001 From: xuexiangjys Date: Thu, 28 Nov 2019 10:16:47 +0800 Subject: [PATCH 22/27] =?UTF-8?q?=E4=BC=98=E5=8C=96MarqueeTextView?= =?UTF-8?q?=E3=80=81SuperTextView=E3=80=81Banner=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xuidemo/activity/TranslucentActivity.java | 8 +- .../adapter/RefreshHeadViewAdapter.java | 12 +- .../xuidemo/fragment/SettingFragment.java | 2 +- .../components/MarqueeViewFragment.java | 11 +- .../banner/ViewPagerBannerFragment.java | 72 ++--- .../swipe/SwipeHeadFootViewFragment.java | 5 +- .../refresh/swipe/SwipeRefreshFragment.java | 5 +- .../supertextview/SuperClickFragment.java | 35 +-- .../main/res/layout/fragment_super_click.xml | 6 + app/src/main/res/values/styles_demo.xml | 6 +- .../xui/widget/actionbar/TitleBar.java | 2 +- .../banner/widget/banner/base/BaseBanner.java | 49 ++-- .../xui/widget/textview/MarqueeTextView.java | 9 +- .../textview/marqueen/MarqueeFactory.java | 25 +- .../textview/supertextview/SuperTextView.java | 256 +++++++++++------- xui_lib/src/main/res/values/stv_attrs.xml | 12 +- 16 files changed, 293 insertions(+), 222 deletions(-) diff --git a/app/src/main/java/com/xuexiang/xuidemo/activity/TranslucentActivity.java b/app/src/main/java/com/xuexiang/xuidemo/activity/TranslucentActivity.java index 3c61227e..6b635ca8 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/activity/TranslucentActivity.java +++ b/app/src/main/java/com/xuexiang/xuidemo/activity/TranslucentActivity.java @@ -1,11 +1,13 @@ package com.xuexiang.xuidemo.activity; import android.os.Bundle; +import android.view.View; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import com.xuexiang.xui.utils.StatusBarUtils; +import com.xuexiang.xui.widget.banner.widget.banner.BannerItem; import com.xuexiang.xui.widget.banner.widget.banner.SimpleImageBanner; import com.xuexiang.xui.widget.banner.widget.banner.base.BaseBanner; import com.xuexiang.xuidemo.DemoDataProvider; @@ -35,10 +37,10 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { ButterKnife.bind(this); sibSimpleUsage.setSource(DemoDataProvider.getBannerList()) - .setOnItemClickL(new BaseBanner.OnItemClickL() { + .setOnItemClickListener(new BaseBanner.OnItemClickListener() { @Override - public void onItemClick(int position) { - XToastUtils.toast("position--->" + position); + public void onItemClick(View view, BannerItem item, int position) { + XToastUtils.toast("headBanner position--->" + position); } }).startScroll(); diff --git a/app/src/main/java/com/xuexiang/xuidemo/adapter/RefreshHeadViewAdapter.java b/app/src/main/java/com/xuexiang/xuidemo/adapter/RefreshHeadViewAdapter.java index 74e7946e..735e57ca 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/adapter/RefreshHeadViewAdapter.java +++ b/app/src/main/java/com/xuexiang/xuidemo/adapter/RefreshHeadViewAdapter.java @@ -1,5 +1,7 @@ package com.xuexiang.xuidemo.adapter; +import android.view.View; + import androidx.annotation.NonNull; import com.xuexiang.xui.adapter.recyclerview.BaseRecyclerAdapter; @@ -72,9 +74,9 @@ protected void bindData(@NonNull RecyclerViewHolder holder, int position, String if (getItemViewType(position) == TYPE_BANNER_HEAD) { headBanner = holder.findViewById(R.id.sib_simple_usage); headBanner.setSource(mData) - .setOnItemClickL(new BaseBanner.OnItemClickL() { + .setOnItemClickListener(new BaseBanner.OnItemClickListener() { @Override - public void onItemClick(int position) { + public void onItemClick(View view, BannerItem item, int position) { XToastUtils.toast("headBanner position--->" + position); } }).startScroll(); @@ -82,10 +84,10 @@ public void onItemClick(int position) { } else if (getItemViewType(position) == TYPE_BANNER_FOOT) { footBanner = holder.findViewById(R.id.sib_simple_usage); footBanner.setSource(mData) - .setOnItemClickL(new BaseBanner.OnItemClickL() { + .setOnItemClickListener(new BaseBanner.OnItemClickListener() { @Override - public void onItemClick(int position) { - XToastUtils.toast("footBanner position--->" + position); + public void onItemClick(View view, BannerItem item, int position) { + XToastUtils.toast("headBanner position--->" + position); } }).startScroll(); } else { diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/SettingFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/SettingFragment.java index 9af0f967..ad5c81c5 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/fragment/SettingFragment.java +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/SettingFragment.java @@ -56,7 +56,7 @@ protected void initViews() { stvSwitchCustomTheme.setSwitchIsChecked(SettingSPUtils.getInstance().isUseCustomTheme()); stvSwitchCustomTheme.setOnSuperTextViewClickListener(new SuperTextView.OnSuperTextViewClickListener() { @Override - public void onClickListener(SuperTextView superTextView) { + public void onClick(SuperTextView superTextView) { stvSwitchCustomTheme.setSwitchIsChecked(!stvSwitchCustomTheme.getSwitchIsChecked(), false); } }); diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/MarqueeViewFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/MarqueeViewFragment.java index d25cf3ff..9bd14b98 100755 --- a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/MarqueeViewFragment.java +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/MarqueeViewFragment.java @@ -1,5 +1,6 @@ package com.xuexiang.xuidemo.fragment.components; +import android.view.View; import android.widget.RelativeLayout; import android.widget.TextView; @@ -59,7 +60,7 @@ protected void initViews() { marqueeView1.startFlipping(); marqueeFactory1.setOnItemClickListener(new MarqueeFactory.OnItemClickListener() { @Override - public void onItemClickListener(MarqueeFactory.ViewHolder holder) { + public void onItemClick(View view, MarqueeFactory.ViewHolder holder) { XToastUtils.toast(holder.getData()); } }); @@ -68,7 +69,7 @@ public void onItemClickListener(MarqueeFactory.ViewHolder hold MarqueeFactory marqueeFactory2 = new SimpleNoticeMF(getContext()); marqueeFactory2.setOnItemClickListener(new MarqueeFactory.OnItemClickListener() { @Override - public void onItemClickListener(MarqueeFactory.ViewHolder holder) { + public void onItemClick(View view, MarqueeFactory.ViewHolder holder) { XToastUtils.toast(holder.getData()); } }); @@ -81,7 +82,7 @@ public void onItemClickListener(MarqueeFactory.ViewHolder hold MarqueeFactory marqueeFactory3 = new SimpleNoticeMF(getContext()); marqueeFactory3.setOnItemClickListener(new MarqueeFactory.OnItemClickListener() { @Override - public void onItemClickListener(MarqueeFactory.ViewHolder holder) { + public void onItemClick(View view, MarqueeFactory.ViewHolder holder) { XToastUtils.toast(holder.getData()); } }); @@ -95,7 +96,7 @@ public void onItemClickListener(MarqueeFactory.ViewHolder hold MarqueeFactory marqueeFactory4 = new SimpleNoticeMF(getContext()); marqueeFactory4.setOnItemClickListener(new MarqueeFactory.OnItemClickListener() { @Override - public void onItemClickListener(MarqueeFactory.ViewHolder holder) { + public void onItemClick(View view, MarqueeFactory.ViewHolder holder) { XToastUtils.toast(holder.getData()); } }); @@ -111,7 +112,7 @@ public void onItemClickListener(MarqueeFactory.ViewHolder hold MarqueeFactory marqueeFactory5 = new ComplexViewMF(getContext()); marqueeFactory5.setOnItemClickListener(new MarqueeFactory.OnItemClickListener() { @Override - public void onItemClickListener(MarqueeFactory.ViewHolder holder) { + public void onItemClick(View view, MarqueeFactory.ViewHolder holder) { XToastUtils.toast(holder.getData().toString()); } }); diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/banner/ViewPagerBannerFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/banner/ViewPagerBannerFragment.java index b3fdfad4..43e0721b 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/banner/ViewPagerBannerFragment.java +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/banner/ViewPagerBannerFragment.java @@ -51,7 +51,7 @@ * @date 2017/10/15 下午1:17 */ @Page(name = "使用ViewPager实现的Banner") -public class ViewPagerBannerFragment extends BaseFragment { +public class ViewPagerBannerFragment extends BaseFragment implements BaseBanner.OnItemClickListener { private List mData; @BindView(R.id.sib_simple_usage) @@ -136,10 +136,9 @@ public void onClick(View v) { */ private void sib_simple_usage() { sib_simple_usage.setSource(mData) - .setOnItemClickL(new BaseBanner.OnItemClickL() { + .setOnItemClickListener(new BaseBanner.OnItemClickListener() { @Override - public void onItemClick(int position) { - XToastUtils.toast("position--->" + position); + public void onItemClick(View view, BannerItem t, int position) { } }) .setIsOnePageLoop(false).startScroll(); @@ -171,12 +170,7 @@ private void sib_the_most_comlex_usage() { // .setPeriod(10) //scroll setPeriod .setSource(mData) //data source list .setTransformerClass(ZoomOutSlideTransformer.class) //set page transformer - .setOnItemClickL(new BaseBanner.OnItemClickL() { - @Override - public void onItemClick(int position) { - XToastUtils.toast("position--->" + position); - } - }) + .setOnItemClickListener(this) .startScroll(); //start scroll,the last method to call } @@ -188,12 +182,7 @@ private void sib_res() { // .setIndicatorStyle(SimpleImageBanner.STYLE_DRAWABLE_RESOURCE) // .setIndicatorSelectorRes(R.mipmap.banner_dot_unselect, R.mipmap.banner_dot_select) .setSource(mData) - .setOnItemClickL(new BaseBanner.OnItemClickL() { - @Override - public void onItemClick(int position) { - XToastUtils.toast("position--->" + position); - } - }) + .setOnItemClickListener(this) .startScroll(); } @@ -204,12 +193,7 @@ private void sib_rectangle() { sib_rectangle // .setIndicatorCornerRadius(0) .setSource(mData) - .setOnItemClickL(new BaseBanner.OnItemClickL() { - @Override - public void onItemClick(int position) { - XToastUtils.toast("position--->" + position); - } - }) + .setOnItemClickListener(this) .startScroll(); } @@ -223,12 +207,7 @@ private void sib_corner_rectangle() { // .setIndicatorHeight(4) // .setIndicatorCornerRadius(2) .setSource(mData) - .setOnItemClickL(new BaseBanner.OnItemClickL() { - @Override - public void onItemClick(int position) { - XToastUtils.toast("position--->" + position); - } - }) + .setOnItemClickListener(this) .startScroll(); } @@ -240,12 +219,7 @@ public void onItemClick(int position) { private void sib_indicator_right_with_text() { sib_indicator_right_with_text .setSource(mData) - .setOnItemClickL(new BaseBanner.OnItemClickL() { - @Override - public void onItemClick(int position) { - XToastUtils.toast("position--->" + position); - } - }) + .setOnItemClickListener(this) .startScroll(); } @@ -255,12 +229,7 @@ public void onItemClick(int position) { private void sib_indicator_left_with_text() { sib_indicator_left_with_text .setSource(mData) - .setOnItemClickL(new BaseBanner.OnItemClickL() { - @Override - public void onItemClick(int position) { - XToastUtils.toast("position--->" + position); - } - }) + .setOnItemClickListener(this) .startScroll(); } @@ -271,12 +240,7 @@ private void sib_anim() { sib_anim .setSelectAnimClass(ZoomInEnter.class) .setSource(mData) - .setOnItemClickL(new BaseBanner.OnItemClickL() { - @Override - public void onItemClick(int position) { - XToastUtils.toast("position--->" + position); - } - }) + .setOnItemClickListener(this) .startScroll(); } @@ -289,12 +253,7 @@ private void sib_anim2() { .setSelectAnimClass(RotateEnter.class) .setUnselectAnimClass(NoAnimExist.class) .setSource(mData) - .setOnItemClickL(new BaseBanner.OnItemClickL() { - @Override - public void onItemClick(int position) { - XToastUtils.toast("position--->" + position); - } - }) + .setOnItemClickListener(this) .startScroll(); } @@ -309,9 +268,9 @@ private void stb() { } stb .setSource(titles) - .setOnItemClickL(new BaseBanner.OnItemClickL() { + .setOnItemClickListener(new BaseBanner.OnItemClickListener() { @Override - public void onItemClick(int position) { + public void onItemClick(View view, String item, int position) { XToastUtils.toast("position--->" + position); } }) @@ -355,4 +314,9 @@ public void onDestroyView() { stb.recycle(); super.onDestroyView(); } + + @Override + public void onItemClick(View view, BannerItem item, int position) { + XToastUtils.toast("position--->" + position + ", item:" + item.title); + } } diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/refresh/swipe/SwipeHeadFootViewFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/refresh/swipe/SwipeHeadFootViewFragment.java index 63a89149..7ce4023d 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/refresh/swipe/SwipeHeadFootViewFragment.java +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/refresh/swipe/SwipeHeadFootViewFragment.java @@ -5,6 +5,7 @@ import com.scwang.smartrefresh.layout.adapter.SmartViewHolder; import com.xuexiang.xpage.annotation.Page; import com.xuexiang.xui.utils.WidgetUtils; +import com.xuexiang.xui.widget.banner.widget.banner.BannerItem; import com.xuexiang.xui.widget.banner.widget.banner.SimpleImageBanner; import com.xuexiang.xui.widget.banner.widget.banner.base.BaseBanner; import com.xuexiang.xuidemo.DemoDataProvider; @@ -49,9 +50,9 @@ protected void initViews() { banner = headerView.findViewById(R.id.sib_simple_usage); banner.setSource(DemoDataProvider.getBannerList()) - .setOnItemClickL(new BaseBanner.OnItemClickL() { + .setOnItemClickListener(new BaseBanner.OnItemClickListener() { @Override - public void onItemClick(int position) { + public void onItemClick(View view, BannerItem item, int position) { XToastUtils.toast("headBanner position--->" + position); } }).startScroll(); diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/refresh/swipe/SwipeRefreshFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/refresh/swipe/SwipeRefreshFragment.java index 1ad9b0f6..919af9cd 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/refresh/swipe/SwipeRefreshFragment.java +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/refresh/swipe/SwipeRefreshFragment.java @@ -7,6 +7,7 @@ import com.xuexiang.xpage.annotation.Page; import com.xuexiang.xui.utils.WidgetUtils; +import com.xuexiang.xui.widget.banner.widget.banner.BannerItem; import com.xuexiang.xui.widget.banner.widget.banner.SimpleImageBanner; import com.xuexiang.xui.widget.banner.widget.banner.base.BaseBanner; import com.xuexiang.xuidemo.DemoDataProvider; @@ -62,9 +63,9 @@ protected void initViews() { banner = headerView.findViewById(R.id.sib_simple_usage); banner.setSource(DemoDataProvider.getBannerList()) - .setOnItemClickL(new BaseBanner.OnItemClickL() { + .setOnItemClickListener(new BaseBanner.OnItemClickListener() { @Override - public void onItemClick(int position) { + public void onItemClick(View view, BannerItem item, int position) { XToastUtils.toast("headBanner position--->" + position); } }).startScroll(); diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/textview/supertextview/SuperClickFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/textview/supertextview/SuperClickFragment.java index ffdaae08..ce19d166 100755 --- a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/textview/supertextview/SuperClickFragment.java +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/textview/supertextview/SuperClickFragment.java @@ -4,6 +4,7 @@ import android.view.View; import android.widget.CompoundButton; import android.widget.ImageView; +import android.widget.TextView; import com.xuexiang.xpage.annotation.Page; import com.xuexiang.xui.widget.layout.ExpandableLayout; @@ -35,7 +36,7 @@ public class SuperClickFragment extends BaseFragment { @BindView(R.id.stv_phone) SuperTextView stvPhone; - Badge mBadge; + private Badge mBadge; @Override protected int getLayoutId() { @@ -61,68 +62,68 @@ protected void initListeners() { */ superTextView.setOnSuperTextViewClickListener(new SuperTextView.OnSuperTextViewClickListener() { @Override - public void onClickListener(SuperTextView superTextView) { + public void onClick(SuperTextView superTextView) { XToastUtils.toast("整个item的点击事件"); } }).setLeftTopTvClickListener(new SuperTextView.OnLeftTopTvClickListener() { @Override - public void onClickListener() { + public void onClick(TextView textView) { XToastUtils.toast(superTextView.getLeftTopString()); } }).setLeftTvClickListener(new SuperTextView.OnLeftTvClickListener() { @Override - public void onClickListener() { + public void onClick(TextView textView) { XToastUtils.toast(superTextView.getLeftString()); } }).setLeftBottomTvClickListener(new SuperTextView.OnLeftBottomTvClickListener() { @Override - public void onClickListener() { + public void onClick(TextView textView) { XToastUtils.toast(superTextView.getLeftBottomString()); } }).setCenterTopTvClickListener(new SuperTextView.OnCenterTopTvClickListener() { @Override - public void onClickListener() { + public void onClick(TextView textView) { XToastUtils.toast(superTextView.getCenterTopString()); } }).setCenterTvClickListener(new SuperTextView.OnCenterTvClickListener() { @Override - public void onClickListener() { + public void onClick(TextView textView) { XToastUtils.toast(superTextView.getCenterString()); } }).setCenterBottomTvClickListener(new SuperTextView.OnCenterBottomTvClickListener() { @Override - public void onClickListener() { + public void onClick(TextView textView) { XToastUtils.toast(superTextView.getCenterBottomString()); } }).setRightTopTvClickListener(new SuperTextView.OnRightTopTvClickListener() { @Override - public void onClickListener() { + public void onClick(TextView textView) { XToastUtils.toast(superTextView.getRightTopString()); } }).setRightTvClickListener(new SuperTextView.OnRightTvClickListener() { @Override - public void onClickListener() { + public void onClick(TextView textView) { XToastUtils.toast(superTextView.getRightString()); } }).setRightBottomTvClickListener(new SuperTextView.OnRightBottomTvClickListener() { @Override - public void onClickListener() { + public void onClick(TextView textView) { XToastUtils.toast(superTextView.getRightBottomString()); } }).setLeftImageViewClickListener(new SuperTextView.OnLeftImageViewClickListener() { @Override - public void onClickListener(ImageView imageView) { + public void onClick(ImageView imageView) { } }).setRightImageViewClickListener(new SuperTextView.OnRightImageViewClickListener() { @Override - public void onClickListener(ImageView imageView) { + public void onClick(ImageView imageView) { } }); superTextView_cb.setOnSuperTextViewClickListener(new SuperTextView.OnSuperTextViewClickListener() { @Override - public void onClickListener(SuperTextView superTextView) { + public void onClick(SuperTextView superTextView) { superTextView.setCheckBoxChecked(!superTextView.getCheckBoxIsChecked()); } }).setCheckBoxCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @@ -134,7 +135,7 @@ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { superTextView_switch.setOnSuperTextViewClickListener(new SuperTextView.OnSuperTextViewClickListener() { @Override - public void onClickListener(SuperTextView superTextView) { + public void onClick(SuperTextView superTextView) { superTextView.setSwitchIsChecked(!superTextView.getSwitchIsChecked(), false); } }).setSwitchCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @@ -146,7 +147,7 @@ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { stvMessage.setOnSuperTextViewClickListener(new SuperTextView.OnSuperTextViewClickListener() { @Override - public void onClickListener(SuperTextView superTextView) { + public void onClick(SuperTextView superTextView) { mBadge.hide(true); } }); @@ -176,7 +177,7 @@ public void onExpansionChanged(float expansion, int state) { }); stvExpandable.setOnSuperTextViewClickListener(new SuperTextView.OnSuperTextViewClickListener() { @Override - public void onClickListener(SuperTextView superTextView) { + public void onClick(SuperTextView superTextView) { if (mExpandableLayout != null) { mExpandableLayout.toggle(); } diff --git a/app/src/main/res/layout/fragment_super_click.xml b/app/src/main/res/layout/fragment_super_click.xml index abbf1ccd..106b9412 100755 --- a/app/src/main/res/layout/fragment_super_click.xml +++ b/app/src/main/res/layout/fragment_super_click.xml @@ -109,6 +109,8 @@ style="@style/EditInfoItem" app:sEditTextButtonType="none" app:sEditTextHint="请输入姓名" + app:sLeftIconRes="@drawable/ic_phone" + app:sLeftIconTint="?attr/colorAccent" app:sLeftTextString="姓名" /> diff --git a/app/src/main/res/values/styles_demo.xml b/app/src/main/res/values/styles_demo.xml index 79995839..3a0c67a8 100644 --- a/app/src/main/res/values/styles_demo.xml +++ b/app/src/main/res/values/styles_demo.xml @@ -116,11 +116,13 @@ 60dp left_center left_center - 25dp - 25dp + 15dp + 15dp 2dp 13sp 0dp + 16dp + 16dp false true diff --git a/xui_lib/src/main/java/com/xuexiang/xui/widget/actionbar/TitleBar.java b/xui_lib/src/main/java/com/xuexiang/xui/widget/actionbar/TitleBar.java index ab1ee364..26d95300 100755 --- a/xui_lib/src/main/java/com/xuexiang/xui/widget/actionbar/TitleBar.java +++ b/xui_lib/src/main/java/com/xuexiang/xui/widget/actionbar/TitleBar.java @@ -596,7 +596,7 @@ public TitleBar setActionTextColor(int colorResId) { /** * Function to set a click listener for Title TextView * - * @param listener the onClickListener + * @param listener the onClick */ public TitleBar setOnTitleClickListener(OnClickListener listener) { mCenterText.setOnClickListener(listener); diff --git a/xui_lib/src/main/java/com/xuexiang/xui/widget/banner/widget/banner/base/BaseBanner.java b/xui_lib/src/main/java/com/xuexiang/xui/widget/banner/widget/banner/base/BaseBanner.java index c30d6b72..38baf095 100644 --- a/xui_lib/src/main/java/com/xuexiang/xui/widget/banner/widget/banner/base/BaseBanner.java +++ b/xui_lib/src/main/java/com/xuexiang/xui/widget/banner/widget/banner/base/BaseBanner.java @@ -6,10 +6,6 @@ import android.graphics.Typeface; import android.os.Handler; import android.os.Message; - -import androidx.viewpager.widget.PagerAdapter; -import androidx.viewpager.widget.ViewPager; -import androidx.viewpager.widget.ViewPager; import android.text.TextUtils; import android.util.AttributeSet; import android.util.DisplayMetrics; @@ -23,6 +19,9 @@ import android.widget.RelativeLayout; import android.widget.TextView; +import androidx.viewpager.widget.PagerAdapter; +import androidx.viewpager.widget.ViewPager; + import com.xuexiang.xui.R; import com.xuexiang.xui.logs.UILog; import com.xuexiang.xui.widget.banner.widget.loopviewpager.FixedSpeedScroller; @@ -600,18 +599,6 @@ public boolean dispatchTouchEvent(MotionEvent ev) { return super.dispatchTouchEvent(ev); } -// @Override -// protected void onWindowVisibilityChanged(int visibility) { -// super.onWindowVisibilityChanged(visibility); -// if (mIsSmart) { -// if (visibility != VISIBLE) { -// pauseScroll(); -// } else { -// goOnScroll(); -// } -// } -// } - private class InnerBannerAdapter extends PagerAdapter { @Override public int getCount() { @@ -624,8 +611,8 @@ public Object instantiateItem(ViewGroup container, final int position) { inflate.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - if (mOnItemClickL != null) { - mOnItemClickL.onItemClick(position); + if (mOnItemClickListener != null) { + mOnItemClickListener.onItemClick(v, getItem(position), position); } } }); @@ -705,15 +692,31 @@ public BaseBanner addOnPageChangeListener(ViewPager.OnPageChangeListener listene return this; } - private OnItemClickL mOnItemClickL; + private OnItemClickListener mOnItemClickListener; - public BaseBanner setOnItemClickL(OnItemClickL onItemClickL) { - this.mOnItemClickL = onItemClickL; + /** + * 设置条目点击监听 + * + * @param onItemClickListener + * @return + */ + public BaseBanner setOnItemClickListener(OnItemClickListener onItemClickListener) { + mOnItemClickListener = onItemClickListener; return this; } - public interface OnItemClickL { - void onItemClick(int position); + /** + * 条目点击监听 + * + * @param + */ + public interface OnItemClickListener { + /** + * @param view + * @param item + * @param position + */ + void onItemClick(View view, E item, int position); } /** diff --git a/xui_lib/src/main/java/com/xuexiang/xui/widget/textview/MarqueeTextView.java b/xui_lib/src/main/java/com/xuexiang/xui/widget/textview/MarqueeTextView.java index fce6869c..4e221e3d 100644 --- a/xui_lib/src/main/java/com/xuexiang/xui/widget/textview/MarqueeTextView.java +++ b/xui_lib/src/main/java/com/xuexiang/xui/widget/textview/MarqueeTextView.java @@ -246,7 +246,8 @@ public boolean removeDisplayString(String displayString) { public boolean removeDisplayEntity(DisplayEntity displayEntity) { if (displayEntity != null && displayEntity.isValid()) { if (isRollingDisplayEntity(displayEntity)) { - if (mCurrentIndex <= mDisplayList.size() - 1) { //防止remove出错 + //防止remove出错 + if (mCurrentIndex <= mDisplayList.size() - 1) { mDisplayList.remove(mCurrentIndex); rollDisplayByIndex(mCurrentIndex); return true; @@ -314,11 +315,13 @@ private void updateDisplayText(DisplayEntity displayEntity) { if (displayEntity != null) { if (mOnMarqueeListener != null) { DisplayEntity temp = mOnMarqueeListener.onStartMarquee(displayEntity, mCurrentIndex); - if (temp != null && temp.isValid()) { //返回的消息有效 + //返回的消息有效 + if (temp != null && temp.isValid()) { displayEntity = temp; mDisplayList.set(mCurrentIndex, displayEntity); } else { //返回的消息无效, 去除该条消息,继续滚动下一条 - if (mCurrentIndex <= mDisplayList.size() - 1) { //防止remove出错 + //防止remove出错 + if (mCurrentIndex <= mDisplayList.size() - 1) { mDisplayList.remove(mCurrentIndex); } rollDisplayByIndex(mCurrentIndex); diff --git a/xui_lib/src/main/java/com/xuexiang/xui/widget/textview/marqueen/MarqueeFactory.java b/xui_lib/src/main/java/com/xuexiang/xui/widget/textview/marqueen/MarqueeFactory.java index 966b9b03..9cc6d26a 100755 --- a/xui_lib/src/main/java/com/xuexiang/xui/widget/textview/marqueen/MarqueeFactory.java +++ b/xui_lib/src/main/java/com/xuexiang/xui/widget/textview/marqueen/MarqueeFactory.java @@ -45,6 +45,7 @@ public void setData(List datas) { /** * 设置Item的监听 + * * @param onItemClickListener */ public void setOnItemClickListener(OnItemClickListener onItemClickListener) { @@ -59,13 +60,13 @@ public List getMarqueeViews() { private void registerOnItemClick() { if (!isOnItemClickRegistered && mOnItemClickListener != null && mDatas != null) { for (int i = 0; i < mDatas.size(); i++) { - T mView = mViews.get(i); + T view = mViews.get(i); E data = mDatas.get(i); - mView.setTag(new ViewHolder(mView, data, i)); - mView.setOnClickListener(new View.OnClickListener() { + final ViewHolder viewHolder = new ViewHolder<>(view, data, i); + view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { - mOnItemClickListener.onItemClickListener((ViewHolder) view.getTag()); + mOnItemClickListener.onItemClick(view, viewHolder); } }); } @@ -73,8 +74,20 @@ public void onClick(View view) { } } + /** + * 条目点击监听 + * + * @param + * @param + */ public interface OnItemClickListener { - void onItemClickListener(ViewHolder holder); + /** + * 条目点击 + * + * @param view + * @param holder + */ + void onItemClick(View view, ViewHolder holder); } public static class ViewHolder { @@ -117,6 +130,6 @@ public ViewHolder setPosition(int position) { } public void setAttachedToMarqueeView(MarqueeView marqueeView) { - mMarqueeView = marqueeView; + mMarqueeView = marqueeView; } } \ No newline at end of file diff --git a/xui_lib/src/main/java/com/xuexiang/xui/widget/textview/supertextview/SuperTextView.java b/xui_lib/src/main/java/com/xuexiang/xui/widget/textview/supertextview/SuperTextView.java index d8c4d9c6..99d23b78 100755 --- a/xui_lib/src/main/java/com/xuexiang/xui/widget/textview/supertextview/SuperTextView.java +++ b/xui_lib/src/main/java/com/xuexiang/xui/widget/textview/supertextview/SuperTextView.java @@ -1,6 +1,7 @@ package com.xuexiang.xui.widget.textview.supertextview; import android.content.Context; +import android.content.res.ColorStateList; import android.content.res.TypedArray; import android.graphics.Typeface; import android.graphics.drawable.Drawable; @@ -48,22 +49,58 @@ public class SuperTextView extends RelativeLayout implements HasTypeface { private ImageView mLeftIconIV, mRightIconIV; private LayoutParams mLeftImgParams, mRightImgParams; - private int mLeftIconWidth;//左边图标的宽 - private int mLeftIconHeight;//左边图标的高 - - private int mRightIconWidth;//右边图标的宽 - private int mRightIconHeight;//右边图标的高 - - private int mLeftIconMarginLeft;//左边图标的左边距 - private int mRightIconMarginRight;//右边图标的右边距 - - private Drawable mLeftIconRes;//左边图标资源 - private Drawable mRightIconRes;//右边图标资源 - - private int mDefaultTextColor;//文字默认颜色 - private int mDefaultTextSize;//默认字体大小 - private int mDefaultMaxEms; //默认文字的最大字符数 - private int mDefaultMargin; //默认间距 + /** + * 左边图标资源 + */ + private Drawable mLeftIconRes; + /** + * 左边图标的宽 + */ + private int mLeftIconWidth; + /** + * 左边图标的高 + */ + private int mLeftIconHeight; + /** + * 左边图标的左边距 + */ + private int mLeftIconMarginLeft; + private ColorStateList mLeftIconTint; + private int mLeftIconPadding; + /** + * 右边图标资源 + */ + private Drawable mRightIconRes; + /** + * 右边图标的宽 + */ + private int mRightIconWidth; + /** + * 右边图标的高 + */ + private int mRightIconHeight; + /** + * 右边图标的右边距 + */ + private int mRightIconMarginRight; + private ColorStateList mRightIconTint; + private int mRightIconPadding; + /** + * 文字默认颜色 + */ + private int mDefaultTextColor; + /** + * 默认字体大小 + */ + private int mDefaultTextSize; + /** + * 默认文字的最大字符数 + */ + private int mDefaultMaxEms; + /** + * 默认间距 + */ + private int mDefaultMargin; private String mLeftTextString; private String mLeftTopTextString; @@ -89,7 +126,6 @@ public class SuperTextView extends RelativeLayout implements HasTypeface { private int mRightTopTextColor; private int mRightBottomTextColor; - private int mLeftTextSize; private int mLeftTopTextSize; private int mLeftBottomTextSize; @@ -165,14 +201,12 @@ public class SuperTextView extends RelativeLayout implements HasTypeface { private static final int GRAVITY_LEFT_CENTER = 0; private static final int GRAVITY_CENTER = 1; private static final int GRAVITY_RIGHT_CENTER = 2; - private static final int DEFAULT_GRAVITY = 1; private int mLeftGravity; private int mCenterGravity; private int mRightGravity; - private int mLeftViewWidth; private View mTopDividerLineView, mBottomDividerLineView; @@ -233,65 +267,84 @@ public class SuperTextView extends RelativeLayout implements HasTypeface { private OnRightImageViewClickListener mRightImageViewClickListener; private boolean mEnableEdit = false; - //输入框 + /** + * 输入框 + */ private EditText mCenterEditText; - //输入框布局参数 - private LayoutParams mCenterEditTextParams; private int mEditTextWidth = LayoutParams.MATCH_PARENT; - //输入框的背景 + private static final int TYPE_NONE = 0; + private static final int TYPE_CLEAR = 1; + private static final int TYPE_PASSWORD = 2; + /** + * 编辑输入框类型 + */ + private int mEditTextButtonType = TYPE_CLEAR; + /** + * 输入框的背景 + */ private Drawable mEditBackground; private String mEditTextHint; private String mEditTextString; private int mEditTextInputType; - //密码输入框文字的样式是否是“*” + /** + * 密码输入框文字的样式是否是“*” + */ private boolean mIsAsteriskStyle; - private static final int TYPE_NONE = 0; - private static final int TYPE_CLEAR = 1; - private static final int TYPE_PASSWORD = 2; - private int mEditTextButtonType = TYPE_CLEAR; - private static final int TYPE_CHECKBOX = 0; private static final int TYPE_SWITCH = 1; private int mRightViewType; - - //右边checkbox + /** + * 右边checkbox + */ private CheckBox mRightCheckBox; - //右边checkbox - private LayoutParams mRightCheckBoxParams; - //checkBox的背景 + /** + * checkBox的背景 + */ private Drawable mRightCheckBoxBg; - //右边checkBox的右边距 + /** + * 右边checkBox的右边距 + */ private int mRightCheckBoxMarginRight; - //是否默认选中 + /** + * 是否默认选中 + */ private boolean mIsChecked; - - //中间空间的高度 + /** + * 中间空间的高度 + */ private int mCenterSpaceHeight; - //右边switch + /** + * 右边switch + */ private Switch mRightSwitch; - private LayoutParams mRightSwitchParams; private int mRightSwitchMarginRight; private boolean mSwitchIsChecked; - //Switch开关关闭的文字提示 + /** + * Switch开关关闭的文字提示 + */ private String mSwitchTextOff; - //Switch开关打开的文字提示 + /** + * Switch开关打开的文字提示 + */ private String mSwitchTextOn; - private int mSwitchMinWidth; private int mSwitchPadding; - private int mThumbTextPadding; - - //Switch开关的滑块样式 + /** + * Switch开关的滑块样式 + */ private Drawable mSwitchThumbResource; - //Switch开关的底层样式 + /** + * Switch开关的底层样式 + */ private Drawable mSwitchTrackResource; - /////////////////////一下是shape相关属性 + //====================一下是shape相关属性==================// + private int mDefaultShapeColor; private int mSelectorPressedColor; @@ -464,17 +517,19 @@ private void getAttr(AttributeSet attrs) { mRightViewMarginLeft = typedArray.getDimensionPixelSize(R.styleable.SuperTextView_sRightViewMarginLeft, mDefaultMargin); mRightViewMarginRight = typedArray.getDimensionPixelSize(R.styleable.SuperTextView_sRightViewMarginRight, mDefaultMargin); /////////////////////////////////////////////// + mLeftIconRes = ResUtils.getDrawableAttrRes(getContext(), typedArray, R.styleable.SuperTextView_sLeftIconRes); mLeftIconWidth = typedArray.getDimensionPixelSize(R.styleable.SuperTextView_sLeftIconWidth, 0); mLeftIconHeight = typedArray.getDimensionPixelSize(R.styleable.SuperTextView_sLeftIconHeight, 0); + mLeftIconMarginLeft = typedArray.getDimensionPixelSize(R.styleable.SuperTextView_sLeftIconMarginLeft, mDefaultMargin); + mLeftIconTint = typedArray.getColorStateList(R.styleable.SuperTextView_sLeftIconTint); + mLeftIconPadding = typedArray.getDimensionPixelSize(R.styleable.SuperTextView_sLeftIconPadding, 0); + mRightIconRes = ResUtils.getDrawableAttrRes(getContext(), typedArray, R.styleable.SuperTextView_sRightIconRes); mRightIconWidth = typedArray.getDimensionPixelSize(R.styleable.SuperTextView_sRightIconWidth, 0); mRightIconHeight = typedArray.getDimensionPixelSize(R.styleable.SuperTextView_sRightIconHeight, 0); - - mLeftIconMarginLeft = typedArray.getDimensionPixelSize(R.styleable.SuperTextView_sLeftIconMarginLeft, mDefaultMargin); mRightIconMarginRight = typedArray.getDimensionPixelSize(R.styleable.SuperTextView_sRightIconMarginRight, mDefaultMargin); - - mLeftIconRes = ResUtils.getDrawableAttrRes(getContext(), typedArray, R.styleable.SuperTextView_sLeftIconRes); - mRightIconRes = ResUtils.getDrawableAttrRes(getContext(), typedArray, R.styleable.SuperTextView_sRightIconRes); + mRightIconTint = typedArray.getColorStateList(R.styleable.SuperTextView_sLeftIconTint); + mRightIconPadding = typedArray.getDimensionPixelSize(R.styleable.SuperTextView_sLeftIconPadding, 0); ////////////////////////////////////////////// mLeftTopTextBold = typedArray.getBoolean(R.styleable.SuperTextView_sLeftTopTextIsBold, false); @@ -622,10 +677,16 @@ private void initLeftIcon() { mLeftIconIV.setScaleType(ImageView.ScaleType.FIT_CENTER); mLeftIconIV.setId(R.id.sLeftImgId); mLeftIconIV.setLayoutParams(mLeftImgParams); + mLeftIconIV.setPadding(mLeftIconPadding, mLeftIconPadding, mLeftIconPadding, mLeftIconPadding); if (mLeftIconRes != null) { mLeftImgParams.setMargins(mLeftIconMarginLeft, 0, 0, 0); mLeftIconIV.setImageDrawable(mLeftIconRes); } + if (mLeftIconTint != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + mLeftIconIV.setImageTintList(mLeftIconTint); + } + } addView(mLeftIconIV); } @@ -659,10 +720,16 @@ private void initRightIcon() { mRightIconIV.setScaleType(ImageView.ScaleType.FIT_CENTER); mRightIconIV.setId(R.id.sRightImgId); mRightIconIV.setLayoutParams(mRightImgParams); + mRightIconIV.setPadding(mRightIconPadding, mRightIconPadding, mRightIconPadding, mRightIconPadding); if (mRightIconRes != null) { mRightImgParams.setMargins(0, 0, mRightIconMarginRight, 0); mRightIconIV.setImageDrawable(mRightIconRes); } + if (mRightIconTint != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + mRightIconIV.setImageTintList(mRightIconTint); + } + } addView(mRightIconIV); } @@ -712,7 +779,10 @@ private void initCenterTextView() { ((PasswordEditText) mCenterEditText).setIsAsteriskStyle(mIsAsteriskStyle); } } - mCenterEditTextParams = new LayoutParams(mEditTextWidth, LayoutParams.WRAP_CONTENT); + /** + * 输入框布局参数 + */ + LayoutParams mCenterEditTextParams = new LayoutParams(mEditTextWidth, LayoutParams.WRAP_CONTENT); mCenterEditTextParams.addRule(RelativeLayout.CENTER_IN_PARENT, TRUE); mCenterEditTextParams.addRule(RelativeLayout.CENTER_VERTICAL, TRUE); @@ -824,7 +894,8 @@ private void initRightCheckBox() { if (mRightCheckBox == null) { mRightCheckBox = new CheckBox(mContext); } - mRightCheckBoxParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + //右边checkbox + LayoutParams mRightCheckBoxParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); mRightCheckBoxParams.addRule(ALIGN_PARENT_RIGHT, TRUE); mRightCheckBoxParams.addRule(RelativeLayout.CENTER_VERTICAL, TRUE); @@ -847,7 +918,7 @@ private void initRightSwitch() { if (mRightSwitch == null) { mRightSwitch = new Switch(mContext); } - mRightSwitchParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + LayoutParams mRightSwitchParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); mRightSwitchParams.addRule(ALIGN_PARENT_RIGHT, TRUE); mRightSwitchParams.addRule(RelativeLayout.CENTER_VERTICAL, TRUE); @@ -1009,6 +1080,8 @@ private void setGravity(BaseTextView baseTextView, int gravity) { case GRAVITY_RIGHT_CENTER: baseTextView.setGravity(Gravity.RIGHT | Gravity.CENTER_VERTICAL); break; + default: + break; } } @@ -1074,6 +1147,8 @@ private void initDividerLineView() { setTopDividerLineView(); setBottomDividerLineView(); break; + default: + break; } } @@ -1149,22 +1224,21 @@ private void initBottomDividerLineView(int marginLeft, int marginRight) { * * @param baseTextView baseTextView */ - private void setDefaultLeftViewClickListener(BaseTextView baseTextView) { + private void setDefaultLeftViewClickListener(final BaseTextView baseTextView) { if (baseTextView != null) { if (mLeftTopTvClickListener != null) { baseTextView.getTopTextView().setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - mLeftTopTvClickListener.onClickListener(); + mLeftTopTvClickListener.onClick(baseTextView.getTopTextView()); } }); } - if (mLeftTvClickListener != null) { baseTextView.getCenterTextView().setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - mLeftTvClickListener.onClickListener(); + mLeftTvClickListener.onClick(baseTextView.getCenterTextView()); } }); } @@ -1172,7 +1246,7 @@ public void onClick(View v) { baseTextView.getBottomTextView().setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - mLeftBottomTvClickListener.onClickListener(); + mLeftBottomTvClickListener.onClick(baseTextView.getBottomTextView()); } }); } @@ -1185,22 +1259,21 @@ public void onClick(View v) { * * @param baseTextView baseTextView */ - private void setDefaultCenterViewClickListener(BaseTextView baseTextView) { + private void setDefaultCenterViewClickListener(final BaseTextView baseTextView) { if (baseTextView != null) { if (mCenterTopTvClickListener != null) { baseTextView.getTopTextView().setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - mCenterTopTvClickListener.onClickListener(); + mCenterTopTvClickListener.onClick(baseTextView.getTopTextView()); } }); } - if (mCenterTvClickListener != null) { baseTextView.getCenterTextView().setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - mCenterTvClickListener.onClickListener(); + mCenterTvClickListener.onClick(baseTextView.getCenterTextView()); } }); } @@ -1208,7 +1281,7 @@ public void onClick(View v) { baseTextView.getBottomTextView().setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - mCenterBottomTvClickListener.onClickListener(); + mCenterBottomTvClickListener.onClick(baseTextView.getBottomTextView()); } }); } @@ -1222,22 +1295,21 @@ public void onClick(View v) { * * @param baseTextView baseTextView */ - private void setDefaultRightViewClickListener(BaseTextView baseTextView) { + private void setDefaultRightViewClickListener(final BaseTextView baseTextView) { if (baseTextView != null) { if (mRightTopTvClickListener != null) { baseTextView.getTopTextView().setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - mRightTopTvClickListener.onClickListener(); + mRightTopTvClickListener.onClick(baseTextView.getTopTextView()); } }); } - if (mRightTvClickListener != null) { baseTextView.getCenterTextView().setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - mRightTvClickListener.onClickListener(); + mRightTvClickListener.onClick(baseTextView.getCenterTextView()); } }); } @@ -1245,7 +1317,7 @@ public void onClick(View v) { baseTextView.getBottomTextView().setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - mRightBottomTvClickListener.onClickListener(); + mRightBottomTvClickListener.onClick(baseTextView.getBottomTextView()); } }); } @@ -2130,7 +2202,7 @@ public SuperTextView setOnSuperTextViewClickListener(OnSuperTextViewClickListene this.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - mSuperTextViewClickListener.onClickListener(SuperTextView.this); + mSuperTextViewClickListener.onClick(SuperTextView.this); } }); } @@ -2218,13 +2290,13 @@ public SuperTextView setRightBottomTvClickListener(OnRightBottomTvClickListener } public SuperTextView setLeftImageViewClickListener(OnLeftImageViewClickListener listener) { - this.mLeftImageViewClickListener = listener; + mLeftImageViewClickListener = listener; if (mLeftIconIV != null) { mLeftIconIV.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - mLeftImageViewClickListener.onClickListener(mLeftIconIV); + mLeftImageViewClickListener.onClick(mLeftIconIV); } }); } @@ -2237,7 +2309,7 @@ public SuperTextView setRightImageViewClickListener(final OnRightImageViewClickL mRightIconIV.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - mRightImageViewClickListener.onClickListener(mRightIconIV); + mRightImageViewClickListener.onClick(mRightIconIV); } }); } @@ -2280,59 +2352,56 @@ public void setTypeface(Typeface typeface) { } //////////////////////////////////////////////////////////////////////////////////// + public interface OnSuperTextViewClickListener { - void onClickListener(SuperTextView superTextView); + void onClick(SuperTextView superTextView); } public interface OnLeftTopTvClickListener { - void onClickListener(); + void onClick(TextView textView); } public interface OnLeftTvClickListener { - void onClickListener(); + void onClick(TextView textView); } public interface OnLeftBottomTvClickListener { - void onClickListener(); + void onClick(TextView textView); } public interface OnCenterTopTvClickListener { - void onClickListener(); - } - - public interface OnCenterEditTextClickListener { - void onClickListener(); + void onClick(TextView textView); } public interface OnCenterTvClickListener { - void onClickListener(); + void onClick(TextView textView); } public interface OnCenterBottomTvClickListener { - void onClickListener(); + void onClick(TextView textView); } public interface OnRightTopTvClickListener { - void onClickListener(); + void onClick(TextView textView); } public interface OnRightTvClickListener { - void onClickListener(); + void onClick(TextView textView); } public interface OnRightBottomTvClickListener { - void onClickListener(); + void onClick(TextView textView); } public interface OnLeftImageViewClickListener { - void onClickListener(ImageView imageView); + void onClick(ImageView imageView); } public interface OnRightImageViewClickListener { - void onClickListener(ImageView imageView); + void onClick(ImageView imageView); } - // TODO: 2017/7/10 一下是shape相关属性方法 + //=================以下是shape相关属性方法================// /** * 获取设置之后的Selector @@ -2383,7 +2452,8 @@ private void setBorder() { */ private void setRadius() { if (mCornersRadius != 0) { - mGradientDrawable.setCornerRadius(mCornersRadius);//设置圆角的半径 + //设置圆角的半径 + mGradientDrawable.setCornerRadius(mCornersRadius); } else { //1、2两个参数表示左上角,3、4表示右上角,5、6表示右下角,7、8表示左下角 mGradientDrawable.setCornerRadii( diff --git a/xui_lib/src/main/res/values/stv_attrs.xml b/xui_lib/src/main/res/values/stv_attrs.xml index 61819303..ed37a908 100755 --- a/xui_lib/src/main/res/values/stv_attrs.xml +++ b/xui_lib/src/main/res/values/stv_attrs.xml @@ -162,20 +162,22 @@ - - + + + + + + + - - - From 67bcbf120291582b2e41e6685ac58be98392d630 Mon Sep 17 00:00:00 2001 From: xuexiangjys Date: Thu, 28 Nov 2019 17:34:10 +0800 Subject: [PATCH 23/27] =?UTF-8?q?=E5=A2=9E=E5=8A=A0DropDownMenu=E4=B8=8B?= =?UTF-8?q?=E6=8B=89=E9=80=89=E6=8B=A9=E8=8F=9C=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dropdownmenu/CityDropDownAdapter.java | 100 ++++ .../dropdownmenu/ConstellationAdapter.java | 97 ++++ .../dropdownmenu/ListDropDownAdapter.java | 102 ++++ .../fragment/components/SpinnerFragment.java | 2 + .../spinner/DropDownMenuFragment.java | 198 +++++++ .../main/res/drawable/ic_checked_right.xml | 21 + .../res/drawable/selector_bg_tag_stroke.xml | 40 ++ .../adapter_drop_down_constellation.xml | 32 ++ .../layout/adapter_drop_down_list_item.xml | 39 ++ .../res/layout/fragment_drop_down_menu.xml | 39 ++ .../res/layout/layout_drop_down_custom.xml | 45 ++ app/src/main/res/values/arrays.xml | 47 ++ app/src/main/res/values/colors.xml | 7 + .../com/xuexiang/xui/utils/DeviceUtils.java | 24 +- .../java/com/xuexiang/xui/utils/ResUtils.java | 2 +- .../xui/widget/guidview/GuideCaseView.java | 1 - .../xuexiang/xui/widget/picker/RulerView.java | 540 +++++++++--------- .../xui/widget/spinner/DropDownMenu.java | 297 ++++++++++ xui_lib/src/main/res/anim/ddm_mask_in.xml | 8 + xui_lib/src/main/res/anim/ddm_mask_out.xml | 8 + xui_lib/src/main/res/anim/ddm_menu_in.xml | 8 + xui_lib/src/main/res/anim/ddm_menu_out.xml | 8 + .../res/anim/picker_view_dialog_scale_in.xml | 27 +- .../res/anim/picker_view_dialog_scale_out.xml | 2 - .../main/res/anim/pop_grow_from_bottom.xml | 24 +- .../pop_grow_from_bottomleft_to_topright.xml | 24 +- .../pop_grow_from_bottomright_to_topleft.xml | 24 +- .../src/main/res/anim/pop_grow_from_top.xml | 24 +- .../pop_grow_from_topleft_to_bottomright.xml | 24 +- .../pop_grow_from_topright_to_bottomleft.xml | 24 +- .../main/res/anim/pop_shrink_from_bottom.xml | 24 +- ...pop_shrink_from_bottomleft_to_topright.xml | 24 +- ...pop_shrink_from_bottomright_to_topleft.xml | 24 +- .../src/main/res/anim/pop_shrink_from_top.xml | 24 +- ...pop_shrink_from_topleft_to_bottomright.xml | 24 +- ...pop_shrink_from_topright_to_bottomleft.xml | 24 +- xui_lib/src/main/res/anim/srb_rotation.xml | 17 +- .../color/xui_selector_content_text_color.xml | 25 + .../res/drawable-v21/ms_ic_arrow_down.xml | 2 +- .../main/res/drawable/ms_ic_arrow_down.xml | 2 +- xui_lib/src/main/res/values/xui_attrs.xml | 17 +- 41 files changed, 1608 insertions(+), 437 deletions(-) create mode 100644 app/src/main/java/com/xuexiang/xuidemo/adapter/dropdownmenu/CityDropDownAdapter.java create mode 100644 app/src/main/java/com/xuexiang/xuidemo/adapter/dropdownmenu/ConstellationAdapter.java create mode 100644 app/src/main/java/com/xuexiang/xuidemo/adapter/dropdownmenu/ListDropDownAdapter.java create mode 100644 app/src/main/java/com/xuexiang/xuidemo/fragment/components/spinner/DropDownMenuFragment.java create mode 100644 app/src/main/res/drawable/ic_checked_right.xml create mode 100644 app/src/main/res/drawable/selector_bg_tag_stroke.xml create mode 100644 app/src/main/res/layout/adapter_drop_down_constellation.xml create mode 100644 app/src/main/res/layout/adapter_drop_down_list_item.xml create mode 100644 app/src/main/res/layout/fragment_drop_down_menu.xml create mode 100644 app/src/main/res/layout/layout_drop_down_custom.xml create mode 100644 xui_lib/src/main/java/com/xuexiang/xui/widget/spinner/DropDownMenu.java create mode 100644 xui_lib/src/main/res/anim/ddm_mask_in.xml create mode 100644 xui_lib/src/main/res/anim/ddm_mask_out.xml create mode 100644 xui_lib/src/main/res/anim/ddm_menu_in.xml create mode 100644 xui_lib/src/main/res/anim/ddm_menu_out.xml create mode 100644 xui_lib/src/main/res/color/xui_selector_content_text_color.xml diff --git a/app/src/main/java/com/xuexiang/xuidemo/adapter/dropdownmenu/CityDropDownAdapter.java b/app/src/main/java/com/xuexiang/xuidemo/adapter/dropdownmenu/CityDropDownAdapter.java new file mode 100644 index 00000000..d78734bf --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/adapter/dropdownmenu/CityDropDownAdapter.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.xuexiang.xuidemo.adapter.dropdownmenu; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.TextView; + +import com.xuexiang.xui.utils.ResUtils; +import com.xuexiang.xui.utils.ThemeUtils; +import com.xuexiang.xuidemo.R; + +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; + + +public class CityDropDownAdapter extends BaseAdapter { + + private List list; + private int checkItemPosition = 0; + + public void setCheckItem(int position) { + checkItemPosition = position; + notifyDataSetChanged(); + } + + public CityDropDownAdapter(List list) { + this.list = list; + } + + @Override + public int getCount() { + return list.size(); + } + + @Override + public Object getItem(int position) { + return null; + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + ViewHolder viewHolder; + if (convertView != null) { + viewHolder = (ViewHolder) convertView.getTag(); + } else { + convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_drop_down_list_item, null); + viewHolder = new ViewHolder(convertView); + convertView.setTag(viewHolder); + } + fillValue(position, viewHolder); + return convertView; + } + + private void fillValue(int position, ViewHolder viewHolder) { + viewHolder.mText.setText(list.get(position)); + if (checkItemPosition != -1) { + if (checkItemPosition == position) { + viewHolder.mText.setSelected(true); + viewHolder.mText.setCompoundDrawablesWithIntrinsicBounds(null, null, ResUtils.getVectorDrawable(viewHolder.mText.getContext(), R.drawable.ic_checked_right), null); + } else { + viewHolder.mText.setSelected(false); + viewHolder.mText.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null); + } + } + } + + static class ViewHolder { + @BindView(R.id.text) + TextView mText; + + ViewHolder(View view) { + ButterKnife.bind(this, view); + } + } +} diff --git a/app/src/main/java/com/xuexiang/xuidemo/adapter/dropdownmenu/ConstellationAdapter.java b/app/src/main/java/com/xuexiang/xuidemo/adapter/dropdownmenu/ConstellationAdapter.java new file mode 100644 index 00000000..e7cf4c63 --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/adapter/dropdownmenu/ConstellationAdapter.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.xuexiang.xuidemo.adapter.dropdownmenu; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.TextView; + +import com.xuexiang.xui.utils.ResUtils; +import com.xuexiang.xuidemo.R; + +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; + + +public class ConstellationAdapter extends BaseAdapter { + + private List list; + private int checkItemPosition = 0; + + public void setCheckItem(int position) { + checkItemPosition = position; + notifyDataSetChanged(); + } + + public ConstellationAdapter(List list) { + this.list = list; + } + + @Override + public int getCount() { + return list.size(); + } + + @Override + public Object getItem(int position) { + return null; + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + ViewHolder viewHolder; + if (convertView != null) { + viewHolder = (ViewHolder) convertView.getTag(); + } else { + convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_drop_down_constellation, null); + viewHolder = new ViewHolder(convertView); + convertView.setTag(viewHolder); + } + fillValue(position, viewHolder); + return convertView; + } + + private void fillValue(int position, ViewHolder viewHolder) { + viewHolder.mText.setText(list.get(position)); + if (checkItemPosition != -1) { + if (checkItemPosition == position) { + viewHolder.mText.setSelected(true); + } else { + viewHolder.mText.setSelected(false); + } + } + } + + static class ViewHolder { + @BindView(R.id.text) + TextView mText; + + ViewHolder(View view) { + ButterKnife.bind(this, view); + } + } +} diff --git a/app/src/main/java/com/xuexiang/xuidemo/adapter/dropdownmenu/ListDropDownAdapter.java b/app/src/main/java/com/xuexiang/xuidemo/adapter/dropdownmenu/ListDropDownAdapter.java new file mode 100644 index 00000000..bda2b7a7 --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/adapter/dropdownmenu/ListDropDownAdapter.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.xuexiang.xuidemo.adapter.dropdownmenu; + +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.TextView; + +import com.xuexiang.xui.utils.ResUtils; +import com.xuexiang.xuidemo.R; + +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; + + +public class ListDropDownAdapter extends BaseAdapter { + + private List list; + private int checkItemPosition = 0; + + public void setCheckItem(int position) { + checkItemPosition = position; + notifyDataSetChanged(); + } + + public ListDropDownAdapter(List list) { + this.list = list; + } + + @Override + public int getCount() { + return list.size(); + } + + @Override + public Object getItem(int position) { + return null; + } + + @Override + public long getItemId(int position) { + return position; + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + ViewHolder viewHolder; + if (convertView != null) { + viewHolder = (ViewHolder) convertView.getTag(); + } else { + convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_drop_down_list_item, null); + viewHolder = new ViewHolder(convertView); + convertView.setTag(viewHolder); + } + fillValue(position, viewHolder); + return convertView; + } + + private void fillValue(int position, ViewHolder viewHolder) { + viewHolder.mText.setText(list.get(position)); + if (checkItemPosition != -1) { + if (checkItemPosition == position) { + viewHolder.mText.setSelected(true); + viewHolder.mText.setBackgroundResource(R.color.check_bg); + } else { + viewHolder.mText.setSelected(false); + viewHolder.mText.setBackgroundResource(R.color.white); + } + } + } + + static class ViewHolder { + @BindView(R.id.text) + TextView mText; + + ViewHolder(View view) { + ButterKnife.bind(this, view); + + mText.setGravity(Gravity.CENTER); + } + } +} diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/SpinnerFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/SpinnerFragment.java index 111d1f56..ada1a273 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/SpinnerFragment.java +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/SpinnerFragment.java @@ -3,6 +3,7 @@ import com.xuexiang.xpage.annotation.Page; import com.xuexiang.xuidemo.R; import com.xuexiang.xuidemo.base.ComponentContainerFragment; +import com.xuexiang.xuidemo.fragment.components.spinner.DropDownMenuFragment; import com.xuexiang.xuidemo.fragment.components.spinner.SpinnerStyleFragment; /** @@ -23,6 +24,7 @@ public class SpinnerFragment extends ComponentContainerFragment { protected Class[] getPagesClasses() { return new Class[]{ SpinnerStyleFragment.class, + DropDownMenuFragment.class }; } } diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/spinner/DropDownMenuFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/spinner/DropDownMenuFragment.java new file mode 100644 index 00000000..c900f00f --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/spinner/DropDownMenuFragment.java @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.xuexiang.xuidemo.fragment.components.spinner; + +import android.util.TypedValue; +import android.view.Gravity; +import android.view.KeyEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.GridView; +import android.widget.ListView; +import android.widget.TextView; + +import com.xuexiang.xaop.annotation.SingleClick; +import com.xuexiang.xpage.annotation.Page; +import com.xuexiang.xui.utils.ResUtils; +import com.xuexiang.xui.widget.actionbar.TitleBar; +import com.xuexiang.xui.widget.spinner.DropDownMenu; +import com.xuexiang.xuidemo.R; +import com.xuexiang.xuidemo.adapter.dropdownmenu.CityDropDownAdapter; +import com.xuexiang.xuidemo.adapter.dropdownmenu.ConstellationAdapter; +import com.xuexiang.xuidemo.adapter.dropdownmenu.ListDropDownAdapter; +import com.xuexiang.xuidemo.base.BaseFragment; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import butterknife.BindView; + +/** + * @author xuexiang + * @since 2019-11-28 15:24 + */ +@Page(name = "DropDownMenu\n下拉选择菜单") +public class DropDownMenuFragment extends BaseFragment { + + @BindView(R.id.ddm_content) + DropDownMenu mDropDownMenu; + + private String[] mHeaders = {"城市", "年龄", "性别", "星座"}; + private List mPopupViews = new ArrayList<>(); + + private CityDropDownAdapter cityAdapter; + private ListDropDownAdapter ageAdapter; + private ListDropDownAdapter sexAdapter; + private ConstellationAdapter constellationAdapter; + + private String[] mCitys; + private String[] mAges; + private String[] mSexs; + private String[] mConstellations; + + private int constellationPosition = 0; + + @Override + protected int getLayoutId() { + return R.layout.fragment_drop_down_menu; + } + + @Override + protected TitleBar initTitle() { + return super.initTitle().setLeftClickListener(new View.OnClickListener() { + @SingleClick + @Override + public void onClick(View v) { + handleBackPressed(); + } + }); + } + + @Override + protected void initArgs() { + mCitys = ResUtils.getStringArray(R.array.city_entry); + mAges = ResUtils.getStringArray(R.array.age_entry); + mSexs = ResUtils.getStringArray(R.array.sex_entry); + mConstellations = ResUtils.getStringArray(R.array.constellation_entry); + } + + @Override + protected void initViews() { + final ListView cityView = new ListView(getContext()); + cityAdapter = new CityDropDownAdapter(Arrays.asList(mCitys)); + cityView.setDividerHeight(0); + cityView.setAdapter(cityAdapter); + + //init age menu + final ListView ageView = new ListView(getContext()); + ageView.setDividerHeight(0); + ageAdapter = new ListDropDownAdapter(Arrays.asList(mAges)); + ageView.setAdapter(ageAdapter); + + //init sex menu + final ListView sexView = new ListView(getContext()); + sexView.setDividerHeight(0); + sexAdapter = new ListDropDownAdapter(Arrays.asList(mSexs)); + sexView.setAdapter(sexAdapter); + + //init constellation + final View constellationView = getLayoutInflater().inflate(R.layout.layout_drop_down_custom, null); + GridView constellation = constellationView.findViewById(R.id.constellation); + constellationAdapter = new ConstellationAdapter(Arrays.asList(mConstellations)); + constellation.setAdapter(constellationAdapter); + constellationView.findViewById(R.id.btn_ok).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mDropDownMenu.setTabText(constellationPosition == 0 ? mHeaders[3] : mConstellations[constellationPosition]); + mDropDownMenu.closeMenu(); + } + }); + + //init mPopupViews + mPopupViews.add(cityView); + mPopupViews.add(ageView); + mPopupViews.add(sexView); + mPopupViews.add(constellationView); + + //add item click event + cityView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + cityAdapter.setCheckItem(position); + mDropDownMenu.setTabText(position == 0 ? mHeaders[0] : mCitys[position]); + mDropDownMenu.closeMenu(); + } + }); + + ageView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + ageAdapter.setCheckItem(position); + mDropDownMenu.setTabText(position == 0 ? mHeaders[1] : mAges[position]); + mDropDownMenu.closeMenu(); + } + }); + + sexView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + sexAdapter.setCheckItem(position); + mDropDownMenu.setTabText(position == 0 ? mHeaders[2] : mSexs[position]); + mDropDownMenu.closeMenu(); + } + }); + + constellation.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + constellationAdapter.setCheckItem(position); + constellationPosition = position; + } + }); + + //init context view + TextView contentView = new TextView(getContext()); + contentView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); + contentView.setText("内容显示区域"); + contentView.setGravity(Gravity.CENTER); + contentView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20); + + //init dropdownview + mDropDownMenu.setDropDownMenu(Arrays.asList(mHeaders), mPopupViews, contentView); + } + + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + handleBackPressed(); + } + return true; + } + + private void handleBackPressed() { + if (mDropDownMenu.isShowing()) { + mDropDownMenu.closeMenu(); + } else { + popToBack(); + } + } + +} diff --git a/app/src/main/res/drawable/ic_checked_right.xml b/app/src/main/res/drawable/ic_checked_right.xml new file mode 100644 index 00000000..7d14f949 --- /dev/null +++ b/app/src/main/res/drawable/ic_checked_right.xml @@ -0,0 +1,21 @@ + + + + + diff --git a/app/src/main/res/drawable/selector_bg_tag_stroke.xml b/app/src/main/res/drawable/selector_bg_tag_stroke.xml new file mode 100644 index 00000000..89540df1 --- /dev/null +++ b/app/src/main/res/drawable/selector_bg_tag_stroke.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/adapter_drop_down_constellation.xml b/app/src/main/res/layout/adapter_drop_down_constellation.xml new file mode 100644 index 00000000..077255ca --- /dev/null +++ b/app/src/main/res/layout/adapter_drop_down_constellation.xml @@ -0,0 +1,32 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/adapter_drop_down_list_item.xml b/app/src/main/res/layout/adapter_drop_down_list_item.xml new file mode 100644 index 00000000..96fa46b0 --- /dev/null +++ b/app/src/main/res/layout/adapter_drop_down_list_item.xml @@ -0,0 +1,39 @@ + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_drop_down_menu.xml b/app/src/main/res/layout/fragment_drop_down_menu.xml new file mode 100644 index 00000000..04cebd71 --- /dev/null +++ b/app/src/main/res/layout/fragment_drop_down_menu.xml @@ -0,0 +1,39 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_drop_down_custom.xml b/app/src/main/res/layout/layout_drop_down_custom.xml new file mode 100644 index 00000000..7562f8e2 --- /dev/null +++ b/app/src/main/res/layout/layout_drop_down_custom.xml @@ -0,0 +1,45 @@ + + + + + + +