diff --git a/README.md b/README.md index d3d6a8ee..897cc0f6 100644 --- a/README.md +++ b/README.md @@ -63,10 +63,10 @@ allprojects { dependencies { ... //androidx项目 - implementation 'com.github.xuexiangjys:XUI:1.1.0' + implementation 'com.github.xuexiangjys:XUI:1.1.1' 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' } @@ -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,9 @@ C*y | 1¥ | 微信 *事 | 10¥ | 微信 优*1 | 168¥ | 微信 *、 | 20¥ | 微信 +*钰晗 | 6¥ | 支付宝 +*娜 | 3¥ | 微信 +*米 | 20¥ | 微信 ## 联系方式 diff --git a/app/build.gradle b/app/build.gradle index d8d026b2..61f05326 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -14,8 +14,8 @@ android { applicationId "com.xuexiang.xuidemo" minSdkVersion 17 targetSdkVersion build_versions.target_sdk - versionCode 11 - versionName "1.1.0" + versionCode 12 + versionName "1.1.1" multiDexEnabled true vectorDrawables.useSupportLibrary = true @@ -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,13 +97,13 @@ 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' //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' //工具类 @@ -126,6 +127,7 @@ dependencies { //弹性布局 implementation 'com.google.android:flexbox:0.3.1' + implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0' //悬浮按钮 implementation 'com.github.clans:fab:1.6.4' //RxUtil2 @@ -156,8 +158,6 @@ dependencies { implementation 'com.github.xuexiangjys.AgentWeb:agentweb-core:1.0.0' implementation 'com.github.xuexiangjys.AgentWeb:agentweb-download:1.0.0'//选填 implementation 'com.github.xuexiangjys.AgentWeb:agentweb-filechooser:1.0.0'//选填 - //WebView的回弹布局 - implementation 'com.lcodecorex:tkrefreshlayout:1.0.7' //侧边栏菜单 implementation 'com.yarolegovich:sliding-root-nav:1.1.0' @@ -185,11 +185,16 @@ 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.3' //版本更新 implementation 'com.github.xuexiangjys:XUpdate:1.1.1' implementation 'com.zhy:okhttputils:2.6.2' + //腾讯的键值对存储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' 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/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e5b6cc86..c56462a2 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -56,9 +56,15 @@ + @@ -66,8 +72,8 @@ - - + + - + + @@ -93,12 +100,14 @@ + android:scheme="xui" /> - + @@ -111,56 +120,59 @@ + android:scheme="http" /> + android:scheme="https" /> + + - - - - + - - - + + 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 b92d9386..ce02babe 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/DemoDataProvider.java +++ b/app/src/main/java/com/xuexiang/xuidemo/DemoDataProvider.java @@ -2,8 +2,11 @@ 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; +import com.xuexiang.xui.adapter.simple.ExpandableItem; import com.xuexiang.xui.widget.banner.transform.DepthTransformer; import com.xuexiang.xui.widget.banner.transform.FadeSlideTransformer; import com.xuexiang.xui.widget.banner.transform.FlowTransformer; @@ -15,6 +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; @@ -89,6 +97,12 @@ public static List getUsertGuides() { new AdapterItem("设置", R.drawable.icon_setting), }; + public static ExpandableItem[] expandableItems = new ExpandableItem[]{ + ExpandableItem.of(new AdapterItem("屏幕尺寸", R.drawable.icon_password_login)).addChild(AdapterItem.arrayof(dpiItems)), + ExpandableItem.of(new AdapterItem("设备亮度", R.drawable.icon_filter)).addChild(menuItems), + ExpandableItem.of(new AdapterItem("屏幕分辨率", R.drawable.icon_setting)).addChild(AdapterItem.arrayof(dpiItems)) + }; + public static List> sPics; public static List> sVideos; @@ -321,8 +335,9 @@ public static List getGifUrls() { * @return 返回拆分后的各个集合 */ public static List> split(List resList, int count) { - if (resList == null || count < 1) + if (resList == null || count < 1) { return null; + } List> ret = new ArrayList<>(); int size = resList.size(); if (size <= count) { //数据量不足count指定的大小 @@ -411,4 +426,36 @@ 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; + } + + @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/activity/LoginActivity.java b/app/src/main/java/com/xuexiang/xuidemo/activity/LoginActivity.java new file mode 100644 index 00000000..ad1a8ed8 --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/activity/LoginActivity.java @@ -0,0 +1,52 @@ +/* + * 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.activity; + +import android.os.Bundle; +import android.view.KeyEvent; + +import com.xuexiang.xui.utils.KeyboardUtils; +import com.xuexiang.xui.utils.StatusBarUtils; +import com.xuexiang.xuidemo.base.BaseActivity; +import com.xuexiang.xuidemo.fragment.LoginFragment; +import com.xuexiang.xutil.display.Colors; + +/** + * 登录页面 + * + * @author xuexiang + * @since 2019-11-17 22:21 + */ +public class LoginActivity extends BaseActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + openPage(LoginFragment.class, getIntent().getExtras()); + } + + @Override + protected void initStatusBarStyle() { + StatusBarUtils.initStatusBarStyle(this, false, Colors.TRANSPARENT); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + return KeyboardUtils.onDisableBackKeyDown(keyCode) && super.onKeyDown(keyCode, event); + } +} diff --git a/app/src/main/java/com/xuexiang/xuidemo/activity/MainActivity.java b/app/src/main/java/com/xuexiang/xuidemo/activity/MainActivity.java index b4252e6d..6f307aee 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/activity/MainActivity.java +++ b/app/src/main/java/com/xuexiang/xuidemo/activity/MainActivity.java @@ -32,6 +32,7 @@ import com.xuexiang.xuidemo.fragment.SettingFragment; import com.xuexiang.xuidemo.fragment.UtilitysFragment; import com.xuexiang.xuidemo.utils.SettingSPUtils; +import com.xuexiang.xuidemo.utils.TokenUtils; import com.xuexiang.xuidemo.utils.Utils; import com.xuexiang.xuidemo.utils.XToastUtils; import com.xuexiang.xutil.common.ClickUtils; @@ -269,7 +270,7 @@ public void onItemSelected(int position) { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); - MobclickAgent.onProfileSignOff(); + TokenUtils.handleLogoutSuccess(); finish(); } }, diff --git a/app/src/main/java/com/xuexiang/xuidemo/activity/SplashActivity.java b/app/src/main/java/com/xuexiang/xuidemo/activity/SplashActivity.java index d8ff3cf9..122c29c6 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/activity/SplashActivity.java +++ b/app/src/main/java/com/xuexiang/xuidemo/activity/SplashActivity.java @@ -6,6 +6,7 @@ import com.xuexiang.xui.widget.activity.BaseSplashActivity; import com.xuexiang.xuidemo.R; import com.xuexiang.xuidemo.utils.SettingSPUtils; +import com.xuexiang.xuidemo.utils.TokenUtils; import com.xuexiang.xutil.app.ActivityUtils; /** @@ -36,7 +37,7 @@ public void onCreateActivity() { ActivityUtils.startActivity(UserGuideActivity.class); finish(); - } else { + } else { if (enableAlphaAnim) { initSplashView(R.drawable.bg_splash); } else { @@ -49,7 +50,11 @@ public void onCreateActivity() { @Override public void onSplashFinished() { if (!isDisplay) { - ActivityUtils.startActivity(MainActivity.class); + if (TokenUtils.hasToken()) { + ActivityUtils.startActivity(MainActivity.class); + } else { + ActivityUtils.startActivity(LoginActivity.class); + } } finish(); } 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/activity/UserGuideActivity.java b/app/src/main/java/com/xuexiang/xuidemo/activity/UserGuideActivity.java index 853d7f35..9aeb10c9 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/activity/UserGuideActivity.java +++ b/app/src/main/java/com/xuexiang/xuidemo/activity/UserGuideActivity.java @@ -22,7 +22,7 @@ protected List getGuideResourceList() { @Override protected Class getSkipClass() { - return MainActivity.class; + return LoginActivity.class; } } 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..a8d8f73c --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/adapter/ExpandableListAdapter.java @@ -0,0 +1,116 @@ +/* + * 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.appcompat.widget.AppCompatImageView; +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); + 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 (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.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) { + 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.fl_title, 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/adapter/FlexboxLayoutAdapter.java b/app/src/main/java/com/xuexiang/xuidemo/adapter/FlexboxLayoutAdapter.java new file mode 100644 index 00000000..b2429f25 --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/adapter/FlexboxLayoutAdapter.java @@ -0,0 +1,162 @@ +/* + * 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.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; + } + + @Override + protected void bindData(@NonNull RecyclerViewHolder holder, int position, String item) { + holder.text(R.id.tv_tag, item); + 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); + } + + /** + * 单选 + * + * @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; + } + + + /** + * @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/adapter/RecyclerViewBannerAdapter.java b/app/src/main/java/com/xuexiang/xuidemo/adapter/RecyclerViewBannerAdapter.java index 96ae7157..5b54b3f0 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/adapter/RecyclerViewBannerAdapter.java +++ b/app/src/main/java/com/xuexiang/xuidemo/adapter/RecyclerViewBannerAdapter.java @@ -25,11 +25,11 @@ import androidx.annotation.NonNull; -import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.xuexiang.xui.adapter.recyclerview.BaseRecyclerAdapter; import com.xuexiang.xui.adapter.recyclerview.RecyclerViewHolder; import com.xuexiang.xui.widget.banner.recycler.BannerLayout; import com.xuexiang.xui.widget.imageview.ImageLoader; +import com.xuexiang.xui.widget.imageview.strategy.DiskCacheStrategyEnum; import com.xuexiang.xuidemo.R; import java.util.Arrays; @@ -93,7 +93,7 @@ public void bindData(@NonNull RecyclerViewHolder holder, final int position, Str if (!TextUtils.isEmpty(imgUrl)) { ImageLoader.get().loadImage(imageView, imgUrl, mColorDrawable, - mEnableCache ? DiskCacheStrategy.RESOURCE : DiskCacheStrategy.NONE); + mEnableCache ? DiskCacheStrategyEnum.RESOURCE : DiskCacheStrategyEnum.NONE); } else { imageView.setImageDrawable(mColorDrawable); } 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/adapter/dropdownmenu/CityDropDownAdapter.java b/app/src/main/java/com/xuexiang/xuidemo/adapter/dropdownmenu/CityDropDownAdapter.java new file mode 100644 index 00000000..f2ce13d5 --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/adapter/dropdownmenu/CityDropDownAdapter.java @@ -0,0 +1,74 @@ +/* + * 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.content.Context; +import android.view.View; +import android.widget.TextView; + +import com.xuexiang.xui.adapter.listview.BaseListAdapter; +import com.xuexiang.xui.utils.ResUtils; +import com.xuexiang.xuidemo.R; + +import butterknife.BindView; +import butterknife.ButterKnife; + + +public class CityDropDownAdapter extends BaseListAdapter { + + public CityDropDownAdapter(Context context) { + super(context); + } + + public CityDropDownAdapter(Context context, String[] data) { + super(context, data); + } + + @Override + protected ViewHolder newViewHolder(View convertView) { + return new ViewHolder(convertView); + } + + @Override + protected int getLayoutId() { + return R.layout.adapter_drop_down_list_item; + } + + @Override + protected void convert(ViewHolder holder, String item, int position) { + holder.mText.setText(item); + if (mSelectPosition != -1) { + if (mSelectPosition == position) { + holder.mText.setSelected(true); + holder.mText.setCompoundDrawablesWithIntrinsicBounds(null, null, ResUtils.getVectorDrawable(holder.mText.getContext(), R.drawable.ic_checked_right), null); + } else { + holder.mText.setSelected(false); + holder.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..18ac4466 --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/adapter/dropdownmenu/ConstellationAdapter.java @@ -0,0 +1,72 @@ +/* + * 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.content.Context; +import android.view.View; +import android.widget.TextView; + +import com.xuexiang.xui.adapter.listview.BaseListAdapter; +import com.xuexiang.xuidemo.R; + +import butterknife.BindView; +import butterknife.ButterKnife; + +/** + * 星座适配器 + * + * @author xuexiang + * @since 2019-11-30 15:55 + */ +public class ConstellationAdapter extends BaseListAdapter { + + public ConstellationAdapter(Context context, String[] data) { + super(context, data); + } + + @Override + protected ViewHolder newViewHolder(View convertView) { + return new ViewHolder(convertView); + } + + @Override + protected int getLayoutId() { + return R.layout.adapter_drop_down_constellation; + } + + @Override + protected void convert(ViewHolder holder, String item, int position) { + holder.mText.setText(item); + if (mSelectPosition != -1) { + if (mSelectPosition == position) { + holder.mText.setSelected(true); + } else { + holder.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..f3bd6a49 --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/adapter/dropdownmenu/ListDropDownAdapter.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.dropdownmenu; + +import android.content.Context; +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.adapter.listview.BaseListAdapter; +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 BaseListAdapter { + + public ListDropDownAdapter(Context context, String[] data) { + super(context, data); + } + + @Override + protected ViewHolder newViewHolder(View convertView) { + return new ViewHolder(convertView); + } + + @Override + protected int getLayoutId() { + return R.layout.adapter_drop_down_list_item; + } + + @Override + protected void convert(ViewHolder holder, String item, int position) { + holder.mText.setText(item); + if (mSelectPosition != -1) { + if (mSelectPosition == position) { + holder.mText.setSelected(true); + holder.mText.setBackgroundResource(R.color.check_bg); + } else { + holder.mText.setSelected(false); + holder.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/base/BaseActivity.java b/app/src/main/java/com/xuexiang/xuidemo/base/BaseActivity.java index 4a4d4eb7..d3a5523a 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/base/BaseActivity.java +++ b/app/src/main/java/com/xuexiang/xuidemo/base/BaseActivity.java @@ -50,7 +50,8 @@ protected void attachBaseContext(Context newBase) { @Override protected void onCreate(Bundle savedInstanceState) { - Utils.initTheme(this); + initAppTheme(); + initStatusBarStyle(); super.onCreate(savedInstanceState); mUnbinder = ButterKnife.bind(this); @@ -63,6 +64,20 @@ protected void onCreate(Bundle savedInstanceState) { } } + /** + * 初始化应用的主题 + */ + protected void initAppTheme() { + Utils.initTheme(this); + } + + /** + * 初始化状态栏的样式 + */ + protected void initStatusBarStyle() { + + } + /** * @return 是否支持侧滑返回 */ 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/WebLayout.java b/app/src/main/java/com/xuexiang/xuidemo/base/webview/WebLayout.java index 297eae7c..296b00d4 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/base/webview/WebLayout.java +++ b/app/src/main/java/com/xuexiang/xuidemo/base/webview/WebLayout.java @@ -17,14 +17,15 @@ package com.xuexiang.xuidemo.base.webview; import android.app.Activity; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import android.view.LayoutInflater; import android.view.ViewGroup; import android.webkit.WebView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.just.agentweb.widget.IWebLayout; -import com.lcodecore.tkrefreshlayout.TwinklingRefreshLayout; +import com.scwang.smartrefresh.layout.SmartRefreshLayout; import com.xuexiang.xuidemo.R; /** @@ -35,19 +36,18 @@ */ public class WebLayout implements IWebLayout { - private final TwinklingRefreshLayout mTwinklingRefreshLayout; + private final SmartRefreshLayout mSmartRefreshLayout; private WebView mWebView; public WebLayout(Activity activity) { - mTwinklingRefreshLayout = (TwinklingRefreshLayout) LayoutInflater.from(activity).inflate(R.layout.fragment_twk_web, null); - mTwinklingRefreshLayout.setPureScrollModeOn(); - mWebView = mTwinklingRefreshLayout.findViewById(R.id.webView); + mSmartRefreshLayout = (SmartRefreshLayout) LayoutInflater.from(activity).inflate(R.layout.fragment_pulldown_web, null); + mWebView = mSmartRefreshLayout.findViewById(R.id.webView); } @NonNull @Override public ViewGroup getLayout() { - return mTwinklingRefreshLayout; + return mSmartRefreshLayout; } @Nullable @@ -56,5 +56,4 @@ public WebView getWebView() { return mWebView; } - } 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/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 new file mode 100644 index 00000000..42d77943 --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/LoginFragment.java @@ -0,0 +1,146 @@ +/* + * 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; + +import android.graphics.Color; +import android.view.View; + +import com.xuexiang.xaop.annotation.SingleClick; +import com.xuexiang.xpage.annotation.Page; +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; +import com.xuexiang.xui.widget.button.roundbutton.RoundButton; +import com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText; +import com.xuexiang.xuidemo.R; +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; + +import butterknife.BindView; +import butterknife.OnClick; + + +/** + * 登录页面 + * + * @author xuexiang + * @since 2019-11-17 22:15 + */ +@Page(anim = CoreAnim.none) +public class LoginFragment extends BaseFragment { + + @BindView(R.id.et_phone_number) + MaterialEditText etPhoneNumber; + @BindView(R.id.et_verify_code) + MaterialEditText etVerifyCode; + @BindView(R.id.btn_get_verify_code) + RoundButton btnGetVerifyCode; + + private CountDownButtonHelper mCountDownHelper; + + @Override + protected int getLayoutId() { + return R.layout.fragment_login; + } + + @Override + protected TitleBar initTitle() { + TitleBar titleBar = super.initTitle() + .setImmersive(true); + titleBar.setBackgroundColor(Color.TRANSPARENT); + titleBar.setTitle(""); + titleBar.setLeftImageDrawable(ResUtils.getVectorDrawable(getContext(), R.drawable.ic_login_close)); + return titleBar; + } + + @Override + protected void initViews() { + mCountDownHelper = new CountDownButtonHelper(btnGetVerifyCode, 60); + + } + + @SingleClick + @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: + if (etPhoneNumber.validate()) { + getVerifyCode(etPhoneNumber.getEditValue()); + } + break; + case R.id.btn_login: + if (etPhoneNumber.validate()) { + if (etVerifyCode.validate()) { + loginByVerifyCode(etPhoneNumber.getEditValue(), etVerifyCode.getEditValue()); + } + } + 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; + } + } + + /** + * 获取验证码 + */ + private void getVerifyCode(String phoneNumber) { + // TODO: 2019-11-18 这里只是界面演示而已 + mCountDownHelper.start(); + } + + /** + * 根据验证码登录 + * + * @param phoneNumber 手机号 + * @param verifyCode 验证码 + */ + private void loginByVerifyCode(String phoneNumber, String verifyCode) { + // TODO: 2019-11-18 这里只是界面演示而已 + String token = RandomUtils.getRandomNumbersAndLetters(16); + if (TokenUtils.handleLoginSuccess(token)) { + popToBack(); + ActivityUtils.startActivity(MainActivity.class); + } + } + + + @Override + public void onDestroyView() { + if (mCountDownHelper != null) { + mCountDownHelper.recycle(); + } + super.onDestroyView(); + } +} 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/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/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/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/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/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/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/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/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..ee84fc7d --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/flowlayout/FlexboxLayoutFragment.java @@ -0,0 +1,140 @@ +/* + * 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 com.xuexiang.xutil.common.StringUtils; + +import butterknife.BindView; + +/** + * @author xuexiang + * @since 2019-11-23 01:23 + */ +@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() { + 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).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()); + //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.select(position)) { + XToastUtils.toast("选中的内容:" + mAdapter2.getSelectContent()); + } + } + }); + + mAdapter3.setOnItemClickListener(new RecyclerViewHolder.OnItemClickListener() { + @Override + public void onItemClick(View itemView, String item, int position) { + 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/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/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..10f1c5e1 --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/layout/expandable/ExpandableHorizontalFragment.java @@ -0,0 +1,70 @@ +/* + * 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) { + if (expandButton != null) { + 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..9198ee48 --- /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); + + 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/java/com/xuexiang/xuidemo/fragment/components/popupwindow/PopupWindowStyleFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/popupwindow/PopupWindowStyleFragment.java index 3525f61a..297f7ec8 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/fragment/components/popupwindow/PopupWindowStyleFragment.java +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/popupwindow/PopupWindowStyleFragment.java @@ -5,8 +5,11 @@ import com.xuexiang.xaop.annotation.SingleClick; import com.xuexiang.xpage.annotation.Page; import com.xuexiang.xui.adapter.simple.AdapterItem; +import com.xuexiang.xui.adapter.simple.ExpandableItem; import com.xuexiang.xui.adapter.simple.XUISimpleAdapter; +import com.xuexiang.xui.adapter.simple.XUISimpleExpandableListAdapter; import com.xuexiang.xui.widget.actionbar.TitleBar; +import com.xuexiang.xui.widget.popupwindow.popup.XUISimpleExpandablePopup; import com.xuexiang.xui.widget.popupwindow.popup.XUISimplePopup; import com.xuexiang.xuidemo.DemoDataProvider; import com.xuexiang.xuidemo.R; @@ -23,6 +26,7 @@ @Page(name = "弹出框统一样式") public class PopupWindowStyleFragment extends BaseFragment { private XUISimplePopup mListPopup; + private XUISimpleExpandablePopup mExpandableListPopup; private XUISimplePopup mMenuPopup; @Override @@ -53,6 +57,7 @@ protected int getLayoutId() { @Override protected void initViews() { initListPopup(); + initExpandableListPopup(); initMenuPopup(); } @@ -72,6 +77,17 @@ public void onItemClick(XUISimpleAdapter adapter, AdapterItem item, int position .setHasDivider(true); } + private void initExpandableListPopup() { + mExpandableListPopup = new XUISimpleExpandablePopup(getContext(), DemoDataProvider.expandableItems) + .create(DensityUtils.dip2px(getContext(), 200), DensityUtils.dip2px(getContext(), 200)) + .setOnExpandableItemClickListener(false, new XUISimpleExpandablePopup.OnExpandableItemClickListener() { + @Override + public void onExpandableItemClick(XUISimpleExpandableListAdapter adapter, ExpandableItem group, int groupPosition, int childPosition) { + XToastUtils.toast(group.getChildItem(childPosition).getTitle()); + } + }); + } + private void initMenuPopup() { mMenuPopup = new XUISimplePopup(getContext(), DemoDataProvider.menuItems) .create(new XUISimplePopup.OnPopupItemClickListener() { @@ -83,12 +99,16 @@ public void onItemClick(XUISimpleAdapter adapter, AdapterItem item, int position } @SingleClick - @OnClick({R.id.btn_commonlist_popup, R.id.btn_menu_popup}) + @OnClick({R.id.btn_commonlist_popup, R.id.btn_expandable_popup, R.id.btn_menu_popup}) void onClick(View v) { switch (v.getId()) { case R.id.btn_commonlist_popup: mListPopup.showDown(v); break; + case R.id.btn_expandable_popup: + mExpandableListPopup.clearExpandStatus(); + mExpandableListPopup.showDown(v); + break; case R.id.btn_menu_popup: mMenuPopup.showDown(v); break; 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 e3aa7a5b..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 @@ -1,15 +1,20 @@ 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.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; 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 +28,7 @@ public class SwipeRefreshFragment extends BaseFragment { private SimpleRecyclerAdapter mAdapter; + private SimpleImageBanner banner; @BindView(R.id.recycler_view) SwipeRecyclerView recyclerView; @@ -32,6 +38,9 @@ public class SwipeRefreshFragment extends BaseFragment { private Handler mHandler = new Handler(); private boolean mEnableLoadMore; + + private int mIndex = 0; + MaterialLoadMoreView mLoadMoreView; /** * 布局的资源id * @@ -49,6 +58,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()) + .setOnItemClickListener(new BaseBanner.OnItemClickListener() { + @Override + public void onItemClick(View view, BannerItem item, 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 +82,7 @@ protected void initListeners() { // 刷新监听。 swipeRefreshLayout.setOnRefreshListener(mRefreshListener); - refresh(); + autoRefresh(); } /** @@ -69,16 +91,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 +120,6 @@ public void run() { private void enableLoadMore() { if (recyclerView != null && !mEnableLoadMore) { mEnableLoadMore = true; - //SwipeRefreshLayout不支持加载更多 -// recyclerView.useDefaultLoadMore(); useMaterialLoadMore(); // 加载更多的监听。 recyclerView.setLoadMoreListener(mLoadMoreListener); @@ -107,9 +128,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 +162,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 +173,9 @@ public void run() { if (recyclerView != null) { recyclerView.loadMoreFinish(false, true); } + if (mIndex >= 2) { + disEnableLoadMore(); + } // 如果加载失败调用下面的方法,传入errorCode和errorMessage。 // errorCode随便传,你自定义LoadMoreView时可以根据errorCode判断错误类型。 // errorMessage是会显示到loadMoreView上的,用户可以看到。 @@ -140,9 +188,11 @@ public void run() { @Override public void onDestroyView() { + banner.recycle(); mHandler.removeCallbacksAndMessages(null); super.onDestroyView(); } + } 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..d9ce8244 --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/spinner/DropDownMenuFragment.java @@ -0,0 +1,196 @@ +/* + * 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 com.xuexiang.xutil.common.StringUtils; + +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 mCityAdapter; + private ListDropDownAdapter mAgeAdapter; + private ListDropDownAdapter mSexAdapter; + private ConstellationAdapter mConstellationAdapter; + + private String[] mCitys; + private String[] mAges; + private String[] mSexs; + private String[] mConstellations; + + @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()); + mCityAdapter = new CityDropDownAdapter(getContext(), mCitys); + cityView.setDividerHeight(0); + cityView.setAdapter(mCityAdapter); + + //init age menu + final ListView ageView = new ListView(getContext()); + ageView.setDividerHeight(0); + mAgeAdapter = new ListDropDownAdapter(getContext(), mAges); + ageView.setAdapter(mAgeAdapter); + + //init sex menu + final ListView sexView = new ListView(getContext()); + sexView.setDividerHeight(0); + mSexAdapter = new ListDropDownAdapter(getContext(), mSexs); + sexView.setAdapter(mSexAdapter); + + //init constellation + final View constellationView = getLayoutInflater().inflate(R.layout.layout_drop_down_custom, null); + GridView constellation = constellationView.findViewById(R.id.constellation); + mConstellationAdapter = new ConstellationAdapter(getContext(), mConstellations); + constellation.setAdapter(mConstellationAdapter); + constellationView.findViewById(R.id.btn_ok).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mDropDownMenu.setTabMenuText(mConstellationAdapter.getSelectPosition() == 0 ? mHeaders[3] : mConstellationAdapter.getSelectItem()); + 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) { + mCityAdapter.setSelectPosition(position); + mDropDownMenu.setTabMenuText(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) { + mAgeAdapter.setSelectPosition(position); + mDropDownMenu.setTabMenuText(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) { + mSexAdapter.setSelectPosition(position); + mDropDownMenu.setTabMenuText(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) { + mConstellationAdapter.setSelectPosition(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(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/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/components/textview/supertextview/SuperClickFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/components/textview/supertextview/SuperClickFragment.java index e60b9d60..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,8 +4,10 @@ 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; 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,12 +27,16 @@ 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) SuperTextView stvPhone; - Badge mBadge; + private Badge mBadge; @Override protected int getLayoutId() { @@ -56,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() { @@ -129,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() { @@ -141,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); } }); @@ -159,6 +165,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 onClick(SuperTextView superTextView) { + if (mExpandableLayout != null) { + mExpandableLayout.toggle(); + } + } + }); + + } } 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/fragment/expands/LinkageRecyclerViewFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/LinkageRecyclerViewFragment.java new file mode 100644 index 00000000..e0358522 --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/LinkageRecyclerViewFragment.java @@ -0,0 +1,62 @@ +/* + * 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.LinkageRecyclerViewElemeFragment; +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, + LinkageRecyclerViewElemeFragment.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/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 new file mode 100644 index 00000000..fb0fc0aa --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/expands/linkage/LinkageRecyclerViewSimpleFragment.java @@ -0,0 +1,101 @@ +/* + * 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 com.kunminx.linkage.LinkageRecyclerView; +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 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..ab741341 --- /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 R.layout.adapter_linkage_empty_footer; + } + + @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/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..e2ea7079 --- /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 R.layout.adapter_linkage_empty_footer; + } + + @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/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/java/com/xuexiang/xuidemo/fragment/utils/ViewUtilsFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/utils/ViewUtilsFragment.java index f6dded43..8fe7b30a 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/fragment/utils/ViewUtilsFragment.java +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/utils/ViewUtilsFragment.java @@ -19,6 +19,7 @@ import com.xuexiang.xpage.annotation.Page; import com.xuexiang.xuidemo.R; import com.xuexiang.xuidemo.base.ComponentContainerFragment; +import com.xuexiang.xuidemo.fragment.utils.view.ObjectAnimationFragment; import com.xuexiang.xuidemo.fragment.utils.view.ViewAnimationFragment; import com.xuexiang.xuidemo.fragment.utils.view.ViewPaddingFragment; @@ -32,7 +33,8 @@ public class ViewUtilsFragment extends ComponentContainerFragment { protected Class[] getPagesClasses() { return new Class[]{ ViewAnimationFragment.class, - ViewPaddingFragment.class + ViewPaddingFragment.class, + ObjectAnimationFragment.class }; } } diff --git a/app/src/main/java/com/xuexiang/xuidemo/fragment/utils/view/ObjectAnimationFragment.java b/app/src/main/java/com/xuexiang/xuidemo/fragment/utils/view/ObjectAnimationFragment.java new file mode 100644 index 00000000..5904b0bb --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/fragment/utils/view/ObjectAnimationFragment.java @@ -0,0 +1,271 @@ +/* + * 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.utils.view; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.animation.PropertyValuesHolder; +import android.animation.TypeEvaluator; +import android.animation.ValueAnimator; +import android.graphics.PointF; +import android.view.View; +import android.view.animation.AccelerateDecelerateInterpolator; +import android.view.animation.AccelerateInterpolator; +import android.view.animation.AnticipateInterpolator; +import android.view.animation.AnticipateOvershootInterpolator; +import android.view.animation.BounceInterpolator; +import android.view.animation.CycleInterpolator; +import android.view.animation.DecelerateInterpolator; +import android.view.animation.LinearInterpolator; +import android.view.animation.OvershootInterpolator; +import android.widget.TextView; + +import com.xuexiang.xaop.annotation.SingleClick; +import com.xuexiang.xpage.annotation.Page; +import com.xuexiang.xuidemo.R; +import com.xuexiang.xuidemo.base.BaseFragment; + +import butterknife.BindView; +import butterknife.OnClick; + +/** + * ObjectAnimator 对象动画 + * ValueAnimator 值动画 + * PropertyValueHolder 用于同时执行多个动画 + * TypeEvaluator 估值器 + * AnimatorSet 动画集合 + * Interpolator 差值器(已经预先定义好的估值器) + * + * @author xuexiang + * @since 2019-11-30 17:29 + */ +@Page(name = "属性动画") +public class ObjectAnimationFragment extends BaseFragment { + + @BindView(R.id.tv_content) + TextView tvContent; + + @Override + protected int getLayoutId() { + return R.layout.fragment_object_animation; + } + + @Override + protected void initViews() { + + } + + @SingleClick + @OnClick({R.id.btn_alpha, R.id.btn_translation, R.id.btn_scale, R.id.btn_rotation, R.id.btn_value_animator, R.id.btn_type_evaluator, R.id.btn_compose1, R.id.btn_compose2}) + public void onViewClicked(View view) { + switch (view.getId()) { + case R.id.btn_alpha: + doAlphaAnimation(tvContent); + break; + case R.id.btn_translation: + doTranslationAnimation(tvContent); + break; + case R.id.btn_scale: + doScaleAnimation(tvContent); + break; + case R.id.btn_rotation: + doRotationAnimation(tvContent); + break; + case R.id.btn_value_animator: + doValueAnimator(tvContent); + break; + case R.id.btn_type_evaluator: + doTypeEvaluator(tvContent); + break; + case R.id.btn_compose1: + doComposeAnimation1(tvContent); + break; + case R.id.btn_compose2: + doComposeAnimation2(tvContent); + break; + default: + break; + } + } + + /** + * 透明度动画 + * + * @param view + */ + private void doAlphaAnimation(View view) { + ObjectAnimator animator = ObjectAnimator.ofFloat(view, "alpha", 1, 0, 1); + animator.setDuration(2000); + animator.start(); + } + + /** + * 平移动画 + * + * @param view + */ + private void doTranslationAnimation(View view) { + ObjectAnimator animatorX = ObjectAnimator.ofFloat(view, "translationX", 0, 200, 0, -200, 0); + ObjectAnimator animatorY = ObjectAnimator.ofFloat(view, "translationY", 0, 200, 0, -200, 0); + AnimatorSet animatorSet = new AnimatorSet(); + animatorSet.play(animatorX).before(animatorY); + animatorSet.setDuration(2000); + animatorSet.start(); + } + + /** + * 缩放动画 + * + * @param view + */ + private void doScaleAnimation(View view) { + ObjectAnimator animatorX = ObjectAnimator.ofFloat(view, "scaleX", 1F, 0.5F, 1F, 1.5F, 1F); + ObjectAnimator animatorY = ObjectAnimator.ofFloat(view, "scaleY", 1F, 0.5F, 1F, 1.5F, 1F); + AnimatorSet animatorSet = new AnimatorSet(); + animatorSet.play(animatorX).with(animatorY); + animatorSet.setDuration(2000); + animatorSet.start(); + } + + /** + * 旋转动画 + * + * @param view + */ + private void doRotationAnimation(View view) { + ObjectAnimator animator = ObjectAnimator.ofFloat(view, "rotation", 0, 360, 0); + animator.setDuration(2000); + //加速查值器,参数越大,速度越来越快 + animator.setInterpolator(new AccelerateInterpolator(2)); +// //减速差值起,和上面相反 +// animator.setInterpolator(new DecelerateInterpolator(10)); +// //先加速后减速插值器 +// animator.setInterpolator(new AccelerateDecelerateInterpolator()); +// //张力值,默认为2,T越大,初始的偏移越大,而且速度越快 +// animator.setInterpolator(new AnticipateInterpolator(3)); +// //张力值tension,默认为2,张力越大,起始时和结束时的偏移越大 +// animator.setInterpolator(new AnticipateOvershootInterpolator(6)); +// //弹跳插值器 +// animator.setInterpolator(new BounceInterpolator()); +// //周期插值器 +// animator.setInterpolator(new CycleInterpolator(2)); +// //线性差值器,匀速 +// animator.setInterpolator(new LinearInterpolator()); +// //张力插值器,扩散反弹一下 +// animator.setInterpolator(new OvershootInterpolator(2)); + animator.start(); + } + + + /** + * 值动画,适合构建复杂的动画 + * + * @param view + */ + private void doValueAnimator(View view) { + //值的变化,与控件无关 + ValueAnimator animator = ValueAnimator.ofFloat(1, 0, 1); + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + float value = (float) animation.getAnimatedValue(); + view.setScaleX(value); + view.setScaleY(value); + view.setAlpha(value); + view.setRotation(360 * (1 - value)); + } + }); + animator.setDuration(2000).start(); + } + + + /** + * 估值器(实现重力下落的效果) + * + * @param view + */ + private void doTypeEvaluator(final View view) { + ValueAnimator animator = new ValueAnimator(); + animator.setDuration(3000); + animator.setObjectValues(new PointF(0, 0)); + final PointF pointF = new PointF(); + animator.setEvaluator(new TypeEvaluator() { + @Override + public Object evaluate(float fraction, Object startValue, Object endValue) { + //fraction是运动中的匀速变化的值 + //根据重力计算实际的运动y=vt=0.5*g*t*t + //g越大效果越明显 + pointF.x = 100 * (fraction * 5); + pointF.y = 0.5f * 300f * (fraction * 5) * (fraction * 5); + return pointF; + } + }); + animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + PointF p = (PointF) animation.getAnimatedValue(); + view.setX(p.x); + view.setY(p.y); + } + }); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + //还原到原始的位置 + view.setTranslationX(0); + view.setTranslationY(0); + } + }); + animator.start(); + } + + + /** + * 组合动画 + * + * @param view + */ + private void doComposeAnimation1(View view) { + ObjectAnimator alpha = ObjectAnimator.ofFloat(view, "alpha", 1, 0, 1); + ObjectAnimator scaleX = ObjectAnimator.ofFloat(view, "scaleX", 1, 0, 1); + ObjectAnimator scaleY = ObjectAnimator.ofFloat(view, "scaleY", 1, 0, 1); + ObjectAnimator rotation = ObjectAnimator.ofFloat(view, "rotation", 0, 360, 0); + + AnimatorSet animatorSet = new AnimatorSet(); + animatorSet.play(alpha).with(scaleX).with(scaleY).with(rotation); + animatorSet.setDuration(2000).start(); + } + + + /** + * 组合动画 + * + * @param view + */ + private void doComposeAnimation2(View view) { + PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1, 0, 1); + PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1, 0, 1); + PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY", 1, 0, 1); + PropertyValuesHolder rotation = PropertyValuesHolder.ofFloat("rotation", 0, 360, 0); + + ValueAnimator animator = ObjectAnimator.ofPropertyValuesHolder(view, alpha, scaleX, scaleY, rotation); + animator.setDuration(2000).start(); + } +} diff --git a/app/src/main/java/com/xuexiang/xuidemo/utils/TokenUtils.java b/app/src/main/java/com/xuexiang/xuidemo/utils/TokenUtils.java new file mode 100644 index 00000000..eff55e31 --- /dev/null +++ b/app/src/main/java/com/xuexiang/xuidemo/utils/TokenUtils.java @@ -0,0 +1,95 @@ +/* + * 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.utils; + +import android.content.Context; + +import com.tencent.mmkv.MMKV; +import com.umeng.analytics.MobclickAgent; +import com.xuexiang.xuidemo.activity.LoginActivity; +import com.xuexiang.xutil.app.ActivityUtils; +import com.xuexiang.xutil.common.StringUtils; + +/** + * Token管理工具 + * + * @author xuexiang + * @since 2019-11-17 22:37 + */ +public final class TokenUtils { + + private static String sToken; + + private static final String KEY_TOKEN = "com.xuexiang.xuidemo.utils.KEY_TOKEN"; + + private TokenUtils() { + throw new UnsupportedOperationException("u can't instantiate me..."); + } + + /** + * 初始化Token信息 + */ + public static void init(Context context) { + MMKV.initialize(context); + sToken = MMKV.defaultMMKV().decodeString(KEY_TOKEN, ""); + } + + public static void setToken(String token) { + sToken = token; + MMKV.defaultMMKV().putString(KEY_TOKEN, token); + } + + public static void clearToken() { + sToken = null; + MMKV.defaultMMKV().remove(KEY_TOKEN); + } + + public static boolean hasToken() { + return MMKV.defaultMMKV().containsKey(KEY_TOKEN); + } + + /** + * 处理登录成功的事件 + * + * @param token 账户信息 + */ + public static boolean handleLoginSuccess(String token) { + if (!StringUtils.isEmpty(token)) { + XToastUtils.success("登录成功!"); + MobclickAgent.onProfileSignIn("github", token); + setToken(token); + return true; + } else { + XToastUtils.error("登录失败!"); + return false; + } + } + + /** + * 处理登出的事件 + */ + public static void handleLogoutSuccess() { + MobclickAgent.onProfileSignOff(); + //登出时,清除账号信息 + clearToken(); + XToastUtils.success("登出成功!"); + //跳转到登录页 + ActivityUtils.startActivity(LoginActivity.class); + } + +} 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/java/com/xuexiang/xuidemo/utils/sdkinit/XBasicLibInit.java b/app/src/main/java/com/xuexiang/xuidemo/utils/sdkinit/XBasicLibInit.java index 6a78b123..aa0f5d09 100644 --- a/app/src/main/java/com/xuexiang/xuidemo/utils/sdkinit/XBasicLibInit.java +++ b/app/src/main/java/com/xuexiang/xuidemo/utils/sdkinit/XBasicLibInit.java @@ -27,6 +27,7 @@ import com.xuexiang.xuidemo.MyApp; import com.xuexiang.xuidemo.base.BaseActivity; import com.xuexiang.xuidemo.utils.LocationService; +import com.xuexiang.xuidemo.utils.TokenUtils; import com.xuexiang.xuidemo.utils.XToastUtils; import com.xuexiang.xutil.XUtil; import com.xuexiang.xutil.common.StringUtils; @@ -65,6 +66,7 @@ private static void initUtils(Application application) { XUtil.debug(MyApp.isDebug()); //百度定位 LocationService.get().init(application); + TokenUtils.init(application); } 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 diff --git a/app/src/main/res/color/selector_round_button_main_theme_color.xml b/app/src/main/res/color/selector_round_button_main_theme_color.xml new file mode 100644 index 00000000..16fd2c79 --- /dev/null +++ b/app/src/main/res/color/selector_round_button_main_theme_color.xml @@ -0,0 +1,24 @@ + + + + + + + + + \ No newline at end of file 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 00000000..97dd5f34 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_expand_linkage_list.png differ 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 00000000..3fbfc906 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/bg_food_sample.png differ diff --git a/app/src/main/res/drawable-xxhdpi/btn_add_food.png b/app/src/main/res/drawable-xxhdpi/btn_add_food.png new file mode 100644 index 00000000..20843773 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/btn_add_food.png differ 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 00000000..ef42dec2 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/tag_new_good.png differ 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 00000000..2ba0db98 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_chevron_right_black_48dp.png differ 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/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/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/ic_login_close.xml b/app/src/main/res/drawable/ic_login_close.xml new file mode 100644 index 00000000..178ac091 --- /dev/null +++ b/app/src/main/res/drawable/ic_login_close.xml @@ -0,0 +1,21 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_password.xml b/app/src/main/res/drawable/ic_password.xml new file mode 100644 index 00000000..716e402a --- /dev/null +++ b/app/src/main/res/drawable/ic_password.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/app/src/main/res/drawable/ic_phone.xml b/app/src/main/res/drawable/ic_phone.xml new file mode 100644 index 00000000..56cf551f --- /dev/null +++ b/app/src/main/res/drawable/ic_phone.xml @@ -0,0 +1,4 @@ + + + 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/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 @@ - - + + + + + + \ 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/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 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..099f3033 --- /dev/null +++ b/app/src/main/res/layout/adapter_expandable_list_item.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file 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/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/app/src/main/res/layout/fragment_about.xml b/app/src/main/res/layout/fragment_about.xml index 69b06341..b95e1b24 100644 --- a/app/src/main/res/layout/fragment_about.xml +++ b/app/src/main/res/layout/fragment_about.xml @@ -19,52 +19,54 @@ android:layout_height="match_parent" android:orientation="vertical"> - + - + - - - - - + android:gravity="center_horizontal" + android:orientation="vertical" + android:paddingTop="50dp" + android:paddingBottom="25dp"> - + - + + + + + + + + + - + + - \ No newline at end of file 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..99f1bd2a --- /dev/null +++ b/app/src/main/res/layout/fragment_drop_down_menu.xml @@ -0,0 +1,28 @@ + + + + + + + \ 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/fragment_flexbox_layout.xml b/app/src/main/res/layout/fragment_flexbox_layout.xml new file mode 100644 index 00000000..2e8c0f30 --- /dev/null +++ b/app/src/main/res/layout/fragment_flexbox_layout.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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 @@ + + - + - + - + + + + \ No newline at end of file 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_linkage_recyclerview.xml b/app/src/main/res/layout/fragment_linkage_recyclerview.xml new file mode 100644 index 00000000..e0a92841 --- /dev/null +++ b/app/src/main/res/layout/fragment_linkage_recyclerview.xml @@ -0,0 +1,28 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_login.xml b/app/src/main/res/layout/fragment_login.xml new file mode 100644 index 00000000..9bc85069 --- /dev/null +++ b/app/src/main/res/layout/fragment_login.xml @@ -0,0 +1,200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_object_animation.xml b/app/src/main/res/layout/fragment_object_animation.xml new file mode 100644 index 00000000..466abdaf --- /dev/null +++ b/app/src/main/res/layout/fragment_object_animation.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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="滤镜" /> + + + + + + + + + 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_super_click.xml b/app/src/main/res/layout/fragment_super_click.xml index 246afe42..106b9412 100755 --- a/app/src/main/res/layout/fragment_super_click.xml +++ b/app/src/main/res/layout/fragment_super_click.xml @@ -1,95 +1,142 @@ - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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/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 diff --git a/app/src/main/res/layout/fragment_view_padding.xml b/app/src/main/res/layout/fragment_view_padding.xml index 310a01db..794f8c96 100644 --- a/app/src/main/res/layout/fragment_view_padding.xml +++ b/app/src/main/res/layout/fragment_view_padding.xml @@ -69,7 +69,6 @@ + android:max="100" + android:progress="20" /> 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/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 @@ + + + + + + +