diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..1207ec8 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2022 Leaqi + + 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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..475608a --- /dev/null +++ b/README.md @@ -0,0 +1,65 @@ +# SwipeDrawer · [![Star](https://img.shields.io/github/stars/Leaqi/SwipeDrawer?color=fb6698&label=Star "Star")](https://github.com/Leaqi/SwipeDrawer/stargazers "Star") [![Fork](https://img.shields.io/github/forks/Leaqi/SwipeDrawer?color=2196f3&label=Fork "Fork")](https://github.com/Leaqi/SwipeDrawer/network "Fork") [![API](https://img.shields.io/badge/API-14%2B-04d8bb "API")](https://github.com/Leaqi/SwipeDrawer/ "API") [![JitPack](https://jitpack.io/v/Leaqi/SwipeDrawer.svg "JitPack")](https://jitpack.io/#cn.Leaqi/SwipeDrawer "JitPack") [![Release](https://img.shields.io/github/v/release/Leaqi/SwipeDrawer?label=Release&color=06da47 "Release")](https://github.com/Leaqi/SwipeDrawer/releases "Release") [![License](https://img.shields.io/badge/License-Apache--2.0-e0b003 "License")](https://github.com/Leaqi/SwipeDrawer/blob/master/LICENSE "License") [![Download Demo Apk](https://img.shields.io/badge/Download-Demo%20Apk-45c703 "Download Demo Apk")](https://github.com/Leaqi/SwipeDrawer/releases/download/1.0/demo.apk "Download Demo Apk") +#### 中文 README | [English README](https://github.com/Leaqi/SwipeDrawer/blob/master/README_en.md "English README") +Android SwipeDrawer滑动抽屉库,可同时添加上下左右四个方向抽屉布局,抽屉打开模式有抽屉模式、覆盖模式、固定模式三种,支持无限嵌套,支持边缘滑动打开等,SwipeDrawer还可以当做下拉刷新布局使用,支持ListView、RecyclerView、GridView、ScrollView等。 +#### 中文: +[![点击查看使用文档](https://img.shields.io/badge/SwipeDrawer-%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3-blue "点击查看使用文档")](https://Leaqi.github.io/SwipeDrawer/ "点击查看使用文档") [![点击查看功能详解](https://img.shields.io/badge/SwipeDrawer-%E5%8A%9F%E8%83%BD%E8%AF%A6%E8%A7%A3-orange "点击查看功能详解")](https://Leaqi.github.io/SwipeDrawer/code.html "点击查看功能详解") [![点击查看图片演示](https://img.shields.io/badge/SwipeDrawer-%E5%9B%BE%E7%89%87%E6%BC%94%E7%A4%BA-green "点击查看图片演示")](https://Leaqi.github.io/SwipeDrawer/pics.html "点击查看图片演示") + +#### English: +[![Click to view Use Docs](https://img.shields.io/badge/SwipeDrawer-Use%20Docs-blue "Click to view Use Docs")](https://Leaqi.github.io/SwipeDrawer_en/ "Click to view Use Docs") [![Click to view Detailed Docs](https://img.shields.io/badge/SwipeDrawer-Detailed%20Docs-orange "Click to view Detailed Docs")](https://Leaqi.github.io/SwipeDrawer_en/code.html "Click to view Detailed Docs") [![Click to view Picture Preview](https://img.shields.io/badge/SwipeDrawer-Picture%20Preview-green "Click to view Picture Preview")](https://Leaqi.github.io/SwipeDrawer_en/pics.html "Click to view Picture Preview") + +## 开始使用 +添加 `jitpack` 仓库地址: + + allprojects { + repositories { + ... + maven { url "https://jitpack.io" } + } + } + +添加 `SwipeDrawer` 依赖: + + dependencies { + ... + implementation 'cn.Leaqi.SwipeDrawer:1.0' + } + +在布局文件中加入 `SwipeDrawer` : + + + + + + + + + + + + + + +## 图片预览 · [![查看更多](https://img.shields.io/badge/More-%E6%9F%A5%E7%9C%8B%E6%9B%B4%E5%A4%9A-blue "查看更多")](https://Leaqi.github.io/SwipeDrawer/pics.html "查看更多") +[![Demo](https://p.ssl.qhimg.com/t0127d8ad395f6aff6f.jpg "Demo")](https://Leaqi.github.io/SwipeDrawer/pics.html "Demo") [![Demo](https://p.ssl.qhimg.com/t017c6a31eaa1242d0a.jpg "Demo")](https://Leaqi.github.io/SwipeDrawer/pics.html "Demo") [![Demo](https://p.ssl.qhimg.com/t0131cdd3e8c2ca7d41.jpg "Demo")](https://Leaqi.github.io/SwipeDrawer/pics.html "Demo") [![Demo](https://p.ssl.qhimg.com/t019aa5b68b427443c9.jpg "Demo")](https://Leaqi.github.io/SwipeDrawer/pics.html "Demo") + +## License +[Apache-2.0 License](https://github.com/Leaqi/SwipeDrawer/blob/master/LICENSE "Apache-2.0 License") + +Copyright (c) 2022 Leaqi \ No newline at end of file diff --git a/README_en.md b/README_en.md new file mode 100644 index 0000000..ce953cf --- /dev/null +++ b/README_en.md @@ -0,0 +1,66 @@ +# SwipeDrawer · [![Star](https://img.shields.io/github/stars/Leaqi/SwipeDrawer?color=fb6698&label=Star "Star")](https://github.com/Leaqi/SwipeDrawer/stargazers "Star") [![Fork](https://img.shields.io/github/forks/Leaqi/SwipeDrawer?color=2196f3&label=Fork "Fork")](https://github.com/Leaqi/SwipeDrawer/network "Fork") [![API](https://img.shields.io/badge/API-14%2B-04d8bb "API")](https://github.com/Leaqi/SwipeDrawer/ "API") [![JitPack](https://jitpack.io/v/Leaqi/SwipeDrawer.svg "JitPack")](https://jitpack.io/#cn.Leaqi/SwipeDrawer "JitPack") [![Release](https://img.shields.io/github/v/release/Leaqi/SwipeDrawer?label=Release&color=06da47 "Release")](https://github.com/Leaqi/SwipeDrawer/releases "Release") [![License](https://img.shields.io/badge/License-Apache--2.0-e0b003 "License")](https://github.com/Leaqi/SwipeDrawer/blob/master/LICENSE "License") [![Download Demo Apk](https://img.shields.io/badge/Download-Demo%20Apk-45c703 "Download Demo Apk")](https://github.com/Leaqi/SwipeDrawer/releases/download/1.0/demo.apk "Download Demo Apk") +#### English README | [中文 README](https://github.com/Leaqi/SwipeDrawer/ "中文 README") +Android SwipeDrawer sliding drawer library can add up, down, left and right drawer layouts at the same time. There are three drawer opening modes: drawer mode, overlay mode and fixed mode. It supports unlimited nesting and edge sliding opening. Swipedrawer can also be used as a drop-down refresh layout, and supports listview, recyclerview, GridView, Scrollview, etc. + +#### English: +[![Click to view Use Docs](https://img.shields.io/badge/SwipeDrawer-Use%20Docs-blue "Click to view Use Docs")](https://Leaqi.github.io/SwipeDrawer_en/ "Click to view Use Docs") [![Click to view Detailed Docs](https://img.shields.io/badge/SwipeDrawer-Detailed%20Docs-orange "Click to view Detailed Docs")](https://Leaqi.github.io/SwipeDrawer_en/code.html "Click to view Detailed Docs") [![Click to view Picture Preview](https://img.shields.io/badge/SwipeDrawer-Picture%20Preview-green "Click to view Picture Preview")](https://Leaqi.github.io/SwipeDrawer_en/pics.html "Click to view Picture Preview") + +#### 中文: +[![点击查看使用文档](https://img.shields.io/badge/SwipeDrawer-%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3-blue "点击查看使用文档")](https://Leaqi.github.io/SwipeDrawer/ "点击查看使用文档") [![点击查看功能详解](https://img.shields.io/badge/SwipeDrawer-%E5%8A%9F%E8%83%BD%E8%AF%A6%E8%A7%A3-orange "点击查看功能详解")](https://Leaqi.github.io/SwipeDrawer/code.html "点击查看功能详解") [![点击查看图片演示](https://img.shields.io/badge/SwipeDrawer-%E5%9B%BE%E7%89%87%E6%BC%94%E7%A4%BA-green "点击查看图片演示")](https://Leaqi.github.io/SwipeDrawer/pics.html "点击查看图片演示") + +## Setup +Add `jitpack` repositories: + + allprojects { + repositories { + ... + maven { url "https://jitpack.io" } + } + } + +Add `SwipeDrawer` dependencies: + + dependencies { + ... + implementation 'cn.Leaqi.SwipeDrawer:1.0' + } + +Add `SwipeDrawer` to the layout file : + + + + + + + + + + + + + + +## Picture preview · [![See More](https://img.shields.io/badge/See-More-blue "See More")](https://Leaqi.github.io/SwipeDrawer/pics.html "See More") +[![Demo](https://p.ssl.qhimg.com/t0127d8ad395f6aff6f.jpg "Demo")](https://Leaqi.github.io/SwipeDrawer/pics.html "Demo") [![Demo](https://p.ssl.qhimg.com/t017c6a31eaa1242d0a.jpg "Demo")](https://Leaqi.github.io/SwipeDrawer/pics.html "Demo") [![Demo](https://p.ssl.qhimg.com/t0131cdd3e8c2ca7d41.jpg "Demo")](https://Leaqi.github.io/SwipeDrawer/pics.html "Demo") [![Demo](https://p.ssl.qhimg.com/t019aa5b68b427443c9.jpg "Demo")](https://Leaqi.github.io/SwipeDrawer/pics.html "Demo") + +## License +[Apache-2.0 License](https://github.com/Leaqi/SwipeDrawer/blob/master/LICENSE "Apache-2.0 License") + +Copyright (c) 2022 Leaqi \ No newline at end of file diff --git a/apk/README.md b/apk/README.md new file mode 100644 index 0000000..27e360d --- /dev/null +++ b/apk/README.md @@ -0,0 +1,32 @@ +# Demo-App · [![下载APK](https://img.shields.io/badge/Download-Demo%20Apk-45c703 "下载APK")](https://github.com/Leaqi/SwipeDrawer/releases/download/1.0/demo.apk "下载APK") +## 图片预览 · [![查看更多](https://img.shields.io/badge/More-%E6%9F%A5%E7%9C%8B%E6%9B%B4%E5%A4%9A-blue "查看更多")](https://Leaqi.github.io/SwipeDrawer/pics.html "查看更多") +### Demo Home: +[![Demo Home](https://p.ssl.qhimg.com/t01b36f1353d11068a0.jpg "Demo Home")](https://Leaqi.github.io/SwipeDrawer/pics.html "Demo Home") +### Demo 1: +[![Demo 1](https://p.ssl.qhimg.com/t01433cdb424d19230d.jpg "Demo 1")](https://Leaqi.github.io/SwipeDrawer/pics.html "Demo 1") +### Demo 2: +[![Demo 2](https://p.ssl.qhimg.com/t01b761c28a2bc1308a.jpg "Demo 2")](https://Leaqi.github.io/SwipeDrawer/pics.html "Demo 2") +### Demo 3: +[![Demo 3](https://p.ssl.qhimg.com/t0193c2274ce418c2c7.jpg "Demo 3")](https://Leaqi.github.io/SwipeDrawer/pics.html "Demo 3") +### Demo 4: +[![Demo 4](https://p.ssl.qhimg.com/t01c2dc0d5aa1e6af03.jpg "Demo 4")](https://Leaqi.github.io/SwipeDrawer/pics.html "Demo 4") +### Demo 5: +[![Demo 5](https://p.ssl.qhimg.com/t0111a3d372c8b617f8.jpg "Demo 5")](https://Leaqi.github.io/SwipeDrawer/pics.html "Demo 5") +### Demo 6: +[![Demo 6](https://p.ssl.qhimg.com/t0113a7f76f1bb376de.jpg "Demo 6")](https://Leaqi.github.io/SwipeDrawer/pics.html "Demo 6") +### Demo 7: +[![Demo 7](https://p.ssl.qhimg.com/t011f4aa76371a97c2d.jpg "Demo 7")](https://Leaqi.github.io/SwipeDrawer/pics.html "Demo 7") +### Demo 8: +[![Demo 8](https://p.ssl.qhimg.com/t018869655c0d14c571.jpg "Demo 8")](https://Leaqi.github.io/SwipeDrawer/pics.html "Demo 8") +### Demo 9: +[![Demo 9](https://p.ssl.qhimg.com/t012558e45962de481d.jpg "Demo 9")](https://Leaqi.github.io/SwipeDrawer/pics.html "Demo 9") +### Demo 10: +[![Demo 10](https://p.ssl.qhimg.com/t01160d20033ea317c6.jpg "Demo 10")](https://Leaqi.github.io/SwipeDrawer/pics.html "Demo 10") +### Demo 11: +[![Demo 11](https://p.ssl.qhimg.com/t01ae673f305442d7b9.jpg "Demo 11")](https://Leaqi.github.io/SwipeDrawer/pics.html "Demo 11") +### Demo 12: +[![Demo 12](https://p.ssl.qhimg.com/t01c6421d5583a403bb.jpg "Demo 12")](https://Leaqi.github.io/SwipeDrawer/pics.html "Demo 12") +### Demo 13: +[![Demo 13](https://p.ssl.qhimg.com/t01fedfa4a1f176dc57.jpg "Demo 13")](https://Leaqi.github.io/SwipeDrawer/pics.html "Demo 13") +### Demo 14: +[![Demo 14](https://p.ssl.qhimg.com/t012f200826d70e56be.jpg "Demo 14")](https://Leaqi.github.io/SwipeDrawer/pics.html "Demo 14") diff --git a/apk/demo-app.apk b/apk/demo-app.apk new file mode 100644 index 0000000..b4db8fa Binary files /dev/null and b/apk/demo-app.apk differ diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..e17955b --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,26 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 29 + buildToolsVersion "29.0.3" + defaultConfig { + applicationId "cn.leaqi.drawerapp" + minSdkVersion 16 + targetSdkVersion 29 + versionCode 1 + versionName "1.0" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation project(path: ':drawer') + implementation 'androidx.appcompat:appcompat:1.3.1' + implementation 'androidx.recyclerview:recyclerview:1.1.0' + implementation 'com.google.android.material:material:1.2.0' +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..8da6e7b --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,212 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/cn/leaqi/drawerapp/Demo10Activity.java b/app/src/main/java/cn/leaqi/drawerapp/Demo10Activity.java new file mode 100644 index 0000000..3f2f435 --- /dev/null +++ b/app/src/main/java/cn/leaqi/drawerapp/Demo10Activity.java @@ -0,0 +1,736 @@ +package cn.leaqi.drawerapp; + +import android.app.Activity; +import android.content.Context; +import android.graphics.drawable.AnimationDrawable; +import android.os.Bundle; +import android.os.Handler; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.viewpager.widget.PagerAdapter; +import androidx.viewpager.widget.ViewPager; +import androidx.viewpager2.widget.ViewPager2; + +import com.google.android.material.tabs.TabLayout; +import cn.leaqi.drawerapp.Utils.Common; +import cn.leaqi.drawerapp.Utils.Config; +import cn.leaqi.drawerapp.Views.MarqueView; +import cn.leaqi.drawerapp.Views.TopBar; +import cn.leaqi.drawerapp.Views.UserComment; +import cn.leaqi.drawerapp.Views.UserHome; +import cn.leaqi.drawerapp.Views.UserMenu; +import cn.leaqi.drawerapp.Views.UserShare; +import cn.leaqi.drawerapp.Views.VideoPlay; +import cn.leaqi.drawer.SwipeDrawer; +import cn.leaqi.drawer.OnDrawerChange; +import cn.leaqi.drawer.OnDrawerState; +import cn.leaqi.drawer.OnDrawerSwitch; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class Demo10Activity extends Activity implements View.OnClickListener, OnDrawerState, OnDrawerSwitch { + + TopBar topBar = null; + SwipeDrawer lastDrawer = null; + SwipeDrawer rootDrawer = null; + ViewPager mainView = null; + List viewList = null; + TabLayout tabLayout = null; + View topTab = null; + View topSet = null; + View topSo = null; + View topLoad = null; + EditText soVal = null; + UserHome userHome; + List tabList = new ArrayList(){{ + add("同城"); + add("关注"); + add("推荐"); + }}; + List viewPagerList = new ArrayList<>(); + List viewAdapterList = new ArrayList<>(); + + RecyclerView topList = null; + List topListData = null; + TopListAdapter topListAdapter = null; + + int tabIndex = 0; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_demo10); + topBar = new TopBar(this, false); // 头部操作类 + rootDrawer = findViewById(R.id.rootDrawer); + mainView = findViewById(R.id.mainView); + tabLayout = findViewById(R.id.tabLayout); + topTab = findViewById(R.id.topTab); + topSet = findViewById(R.id.topSet); + topSo = findViewById(R.id.topSo); + soVal = findViewById(R.id.soVal); + topLoad = findViewById(R.id.topLoad); + viewList = new ArrayList<>(); + userHome = new UserHome(this); // 用户主页类 + new UserMenu(this); // 左侧边栏用户菜单操作类 + new UserShare(this); // 用户分享类 + topBar.setNavigationBar(); + AppInit(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { // 监听返回键 + if (closeLast()) { // 如果是打开状态则关闭 + return true; // 拦截 + } + } + return super.onKeyDown(keyCode, event); + } + + @Override + protected void onStart() { + super.onStart(); + playVideo(true); + } + + @Override + protected void onStop() { + playVideo(false); + super.onStop(); + } + + @Override + public void onClick(View view) { + int getId = view.getId(); + switch (getId) { + case R.id.shareClose : // 视频分享关闭按钮 + case R.id.soBack : // 搜索顶部返回按钮 + rootDrawer.closeDrawer(); // 关闭 + break; + case R.id.topSet : // 顶部左边设置按钮 + rootDrawer.openDrawer(SwipeDrawer.DIRECTION_LEFT); // 打开Left方向 + break; + case R.id.topSo : // 顶部右边搜索按钮 + rootDrawer.openDrawer(SwipeDrawer.DIRECTION_TOP); // 打开Top方向 + break; + case R.id.soCode : // 搜索扫码按钮 + Common.showToast("扫码"); + break; + case R.id.soBtn : // 搜索提交按钮 + // 提交搜索词至搜索记录 list + String getText = soVal.getText().toString(); + if (getText.length() > 0) { + Common.hideInput(this); + topListData.add(0, getText); + topListAdapter.notifyItemInserted(0); + topList.scrollToPosition(0); + soVal.setText(""); + } + break; + } + } + + @Override + public void onStart(int type) { } + + @Override + public void onMove(int type, float progress) { + topTab.setAlpha(1 - progress); + } + + @Override + public void onOpen(int type) { } + + @Override + public void onClose(int type) { } + + @Override + public void onCancel(int type) { } + + @Override + public void onOpen(SwipeDrawer view) { // 打开 + closeLast(); + lastDrawer = view; + if (view == rootDrawer) { // 如果是最外层 SwipeDrawer 则暂停视频 + playVideo(false); + } + } + + @Override + public void onClose(SwipeDrawer view) { // 关闭 + lastDrawer = null; + if (view == rootDrawer) { // 如果是最外层 SwipeDrawer 则播放视频 + playVideo(true); + soVal.setText(""); + } + Common.hideInput(this); + } + + private void AppInit() { + final View userTop = findViewById(R.id.userTop); + final View topLayout = findViewById(R.id.topLayout); + // 空出状态栏高度 + topTab.setPadding(0, topBar.getStatusHeight(), 0, 0); + userTop.setPadding(0, topBar.getStatusHeight(), 0, 0); + topLayout.setPadding(0, topBar.getStatusHeight(), 0, 0); + // 绑定按钮点击事件 + findViewById(R.id.shareClose).setOnClickListener(this); + findViewById(R.id.soBack).setOnClickListener(this); + findViewById(R.id.soCode).setOnClickListener(this); + findViewById(R.id.soBtn).setOnClickListener(this); + topSet.setOnClickListener(this); + topSo.setOnClickListener(this); + + createPage(0); // 同城Page + createPage(1); // 关注Page + createPage(2); // 推荐Page + + tabLayout.setupWithViewPager(mainView); // tab绑定ViewPager + + mainView.setOffscreenPageLimit(3); + mainView.setAdapter(new ListPageAdapter(viewList)); + mainView.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } + @Override + public void onPageSelected(int position) { + tabLayout.getTabAt(position).select(); + closeLast(); + playVideo(true); // ViewPager切换后播放视频 + } + @Override + public void onPageScrollStateChanged(int state) { + if (state == ViewPager.SCROLL_STATE_DRAGGING) { // ViewPager切换时 + VideoPlay.setViewAlpha(0); // 隐藏视频控制器 + setViewAlpha(0.2f); // 主体内容透明 + } else { // ViewPager切换完毕 + VideoPlay.setViewAlpha(1); // 显示视频控制器 + setViewAlpha(1f); // 恢复主体内容透明 + } + } + }); + + tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { + @Override + public void onTabSelected(TabLayout.Tab tab) { } + @Override + public void onTabUnselected(TabLayout.Tab tab) { } + @Override + public void onTabReselected(TabLayout.Tab tab) { // 点击tab按钮 + if (tabIndex == tab.getPosition()) { // 如果点击是当前位置按钮则执行刷新 + topSet.setVisibility(View.GONE); // 隐藏设置按钮 + topSo.setVisibility(View.GONE); // 隐藏搜索按钮 + topLoad.setVisibility(View.VISIBLE); // 显示刷新布局 + ((AnimationDrawable) topLoad.getBackground()).start(); // 执行刷新动画 + // 动画延迟1.5秒 + topLoad.postDelayed(new Runnable() { + @Override + public void run() { + // 刷新更新数据 + viewAdapterList.get(tabIndex).randData(); + viewPagerList.get(tabIndex).setAdapter(viewAdapterList.get(tabIndex)); + topSet.setVisibility(View.VISIBLE); + topSo.setVisibility(View.VISIBLE); + topLoad.setVisibility(View.GONE); + ((AnimationDrawable) topLoad.getBackground()).stop(); + } + }, 1500); + } + tabIndex = tab.getPosition(); + } + }); + + // 监听 SwipeDrawer 状态 + rootDrawer.setOnDrawerState(this); + rootDrawer.setOnDrawerSwitch(this); + tabLayout.getTabAt(2).select(); // 默认显示推荐tab + mainView.setCurrentItem(2); // 默认显示推荐Page + + TopListData(); + } + + // 创建Page + private void createPage(final int index) { + final View page = LayoutInflater.from(this).inflate(R.layout.video_page, null); + final SwipeDrawer loadDrawer = page.findViewById(R.id.loadDrawer); + final ImageView reTopIcon = page.findViewById(R.id.reTopIcon); + final ViewPager2 mainPage = page.findViewById(R.id.mainPage); + final List mainList = new ArrayList(){{ + for(int i = 0; i < Config.VideoList.size(); i++) { + int key = Config.VideoList.keyAt(i); + Config.UserBean user = Config.UserList.get(key); + Config.VideoBean video = Config.VideoList.get(key); + Config.MusicBean music = Config.MusicList.get(key); + add(new ItemBean(user, video, music)); + } + }}; + Collections.shuffle(mainList); + final VideoPageAdapter adapter = new VideoPageAdapter(mainList, index); + mainPage.setOffscreenPageLimit(3); + mainPage.setAdapter(adapter); + + + loadDrawer.setOnDrawerChange(new OnDrawerChange() { + private void topOver() { + // 当前Page下拉刷新完毕 + adapter.randData(); + mainPage.setAdapter(adapter); + ((AnimationDrawable) reTopIcon.getBackground()).stop(); + reTopIcon.setScaleX(1); + reTopIcon.setScaleY(1); + // 0.3秒后关闭下拉属性布局 + reTopIcon.postDelayed(new Runnable() { + @Override + public void run() { + loadDrawer.closeDrawer(); + } + }, 300); + } + @Override + public void onChange(final SwipeDrawer view, int state, float progress) { + boolean isTop = view.getDirection() == SwipeDrawer.DIRECTION_TOP; + switch (state) { + case SwipeDrawer.STATE_PROGRESS : + if (!view.getShow()) { + if (progress > 1) progress = 1; + if (isTop) { + topTab.setAlpha(1 - progress); // 根据下拉进度设置头部透明度 + // 根据下拉进度放大缩小刷新图标 + reTopIcon.setScaleX(progress); + reTopIcon.setScaleY(progress); + } + } + break; + case SwipeDrawer.STATE_OPEN : + if (isTop) { + // 打开后执行动画 + ((AnimationDrawable) reTopIcon.getBackground()).start(); + // 1.5秒后执行关闭 + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + if (view.getShow()) { + topOver(); + } + } + }, 1500); + } + break; + case SwipeDrawer.STATE_ANIM_OVER: + if (!view.getShow()) { + if (isTop) { + // 刷新完毕初始化布局状态 + ((AnimationDrawable) reTopIcon.getBackground()).stop(); + reTopIcon.setScaleX(1); + reTopIcon.setScaleY(1); + } + } + break; + } + } + }); + + mainPage.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() { + @Override + public void onPageSelected(int position) { + adapter.playVideo(position); // 播放当前位置视频 + } + @Override + public void onPageScrollStateChanged(int state) { + if (state == ViewPager2.SCROLL_STATE_DRAGGING) { // ViewPager2切换时 + VideoPlay.setViewAlpha(0); // 隐藏视频控制器 + setViewAlpha(0.2f); // 主体内容透明 + } else { // ViewPager2切换完毕 + VideoPlay.setViewAlpha(1); // 显示视频控制器 + setViewAlpha(1f); // 恢复主体内容透明 + } + } + }); + viewAdapterList.add(adapter); + viewPagerList.add(mainPage); + viewList.add(page); + } + + // 控制视频播放暂停 + private void playVideo(boolean play) { + VideoPageAdapter adapter; + for (ViewPager2 view : viewPagerList) { + adapter = (VideoPageAdapter) view.getAdapter(); + if (adapter != null) { + if (play) { + adapter.playVideo(view.getCurrentItem()); + } else { + adapter.stopAll(); + } + } + } + } + + // 控制主体内容透明度及音乐旋转与滚动 + private void setViewAlpha(float alpha) { + if (lastHolder.size() > 0) { + for (VideoPageAdapter.ListViewHolder holder : lastHolder) { + holder.infoBox.setAlpha(alpha); + holder.btnBox.setAlpha(alpha); + if (alpha >= 1 && holder.itemVideo.isPlaying()) { + Common.animRotate(holder.itemMusicIcon, 2000); + holder.itemMusicText.setFocused(true); + } else { + holder.itemMusicIcon.clearAnimation(); + holder.itemMusicText.setFocused(false); + } + } + } + } + + // 关闭最后一次打开的SwipeDrawer + private boolean closeLast() { + if (lastDrawer != null) { + if (lastDrawer.getShow()) { + lastDrawer.closeDrawer(); + return true; + } + } + return false; + } + + private class ListPageAdapter extends PagerAdapter { + private List list; + + private ListPageAdapter(List l) { + list = l; + } + + @Override + public int getCount() { + return list.size(); + } + + @Override + public boolean isViewFromObject(@NonNull View view, @NonNull Object object) { + return view == object; + } + + @Override + public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { + container.removeView(list.get(position)); + } + + @NonNull + @Override + public Object instantiateItem(@NonNull ViewGroup container, int position) { + container.addView(list.get(position)); + return list.get(position); + } + + @Nullable + @Override + public CharSequence getPageTitle(int position) { + return tabList.get(position); + } + } + + private class ItemBean { + Config.UserBean user; // 用户类 + Config.VideoBean video; // 视频类 + Config.MusicBean music; // 音乐类 + private ItemBean(Config.UserBean user, Config.VideoBean video, Config.MusicBean music) { + this.user = user; + this.video = video; + this.music = music; + } + } + + private final List lastHolder = new ArrayList<>(); + + private class VideoPageAdapter extends RecyclerView.Adapter implements VideoPlay.OnPlayState { + + private List list; + private int index = -1; + private Map playList = new HashMap<>(); + + private VideoPageAdapter(List l, int i) { + list = l; + index = i; + } + + private void randData() { + Collections.shuffle(list); + } + + private void playVideo(int position) { + stopAll(); + ListViewHolder holder = playList.get(position); + if (holder != null && index == mainView.getCurrentItem()) { + holder.itemVideo.start(); + ItemBean item = list.get(position); + userHome.upHome(item.user); // 更新用户主页为当前用户 + // 是否已经关注 + if (item.user.isFollow) { + holder.iconFollow.setVisibility(View.GONE); + } else { + holder.iconFollow.setImageResource(R.mipmap.follow_add); + holder.iconFollow.setVisibility(View.VISIBLE); + } + } + } + + private void stopAll() { + for (Map.Entry val : playList.entrySet()) { + ListViewHolder item = val.getValue(); + item.itemVideo.pause(); + } + } + + @Override + public void onStart(VideoPlay view) { } + + @Override + public void onPlay(VideoPlay view) { + final ListViewHolder holder = (ListViewHolder) view.getTag(); + if (holder != null) { + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + // 视频开始播放后音乐旋转滚动 + Common.animRotate(holder.itemMusicIcon, 2000); + holder.itemMusicText.setFocused(true); + holder.itemVideo.setAlpha(1f); + holder.itemImg.setVisibility(View.GONE); + } + }, 300); + } + } + + @Override + public void onStop(VideoPlay view) { + ListViewHolder holder = (ListViewHolder) view.getTag(); + if (holder != null) { + // 视频暂停后音乐旋转滚动停止 + holder.itemMusicIcon.clearAnimation(); + holder.itemMusicText.setFocused(false); + } + } + + @Override + public void onError(VideoPlay view) { } + + @NonNull + @Override + public ListViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view = LayoutInflater.from(Demo10Activity.this).inflate(R.layout.video_item, parent, false); + return new ListViewHolder(view); + } + + @Override + public void onBindViewHolder(@NonNull ListViewHolder holder, int position) { + ItemBean item = list.get(position); + holder.itemTitle.setText(("@" + item.user.name)); // 视频标题 + holder.itemText.setText(item.video.text); // 视频描述 + holder.iconFavCount.setText(item.video.getFavCount()); // 点赞数量 + holder.iconSayCount.setText(item.video.getSayCount()); // 评论数量 + holder.iconShareCount.setText(item.video.getShareCount()); // 分享数量 + holder.itemMusicText.setText(item.music.text); // 音乐名称 + Common.setHttpImage(holder.itemImg, item.video.img); // 默认视频背景 + Common.setHttpImage(holder.itemIcon, item.user.icon, R.mipmap.icon_user); // 用户头像 + Common.setHttpImage(holder.iconMusic, item.music.icon, R.mipmap.icon); // 音乐图标 + holder.iconFav.setImageResource(item.video.isFav ? R.mipmap.icon_fav_cur : R.mipmap.icon_fav); // 是否点赞 + holder.iconFollow.setVisibility(item.user.isFollow ? View.GONE : View.VISIBLE); // 是都关注 + + playList.put(position, holder); + holder.itemVideo.setTag(holder); + holder.itemVideo.setVideoPath(item.video.src); + holder.itemVideo.setOnPlayState(this); + holder.userComment.setData(); // 设置评论数据 + } + + @Override + public void onViewAttachedToWindow(@NonNull ListViewHolder holder) { + super.onViewAttachedToWindow(holder); + lastHolder.add(holder); + } + + @Override + public void onViewDetachedFromWindow(@NonNull ListViewHolder holder) { + super.onViewDetachedFromWindow(holder); + lastHolder.remove(holder); + } + + @Override + public int getItemCount() { + return list.size(); + } + + private class ListViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{ + private SwipeDrawer itemDrawer; + private ImageView itemImg; + private View itemVideoBox; + private VideoPlay itemVideo; + private ImageView itemIcon; + private ImageView iconFollow; + private View itemFav; + private ImageView iconFav; + private View itemSay; + private TextView iconFavCount; + private TextView iconSayCount; + private TextView iconShareCount; + private View sayClose; + private View itemShare; + private TextView itemTitle; + private TextView itemText; + private View itemMusicIcon; + private ImageView iconMusic; + private MarqueView itemMusicText; + + private View infoBox; + private View btnBox; + + private UserComment userComment; + + private ListViewHolder(@NonNull View itemView) { + super(itemView); + itemDrawer = itemView.findViewById(R.id.itemDrawer); + itemImg = itemView.findViewById(R.id.itemImg); + itemVideoBox = itemView.findViewById(R.id.itemVideoBox); + itemVideo = itemView.findViewById(R.id.itemVideo); + itemIcon = itemView.findViewById(R.id.itemIcon); + iconFollow = itemView.findViewById(R.id.iconFollow); + itemFav = itemView.findViewById(R.id.itemFav); + iconFav = itemView.findViewById(R.id.iconFav); + itemSay = itemView.findViewById(R.id.itemSay); + iconFavCount = itemView.findViewById(R.id.iconFavCount); + iconSayCount = itemView.findViewById(R.id.iconSayCount); + iconShareCount = itemView.findViewById(R.id.iconShareCount); + sayClose = itemView.findViewById(R.id.sayClose); + itemShare = itemView.findViewById(R.id.itemShare); + itemTitle = itemView.findViewById(R.id.itemTitle); + itemText = itemView.findViewById(R.id.itemText); + itemMusicIcon = itemView.findViewById(R.id.itemMusicIcon); + itemMusicText = itemView.findViewById(R.id.itemMusicText); + iconMusic = itemView.findViewById(R.id.iconMusic); + infoBox = itemView.findViewById(R.id.infoBox); + btnBox = itemView.findViewById(R.id.btnBox); + userComment = new UserComment(Demo10Activity.this, itemView); + itemTitle.setOnClickListener(this); + itemIcon.setOnClickListener(this); + iconFollow.setOnClickListener(this); + itemFav.setOnClickListener(this); + itemSay.setOnClickListener(this); + sayClose.setOnClickListener(this); + itemShare.setOnClickListener(this); + itemDrawer.setOnDrawerState(Demo10Activity.this); + itemDrawer.setOnDrawerSwitch(Demo10Activity.this); + } + + @Override + public void onClick(View view) { + int position = getAdapterPosition(); + ItemBean item = list.get(position); + if (view == itemSay) { // 点击打开评论 + itemDrawer.openDrawer(SwipeDrawer.DIRECTION_BOTTOM); // 打开Item下SwipeDrawer Bottom方向评论 + } else if (view == sayClose) { // 点击关闭评论 + itemDrawer.closeDrawer(); // 关闭Item下SwipeDrawer Bottom方向 + } else if (view == iconFollow) { // 点击关注 + if (item.user.isFollow) return; + item.user.isFollow = true; + // 关注加号的动画 + iconFollow.setImageResource(R.mipmap.follow_ok); + Common.scaleHide(iconFollow, 150); + userHome.upHome(item.user); // 关注后更新用户主页 + } else if (view == itemFav) { // 点击点赞 + // 点赞与取消点赞的操作 + item.video.isFav = !item.video.isFav; + item.video.favCount = item.video.isFav ? item.video.favCount + 1 : item.video.favCount - 1; + iconFav.setImageResource(item.video.isFav ? R.mipmap.icon_fav_cur : R.mipmap.icon_fav); + iconFavCount.setText(item.video.getFavCount()); + } else if (view == itemShare) { // 点击分享 + rootDrawer.openDrawer(SwipeDrawer.DIRECTION_BOTTOM); // 打开最外层SwipeDrawer Bottom方向分享 + } else if (view == itemIcon || view == itemTitle) { // 点击用户头像或用户名称 + rootDrawer.openDrawer(SwipeDrawer.DIRECTION_RIGHT); // 打开最外层SwipeDrawer Right方向用户主页 + } + } + + } + } + + // 顶部搜索list + private void TopListData() { + topList = findViewById(R.id.topList); + topListData = new ArrayList(){{ + add("DrawerApp"); + add("SwipeDrawer"); + }}; + topListAdapter = new TopListAdapter(this, R.layout.item_so, topListData); + topList.setLayoutManager(new LinearLayoutManager(this)); + topList.setAdapter(topListAdapter); + } + + private class TopListAdapter extends RecyclerView.Adapter { + private int layout; + private LayoutInflater inflater; + private List list; + + private TopListAdapter(Context context, int resource, List objects) { + layout = resource; + inflater = LayoutInflater.from(context); + list = objects; + notifyDataSetChanged(); + } + + @NonNull + @Override + public ListViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View addView = inflater.inflate(layout, parent, false); + return new ListViewHolder(addView); + } + + @Override + public void onBindViewHolder(@NonNull ListViewHolder holder, int position) { + holder.title.setText(list.get(position)); + } + + @Override + public int getItemCount() { + return list.size(); + } + + private class ListViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + TextView title; + View del; + + private ListViewHolder(View view) { + super(view); + title = view.findViewById(R.id.item_title); + del = view.findViewById(R.id.item_del); + title.setOnClickListener(this); + del.setOnClickListener(this); + } + + @Override + public void onClick(View view) { + if (view == title) { + Common.showToast(list.get(getAdapterPosition())); + } else if (view == del) { + topListData.remove(getAdapterPosition()); + topListAdapter.notifyItemRemoved(getAdapterPosition()); + } + } + } + + } + +} diff --git a/app/src/main/java/cn/leaqi/drawerapp/Demo11Activity.java b/app/src/main/java/cn/leaqi/drawerapp/Demo11Activity.java new file mode 100644 index 0000000..1a8db01 --- /dev/null +++ b/app/src/main/java/cn/leaqi/drawerapp/Demo11Activity.java @@ -0,0 +1,285 @@ +package cn.leaqi.drawerapp; + +import androidx.annotation.NonNull; + +import android.app.Activity; +import android.content.Context; +import android.os.Bundle; +import android.os.Handler; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.ImageView; +import android.widget.ListView; +import android.widget.TextView; + +import cn.leaqi.drawerapp.Utils.Common; +import cn.leaqi.drawerapp.Views.TopBar; +import cn.leaqi.drawer.SwipeDrawer; +import cn.leaqi.drawer.OnDrawerChange; + +import java.util.ArrayList; +import java.util.List; + +public class Demo11Activity extends Activity { + + TopBar topBar = null; + private List listData; + private ListAdapter listAdapter; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_demo11); + topBar = new TopBar(this); // 头部操作类 + topBar.setTitle("ListView 下拉刷新"); // 头部标题 + topBar.showLeftBack(); // 显示头部返回按钮 + AppInit(); + } + + public void AppInit() { + final SwipeDrawer mainDrawer = findViewById(R.id.mainDrawer); + final View gesture = findViewById(R.id.gesture); // 方向引导布局 + final View loadBg1 = findViewById(R.id.loadBg1); // 背景1 + final View loadBg2 = findViewById(R.id.loadBg2); // 背景2 + final View loadMain = findViewById(R.id.loadMain); // 骑行区域 + final View loadWheel1 = findViewById(R.id.loadWheel1); // 轮子1 + final View loadWheel2 = findViewById(R.id.loadWheel2); // 轮子1 + final View loadSun = findViewById(R.id.loadSun); // 太阳 + final ImageView reBottomIcon = findViewById(R.id.reBottomIcon); // 底部加载图标 + + + // 设置头部右边图标并设置点击事件 + topBar.showRight(R.mipmap.icon_re, new TopBar.OnTopClickListener() { + @Override + public void onClick(View view) { + mainDrawer.openDrawer(SwipeDrawer.DIRECTION_TOP); // 点击开始刷新 + } + }); + + // 监听 SwipeDrawer 改变 + mainDrawer.setOnDrawerChange(new OnDrawerChange() { + private boolean isClose = false; + private void topOver() { // 刷新完毕 + // 显示刷新完成状态 + isClose = true; + SetList(0); + topBar.getTopRightIcon().clearAnimation(); + topBar.getTopRightIcon().setRotation(0); + // 0.5秒后关闭 + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + mainDrawer.closeDrawer(); + } + }, 500); + } + private void bottomOver() { // 加载完毕 + // 显示加载完成状态 + isClose = true; + SetList(10); + topBar.getTopRightIcon().clearAnimation(); + topBar.getTopRightIcon().setRotation(0); + reBottomIcon.clearAnimation(); + reBottomIcon.setScaleX(1); + reBottomIcon.setScaleY(1); + reBottomIcon.setImageResource(R.mipmap.icon_complete); + // 0.5秒后关闭 + reBottomIcon.postDelayed(new Runnable() { + @Override + public void run() { + mainDrawer.closeDrawer(); + } + }, 500); + } + @Override + public void onChange(final SwipeDrawer view, int state, float progress) { + boolean isTop = view.getDirection() == SwipeDrawer.DIRECTION_TOP; + boolean isBottom = view.getDirection() == SwipeDrawer.DIRECTION_BOTTOM; + int setWidth = mainDrawer.getMeasuredWidth() / 2 - loadMain.getMeasuredWidth() / 2; + int bgWidth = loadBg1.getMeasuredWidth(); + switch (state) { + case SwipeDrawer.STATE_START: // 拖拽开始 + case SwipeDrawer.STATE_CALL_OPEN: // 调用 openDrawer 方法打开 + Common.animHide(gesture, 200); // 隐藏方向引导 + break; + case SwipeDrawer.STATE_PROGRESS : // 移动,progress 获取进度 + if (progress > 2) progress = 2; // 限制进度最大2倍 + if (!view.getShow() && view.getIntercept()) { // 非开启状态,且是手动拖拽 + topBar.getTopRightIcon().setRotation(progress * 360); // 头部右边图标根据进度旋转 + } + if (progress > 1) progress = 1f; + if (isTop) { + if (isClose) { + progress = 2 - progress; + loadMain.setX(progress * setWidth); // 骑行区域根据进度前进后退 + } else if (!view.getShow()) { + loadMain.setX(progress * setWidth); // 骑行区域根据进度前进后退 + loadBg1.setX(-(progress * bgWidth)); // 背景1无缝滚动 + loadBg2.setX(bgWidth + -(progress * bgWidth)); // 背景2无缝滚动 + loadWheel1.setRotation(progress * 1800); // 轮子1转动 + loadWheel2.setRotation(progress * 1800); // 轮子2转动 + loadSun.setRotation(progress * 360); // 太阳转动 + } + } else if (isBottom) { + // 底部加载图标根据进度放大缩小 + reBottomIcon.setScaleX(progress); + reBottomIcon.setScaleY(progress); + } + break; + case SwipeDrawer.STATE_OPEN : // 打开 + Common.animRotate(topBar.getTopRightIcon(), 600); // 头部右边图标旋转动画 + if (isTop) { + loadMain.setX(setWidth); + loadBg1.setX(0); + loadBg2.setX(bgWidth); + Common.animShake(loadMain, 0.2f ,6 , 2000); // 骑行区域抖动动画 + Common.animTranslate(loadBg1, 0, -1, 0, 0, 3000); // 背景1无缝滚动动画 + Common.animTranslate(loadBg2, 0, -1, 0, 0, 3000); // 背景2无缝滚动动画 + Common.animRotate(loadWheel1, 500); // 轮子1旋转动画 + Common.animRotate(loadWheel2, 500); // 轮子2旋转动画 + Common.animRotate(loadSun, 2000); // 太阳旋转动画 + // 2秒后结束刷新 + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + if (view.getShow()) { + topOver(); + } + } + }, 2000); + } else if (isBottom) { + Common.animShake(reBottomIcon, 8, 8, 1600); // 底部加载图标旋转动画 + // 2秒后结束加载 + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + if (view.getShow()) { + bottomOver(); + } + } + }, 2000); + } + break; + case SwipeDrawer.STATE_ANIM_OVER: // 动画执行完毕 + if (view.getShow()) { + Common.animHide(gesture, 200); // 隐藏方向引导 + } else { + Common.animShow(gesture, 200); // 显示方向引导 + topBar.getTopRightIcon().clearAnimation(); // 清除头部右边图标动画 + topBar.getTopRightIcon().setRotation(0); // 回正头部右边图标方向 + if (isTop) { + // 刷新完毕初始化布局状态 + loadMain.clearAnimation(); + loadBg1.clearAnimation(); + loadBg2.clearAnimation(); + loadWheel1.clearAnimation(); + loadWheel2.clearAnimation(); + loadSun.clearAnimation(); + loadMain.setX(0); + loadBg1.setX(0); + loadBg2.setX(0); + loadWheel1.setRotation(0); + loadWheel2.setRotation(0); + loadSun.setRotation(0); + } else if (isBottom) { + // 加载完毕初始化布局状态 + reBottomIcon.clearAnimation(); + reBottomIcon.setScaleX(1); + reBottomIcon.setScaleY(1); + reBottomIcon.setImageResource(R.mipmap.icon_machine); + } + isClose = false; + } + break; + } + } + }); + + ListData(); + } + + /** + * 更新 list 数据 + * @param num 更新条数 + */ + private void SetList(int num) { + if (num > 0) { + int sNum = listData.size(); + int eNum = listData.size() + num; + for (int i = sNum; i < eNum; i++) { + listData.add("ListView : " + (i + 1)); + } + listAdapter.notifyDataSetChanged(); + } else { + listData.clear(); + listAdapter.notifyDataSetChanged(); + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + for (int i = 0; i < 20; i++) { + listData.add("ListView : " + (i + 1)); + } + listAdapter.notifyDataSetChanged(); + } + }, 100); + } + } + + /** + * 给 ListView 填充数据 + */ + private void ListData() { + final ListView mainList = findViewById(R.id.mainList); + listData = new ArrayList(){{ + for (int i = 0; i < 20; i++) { + add("ListView : " + (i + 1)); + } + }}; + listAdapter = new ListAdapter(this, R.layout.list_icon, listData); + mainList.setAdapter(listAdapter); + mainList.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView adapterView, View view, int i, long l) { + Common.showToast(listData.get(i)); + } + }); + } + + private class ListAdapter extends ArrayAdapter { + private int layout; + private LayoutInflater inflater; + private List list; + + private ListAdapter(Context context, int resource, List objects) { + super(context, resource, objects); + layout = resource; + inflater = LayoutInflater.from(context); + list = objects; + } + + @NonNull + public View getView(int position, View convertView, @NonNull ViewGroup parent) { + View view; + ViewHolder viewHolder; + if (convertView == null) { + view = inflater.inflate(layout, null); + viewHolder = new ViewHolder(); + viewHolder.title = view.findViewById(R.id.item_title); + view.setTag(viewHolder); + } else { + view = convertView; + viewHolder = (ViewHolder) view.getTag(); + } + viewHolder.title.setText(list.get(position)); + return view; + } + + private class ViewHolder { + TextView title; + } + } + +} diff --git a/app/src/main/java/cn/leaqi/drawerapp/Demo12Activity.java b/app/src/main/java/cn/leaqi/drawerapp/Demo12Activity.java new file mode 100644 index 0000000..c730a9c --- /dev/null +++ b/app/src/main/java/cn/leaqi/drawerapp/Demo12Activity.java @@ -0,0 +1,282 @@ +package cn.leaqi.drawerapp; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.DividerItemDecoration; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import android.app.Activity; +import android.content.Context; +import android.os.Bundle; +import android.os.Handler; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import cn.leaqi.drawerapp.Utils.Common; +import cn.leaqi.drawerapp.Views.TopBar; +import cn.leaqi.drawer.SwipeDrawer; +import cn.leaqi.drawer.OnDrawerChange; + +import java.util.ArrayList; +import java.util.List; + +public class Demo12Activity extends Activity { + + TopBar topBar = null; + private List listData; + private ListAdapter listAdapter; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_demo12); + topBar = new TopBar(this); // 头部操作类 + topBar.setTitle("RecyclerView 下拉刷新"); // 头部标题 + topBar.showLeftBack(); // 显示头部返回按钮 + AppInit(); + } + + public void AppInit() { + final SwipeDrawer mainDrawer = findViewById(R.id.mainDrawer); + final View gesture = findViewById(R.id.gesture); // 方向引导布局 + final ImageView reTopIcon = findViewById(R.id.reTopIcon); + final TextView reTopText = findViewById(R.id.reTopText); + final ImageView reBottomIcon = findViewById(R.id.reBottomIcon); + final TextView reBottomText = findViewById(R.id.reBottomText); + + + // 设置头部右边图标并设置点击事件 + topBar.showRight(R.mipmap.icon_re, new TopBar.OnTopClickListener() { + @Override + public void onClick(View view) { + mainDrawer.openDrawer(SwipeDrawer.DIRECTION_TOP); // 点击开始刷新 + } + }); + + // 监听 SwipeDrawer 改变 + mainDrawer.setOnDrawerChange(new OnDrawerChange() { + private void topOver() { // 刷新完毕 + // 显示刷新完成状态 + SetList(0); + topBar.getTopRightIcon().clearAnimation(); + topBar.getTopRightIcon().setRotation(0); + reTopIcon.clearAnimation(); + reTopIcon.setRotation(0); + reTopIcon.setVisibility(View.GONE); + reTopText.setText("刷新完成"); + // 0.6秒后关闭 + reTopText.postDelayed(new Runnable() { + @Override + public void run() { + mainDrawer.closeDrawer(); + } + }, 600); + } + private void bottomOver() { // 加载完毕 + // 显示加载完成状态 + SetList(10); + topBar.getTopRightIcon().clearAnimation(); + topBar.getTopRightIcon().setRotation(0); + reBottomIcon.clearAnimation(); + reBottomIcon.setRotation(0); + reBottomIcon.setVisibility(View.GONE); + reBottomText.setText("加载完成"); + // 0.6秒后关闭 + reBottomText.postDelayed(new Runnable() { + @Override + public void run() { + mainDrawer.closeDrawer(); + } + }, 600); + } + @Override + public void onChange(final SwipeDrawer view, int state, float progress) { + boolean isTop = view.getDirection() == SwipeDrawer.DIRECTION_TOP; + boolean isBottom = view.getDirection() == SwipeDrawer.DIRECTION_BOTTOM; + switch (state) { + case SwipeDrawer.STATE_START: // 拖拽开始 + case SwipeDrawer.STATE_CALL_OPEN: // 调用 openDrawer 方法打开 + Common.animHide(gesture, 200); // 隐藏方向引导 + break; + case SwipeDrawer.STATE_PROGRESS : // 移动,progress 获取进度 + if (!view.getShow() && view.getIntercept()) { // 非开启状态,且是手动拖拽 + if (progress > 2) progress = 2; // 限制进度最大2倍 + topBar.getTopRightIcon().setRotation(progress * 360); // 头部右边图标根据进度旋转 + if (progress > 1) progress = 1; + if (isTop) { + reTopIcon.setRotation(progress * 360); // 顶部刷新图标根据进度旋转 + } else if (isBottom) { + reBottomIcon.setRotation(progress * 360); // 底部加载图标根据进度旋转 + } + } + break; + case SwipeDrawer.STATE_OPEN : // 打开 + Common.animRotate(topBar.getTopRightIcon(), 600); // 头部右边图标旋转动画 + if (isTop) { + reTopText.setText("正在刷新"); + reTopIcon.setImageResource(R.mipmap.icon_more); + Common.animRotate(reTopIcon, 800); // 顶部刷新图标旋转动画 + // 1.5秒后结束刷新 + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + if (view.getShow()) { + topOver(); + } + } + }, 1500); + } else if (isBottom) { + reBottomText.setText("正在加载"); + reBottomIcon.setImageResource(R.mipmap.icon_more); + Common.animRotate(reBottomIcon, 800); // 底部加载图标旋转动画 + // 1.5秒后结束加载 + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + if (view.getShow()) { + bottomOver(); + } + } + }, 1500); + } + break; + case SwipeDrawer.STATE_ANIM_OVER: // 动画执行完毕 + if (view.getShow()) { + Common.animHide(gesture, 200); // 隐藏方向引导 + } else { + Common.animShow(gesture, 200); // 显示方向引导 + topBar.getTopRightIcon().clearAnimation(); // 清除头部右边图标动画 + topBar.getTopRightIcon().setRotation(0); // 回正头部右边图标方向 + if (isTop) { + // 刷新完毕初始化布局状态 + reTopIcon.clearAnimation(); + reTopIcon.setRotation(0); + reTopIcon.setVisibility(View.VISIBLE); + reTopIcon.setImageResource(R.mipmap.icon_down); + } else if (isBottom) { + // 加载完毕初始化布局状态 + reBottomIcon.clearAnimation(); + reBottomIcon.setRotation(0); + reBottomIcon.setVisibility(View.VISIBLE); + reBottomIcon.setImageResource(R.mipmap.icon_up); + } + } + break; + case SwipeDrawer.STATE_DRAG_INTO : // 拖拽超过 shrinkRange 距离 + if (!view.getShow()) { + if (isTop) { + reTopText.setText("松开刷新"); + } else if (isBottom) { + reBottomText.setText("松开加载"); + } + } + break; + case SwipeDrawer.STATE_DRAG_OUT : // 拖拽未超过 shrinkRange 距离 + if (!view.getShow()) { + if (isTop) { + reTopText.setText("下拉刷新"); + } else if (isBottom) { + reBottomText.setText("上拉加载"); + } + } + break; + } + } + }); + + ListData(); + } + + /** + * 更新 list 数据 + * @param num 更新条数 + */ + private void SetList(int num) { + if (num > 0) { + int sNum = listData.size(); + int eNum = listData.size() + num; + for (int i = sNum; i < eNum; i++) { + listData.add("RecyclerView : " + (i + 1)); + } + listAdapter.notifyDataSetChanged(); + } else { + listData.clear(); + listAdapter.notifyDataSetChanged(); + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + for (int i = 0; i < 20; i++) { + listData.add("RecyclerView : " + (i + 1)); + } + listAdapter.notifyDataSetChanged(); + } + }, 100); + } + } + + /** + * 给 RecyclerView 填充数据 + */ + private void ListData() { + final RecyclerView mainList = findViewById(R.id.mainList); + listData = new ArrayList(){{ + for (int i = 0; i < 20; i++) { + add("RecyclerView : " + (i + 1)); + } + }}; + listAdapter = new ListAdapter(this, R.layout.list_icon, listData); + mainList.setLayoutManager(new LinearLayoutManager(this)); + mainList.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL)); + mainList.setAdapter(listAdapter); + } + + private class ListAdapter extends RecyclerView.Adapter { + private int layout; + private LayoutInflater inflater; + private List list; + + private ListAdapter(Context context, int resource, List objects) { + layout = resource; + inflater = LayoutInflater.from(context); + list = objects; + notifyDataSetChanged(); + } + + @NonNull + @Override + public ListViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View addView = inflater.inflate(layout, parent, false); + return new ListViewHolder(addView); + } + + @Override + public void onBindViewHolder(@NonNull ListViewHolder holder, int position) { + holder.title.setText(list.get(position)); + } + + @Override + public int getItemCount() { + return list.size(); + } + + private class ListViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + TextView title; + + private ListViewHolder(View view) { + super(view); + title = view.findViewById(R.id.item_title); + view.setOnClickListener(this); + } + + @Override + public void onClick(View view) { + Common.showToast(list.get(getAdapterPosition())); + } + } + + } + +} diff --git a/app/src/main/java/cn/leaqi/drawerapp/Demo13Activity.java b/app/src/main/java/cn/leaqi/drawerapp/Demo13Activity.java new file mode 100644 index 0000000..f8fbcf9 --- /dev/null +++ b/app/src/main/java/cn/leaqi/drawerapp/Demo13Activity.java @@ -0,0 +1,258 @@ +package cn.leaqi.drawerapp; + + +import android.app.Activity; +import android.content.Context; +import android.os.Bundle; +import android.os.Handler; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.GridView; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import cn.leaqi.drawerapp.Utils.Common; +import cn.leaqi.drawerapp.Views.TopBar; +import cn.leaqi.drawer.SwipeDrawer; +import cn.leaqi.drawer.OnDrawerChange; + +import java.util.ArrayList; +import java.util.List; + +public class Demo13Activity extends Activity { + + TopBar topBar = null; + private List listData; + private ListAdapter listAdapter; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_demo13); + topBar = new TopBar(this); // 头部操作类 + topBar.setTitle("GridView 下拉刷新"); // 头部标题 + topBar.showLeftBack(); // 显示头部返回按钮 + AppInit(); + } + + public void AppInit() { + final SwipeDrawer mainDrawer = findViewById(R.id.mainDrawer); + final View gesture = findViewById(R.id.gesture); // 方向引导布局 + final ImageView reTopIcon = findViewById(R.id.reTopIcon); + final ImageView reBottomIcon = findViewById(R.id.reBottomIcon); + + + // 设置头部右边图标并设置点击事件 + topBar.showRight(R.mipmap.icon_re, new TopBar.OnTopClickListener() { + @Override + public void onClick(View view) { + mainDrawer.openDrawer(SwipeDrawer.DIRECTION_TOP); // 点击开始刷新 + } + }); + + // 监听 SwipeDrawer 改变 + mainDrawer.setOnDrawerChange(new OnDrawerChange() { + private void topOver() { // 刷新完毕 + // 显示刷新完成状态 + SetList(0); + topBar.getTopRightIcon().clearAnimation(); + topBar.getTopRightIcon().setRotation(0); + reTopIcon.clearAnimation(); + reTopIcon.setRotation(0); + reTopIcon.setScaleX(1); + reTopIcon.setScaleY(1); + // 0.3秒后关闭 + reTopIcon.postDelayed(new Runnable() { + @Override + public void run() { + mainDrawer.closeDrawer(); + } + }, 300); + } + private void bottomOver() { // 加载完毕 + // 显示加载完成状态 + SetList(10); + topBar.getTopRightIcon().clearAnimation(); + topBar.getTopRightIcon().setRotation(0); + reBottomIcon.clearAnimation(); + reBottomIcon.setRotation(0); + reBottomIcon.setScaleX(1); + reBottomIcon.setScaleY(1); + // 0.3秒后关闭 + reBottomIcon.postDelayed(new Runnable() { + @Override + public void run() { + mainDrawer.closeDrawer(); + } + }, 300); + } + @Override + public void onChange(final SwipeDrawer view, int state, float progress) { + boolean isTop = view.getDirection() == SwipeDrawer.DIRECTION_TOP; + boolean isBottom = view.getDirection() == SwipeDrawer.DIRECTION_BOTTOM; + switch (state) { + case SwipeDrawer.STATE_START: // 拖拽开始 + case SwipeDrawer.STATE_CALL_OPEN: // 调用 openDrawer 方法打开 + Common.animHide(gesture, 200); // 隐藏方向引导 + break; + case SwipeDrawer.STATE_PROGRESS : // 移动,progress 获取进度 + if (!view.getShow()) { + if (progress > 1) progress = 1; // 限制进度最大1倍 + if (view.getIntercept()) { // 手动拖拽 + topBar.getTopRightIcon().setRotation(progress * 360); // 头部右边图标根据进度旋转 + } + if (isTop) { + // 顶部刷新图标根据进度放大缩小 + reTopIcon.setScaleX(progress); + reTopIcon.setScaleY(progress); + reTopIcon.setRotation(progress * 360); // 顶部刷新图标根据进度旋转 + } else if (isBottom) { + // 底部加载图标根据进度放大缩小 + reBottomIcon.setScaleX(progress); + reBottomIcon.setScaleY(progress); + reBottomIcon.setRotation(progress * 360); // 底部加载图标根据进度旋转 + } + } + break; + case SwipeDrawer.STATE_OPEN : // 打开 + Common.animRotate(topBar.getTopRightIcon(), 600); + if (isTop) { + Common.animRotate(reTopIcon, 800); // 顶部刷新图标旋转动画 + // 1.5秒后结束刷新 + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + if (view.getShow()) { + topOver(); + } + } + }, 1500); + } else if (isBottom) { + Common.animRotate(reBottomIcon, 800); // 底部加载图标旋转动画 + // 1.5秒后结束加载 + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + if (view.getShow()) { + bottomOver(); + } + } + }, 1500); + } + break; + case SwipeDrawer.STATE_ANIM_OVER: // 动画执行完毕 + if (view.getShow()) { + Common.animHide(gesture, 200); // 隐藏方向引导 + } else { + Common.animShow(gesture, 200); // 显示方向引导 + topBar.getTopRightIcon().clearAnimation(); // 清除头部右边图标动画 + topBar.getTopRightIcon().setRotation(0); // 回正头部右边图标方向 + if (isTop) { + // 刷新完毕初始化布局状态 + reTopIcon.clearAnimation(); + reTopIcon.setRotation(0); + reTopIcon.setScaleX(1); + reTopIcon.setScaleY(1); + } else if (isBottom) { + // 加载完毕初始化布局状态 + reBottomIcon.clearAnimation(); + reBottomIcon.setRotation(0); + reBottomIcon.setScaleX(1); + reBottomIcon.setScaleY(1); + } + } + break; + } + } + }); + + ListData(); + } + + /** + * 更新 list 数据 + * @param num 更新条数 + */ + private void SetList(int num) { + if (num > 0) { + int sNum = listData.size(); + int eNum = listData.size() + num; + for (int i = sNum; i < eNum; i++) { + listData.add("GridView : " + (i + 1)); + } + listAdapter.notifyDataSetChanged(); + } else { + listData.clear(); + listAdapter.notifyDataSetChanged(); + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + for (int i = 0; i < 40; i++) { + listData.add("GridView : " + (i + 1)); + } + listAdapter.notifyDataSetChanged(); + } + }, 100); + } + } + + /** + * 给 GridView 填充数据 + */ + private void ListData() { + final GridView mainList = findViewById(R.id.mainList); + listData = new ArrayList() {{ + for (int i = 0; i < 40; i++) { + add("GridView : " + (i + 1)); + } + }}; + listAdapter = new ListAdapter(this, R.layout.grid_text, listData); + mainList.setAdapter(listAdapter); + mainList.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView adapterView, View view, int i, long l) { + Common.showToast(listData.get(i)); + } + }); + } + + private class ListAdapter extends ArrayAdapter { + private int layout; + private LayoutInflater inflater; + private List list; + + private ListAdapter(Context context, int resource, List objects) { + super(context, resource, objects); + layout = resource; + inflater = LayoutInflater.from(context); + list = objects; + } + + @NonNull + public View getView(int position, View convertView, @NonNull ViewGroup parent) { + View view; + ViewHolder viewHolder; + if (convertView == null) { + view = inflater.inflate(layout, null); + viewHolder = new ViewHolder(); + viewHolder.title = view.findViewById(R.id.item_title); + view.setTag(viewHolder); + } else { + view = convertView; + viewHolder = (ViewHolder) view.getTag(); + } + viewHolder.title.setText(list.get(position)); + return view; + } + + private class ViewHolder { + TextView title; + } + } + +} diff --git a/app/src/main/java/cn/leaqi/drawerapp/Demo14Activity.java b/app/src/main/java/cn/leaqi/drawerapp/Demo14Activity.java new file mode 100644 index 0000000..d528135 --- /dev/null +++ b/app/src/main/java/cn/leaqi/drawerapp/Demo14Activity.java @@ -0,0 +1,134 @@ +package cn.leaqi.drawerapp; + + +import android.app.Activity; +import android.os.Bundle; +import android.os.Handler; +import android.view.View; +import android.widget.ImageView; +import android.widget.ScrollView; +import android.widget.TextView; + +import cn.leaqi.drawerapp.Utils.Common; +import cn.leaqi.drawerapp.Views.TopBar; +import cn.leaqi.drawer.SwipeDrawer; +import cn.leaqi.drawer.OnDrawerChange; + +public class Demo14Activity extends Activity { + + TopBar topBar = null; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_demo14); + topBar = new TopBar(this); // 头部操作类 + topBar.setTitle("ScrollView 下拉刷新"); // 头部标题 + topBar.showLeftBack(); // 显示头部返回按钮 + AppInit(); + } + + public void AppInit() { + final SwipeDrawer mainDrawer = findViewById(R.id.mainDrawer); + final ScrollView mainList = findViewById(R.id.mainList); + final View gesture = findViewById(R.id.gesture); // 方向引导布局 + final ImageView reTopIcon = findViewById(R.id.reTopIcon); + final TextView reTopText = findViewById(R.id.reTopText); + + + // 设置头部右边图标并设置点击事件 + topBar.showRight(R.mipmap.icon_re, new TopBar.OnTopClickListener() { + @Override + public void onClick(View view) { + mainDrawer.openDrawer(SwipeDrawer.DIRECTION_TOP); // 点击开始刷新 + } + }); + + // 监听 SwipeDrawer 改变 + mainDrawer.setOnDrawerChange(new OnDrawerChange() { + private void topOver() { // 刷新完毕 + // 显示刷新完成状态 + mainList.smoothScrollTo(0, 0); + topBar.getTopRightIcon().clearAnimation(); + topBar.getTopRightIcon().setRotation(0); + reTopIcon.clearAnimation(); + reTopIcon.setRotation(0); + reTopIcon.setImageResource(R.mipmap.icon_over); + reTopText.setText("刷新完成"); + // 0.6秒后关闭 + reTopText.postDelayed(new Runnable() { + @Override + public void run() { + mainDrawer.closeDrawer(); + } + }, 600); + } + @Override + public void onChange(final SwipeDrawer view, int state, float progress) { + boolean isTop = view.getDirection() == SwipeDrawer.DIRECTION_TOP; + switch (state) { + case SwipeDrawer.STATE_START: // 拖拽开始 + case SwipeDrawer.STATE_CALL_OPEN: // 调用 openDrawer 方法打开 + Common.animHide(gesture, 200); // 隐藏方向引导 + break; + case SwipeDrawer.STATE_PROGRESS : // 移动,progress 获取进度 + if (!view.getShow() && view.getIntercept()) { // 非开启状态,且是手动拖拽 + if (progress > 2) progress = 2; // 限制进度最大2倍 + topBar.getTopRightIcon().setRotation(progress * 360); // 头部右边图标根据进度旋转 + if (isTop) { + reTopIcon.setRotation(progress * 360); // 顶部刷新图标根据进度旋转 + } + } + break; + case SwipeDrawer.STATE_OPEN : // 打开 + Common.animRotate(topBar.getTopRightIcon(), 600); // 头部右边图标旋转动画 + if (isTop) { + reTopText.setText("正在刷新"); + Common.animRotate(reTopIcon, 600); // 顶部刷新图标旋转动画 + // 1.5秒后结束刷新 + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + if (view.getShow()) { + topOver(); + } + } + }, 1500); + } + break; + case SwipeDrawer.STATE_ANIM_OVER: // 动画执行完毕 + if (view.getShow()) { + Common.animHide(gesture, 200); // 隐藏方向引导 + } else { + Common.animShow(gesture, 200); // 显示方向引导 + topBar.getTopRightIcon().clearAnimation(); // 清除头部右边图标动画 + topBar.getTopRightIcon().setRotation(0); // 回正头部右边图标方向 + if (isTop) { + // 刷新完毕初始化布局状态 + reTopIcon.clearAnimation(); + reTopIcon.setRotation(0); + reTopIcon.setImageResource(R.mipmap.icon_load); + } + } + break; + case SwipeDrawer.STATE_DRAG_INTO : // 拖拽超过 shrinkRange 距离 + if (!view.getShow()) { + if (isTop) { + reTopText.setText("松开刷新"); + } + } + break; + case SwipeDrawer.STATE_DRAG_OUT : // 拖拽未超过 shrinkRange 距离 + if (!view.getShow()) { + if (isTop) { + reTopText.setText("下拉刷新"); + } + } + break; + } + } + }); + + } + +} diff --git a/app/src/main/java/cn/leaqi/drawerapp/Demo1Activity.java b/app/src/main/java/cn/leaqi/drawerapp/Demo1Activity.java new file mode 100644 index 0000000..89de799 --- /dev/null +++ b/app/src/main/java/cn/leaqi/drawerapp/Demo1Activity.java @@ -0,0 +1,209 @@ +package cn.leaqi.drawerapp; + +import androidx.annotation.NonNull; + +import android.app.Activity; +import android.content.Context; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ListView; +import android.widget.TextView; + +import cn.leaqi.drawerapp.Utils.Common; +import cn.leaqi.drawerapp.Views.TopBar; +import cn.leaqi.drawer.DrawerHolder; +import cn.leaqi.drawer.SwipeDrawer; +import cn.leaqi.drawer.OnDrawerState; + +import java.util.ArrayList; +import java.util.List; + +public class Demo1Activity extends Activity { + + TopBar topBar = null; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_demo1); + topBar = new TopBar(this); // 头部操作类 + topBar.setTitle("ListView"); // 头部标题 + topBar.showLeftBack(); // 显示头部返回按钮 + AppInit(); + } + + public void AppInit() { + final SwipeDrawer mainDrawer = findViewById(R.id.mainDrawer); + final View gesture = findViewById(R.id.gesture); // 方向引导布局 + // 监听 SwipeDrawer 状态 + mainDrawer.setOnDrawerState(new OnDrawerState() { + @Override + public void onStart(int type) { // 拖拽开始 + Common.animHide(gesture, 200); // 隐藏方向引导 + } + @Override + public void onMove(int type, float progress) { } + @Override + public void onOpen(int type) { } + @Override + public void onClose(int type) { // 关闭 + Common.animShow(gesture, 200); // 显示方向引导 + } + @Override + public void onCancel(int type) { // 取消操作 + if (mainDrawer.getShow()) { // 判断是否打开 + Common.animHide(gesture, 200); // 隐藏方向引导 + } else { + Common.animShow(gesture, 200); // 显示方向引导 + } + } + }); + ListData(); + } + + /** + * 给 ListView 填充数据 + */ + private void ListData() { + final ListView mainList = findViewById(R.id.mainList); + final List listData = new ArrayList(){{ + for (int i = 0; i < 30; i++) { + add("ListView : " + (i + 1)); + } + }}; + final ListAdapter listAdapter = new ListAdapter(this, R.layout.list_item, listData); + // 绑定 item 点击事件 + listAdapter.setOnItemClick(new OnItemClick() { + @Override + public void onClick(SwipeDrawer swipeDrawer, int position, int id) { + switch (id) { + case R.id.itemMain : // 点击了主布局 + Common.showToast(listData.get(position)); + break; + case R.id.itemDing : // 点击了 Left 置顶按钮 + swipeDrawer.closeDrawer(false); // 非动画关闭当前 item + String getText = listData.get(position); + listData.remove(position); // 移除 item + listData.add(0, getText); // 添加到顶部 + listAdapter.notifyDataSetChanged(); // 更新 list + break; + case R.id.itemDel : // 点击了 Right 删除按钮 + swipeDrawer.closeDrawer(false); // 非动画关闭当前 item + listData.remove(position); // 删除 item + listAdapter.notifyDataSetChanged(); // 更新 list + break; + case R.id.itemClose : // 点击了 Right 关闭按钮 + swipeDrawer.closeDrawer(true); // 关闭当前 item + break; + } + } + }); + mainList.setAdapter(listAdapter); + final String autoText = "✔ 自动关闭"; + final String shutText = "✘ 自动关闭"; + // 自定义头部右边文本并设置点击事件 + topBar.setRightText(shutText, new TopBar.OnTopClickListener() { + @Override + public void onClick(View view) { + String getText = ((TextView) view).getText().toString(); + if (getText.equals(autoText)) { + topBar.setRightText(shutText); // 更新文本 + listAdapter.setAutoClose(false); // 取消自动关闭 + } else { + topBar.setRightText(autoText); // 更新文本 + listAdapter.setAutoClose(true); // 设置自动关闭 + } + } + }); + } + + private interface OnItemClick { + void onClick(SwipeDrawer swipeDrawer, int position, int id); + } + + private class ListAdapter extends ArrayAdapter implements View.OnClickListener { + private int layout; + private LayoutInflater inflater; + private List list; + private OnItemClick onItemClick = null; + private boolean autoClose = false; + + // 创建 DrawerHolder 对象,非自动关闭的情况保存 item 状态使用 + private DrawerHolder drawerHolder = new DrawerHolder(); + + private ListAdapter(Context context, int resource, List objects) { + super(context, resource, objects); + layout = resource; + inflater = LayoutInflater.from(context); + list = objects; + } + + private void setOnItemClick(OnItemClick click) { + onItemClick = click; + } + + private void setAutoClose(boolean bool) { + autoClose = bool; + drawerHolder.clearHolder(); // 清除已保存状态并关闭所有已打开 item + notifyDataSetChanged(); // 更新 list + } + + @Override + public void onClick(View view) { + int id = view.getId(); + int position = (int) view.getTag(); + SwipeDrawer swipeDrawer = SwipeDrawer.getParentDrawer(view); + if (swipeDrawer == null) return; + if (onItemClick != null) { // 点击事件回调 + onItemClick.onClick(swipeDrawer, position, id); + } + } + + @NonNull + public View getView(int position, View convertView, @NonNull ViewGroup parent) { + View view; + ViewHolder viewHolder; + if (convertView == null) { + view = inflater.inflate(layout, null); + viewHolder = new ViewHolder(); + viewHolder.title = view.findViewById(R.id.item_title); + viewHolder.itemMain = view.findViewById(R.id.itemMain); + viewHolder.itemDing = view.findViewById(R.id.itemDing); + viewHolder.itemDel = view.findViewById(R.id.itemDel); + viewHolder.itemClose = view.findViewById(R.id.itemClose); + viewHolder.itemMain.setOnClickListener(this); + viewHolder.itemDing.setOnClickListener(this); + viewHolder.itemDel.setOnClickListener(this); + viewHolder.itemClose.setOnClickListener(this); + view.setTag(viewHolder); + } else { + view = convertView; + viewHolder = (ViewHolder) view.getTag(); + } + SwipeDrawer swipeDrawer = ((SwipeDrawer) view); + swipeDrawer.setAutoClose(autoClose); // 设置是否自动关闭 + viewHolder.itemMain.setTag(position); + viewHolder.itemDing.setTag(position); + viewHolder.itemDel.setTag(position); + viewHolder.itemClose.setTag(position); + viewHolder.title.setText(list.get(position)); + + // bindHolder 的第一个参数传递 item 的 SwipeDrawer 布局 + // bindHolder 的第二个参数传递唯一对象 + drawerHolder.bindHolder(swipeDrawer, list.get(position)); + return view; + } + + private class ViewHolder { + View itemMain; + View itemDing; + View itemDel; + View itemClose; + TextView title; + } + } + +} diff --git a/app/src/main/java/cn/leaqi/drawerapp/Demo2Activity.java b/app/src/main/java/cn/leaqi/drawerapp/Demo2Activity.java new file mode 100644 index 0000000..34196f3 --- /dev/null +++ b/app/src/main/java/cn/leaqi/drawerapp/Demo2Activity.java @@ -0,0 +1,216 @@ +package cn.leaqi.drawerapp; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.DividerItemDecoration; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import android.app.Activity; +import android.content.Context; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import cn.leaqi.drawerapp.Utils.Common; +import cn.leaqi.drawerapp.Views.TopBar; +import cn.leaqi.drawer.DrawerHolder; +import cn.leaqi.drawer.SwipeDrawer; +import cn.leaqi.drawer.OnDrawerState; + +import java.util.ArrayList; +import java.util.List; + +public class Demo2Activity extends Activity { + + TopBar topBar = null; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_demo2); + topBar = new TopBar(this); // 头部操作类 + topBar.setTitle("RecyclerView"); // 头部标题 + topBar.showLeftBack(); // 显示头部返回按钮 + AppInit(); + } + + public void AppInit() { + final SwipeDrawer mainDrawer = findViewById(R.id.mainDrawer); + final View gesture = findViewById(R.id.gesture); // 方向引导布局 + // 监听 SwipeDrawer 状态 + mainDrawer.setOnDrawerState(new OnDrawerState() { + @Override + public void onStart(int type) { // 拖拽开始 + Common.animHide(gesture, 200); // 隐藏方向引导 + } + @Override + public void onMove(int type, float progress) { } + @Override + public void onOpen(int type) { } + @Override + public void onClose(int type) { // 关闭 + Common.animShow(gesture, 200); // 显示方向引导 + } + @Override + public void onCancel(int type) { // 取消操作 + if (mainDrawer.getShow()) { // 判断是否打开 + Common.animHide(gesture, 200); // 隐藏方向引导 + } else { + Common.animShow(gesture, 200); // 显示方向引导 + } + } + }); + ListData(); + } + + /** + * 给 ListView 填充数据 + */ + private void ListData() { + final RecyclerView mainList = findViewById(R.id.mainList); + final List listData = new ArrayList(){{ + for (int i = 0; i < 30; i++) { + add("RecyclerView : " + (i + 1)); + } + }}; + final ListAdapter listAdapter = new ListAdapter(this, R.layout.list_item, listData); + // 绑定 item 点击事件 + listAdapter.setOnItemClick(new OnItemClick() { + @Override + public void onClick(SwipeDrawer swipeDrawer, int position, int id) { + switch (id) { + case R.id.itemMain : // 点击了主布局 + Common.showToast(listData.get(position)); + break; + case R.id.itemDing : // 点击了 Left 置顶按钮 + swipeDrawer.closeDrawer(false); // 非动画关闭当前 item + String getText = listData.get(position); + listData.remove(position); // 移除 item + listData.add(0, getText); // 添加到顶部 + // 更新 list + listAdapter.notifyItemRemoved(position); + listAdapter.notifyItemRangeInserted(0, 1); + break; + case R.id.itemDel : // 点击了 Right 删除按钮 + swipeDrawer.closeDrawer(false); // 非动画关闭当前 item + listData.remove(position); // 删除 item + listAdapter.notifyItemRemoved(position); // 更新 list + break; + case R.id.itemClose : // 点击了 Right 关闭按钮 + swipeDrawer.closeDrawer(true); // 关闭当前 item + break; + } + } + }); + mainList.setLayoutManager(new LinearLayoutManager(this)); + mainList.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL)); + mainList.setAdapter(listAdapter); + // 自定义头部右边文本并设置点击事件 + final String autoText = "✔ 自动关闭"; + final String shutText = "✘ 自动关闭"; + topBar.setRightText(autoText, new TopBar.OnTopClickListener() { + @Override + public void onClick(View view) { + String getText = ((TextView) view).getText().toString(); + if (getText.equals(autoText)) { + topBar.setRightText(shutText); // 更新文本 + listAdapter.setAutoClose(false); // 取消自动关闭 + } else { + topBar.setRightText(autoText); // 更新文本 + listAdapter.setAutoClose(true); // 设置自动关闭 + } + } + }); + } + + private interface OnItemClick { + void onClick(SwipeDrawer swipeDrawer, int position, int id); + } + + private class ListAdapter extends RecyclerView.Adapter { + private int layout; + private LayoutInflater inflater; + private List list; + private OnItemClick onItemClick = null; + private boolean autoClose = true; + + // 创建 DrawerHolder 对象,非自动关闭的情况保存 item 状态使用 + private DrawerHolder drawerHolder = new DrawerHolder(); + + private ListAdapter(Context context, int resource, List objects) { + layout = resource; + inflater = LayoutInflater.from(context); + list = objects; + notifyDataSetChanged(); + } + + private void setOnItemClick(OnItemClick click) { + onItemClick = click; + } + + private void setAutoClose(boolean bool) { + autoClose = bool; + drawerHolder.clearHolder(); // 清除已保存状态并关闭所有已打开 item + notifyDataSetChanged(); // 更新 list + } + + @NonNull + @Override + public ListViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View addView = inflater.inflate(layout, parent, false); + return new ListViewHolder(addView); + } + + @Override + public void onBindViewHolder(@NonNull ListViewHolder holder, int position) { + holder.item.setAutoClose(autoClose); // 设置是否自动关闭 + holder.title.setText(list.get(position)); + + // bindHolder 的第一个参数传递 item 的 SwipeDrawer 布局 + // bindHolder 的第二个参数传递唯一对象 + drawerHolder.bindHolder(holder.item, list.get(position)); + } + + @Override + public int getItemCount() { + return list.size(); + } + + private class ListViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + SwipeDrawer item; + View itemMain; + View itemDing; + View itemDel; + View itemClose; + TextView title; + + private ListViewHolder(View view) { + super(view); + item = (SwipeDrawer) view; + title = view.findViewById(R.id.item_title); + itemMain = view.findViewById(R.id.itemMain); + itemDing = view.findViewById(R.id.itemDing); + itemDel = view.findViewById(R.id.itemDel); + itemClose = view.findViewById(R.id.itemClose); + itemMain.setOnClickListener(this); + itemDing.setOnClickListener(this); + itemDel.setOnClickListener(this); + itemClose.setOnClickListener(this); + } + + @Override + public void onClick(View view) { + int id = view.getId(); + int position = getAdapterPosition(); + if (onItemClick != null) { + onItemClick.onClick(item, position, id); + } + } + + } + + } + +} diff --git a/app/src/main/java/cn/leaqi/drawerapp/Demo3Activity.java b/app/src/main/java/cn/leaqi/drawerapp/Demo3Activity.java new file mode 100644 index 0000000..f54c5d0 --- /dev/null +++ b/app/src/main/java/cn/leaqi/drawerapp/Demo3Activity.java @@ -0,0 +1,210 @@ +package cn.leaqi.drawerapp; + + +import android.app.Activity; +import android.content.Context; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.GridView; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import cn.leaqi.drawerapp.Utils.Common; +import cn.leaqi.drawerapp.Views.TopBar; +import cn.leaqi.drawer.DrawerHolder; +import cn.leaqi.drawer.SwipeDrawer; +import cn.leaqi.drawer.OnDrawerState; + +import java.util.ArrayList; +import java.util.List; + +public class Demo3Activity extends Activity { + + TopBar topBar = null; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_demo3); + topBar = new TopBar(this); // 头部操作类 + topBar.setTitle("GridView"); // 头部标题 + topBar.showLeftBack(); // 显示头部返回按钮 + AppInit(); + } + + public void AppInit() { + final SwipeDrawer mainDrawer = findViewById(R.id.mainDrawer); + final View gesture = findViewById(R.id.gesture); // 方向引导布局 + // 监听 SwipeDrawer 状态 + mainDrawer.setOnDrawerState(new OnDrawerState() { + @Override + public void onStart(int type) { // 拖拽开始 + Common.animHide(gesture, 200); // 隐藏方向引导 + } + @Override + public void onMove(int type, float progress) { } + @Override + public void onOpen(int type) { } + @Override + public void onClose(int type) { // 关闭 + Common.animShow(gesture, 200); // 显示方向引导 + } + @Override + public void onCancel(int type) { // 取消操作 + if (mainDrawer.getShow()) { // 判断是否打开 + Common.animHide(gesture, 200); // 隐藏方向引导 + } else { + Common.animShow(gesture, 200); // 显示方向引导 + } + } + }); + ListData(); + } + + /** + * 给 ListView 填充数据 + */ + private void ListData() { + final GridView mainList = findViewById(R.id.mainList); + final List listData = new ArrayList() {{ + for (int i = 0; i < 50; i++) { + add("GridView : " + (i + 1)); + } + }}; + final ListAdapter listAdapter = new ListAdapter(this, R.layout.grid_item, listData); + // 绑定 item 点击事件 + listAdapter.setOnItemClick(new OnItemClick() { + @Override + public void onClick(SwipeDrawer swipeDrawer, int position, int id) { + switch (id) { + case R.id.itemMain : // 点击了主布局 + Common.showToast(listData.get(position)); + break; + case R.id.itemDing : // 点击了 Left 置顶按钮 + swipeDrawer.closeDrawer(false); // 非动画关闭当前 item + String getText = listData.get(position); + listData.remove(position); // 删除 item + listData.add(0, getText); // 添加到顶部 + listAdapter.notifyDataSetChanged(); // 更新 list + break; + case R.id.itemDel : // 点击了 Right 删除按钮 + swipeDrawer.closeDrawer(false); // 非动画关闭当前 item + listData.remove(position); // 删除 item + listAdapter.notifyDataSetChanged(); // 更新 list + break; + case R.id.itemClose : // 点击了 Right 关闭按钮 + swipeDrawer.closeDrawer(true); // 关闭当前 item + break; + } + } + }); + mainList.setAdapter(listAdapter); + final String autoText = "✔ 自动关闭"; + final String shutText = "✘ 自动关闭"; + // 自定义头部右边文本并设置点击事件 + topBar.setRightText(shutText, new TopBar.OnTopClickListener() { + @Override + public void onClick(View view) { + String getText = ((TextView) view).getText().toString(); + if (getText.equals(autoText)) { + topBar.setRightText(shutText); // 更新文本 + listAdapter.setAutoClose(false); // 取消自动关闭 + } else { + topBar.setRightText(autoText); // 更新文本 + listAdapter.setAutoClose(true); // 设置自动关闭 + } + } + }); + } + + private interface OnItemClick { + void onClick(SwipeDrawer swipeDrawer, int position, int id); + } + + private class ListAdapter extends ArrayAdapter implements View.OnClickListener { + private int layout; + private LayoutInflater inflater; + private List list; + private OnItemClick onItemClick = null; + private boolean autoClose = false; + + // 创建 DrawerHolder 对象,非自动关闭的情况保存 item 状态使用 + private DrawerHolder drawerHolder = new DrawerHolder(); + + private ListAdapter(Context context, int resource, List objects) { + super(context, resource, objects); + layout = resource; + inflater = LayoutInflater.from(context); + list = objects; + } + + private void setOnItemClick(OnItemClick click) { + onItemClick = click; + } + + private void setAutoClose(boolean bool) { + autoClose = bool; + drawerHolder.clearHolder(); // 清除已保存状态并关闭所有已打开 item + notifyDataSetChanged(); // 更新 list + } + + @Override + public void onClick(View view) { + int id = view.getId(); + int position = (int) view.getTag(); + SwipeDrawer swipeDrawer = SwipeDrawer.getParentDrawer(view); + if (swipeDrawer == null) return; + if (onItemClick != null) { // 点击事件回调 + onItemClick.onClick(swipeDrawer, position, id); + } + } + + @NonNull + public View getView(int position, View convertView, @NonNull ViewGroup parent) { + View view; + ViewHolder viewHolder; + if (convertView == null) { + view = inflater.inflate(layout, null); + viewHolder = new ViewHolder(); + viewHolder.title = view.findViewById(R.id.item_title); + viewHolder.itemMain = view.findViewById(R.id.itemMain); + viewHolder.itemDing = view.findViewById(R.id.itemDing); + viewHolder.itemDel = view.findViewById(R.id.itemDel); + viewHolder.itemClose = view.findViewById(R.id.itemClose); + viewHolder.itemMain.setOnClickListener(this); + viewHolder.itemDing.setOnClickListener(this); + viewHolder.itemDel.setOnClickListener(this); + viewHolder.itemClose.setOnClickListener(this); + view.setTag(viewHolder); + } else { + view = convertView; + viewHolder = (ViewHolder) view.getTag(); + } + SwipeDrawer swipeDrawer = ((SwipeDrawer) view); + swipeDrawer.setAutoClose(autoClose); // 设置是否自动关闭 + viewHolder.itemMain.setTag(position); + viewHolder.itemDing.setTag(position); + viewHolder.itemDel.setTag(position); + viewHolder.itemClose.setTag(position); + viewHolder.title.setText(list.get(position)); + + // bindHolder 的第一个参数传递 item 的 SwipeDrawer 布局 + // bindHolder 的第二个参数传递唯一对象 + drawerHolder.bindHolder(swipeDrawer, list.get(position)); + return view; + } + + private class ViewHolder { + View itemMain; + View itemDing; + View itemDel; + View itemClose; + TextView title; + } + } + +} diff --git a/app/src/main/java/cn/leaqi/drawerapp/Demo4Activity.java b/app/src/main/java/cn/leaqi/drawerapp/Demo4Activity.java new file mode 100644 index 0000000..db64a6c --- /dev/null +++ b/app/src/main/java/cn/leaqi/drawerapp/Demo4Activity.java @@ -0,0 +1,70 @@ +package cn.leaqi.drawerapp; + +import android.app.Activity; +import android.os.Bundle; +import android.view.View; + +import cn.leaqi.drawerapp.Utils.Common; +import cn.leaqi.drawerapp.Views.TopBar; +import cn.leaqi.drawer.SwipeDrawer; +import cn.leaqi.drawer.OnDrawerState; + +public class Demo4Activity extends Activity { + + TopBar topBar = null; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_demo4); + topBar = new TopBar(this); // 头部操作类 + topBar.setTitle("ScrollView"); // 头部标题 + topBar.showLeftBack(); // 显示头部返回按钮 + AppInit(); + } + + public void AppInit() { + final SwipeDrawer mainDrawer = findViewById(R.id.mainDrawer); + final View gesture = findViewById(R.id.gesture); // 方向引导布局 + + // 设置头部右边图标并设置点击事件 + topBar.showRight(R.mipmap.icon_menu, new TopBar.OnTopClickListener() { + @Override + public void onClick(View view) { + mainDrawer.toggleDrawer(SwipeDrawer.DIRECTION_RIGHT); // 点击打开或关闭Right方向 + } + }); + + // 监听 SwipeDrawer 状态 + mainDrawer.setOnDrawerState(new OnDrawerState() { + @Override + public void onStart(int type) { // 拖拽开始 + Common.animHide(gesture, 200); // 隐藏方向引导 + } + @Override + public void onMove(int type, float progress) { } + @Override + public void onOpen(int type) { // 打开 + if (type == SwipeDrawer.DIRECTION_RIGHT) { // 打开了Right方向 + topBar.setRightIcon(R.mipmap.icon_close); // 设置头部右边图标 + } + } + @Override + public void onClose(int type) { // 关闭 + Common.animShow(gesture, 200); // 显示方向引导 + if (type == SwipeDrawer.DIRECTION_RIGHT) { // 关闭了Right方向 + topBar.setRightIcon(R.mipmap.icon_menu); // 设置头部右边图标 + } + } + @Override + public void onCancel(int type) { // 取消操作 + if (mainDrawer.getShow()) { // 判断是否打开 + Common.animHide(gesture, 200); // 隐藏方向引导 + } else { + Common.animShow(gesture, 200); // 显示方向引导 + } + } + }); + } + +} diff --git a/app/src/main/java/cn/leaqi/drawerapp/Demo5Activity.java b/app/src/main/java/cn/leaqi/drawerapp/Demo5Activity.java new file mode 100644 index 0000000..bafd6cb --- /dev/null +++ b/app/src/main/java/cn/leaqi/drawerapp/Demo5Activity.java @@ -0,0 +1,126 @@ +package cn.leaqi.drawerapp; + +import android.app.Activity; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.viewpager.widget.PagerAdapter; +import androidx.viewpager.widget.ViewPager; + +import com.google.android.material.bottomnavigation.BottomNavigationView; +import cn.leaqi.drawerapp.Views.TopBar; +import cn.leaqi.drawer.SwipeDrawer; + +import java.util.ArrayList; +import java.util.List; + +public class Demo5Activity extends Activity { + + TopBar topBar = null; + SwipeDrawer mainDrawer = null; + ViewPager mainView = null; + BottomNavigationView menuView = null; + List viewList = null; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_demo5); + topBar = new TopBar(this); // 头部操作类 + topBar.setTitle("ViewPager"); // 头部标题 + topBar.showLeftBack(); // 显示头部返回按钮 + mainDrawer = findViewById(R.id.mainDrawer); + mainView = findViewById(R.id.mainView); + menuView = findViewById(R.id.menuView); + viewList = new ArrayList<>(); + AppInit(); + } + + private void AppInit() { + showPage(0); + + createPage(1); + createPage(2); + createPage(3); + createPage(4); + + mainView.setAdapter(new ListPageAdapter(viewList)); + // Page切换监听 + mainView.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } + @Override + public void onPageSelected(int position) { + menuView.getMenu().getItem(position).setChecked(true); // 选中导航菜单 + showPage(position); // 更新文本 + } + @Override + public void onPageScrollStateChanged(int state) { } + }); + // 导航菜单点击监听 + menuView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() { + @Override + public boolean onNavigationItemSelected(@NonNull MenuItem item) { + if (mainDrawer.getShow()) { // 如果最外层 SwipeDrawer 是打开状态 + mainDrawer.closeDrawer(); // 关闭 + } + mainView.setCurrentItem(item.getOrder()); // Page切换 + return true; + } + }); + } + + // 创建Page + private void createPage(int position) { + View page = LayoutInflater.from(this).inflate(R.layout.view_page, null); + TextView mainView = page.findViewById(R.id.Main); + TextView topView = page.findViewById(R.id.Top); + TextView bottomView = page.findViewById(R.id.Bottom); + mainView.setText(("ViewPager\n\nPage" + position)); + topView.setText(("ViewPager\n\nPage" + position + " - Top")); + bottomView.setText(("ViewPager\n\nPage" + position + " - Bottom")); + viewList.add(page); + menuView.getMenu().add(0, position - 1, position - 1,"Page" + position).setIcon(R.drawable.menu_item); + } + + // 更新头部文本 + private void showPage(int position) { + topBar.setRightText("Page" + (position + 1)); + } + + private class ListPageAdapter extends PagerAdapter { + List list; + + public ListPageAdapter(List l) { + list = l; + } + + @Override + public int getCount() { + return list.size(); + } + + @Override + public boolean isViewFromObject(@NonNull View view, @NonNull Object object) { + return view == object; + } + + @Override + public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { + container.removeView(list.get(position)); + } + + @NonNull + @Override + public Object instantiateItem(@NonNull ViewGroup container, int position) { + container.addView(list.get(position)); + return list.get(position); + } + } + +} diff --git a/app/src/main/java/cn/leaqi/drawerapp/Demo6Activity.java b/app/src/main/java/cn/leaqi/drawerapp/Demo6Activity.java new file mode 100644 index 0000000..d807e8d --- /dev/null +++ b/app/src/main/java/cn/leaqi/drawerapp/Demo6Activity.java @@ -0,0 +1,20 @@ +package cn.leaqi.drawerapp; + +import android.app.Activity; +import android.os.Bundle; + +import cn.leaqi.drawerapp.Views.TopBar; + +public class Demo6Activity extends Activity { + + TopBar topBar = null; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_demo6); + topBar = new TopBar(this); // 头部操作类 + topBar.setTitle("多层嵌套"); // 头部标题 + topBar.showLeftBack(); // 显示头部返回按钮 + } +} diff --git a/app/src/main/java/cn/leaqi/drawerapp/Demo7Activity.java b/app/src/main/java/cn/leaqi/drawerapp/Demo7Activity.java new file mode 100644 index 0000000..f5dfe24 --- /dev/null +++ b/app/src/main/java/cn/leaqi/drawerapp/Demo7Activity.java @@ -0,0 +1,86 @@ +package cn.leaqi.drawerapp; + +import android.app.Activity; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.View; + +import cn.leaqi.drawerapp.Views.TopBar; +import cn.leaqi.drawerapp.Views.UserInfo; +import cn.leaqi.drawerapp.Views.UserMenu; +import cn.leaqi.drawer.SwipeDrawer; +import cn.leaqi.drawer.OnDrawerState; + +public class Demo7Activity extends Activity { + + TopBar topBar = null; + SwipeDrawer rootDrawer = null; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_demo7); + rootDrawer = findViewById(R.id.rootDrawer); + topBar = new TopBar(this); // 头部操作类 + topBar.setTitle("边缘拖拽"); // 头部标题 + new UserMenu(this); // 左侧边栏用户菜单操作类 + new UserInfo(this); // 右侧边栏用户菜单操作类 + AppInit(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { // 监听返回键 + if (rootDrawer.getShow()) { // 如果是打开状态 + rootDrawer.closeDrawer(); // 关闭 + return true; // 拦截 + } + } + return super.onKeyDown(keyCode, event); + } + + // 设置头部左边图标并设置点击事件 + private void AppInit() { + topBar.showLeft(R.mipmap.icon_menu, new TopBar.OnTopClickListener() { + @Override + public void onClick(View view) { + rootDrawer.toggleDrawer(SwipeDrawer.DIRECTION_LEFT); // 点击打开或关闭Left方向 + } + }); + // 设置头部右边图标并设置点击事件 + topBar.showRight(R.mipmap.icon_menu, new TopBar.OnTopClickListener() { + @Override + public void onClick(View view) { + rootDrawer.toggleDrawer(SwipeDrawer.DIRECTION_RIGHT); // 点击打开或关闭Right方向 + } + }); + + // 监听 SwipeDrawer 状态 + rootDrawer.setOnDrawerState(new OnDrawerState() { + @Override + public void onStart(int type) { } + @Override + public void onMove(int type, float progress) { } + @Override + public void onOpen(int type) { // 打开 + if (type == SwipeDrawer.DIRECTION_LEFT) { // 打开了Left方向 + topBar.setLeftIcon(R.mipmap.icon_close); // 设置头部左边图标 + }else if (type == SwipeDrawer.DIRECTION_RIGHT) { // 打开了Right方向 + topBar.setRightIcon(R.mipmap.icon_close); // 设置头部右边图标 + } + } + @Override + public void onClose(int type) { // 关闭 + if (type == SwipeDrawer.DIRECTION_LEFT) { // 关闭了Left方向 + topBar.setLeftIcon(R.mipmap.icon_menu); // 设置头部左边图标 + }else if (type == SwipeDrawer.DIRECTION_RIGHT) { // 关闭了Right方向 + topBar.setRightIcon(R.mipmap.icon_menu); // 设置头部右边图标 + } + } + @Override + public void onCancel(int type) { } + }); + + } + +} diff --git a/app/src/main/java/cn/leaqi/drawerapp/Demo8Activity.java b/app/src/main/java/cn/leaqi/drawerapp/Demo8Activity.java new file mode 100644 index 0000000..4215b62 --- /dev/null +++ b/app/src/main/java/cn/leaqi/drawerapp/Demo8Activity.java @@ -0,0 +1,97 @@ +package cn.leaqi.drawerapp; + +import android.app.Activity; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.View; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.GridView; +import android.widget.SeekBar; + +import cn.leaqi.drawerapp.Utils.Common; +import cn.leaqi.drawerapp.Views.TopBar; +import cn.leaqi.drawer.SwipeDrawer; + +public class Demo8Activity extends Activity { + TopBar topBar = null; + SwipeDrawer rootDrawer = null; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_demo8); + rootDrawer = findViewById(R.id.rootDrawer); + topBar = new TopBar(this); // 头部操作类 + topBar.setTitle("底部弹出"); // 头部标题 + topBar.setRightText("滑动到底部或者点击➜"); // 显示头部右边文本 + AppInit(); + ListData(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { // 监听返回键 + if (rootDrawer.getShow()) { // 如果是打开状态 + rootDrawer.closeDrawer(); // 关闭 + return true; // 拦截 + } + } + return super.onKeyDown(keyCode, event); + } + + private void AppInit() { + final View bottomLayout = findViewById(R.id.bottomLayout); + final int bottomTop = bottomLayout.getPaddingTop(); // 获取顶部距离 + final SeekBar seekBar = findViewById(R.id.seekBar); + final View close = findViewById(R.id.close); // 关闭按钮 + + // 设置头部右边图标并设置点击事件 + topBar.showRight(R.mipmap.icon_menu, new TopBar.OnTopClickListener() { + @Override + public void onClick(View view) { + rootDrawer.toggleDrawer(SwipeDrawer.DIRECTION_BOTTOM); // 点击打开或关闭Bottom方向 + } + }); + + seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int i, boolean b) { + bottomLayout.setPadding(0, bottomTop + i,0 , 0); // 设置顶部距离 + } + @Override + public void onStartTrackingTouch(SeekBar seekBar) { } + @Override + public void onStopTrackingTouch(SeekBar seekBar) { } + }); + + // 关闭按钮点击事件 + close.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (rootDrawer.getShow()) { + rootDrawer.closeDrawer(); // 关闭 + } + } + }); + } + + /** + * 给 GridView 填充数据 + */ + private void ListData() { + final GridView gridView = findViewById(R.id.gridView); + final String[] dataList = {"视频","问答","漫画","财经","娱乐","科技","国际","军事","直播","情感","租赁","装修","音乐","航空","股票","NBA","短视频","房产","数码","手机","游戏","历史","电影","星座","旅游","图片","教育","育儿","文学","明星","科普","综艺","天气","美容","服饰","影视","美食","健康","搞笑","体育","预约","养生","时尚","公益","汽车","文化","艺术","金融","网游","电竞","商业","中超"}; + ArrayAdapter adapter = new ArrayAdapter<>(this, R.layout.btn_item, dataList); + gridView.setAdapter(adapter); + + gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView adapterView, View view, int i, long l) { + Common.showToast(dataList[i]); + } + }); + + } + +} diff --git a/app/src/main/java/cn/leaqi/drawerapp/Demo9Activity.java b/app/src/main/java/cn/leaqi/drawerapp/Demo9Activity.java new file mode 100644 index 0000000..639b86f --- /dev/null +++ b/app/src/main/java/cn/leaqi/drawerapp/Demo9Activity.java @@ -0,0 +1,133 @@ +package cn.leaqi.drawerapp; + +import android.app.Activity; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.GridView; +import android.widget.TextView; + +import cn.leaqi.drawerapp.Utils.Common; +import cn.leaqi.drawerapp.Views.TopBar; +import cn.leaqi.drawer.SwipeDrawer; +import cn.leaqi.drawer.OnDrawerState; + +public class Demo9Activity extends Activity { + TopBar topBar = null; + SwipeDrawer rootDrawer = null; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_demo9); + rootDrawer = findViewById(R.id.rootDrawer); + topBar = new TopBar(this); // 头部操作类 + topBar.setTitle("顶部弹出"); // 头部标题 + AppInit(); + ListData(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { // 监听返回键 + if (rootDrawer.getShow()) { // 如果是打开状态 + rootDrawer.closeDrawer(); // 关闭 + return true; // 拦截 + } + } + return super.onKeyDown(keyCode, event); + } + + private void AppInit() { + final View mask = findViewById(R.id.mask); // 自定义主布局遮罩 + final View topMask = findViewById(R.id.topMask); // 自定义Top布局遮罩 + final GridView gridView = findViewById(R.id.gridView); // Top布局GridView + final View topLayout = findViewById(R.id.topLayout); + topLayout.post(new Runnable() { + @Override + public void run() { + // 更新高度 + ViewGroup.LayoutParams getLp = topLayout.getLayoutParams(); + getLp.height = rootDrawer.getMeasuredHeight() - topBar.getHeight(); + topLayout.setLayoutParams(getLp); + rootDrawer.requestLayout(); + } + }); + + // 设置头部右边图标并设置点击事件 + topBar.showRight(R.mipmap.icon_menu, new TopBar.OnTopClickListener() { + @Override + public void onClick(View view) { + rootDrawer.toggleDrawer(SwipeDrawer.DIRECTION_TOP); // 点击打开或关闭Top方向 + } + }); + + // 监听 SwipeDrawer 状态 + rootDrawer.setOnDrawerState(new OnDrawerState() { + private boolean radiusBar = false; + @Override + public void onStart(int type) { } + @Override + public void onMove(int type, float progress) { // 移动时 + mask.setAlpha(progress); // 根据打开进度设置主布局遮罩透明度 + topMask.setAlpha(1 - progress); // 根据打开进度设置Top布局遮罩透明度 + gridView.setAlpha(progress); // 根据打开进度设置 GridView 透明度 + // 根据打开进度设置 GridView 的缩放 + gridView.setScaleX(progress); + gridView.setScaleY(progress); + // 根据打开进度设置头部透明度 + topBar.setBarAlpha(rootDrawer.getShow() ? progress * 0.7f : 1 - progress); + // 处理头部圆角 + if (!rootDrawer.getShow()) { + if (progress == 0) { + topBar.normalBar(); + radiusBar = false; + } else { + if (!radiusBar) { + topBar.radiusBar(); + radiusBar = true; + } + } + } + } + @Override + public void onOpen(int type) { // 打开 + if (type == SwipeDrawer.DIRECTION_TOP) { // 打开了Top方向 + topBar.setRightIcon(R.mipmap.icon_close); // 设置头部右边图标 + topBar.radiusBar(); + radiusBar = true; + } + } + @Override + public void onClose(int type) { // 关闭 + if (type == SwipeDrawer.DIRECTION_TOP) { // 关闭了Top方向 + topBar.setRightIcon(R.mipmap.icon_menu); // 设置头部右边图标 + } + } + @Override + public void onCancel(int type) { } + }); + } + + /** + * 给 GridView 填充数据 + */ + private void ListData() { + final GridView gridView = findViewById(R.id.gridView); + final String[] dataList = {"视频","问答","漫画","财经","娱乐","科技","国际","军事","直播","情感","租赁","装修","音乐","航空","股票","NBA","短视频","房产","数码","手机","游戏","历史","电影","星座","旅游","图片","教育","育儿","文学","明星","科普","综艺","天气","美容","服饰","影视","美食","健康","搞笑","体育","预约","养生","时尚","公益","汽车","文化","艺术","金融","网游","电竞","商业","中超"}; + ArrayAdapter adapter = new ArrayAdapter<>(this, R.layout.btn_item, dataList); + gridView.setAdapter(adapter); + + gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView adapterView, View view, int i, long l) { + Common.showToast(dataList[i]); + } + }); + + } + +} diff --git a/app/src/main/java/cn/leaqi/drawerapp/MainActivity.java b/app/src/main/java/cn/leaqi/drawerapp/MainActivity.java new file mode 100644 index 0000000..bb1e23b --- /dev/null +++ b/app/src/main/java/cn/leaqi/drawerapp/MainActivity.java @@ -0,0 +1,249 @@ +package cn.leaqi.drawerapp; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.graphics.Color; +import android.net.Uri; +import android.os.Bundle; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.GridView; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import cn.leaqi.drawer.AnimThread; +import cn.leaqi.drawerapp.Utils.Cache; +import cn.leaqi.drawerapp.Utils.Common; +import cn.leaqi.drawerapp.Views.TopBar; +import cn.leaqi.drawerapp.Views.UserInfo; +import cn.leaqi.drawerapp.Views.UserMenu; +import cn.leaqi.drawer.SwipeDrawer; +import cn.leaqi.drawer.OnDrawerState; + +import java.util.ArrayList; +import java.util.List; + + +public class MainActivity extends Activity { + + TopBar topBar = null; + SwipeDrawer rootDrawer = null; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + topBar = new TopBar(this); // 头部操作类 + rootDrawer = findViewById(R.id.rootDrawer); + new UserMenu(this); // 左侧边栏用户菜单操作类 + new UserInfo(this); // 右侧边栏用户菜单操作类 + AppInit(); + ListData(); + Cache.clearCache(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { // 监听返回键 + if (rootDrawer.getShow()) { // 如果是打开状态 + rootDrawer.closeDrawer(); // 关闭 + return true; // 拦截 + } + } + return super.onKeyDown(keyCode, event); + } + + public void AppInit() { + final View mask = findViewById(R.id.mask); // 自定义遮罩 + final TextView modeDrawer = findViewById(R.id.modeDrawer); // 抽屉模式按钮 + final TextView modeCover = findViewById(R.id.modeCover); // 覆盖模式按钮 + final TextView modeFixed = findViewById(R.id.modeFixed); // 固定模式按钮 + + modeDrawer.setSelected(true); // 默认选中抽屉模式按钮 + View.OnClickListener onClickListener = new View.OnClickListener() { + @Override + public void onClick(View view) { + int isSet = -1; + if (view == modeDrawer && rootDrawer.getMode() != SwipeDrawer.MODE_DRAWER) { // 被点击的是 抽屉模式按钮 且当前状态非抽屉模式 + rootDrawer.setMode(SwipeDrawer.MODE_DRAWER); // 设置模式为抽屉模式 + isSet = rootDrawer.getMode() == SwipeDrawer.MODE_DRAWER ? 1 : 0; // 判断是否设置成功 + } else if (view == modeCover && rootDrawer.getMode() != SwipeDrawer.MODE_COVER) { // 被点击的是 覆盖模式按钮 且当前状态非覆盖模式 + rootDrawer.setMode(SwipeDrawer.MODE_COVER); // 设置模式为覆盖模式 + isSet = rootDrawer.getMode() == SwipeDrawer.MODE_COVER ? 1 : 0; // 判断是否设置成功 + } else if (view == modeFixed && rootDrawer.getMode() != SwipeDrawer.MODE_FIXED) { // 被点击的是 固定模式按钮 且当前状态非固定模式 + rootDrawer.setMode(SwipeDrawer.MODE_FIXED); // 设置模式为固定模式 + isSet = rootDrawer.getMode() == SwipeDrawer.MODE_FIXED ? 1 : 0; // 判断是否设置成功 + } + if (isSet == 1) { // 设置成功 + // 更新选中按钮 + modeFixed.setSelected(view == modeFixed); + modeCover.setSelected(view == modeCover); + modeDrawer.setSelected(view == modeDrawer); + Common.showToast("切换成功"); + } else if (isSet == 0) { + Common.showToast("切换失败"); + } + } + }; + // 绑定按钮点击事件 + modeDrawer.setOnClickListener(onClickListener); + modeCover.setOnClickListener(onClickListener); + modeFixed.setOnClickListener(onClickListener); + + // 设置头部左边图标并设置点击事件 + topBar.showLeft(R.mipmap.icon_menu, new TopBar.OnTopClickListener() { + @Override + public void onClick(View view) { + rootDrawer.toggleDrawer(SwipeDrawer.DIRECTION_LEFT); // 点击打开或关闭Left方向 + } + }); + // 设置头部右边图标并设置点击事件 + topBar.showRight(R.mipmap.icon_menu, new TopBar.OnTopClickListener() { + @Override + public void onClick(View view) { + rootDrawer.toggleDrawer(SwipeDrawer.DIRECTION_RIGHT); // 点击打开或关闭Right方向 + } + }); + + // 监听 SwipeDrawer 状态 + rootDrawer.setOnDrawerState(new OnDrawerState() { + @Override + public void onStart(int type) { } + @Override + public void onMove(int type, float progress) { + mask.setAlpha(progress); // 根据打开进度设置遮罩透明度 + if (rootDrawer.getMode() == SwipeDrawer.MODE_DRAWER && type == SwipeDrawer.DIRECTION_LEFT) { // 模式为 抽屉模式,且操作的是left方向 + progress *= 0.15; // 给进度打个折 + rootDrawer.setMainScale(1 - progress); // 根据打开进度缩放主布局 + } + } + @Override + public void onOpen(int type) { // 打开 + if (type == SwipeDrawer.DIRECTION_LEFT) { // 打开了Left方向 + topBar.setLeftIcon(R.mipmap.icon_close); // 设置头部左边图标 + }else if (type == SwipeDrawer.DIRECTION_RIGHT) { // 打开了Right方向 + topBar.setRightIcon(R.mipmap.icon_close); // 设置头部右边图标 + } + } + @Override + public void onClose(int type) { // 关闭 + if (type == SwipeDrawer.DIRECTION_LEFT) { // 关闭了Left方向 + topBar.setLeftIcon(R.mipmap.icon_menu); // 设置头部左边图标 + }else if (type == SwipeDrawer.DIRECTION_RIGHT) { // 关闭了Right方向 + topBar.setRightIcon(R.mipmap.icon_menu); // 设置头部右边图标 + } + } + @Override + public void onCancel(int type) { } + }); + + } + + /** + * 给 GridView 填充数据 + */ + private void ListData() { + final GridView mainList = findViewById(R.id.mainList); + final List listData = new ArrayList(){{ + add(new BtnBean("ListView", "Demo1", "#3F51B5")); + add(new BtnBean("RecyclerView", "Demo2", "#059C8E")); + add(new BtnBean("GridView", "Demo3", "#A8BB00")); + add(new BtnBean("ScrollView", "Demo4", "#FF5722")); + add(new BtnBean("ViewPager", "Demo5", "#0DAC14")); + add(new BtnBean("多层嵌套", "Demo6", "#B328CA")); + add(new BtnBean("边缘拖拽", "Demo7", "#E91E63")); + add(new BtnBean("底部弹出", "Demo8", "#FF9800")); + add(new BtnBean("顶部弹出", "Demo9", "#4D12F7")); + add(new BtnBean("短视频布局", "Demo10", "#161722")); + add(new BtnBean("ListView 下拉刷新", "Demo11", "#23BB5B")); + add(new BtnBean("RecyclerView 下拉刷新", "Demo12", "#AE4DD1")); + add(new BtnBean("GridView 下拉刷新", "Demo13", "#447CCF")); + add(new BtnBean("ScrollView 下拉刷新", "Demo14", "#20B1AC")); + }}; + final ListAdapter listAdapter = new ListAdapter(this, R.layout.list_btn, listData); + mainList.setAdapter(listAdapter); + } + + private class BtnBean { + String text; // 显示文本 + String link; // 打开链接 + int color; // 背景颜色 + BtnBean(String t, String l, String c) { + text = t; + link = l; + color = Color.parseColor(c); + } + } + + private class ListAdapter extends ArrayAdapter implements View.OnClickListener { + private int layout; + private LayoutInflater inflater; + private List list; + private int TagString = R.attr.TagString; + + private ListAdapter(Context context, int resource, List objects) { + super(context, resource, objects); + layout = resource; + inflater = LayoutInflater.from(context); + list = objects; + } + + @Override + public void onClick(View view) { + String link = (String) view.getTag(TagString); + openActivity(link); + } + + @NonNull + public View getView(int position, View convertView, @NonNull ViewGroup parent) { + View view; + ViewHolder viewHolder; + if (convertView == null) { + view = inflater.inflate(layout, null); + viewHolder = new ViewHolder(); + viewHolder.btnLeft = view.findViewById(R.id.btnLeft); + viewHolder.btnRight = view.findViewById(R.id.btnRight); + viewHolder.btnTop = view.findViewById(R.id.btnTop); + viewHolder.btnBottom = view.findViewById(R.id.btnBottom); + viewHolder.btnText = view.findViewById(R.id.btnText); + view.setTag(viewHolder); + view.setOnClickListener(this); + } else { + view = convertView; + viewHolder = (ViewHolder) view.getTag(); + } + BtnBean item = list.get(position); + viewHolder.btnLeft.setText(item.link); + viewHolder.btnRight.setText(item.link); + viewHolder.btnTop.setText(item.link); + viewHolder.btnBottom.setText(item.link); + viewHolder.btnText.setText(item.text); + viewHolder.btnText.setBackgroundColor(item.color); + view.setTag(TagString, item.link); + return view; + } + + private class ViewHolder { + TextView btnLeft; + TextView btnRight; + TextView btnTop; + TextView btnBottom; + TextView btnText; + } + } + + /** + * 打开 Activity + * @param link 链接 + */ + public void openActivity(String link) { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("drawer://leaqi.cn/" + link)); + MainActivity.this.startActivity(intent); + } + +} diff --git a/app/src/main/java/cn/leaqi/drawerapp/Utils/AppData.java b/app/src/main/java/cn/leaqi/drawerapp/Utils/AppData.java new file mode 100644 index 0000000..aef54d3 --- /dev/null +++ b/app/src/main/java/cn/leaqi/drawerapp/Utils/AppData.java @@ -0,0 +1,19 @@ +package cn.leaqi.drawerapp.Utils; + +import android.app.Application; +import android.content.Context; + +public class AppData extends Application { + + private static Context context; + + @Override + public void onCreate() { + super.onCreate(); + context = getApplicationContext(); + } + + public static Context getContext(){ + return context; + } +} \ No newline at end of file diff --git a/app/src/main/java/cn/leaqi/drawerapp/Utils/Cache.java b/app/src/main/java/cn/leaqi/drawerapp/Utils/Cache.java new file mode 100644 index 0000000..f03f5cb --- /dev/null +++ b/app/src/main/java/cn/leaqi/drawerapp/Utils/Cache.java @@ -0,0 +1,118 @@ +package cn.leaqi.drawerapp.Utils; + +import android.graphics.Bitmap; +import android.net.Uri; +import android.widget.ImageView; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.net.URLEncoder; + +public class Cache { + + /** + * 清除缓存目录 + */ + public static void clearCache() { + try { + delFolder(new File(getCachePath())); + delFolder(AppData.getContext().getCacheDir()); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 删除目录 + * @param dir 路径 + * @return 是否成功 + */ + private static boolean delFolder(File dir) { + boolean isOk = true; + try { + if (dir != null) { + if(dir.isDirectory()) { + String[] list = dir.list(); + if (list != null) { + for (String item : list) { + if (!delFolder(new File(dir, item))) { + return false; + } + } + } + } + isOk = dir.delete(); + } + } catch (Exception e) { + e.printStackTrace(); + } + return isOk; + } + + /** + * 获取缓存路径 + * @return 返回路径 + */ + public static String getCachePath(){ + boolean isPath; + File setPath = new File(AppData.getContext().getFilesDir(), "data"); + if (!setPath.exists()) { + isPath = setPath.mkdirs(); + }else{ + isPath = true; + } + return (isPath ? setPath : AppData.getContext().getCacheDir()).toString(); + } + + /** + * 获取缓存文件 + * @param name 文件名 + * @return 返回文件路径 + */ + public static File getCacheFile(String name){ + try { + name = URLEncoder.encode(name, "UTF-8"); + } catch (Exception e) { + e.printStackTrace(); + } + return new File(getCachePath() + "/" + name + ".Q"); + } + + /** + * 创建文件 + * @param file 文件路径 + * @param bitmap 内容 + * @return 是否成功 + */ + public static boolean fileWrite(File file, Bitmap bitmap){ + try { + BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(file)); + bitmap.compress(Bitmap.CompressFormat.JPEG, 80, stream); + stream.flush(); + return file.exists(); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 显示缓存图片 + * @param img Image + * @param file 文件 + */ + public static boolean showImage(ImageView img, File file){ + try { + if(file.exists()) { + img.setImageURI(Uri.fromFile(file)); + return true; + } + } catch (Exception e) { + e.printStackTrace(); + } + return false; + } + +} + diff --git a/app/src/main/java/cn/leaqi/drawerapp/Utils/Common.java b/app/src/main/java/cn/leaqi/drawerapp/Utils/Common.java new file mode 100644 index 0000000..123a8e0 --- /dev/null +++ b/app/src/main/java/cn/leaqi/drawerapp/Utils/Common.java @@ -0,0 +1,326 @@ +package cn.leaqi.drawerapp.Utils; + +import android.app.Activity; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Color; +import android.net.Uri; +import android.view.View; +import android.view.animation.AlphaAnimation; +import android.view.animation.Animation; +import android.view.animation.AnimationSet; +import android.view.animation.CycleInterpolator; +import android.view.animation.LinearInterpolator; +import android.view.animation.RotateAnimation; +import android.view.animation.ScaleAnimation; +import android.view.animation.TranslateAnimation; +import android.view.inputmethod.InputMethodManager; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigDecimal; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Random; + +public class Common { + + /** + * dp转px + * @param context 上下文 + * @param dpValue dp + * @return px + */ + public static int dipToPx(Context context, float dpValue) { + final float scale = context.getResources().getDisplayMetrics().density; + return (int) (dpValue * scale + 0.5f); + } + + /** + * px转dp + * @param context 上下文 + * @param pxValue px + * @return dp + */ + public static int pxToDip(Context context, float pxValue) { + final float scale = context.getResources().getDisplayMetrics().density; + return (int) (pxValue / scale + 0.5f); + } + + /** + * 设置随机背景颜色,随机值越低颜色越深 + * @param view View + */ + public static void setRndBg(View view){ + Random random = new Random(); + int color = Color.rgb(random.nextInt(180), random.nextInt(180), random.nextInt(180)); + view.setBackgroundColor(color); + } + + /** + * 设置随机文本颜色,随机值越低颜色越深 + * @param view TextView + */ + public static void setRndColor(TextView view){ + Random random = new Random(); + int color = Color.rgb(random.nextInt(180), random.nextInt(180), random.nextInt(180)); + view.setTextColor(color); + } + + /** + * 显示动画 + * @param view View + * @param ms 动画毫秒 + */ + public static void animShow(View view, int ms){ + if(view.getVisibility() == View.VISIBLE) return; + AlphaAnimation animation = new AlphaAnimation(0f, 1f); + animation.setDuration(ms); + view.clearAnimation(); + view.startAnimation(animation); + view.setVisibility(View.VISIBLE); + } + + /** + * 隐藏动画 + * @param view View + * @param ms 动画毫秒 + */ + public static void animHide(View view, int ms){ + if(view.getVisibility() == View.GONE) return; + AlphaAnimation animation = new AlphaAnimation(1f, 0f); + animation.setDuration(ms); + view.clearAnimation(); + view.startAnimation(animation); + view.setVisibility(View.GONE); + } + + /** + * 显示隐藏动画 + * @param view View + * @param ms 动画毫秒 + */ + public static void scaleHide(final View view, final int ms){ + ScaleAnimation scale = new ScaleAnimation(0.5f, 1f, 0.5f, 1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); + scale.setDuration(ms); + view.clearAnimation(); + view.startAnimation(scale); + view.postDelayed(new Runnable() { + @Override + public void run() { + ScaleAnimation scale = new ScaleAnimation(1f, 0.5f, 1f, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); + scale.setDuration(ms); + scale.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + + } + @Override + public void onAnimationEnd(Animation animation) { + view.setVisibility(View.GONE); + } + @Override + public void onAnimationRepeat(Animation animation) { + + } + }); + view.clearAnimation(); + view.startAnimation(scale); + } + },ms + 1500); + } + + /** + * 设置旋转动画 + * @param view View + * @param ms 动画毫秒 + */ + public static void animRotate(View view, int ms){ + Animation animation = new RotateAnimation( + 0f, 360, + Animation.RELATIVE_TO_SELF, 0.5f, + Animation.RELATIVE_TO_SELF, 0.5f + ); + animation.setInterpolator(new LinearInterpolator()); + animation.setRepeatMode(Animation.RESTART); + animation.setDuration(ms); + animation.setRepeatCount(-1); + animation.setFillAfter(true); + view.clearAnimation(); + view.startAnimation(animation); + } + + /** + * 设置平移动画 + * @param view View + * @param ms 动画毫秒 + */ + public static void animTranslate(View view, float fromX, float toX, float fromY, float toY, int ms){ + Animation animation = new TranslateAnimation( + Animation.RELATIVE_TO_SELF, fromX, + Animation.RELATIVE_TO_SELF, toX, + Animation.RELATIVE_TO_SELF, fromY, + Animation.RELATIVE_TO_SELF, toY + ); + animation.setInterpolator(new LinearInterpolator()); + animation.setRepeatMode(Animation.RESTART); + animation.setDuration(ms); + animation.setRepeatCount(-1); + animation.setFillAfter(true); + view.clearAnimation(); + view.startAnimation(animation); + } + + /** + * 抖动动画 + * @param view View + * @param to 偏移量 + * @param cycles 次数 + * @param ms 动画毫秒 + */ + public static void animShake(View view, float to, int cycles, int ms) { + RotateAnimation rotateAnim = new RotateAnimation(0, to, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); + rotateAnim.setInterpolator(new CycleInterpolator(cycles)); + rotateAnim.setRepeatCount(-1); + rotateAnim.setDuration(ms); + view.clearAnimation(); + view.startAnimation(rotateAnim); + } + + /** + * 动画 + * @param view View + * @param ms 动画毫秒 + */ + public static void animScale(View view, int ms){ + AnimationSet animSet = new AnimationSet(false); + ScaleAnimation scale = new ScaleAnimation(0f, 1f, 0f, 1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); + RotateAnimation rotate = new RotateAnimation(0f, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); + AlphaAnimation alpha = new AlphaAnimation(0f, 1f); + animSet.addAnimation(scale); + animSet.addAnimation(rotate); + animSet.addAnimation(alpha); + animSet.setDuration(ms); + animSet.setFillAfter(true); + view.clearAnimation(); + view.startAnimation(animSet); + } + + /** + * 弹出Toast + * @param text 显示文本 + */ + public static void showToast(String text) { + Toast.makeText(AppData.getContext(), text, Toast.LENGTH_SHORT).show(); + } + + /** + * 模拟按键 + * @param keyCode keyCode + */ + public static void sendKeyCode(int keyCode) { + try { + String keyCommand = "input keyevent " + keyCode; + Runtime.getRuntime().exec(keyCommand); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 收起软键盘 + * @param context 上下文 + */ + public static void hideInput(Context context) { + try { + InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); + if (imm != null && imm.isActive()) { + imm.hideSoftInputFromWindow(((Activity) context).getWindow().getDecorView().getWindowToken(), 0); + } + } + catch (Exception e){ + e.printStackTrace(); + } + } + + /** + * 格式化数字 + * @param num 数字 + * @return w + */ + public static String ParseNum(int num) { + try { + int setScale = 0; + float setNum = num; + String setExt = ""; + if (setNum > 10000) { + setScale = 2; + setNum = setNum / 10000; + setExt = "w"; + } + if (setScale > 0) { + BigDecimal bigDecimal = new BigDecimal(setNum); + return bigDecimal.setScale(setScale, BigDecimal.ROUND_HALF_UP).doubleValue() + setExt; + } else { + return String.valueOf(num); + } + }catch (Exception e){ + return String.valueOf(num); + } + } + + /** + * 加载网络图片并缓存 + * @param img ImageView + * @param url 图片地址 + */ + public static void setHttpImage(final ImageView img, final String url) { + setHttpImage(img, url, -1); + } + + /** + * 加载网络图片并缓存 + * @param img ImageView + * @param url 图片地址 + * @param resId // 默认图片 + */ + public static void setHttpImage(final ImageView img, final String url, final int resId) { + final File cacheFile = Cache.getCacheFile(url); + if (Cache.showImage(img, cacheFile)) return; + if (resId != -1) { + img.setImageResource(resId); + } + if (url.length() == 0) return; + new Thread(new Runnable(){ + @Override + public void run() { + try { + URL imgUrl = new URL(url); + HttpURLConnection http = (HttpURLConnection) imgUrl.openConnection(); + http.setDoInput(true); + http.connect(); + InputStream stream = http.getInputStream(); + final Bitmap bitmap = BitmapFactory.decodeStream(stream); + img.post(new Runnable() { + @Override + public void run() { + img.setImageBitmap(bitmap); + } + }); + Cache.fileWrite(cacheFile, bitmap); + stream.close(); + } catch (Exception e) { + //System.out.println("setHttpImage : " + url); + e.printStackTrace(); + } + } + }).start(); + } + +} diff --git a/app/src/main/java/cn/leaqi/drawerapp/Utils/Config.java b/app/src/main/java/cn/leaqi/drawerapp/Utils/Config.java new file mode 100644 index 0000000..7409e1e --- /dev/null +++ b/app/src/main/java/cn/leaqi/drawerapp/Utils/Config.java @@ -0,0 +1,260 @@ +package cn.leaqi.drawerapp.Utils; + +import android.util.SparseArray; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +public class Config { + + // 用户数据 + public static SparseArray UserList = new SparseArray(){{ + put(1, new UserBean(1, "微笑,向前行", "https://p.ssl.qhimg.com/t01f5b748f60e62c1b4.jpg" ,"https://p3.ssl.qhimgs1.com/dr/578_864_/t01e752a6a89da01e13.jpg" ,"湖北武汉大学" ,18 , 1,"要开学了,又有新生要来军训了,该准备西瓜了…")); + put(2, new UserBean(2, "奔雷拳", "https://p.ssl.qhimg.com/t01c1c5570e3dbb0425.jpg" ,"https://p0.ssl.qhimgs1.com/dr/578_384_/t01be93565b295f6f2a.jpg" ,"湖北武汉" ,20 , 1,"眼睛别乱看,看我就行,这么帅的大帅哥站在你们面前都不知道看,一帮子傻孩子!")); + put(3, new UserBean(3, "努力奔向目标", "https://p.ssl.qhimg.com/t01447ac7de787f8fba.jpg" ,"https://p3.ssl.qhimgs1.com/dr/578_384_/t0118d9c58168abac5d.jpg" ,"内蒙呼和浩特" , 2,30 ,"小心点啊同学们,我这个人轻易不出手,出手必伤人,伤人必见血,见血必死人!")); + put(4, new UserBean(4, "未来丶为我们而来", "https://p.ssl.qhimg.com/t01f3e5713b8d1df758.jpg" ,"https://p1.ssl.qhimgs1.com/dr/578_384_/t014581243af77e697b.jpg" ,"山西太原" , 2,36 ,"求晴天,求高温,求四十度求,暴晒求,没风,我们苦点没关系;一定要让高一的学弟学妹们,有个良好的军训环境。")); + put(5, new UserBean(5, "剑舞天涯", "https://p.ssl.qhimg.com/t010a3c59594ee46c1c.jpg" ,"https://p1.ssl.qhimgs1.com/dr/578_432_/t014353b3af6d1a9f87.jpg" ,"山西朔州" ,41 , 2,"站军姿时,某教官看到其他方阵有人晕倒,于是转过身对他方阵的人说:我们这儿的人不许倒下啊!倒下了我就当没看到,踩着他过去……众人无语。")); + put(6, new UserBean(6, "少女总统", "https://p.ssl.qhimg.com/t01c99f6e988f439ff2.jpg" ,"https://p5.ssl.qhimgs1.com/dr/578_670_/t01b223399f42c6b305.jpg" ,"广东深圳" ,22 , 2,"又有一大批“包青天”准备进入中学的大门。")); + put(7, new UserBean(7, "遇见就不再错过", "https://p.ssl.qhimg.com/t01b078a864fbdd6676.jpg" ,"https://p2.ssl.qhimgs1.com/dr/578_384_/t01115afe13160b8d28.jpg" ,"广东广州" ,23 , 2,"You have no idea how I’m feeling so shut up.")); + put(8, new UserBean(8, "女人你给力吗", "https://p.ssl.qhimg.com/t015198455bf5f8b610.jpg" ,"https://p0.ssl.qhimgs1.com/dr/578_432_/t011e61455d215da766.jpg" ,"福建厦门" ,35 , 2,"你以为放手可以成全我的幸福,可你不知道我最大的幸福就是和你手牵手。")); + put(9, new UserBean(9, "一生都得酷", "https://p.ssl.qhimg.com/t01227f53f9ed7daea7.jpg" ,"https://p1.ssl.qhimgs1.com/dr/578_386_/t015189a3a4f35210fb.jpg" ,"福建福州" ,32 , 2,"青春如同奔流的江河,一点一滴的流淌着。")); + put(10, new UserBean(10, "我绝版了i", "https://p.ssl.qhimg.com/t01b9f72e02098beb90.jpg" ,"https://p2.ssl.qhimgs1.com/dr/578_774_/t015822699eef49a5cc.jpg" ,"北京朝阳" ,18 , 2,"个女人都是被种种牵绊舒服在滚滚红尘里,以哀伤的心,慢慢独到年华老去,终此一生。")); + put(11, new UserBean(11, "拿稳我心你称王", "https://p.ssl.qhimg.com/t01aca9887854891929.jpg" ,"https://p3.ssl.qhimgs1.com/dr/578_382_/t01f5e0987e89922aa9.jpg" ,"湖北襄阳" ,19 , 2,"I didn't stop loving you.I just decided not to show my love.")); + put(12, new UserBean(12, "仗剑倚青天つ", "https://p.ssl.qhimg.com/t01fd7fe000944649c6.jpg" ,"https://p5.ssl.qhimgs1.com/dr/578_386_/t01b4f15741b4b7aa15.jpg" ,"湖北天门" ,22 , 2,"这个社会什么都可以是假的,但是,我唯一不能容忍的就是:钱的假的。")); + put(13, new UserBean(13, "一生酷到底━═", "https://p.ssl.qhimg.com/t01942c71ff242289d9.jpg" ,"https://p5.ssl.qhimgs1.com/dr/578_578_/t016177097bcba1bcd5.jpg" ,"湖北宜昌" ,23 , 1,"心总是在最痛时,复苏;爱总是在最深时,落下帷幕。")); + put(14, new UserBean(14, "宇宙第一帅胚", "https://p.ssl.qhimg.com/t01a797c1e165ea9f14.jpg" ,"https://p5.ssl.qhimgs1.com/dr/578_384_/t0169791ab581437fef.jpg" ,"湖南长沙" ,24 , 1,"挤公交是包含散打、瑜珈、柔道、平衡木等多种体育和健身项目于一体的综合性运动。")); + put(15, new UserBean(15, "帅飞一条街", "https://p.ssl.qhimg.com/t01ecc074986ad1a0ba.jpg" ,"https://p1.ssl.qhimgs1.com/dr/578_432_/t017cfb90896b2f775b.jpg" ,"湖南岳阳" ,26 , 1,"原来,很多时候,最让人疼痛的,是孤独。")); + put(16, new UserBean(16, "战神灵魂", "https://p.ssl.qhimg.com/t01a2f82c9aa97a63f4.jpg" ,"https://p0.ssl.qhimgs1.com/dr/578_384_/t01dedde1abb87fe64a.jpg" ,"武汉轻工大学" ,28 , 0,"女生应该骄傲的活着,而不是卑微的恋爱。")); + put(17, new UserBean(17, "从头酷到脚", "https://p.ssl.qhimg.com/t017d10751189aca021.jpg" ,"https://p3.ssl.qhimgs1.com/dr/578_384_/t01fb0e60ff70513e0d.jpg" ,"湖北工业大学" ,21 , 2,"I'll smile before all people look at you, performance.")); + put(18, new UserBean(18, "傲视之巅", "https://p.ssl.qhimg.com/t0112a220bdb5fc5292.jpg" ,"https://p0.ssl.qhimgs1.com/dr/578_384_/t01d0160895cfa7e296.jpg" ,"湖北经济学院" ,31 , 0,"回忆千丝万缕,思念缱倦流年,昨日种种,红叶黄花,一恍如烟霞。")); + put(19, new UserBean(19, "馭電追風雨", "https://p.ssl.qhimg.com/t0197152db76690b5a9.jpg" ,"https://p3.ssl.qhimgs1.com/dr/578_384_/t014749d906dcd5fad3.jpg" ,"上海交通大学" ,32 , 2,"喝白开水的人,不一定很纯。")); + put(20, new UserBean(20, "酷到失控", "https://p.ssl.qhimg.com/t01f1c6faf2bebc07d2.jpg" ,"https://p0.ssl.qhimgs1.com/dr/578_384_/t018a8aab5a54da7fb4.jpg" ,"中国科学技术大学" ,55 , 0,"感情是没有公式,没有原则没有道理可循的,可是人们至死都还在执著与追求。")); + put(21, new UserBean(21, "┌;饕餮噬天", "https://p.ssl.qhimg.com/t01020f0617455b8995.jpg" ,"https://p3.ssl.qhimgs1.com/dr/578_384_/t01a617f89cbc438eb9.jpg" ,"哈尔滨工业大学" ,54 , 1,"Love makes you hold on to things you wouldn’t have been able to.")); + put(22, new UserBean(22, "一秒メ速杀", "https://p.ssl.qhimg.com/t012d3983a0169afa90.jpg" ,"https://p0.ssl.qhimgs1.com/dr/578_868_/t0185dead6ea9dfd14e.jpg" ,"北京航空航天大学" ,46 , 0,"擦干眼泪,抬起头,莪依然拥有最坚强的笑容。")); + put(23, new UserBean(23, "哥丶曾用C车称霸", "https://p.ssl.qhimg.com/t019928cb519504a8c5.jpg" ,"https://p5.ssl.qhimgs1.com/dr/578_864_/t01a881b34f659f4315.jpg" ,"河南信阳" ,37 , 2,"夏天就是不好,穷的时候我连西北风都没有喝。")); + put(24, new UserBean(24, "去爱去疯去执着", "https://p.ssl.qhimg.com/t01a3225285cda30314.jpg" ,"https://p5.ssl.qhimgs1.com/dr/578_432_/t018c9d28095cb10e85.jpg" ,"河南漯河" ,45 , 0,"所有的失敗,與失去自己的失敗比起來,更是微不足道。")); + put(25, new UserBean(25, "酒神", "https://p.ssl.qhimg.com/t01666b511f61006aa2.jpg" ,"https://p0.ssl.qhimgs1.com/dr/578_770_/t016b28f08d3007d974.jpg" ,"广西桂林" ,66 , 0,"她的忧伤,只为一些在颓废中荒废的年华。")); + put(26, new UserBean(26, "哥↖超神了", "https://p.ssl.qhimg.com/t0168cd944ae26436ed.jpg" ,"https://p5.ssl.qhimgs1.com/dr/578_384_/t01d5c1d61d72247ff5.jpg" ,"广西阳朔" ,43 , 0,"有些人永远不会被遗忘,有些人永远只是代替品。")); + put(27, new UserBean(27, "嗜血飞龙", "https://p.ssl.qhimg.com/t01be3b242d22d34c6e.jpg" ,"https://p2.ssl.qhimgs1.com/dr/578_384_/t0180dbeb7b2d466dec.jpg" ,"贵州贵阳" ,22 , 2,"爱情也许会随着季节的变迁而褪去,但友谊会为你全年守侯。")); + put(28, new UserBean(28, "霹雳无敌", "https://p.ssl.qhimg.com/t010e57ddd763c3e814.jpg" ,"https://p1.ssl.qhimgs1.com/dr/578_374_/t0180efa16d4d1cba57.jpg" ,"四川成都" ,28 , 0,"感情是没有公式,没有原则没有道理可循的,可是人们至死都还在执著与追求。")); + put(29, new UserBean(29, "独撑全场", "https://p.ssl.qhimg.com/t016b0e3d5920ce25f1.jpg" ,"https://p0.ssl.qhimgs1.com/dr/578_384_/t011b5790b23c936276.jpg" ,"浙江杭州" ,33 , 2,"怎样的一个冬天,我看见烟火幸福满天。又怎样的一个冬天,冷得让我泪流满面。")); + put(30, new UserBean(30, "不朽神王", "https://p.ssl.qhimg.com/t017081c67288d79538.jpg" ,"https://p2.ssl.qhimgs1.com/dr/578_384_/t01e552cd0ad2e87e52.jpg" ,"安徽合肥" ,26 , 0,"我这人不懂音乐,所以时而不靠谱,时而不着调。")); + }}; + + // 视频数据 + public static SparseArray VideoList = new SparseArray(){{ + put(1, new VideoBean(1, "https://p26.douyinpic.com/tos-cn-p-0015/52a44cd0f20f4e47a02fc024b352abd0_1622205519~tplv-dy-360p.jpeg", "超级鸡马体验超高难度地狱模式,大黄崩溃了", "https://aweme.snssdk.com/aweme/v1/play/?video_id=v0300fg10000c2oe863c77u6arm00r8g&ratio=720p&line=0")); + put(2, new VideoBean(2, "https://p3.douyinpic.com/tos-cn-p-0015/f21cca9009db49fa8673231708170553_1622116507~tplv-dy-360p.jpeg", "超级鸡马基友互坑时刻,失去信心的大黄", "https://aweme.snssdk.com/aweme/v1/play/?video_id=v0200fg10000c2noh33c77u7rldvc80g&ratio=720p&line=0")); + put(3, new VideoBean(3, "https://p3.douyinpic.com/tos-cn-p-0015/c0cb9f67fb7943a597324859f3c6a247_1622992747~tplv-dy-360p.jpeg", "迷你世界无限套娃合西瓜,伙伴捣乱抢生意,那我走?", "https://aweme.snssdk.com/aweme/v1/play/?video_id=v0300fg10000c2ueejbc77u55imc2kh0&ratio=720p&line=0")); + put(4, new VideoBean(4, "https://p9.douyinpic.com/tos-cn-p-0015/d35df6920e304e1d89bc2da2a8542a63_1622992741~tplv-dy-360p.jpeg", "荒野求生出发雪山城堡,媳妇公主现身,名副其实三剑客", "https://aweme.snssdk.com/aweme/v1/play/?video_id=v0300fg10000c2ueefjc77u7pgi7d2l0&ratio=720p&line=0")); + put(5, new VideoBean(5, "https://p26.douyinpic.com/tos-cn-p-0015/8b44de38f0af413cad0309407d9bbb5a_1622910908~tplv-dy-360p.jpeg", "只只大冒险勇闯冰雪天敌,让我们荡起双桨,多米差点被红烧", "https://aweme.snssdk.com/aweme/v1/play/?video_id=v0300fg10000c2tqfcbc77u7pghl11f0&ratio=720p&line=0")); + put(6, new VideoBean(6, "https://p3.douyinpic.com/tos-cn-p-0015/d8b27728ee7c4307a0da0e5375cb6847_1622802859~tplv-dy-360p.jpeg", "迷你世界生存到极致就像开挂狼堡大升级!火柴盒秒变大别墅", "https://aweme.snssdk.com/aweme/v1/play/?video_id=v0300fg10000c2t037bc77u99amfcrcg&ratio=720p&line=0")); + put(7, new VideoBean(7, "https://p9.douyinpic.com/tos-cn-p-0015/f5ffbfac5855435db282a48c21ad86ef_1622802766~tplv-dy-360p.jpeg", "迷你世界流沙来了快建房,建造基岩房,善心大发搭救伙伴?", "https://aweme.snssdk.com/aweme/v1/play/?video_id=v0200fg10000c2t02frc77ue9k8it51g&ratio=720p&line=0")); + put(8, new VideoBean(8, "https://p26.douyinpic.com/tos-cn-p-0015/bc3b441d79634ed2be97bee37cccf0c5_1622740457~tplv-dy-360p.jpeg", "方舟生存进化神奇宝贝61水晶洞穴对抗死亡蠕虫,寻获团结神器", "https://aweme.snssdk.com/aweme/v1/play/?video_id=v0300fg10000c2sgro3c77u6ark8buf0&ratio=720p&line=0")); + put(9, new VideoBean(9, "https://p11.douyinpic.com/tos-cn-p-0015/b4af2f96eba441cda73390c395c11a9e_1610528747~tplv-dy-360p.jpeg", "2021年值得入住的民宿,有生之年一定要去“睡”一次!", "https://aweme.snssdk.com/aweme/v1/play/?video_id=v0300fbd0000bvvbf74f27p33ot7scog&ratio=720p&line=0")); + put(10, new VideoBean(10, "https://p26.douyinpic.com/tos-cn-p-0015/5c135e0e11b24fb0a68753f3d687dea9_1597227392~tplv-dy-360p.jpeg", "国内最美的热气球景点,你们去过吗?", "https://aweme.snssdk.com/aweme/v1/play/?video_id=v0200ffa0000bsps2f19dds8ickgdepg&ratio=720p&line=0")); + put(11, new VideoBean(11, "https://p26.douyinpic.com/tos-cn-p-0015/c21f7fd21d64487da8aa42dce6a03a7f_1597137139~tplv-dy-360p.jpeg", "每个月最适合旅行你过的地方?你真的去对啦吗!", "https://aweme.snssdk.com/aweme/v1/play/?video_id=v0200f710000bsp60uhultt2lbn69dm0&ratio=720p&line=0")); + put(12, new VideoBean(12, "https://p3.douyinpic.com/tos-cn-p-0015/321d3fe11da14debaa027f06be10c23c_1596453366~tplv-dy-360p.jpeg", "没有去过香格里拉,怎知世界的纯净,云南最值得打卡的地方!", "https://aweme.snssdk.com/aweme/v1/play/?video_id=v0200f540000bsjv3pn66jan1d2adivg&ratio=720p&line=0")); + put(13, new VideoBean(13, "https://p11.douyinpic.com/tos-cn-p-0015/422abdf7c362450c8f7c9cb1e960d296_1602583642~tplv-dy-360p.jpeg", "西双版纳4天3晚游才人均不到一千?这份攻略你可要收好了!", "https://aweme.snssdk.com/aweme/v1/play/?video_id=v0300f050000bu2nku3ircaev3kmjkbg&ratio=720p&line=0")); + put(14, new VideoBean(14, "https://p5-ipv6.douyinpic.com/tos-cn-p-0015/be19f7ffbb484918bc887eeabc998884_1610510314~tplv-dy-360p.jpeg", "有种冰雪童话,叫冬天的哈尔滨!", "https://aweme.snssdk.com/aweme/v1/play/?video_id=v0300fe90000bvv6pvnbjpufrvum2u00&ratio=720p&line=0")); + put(15, new VideoBean(15, "https://p5-ipv6.douyinpic.com/tos-cn-p-0015/1a99e8fd03bc460caf84aa907114fb1b_1621522703~tplv-dy-360p.jpeg", "iPad Pro 2021款12.9英寸黑白颜色对比。", "https://aweme.snssdk.com/aweme/v1/play/?video_id=v0300fg10000c2j7h4l0296d5d3stmeg&ratio=720p&line=0")); + put(16, new VideoBean(16, "https://p3.douyinpic.com/tos-cn-p-0015/1ef8c86241794397bab1dc2636829f28_1610682052~tplv-dy-360p.jpeg", "想要主动降噪与好音质,2021年适合iPhone的真无线蓝牙耳机怎么选?", "https://aweme.snssdk.com/aweme/v1/play/?video_id=v0300f620000c00grqvh77phu82ph2vg&ratio=720p&line=0")); + put(17, new VideoBean(17, "https://p9.douyinpic.com/tos-cn-p-0015/6947ee2833d64c759781347bb9493b51_1621682660~tplv-dy-360p.jpeg", "首个进入太空的生物,为什么要选择一只流浪狗呢?", "https://aweme.snssdk.com/aweme/v1/play/?video_id=v0d00fg10000c2kejkjfgt7pa5plj1v0&ratio=720p&line=0")); + put(18, new VideoBean(18, "https://p29.douyinpic.com/tos-cn-p-0015/b9f343aca10d42a3b3f2812d844975e6_1621508159~tplv-dy-360p.jpeg", "同样是鲤鱼,为什么黄河鲤鱼更贵呢?", "https://aweme.snssdk.com/aweme/v1/play/?video_id=v0d00fg10000c2j40anc4lr2q92q4khg&ratio=720p&line=0")); + put(19, new VideoBean(19, "https://p9.douyinpic.com/tos-cn-p-0015/88478c2b62ef4a9698646c1498db03ce_1621338097~tplv-dy-360p.jpeg", "肉被切开后,为什么表面会跳动呢?", "https://aweme.snssdk.com/aweme/v1/play/?video_id=v0300fg10000c2hqfo56j906d0kh5mtg&ratio=720p&line=0")); + put(20, new VideoBean(20, "https://p3.douyinpic.com/tos-cn-p-0015/282e28eca8764b1ca63f2d047d83c0bf_1620819728~tplv-dy-360p.jpeg", "为什么椰子里面会有水呢?", "https://aweme.snssdk.com/aweme/v1/play/?video_id=v0d00fg10000c2drtt8gk4jgd7f6iv70&ratio=720p&line=0")); + put(21, new VideoBean(21, "https://p3.douyinpic.com/tos-cn-p-0015/a3b08e5aafba4fb68dec2787c3106d66_1620644241~tplv-dy-360p.jpeg", "为什么工人要往水泥里加白糖呢?", "https://aweme.snssdk.com/aweme/v1/play/?video_id=v0300fg10000c2ch2offq9lkha32kbhg&ratio=720p&line=0")); + put(22, new VideoBean(22, "https://p3.douyinpic.com/tos-cn-p-0015/27c47da4df52490c8cb7a88e87e3c1a1_1621074960~tplv-dy-360p.jpeg", "科学家为什么不敢把火星土壤带回地球呢?", "https://aweme.snssdk.com/aweme/v1/play/?video_id=v0300fg10000c2fq7akpeg7h5b65tt7g&ratio=720p&line=0")); + put(23, new VideoBean(23, "https://p9.douyinpic.com/tos-cn-p-0015/d0fa69ee574a484890c21a9319d17945_1621335837~tplv-dy-360p.jpeg", "有气囊的鼻托你见过吗?", "https://aweme.snssdk.com/aweme/v1/play/?video_id=v0d00fg10000c2hpt2pd3u0ebthcfs00&ratio=720p&line=0")); + put(24, new VideoBean(24, "https://p3.douyinpic.com/tos-cn-p-0015/feb6883763e14f70a0c1fd72db8bb0a1_1578713534~tplv-dy-360p.jpeg", "我做的红酒雪梨,每次上桌不到1分钟就被抢光,思虑再三,决定把方法发出来,希望学会的能给我个❤️", "https://aweme.snssdk.com/aweme/v1/play/?video_id=v0200f3b0000bock3dfff77e7cs0sg20&ratio=720p&line=0")); + put(25, new VideoBean(25, "https://p9.douyinpic.com/tos-cn-p-0015/ebe5f77db8ec4be2a543d0a4930940cc_1619255418~tplv-dy-360p.jpeg", "的新吃法!真的太好吃了!全麦欧包更适合做主食哦!", "https://aweme.snssdk.com/aweme/v1/play/?video_id=v0d00fg10000c21u0m6e1f8bno2t4g0g&ratio=720p&line=0")); + put(26, new VideoBean(26, "https://p26.douyinpic.com/tos-cn-p-0015/4194debff77a46809f820df7aa576945_1618909651~tplv-dy-360p.jpeg", "月旨期放心吃,吃肉肉掉肉肉", "https://aweme.snssdk.com/aweme/v1/play/?video_id=v0300fg10000c1v9jih8v0llc8ll1nl0&ratio=720p&line=0")); + put(27, new VideoBean(27, "https://p5-ipv6.douyinpic.com/tos-cn-p-0015/5af33941f597475e9384484699b5384c_1618734474~tplv-dy-360p.jpeg", "用茶代替水做出来的红烧肉,肥而不腻,隔壁老王都说好吃!", "https://aweme.snssdk.com/aweme/v1/play/?video_id=v0300fg10000c1tuqn7764jl2usnm9vg&ratio=720p&line=0")); + put(28, new VideoBean(28, "https://p5-ipv6.douyinpic.com/29b0a000063e8b0c4b4b5~tplv-dy-360p.jpeg", "塞尔达传说来到王城遗址,塞尔达公主为我举行授勋仪式", "https://aweme.snssdk.com/aweme/v1/play/?video_id=v0300f2a0000bkg294tj482rnh8bi410&ratio=720p&line=0")); + put(29, new VideoBean(29, "https://p26.douyinpic.com/29428000b866180a60e1c~tplv-dy-360p.jpeg", "塞尔达传说用火把点燃哈特诺之塔,我得到了四大部落的位置", "https://aweme.snssdk.com/aweme/v1/play/?video_id=v0300f880000bke1osdmuq8m6dopcfg0&ratio=720p&line=0")); + put(30, new VideoBean(30, "https://p3.douyinpic.com/27451000a879e0cd3b3d3~tplv-dy-360p.jpeg", "翼龙历险记打败会喷火的龙皇后,5只小翼龙宝宝出生了", "https://aweme.snssdk.com/aweme/v1/play/?video_id=v0300fb70000bk1gdqmt2ulrrokagfg0&ratio=720p&line=0")); + }}; + + // 音乐数据 + public static SparseArray MusicList = new SparseArray(){{ + put(1, new MusicBean(1,"https://p26.douyinpic.com/aweme/200x200/tos-cn-v-2774c002/258d5c278eb0418ea2ea362c21403e27.jpeg", "孤勇者 - 陈奕迅")); + put(2, new MusicBean(2,"https://p26.douyinpic.com/aweme/200x200/tos-cn-v-2774c002/78085574025c4d3cb66009647c379492.jpeg", "Shadow of the Sun - Max Elto")); + put(3, new MusicBean(3,"https://p6.douyinpic.com/aweme/200x200/tos-cn-v-2774c002/756143d75cb04a6e8d280538d9fcbe73.jpeg", "守护着我的光 - 李巍V仔")); + put(4, new MusicBean(4,"https://p9.douyinpic.com/aweme/200x200/tos-cn-v-2774c002/b7528a0aa0164f2aadfe332b2e54ca76.jpeg", "WAVE(Prod by 张杰峻) - 花欲燃")); + put(5, new MusicBean(5,"https://p26.douyinpic.com/aweme/200x200/tos-cn-v-2774c002/5614d4be2fe5475faebad7865050df83.jpeg", "陪你度过漫长岁月 - 张钰琪")); + put(6, new MusicBean(6,"https://p11.douyinpic.com/aweme/200x200/tos-cn-v-2774c002/cbac750dc48b4e8e8f9a88ce8813e49e.jpeg", "哪里都是你(DJR7版) - DJR7")); + put(7, new MusicBean(7,"https://p6.douyinpic.com/aweme/200x200/tos-cn-v-2774c002/6267a87bdc7044949f59eeb624600606.jpeg", "It's a Beautiful Day - Evan McHugh")); + put(8, new MusicBean(8,"https://p9.douyinpic.com/aweme/200x200/tos-cn-v-2774c002/d67d7f6ff98644b58718a6757147b4af.jpeg", "人世间(电视剧《人世间》主题曲) - 雷佳")); + put(9, new MusicBean(9,"https://p6.douyinpic.com/aweme/200x200/tos-cn-v-2774c002/08d50473149248ec9d29419e88fe9fc0.jpeg", "爱丫爱丫 - By2")); + put(10, new MusicBean(10,"https://p26.douyinpic.com/aweme/200x200/tos-cn-v-2774c002/2757047296424a679cca6c017ec1eba0.jpeg", "在草地上肆意奔跑(片段) - 傅如乔")); + put(11, new MusicBean(11,"https://p26.douyinpic.com/aweme/200x200/tos-cn-v-2774c002/23960b32a6b149e3b336b4ecd433246f.jpeg", "落在生命里的光 - 尹昔眠")); + put(12, new MusicBean(12,"https://p6.douyinpic.com/aweme/200x200/tos-cn-v-2774c002/869bd0664feb47e8aa256d090a06d8b6.jpeg", "渐暖片段1 - 时代少年团")); + put(13, new MusicBean(13,"https://p26.douyinpic.com/aweme/200x200/tos-cn-v-2774c002/c44420cfb0d64f6b9516a0b9c41bd49a.jpeg", "行于水 (剪辑版) - 万妮达Vinida Weng")); + put(14, new MusicBean(14,"https://p3.douyinpic.com/aweme/200x200/tos-cn-v-2774c002/70d2e6e3921b42f68265dcd02ecc0b3d.jpeg", "裹着心的光 30s - 林俊杰")); + put(15, new MusicBean(15,"https://p9.douyinpic.com/aweme/200x200/tos-cn-v-2774c002/3d3cb370ddb24e95b54ab9bd58c40872.jpeg", "Something Just Like This - Bely Basarte")); + put(16, new MusicBean(16,"https://p3.douyinpic.com/aweme/200x200/tos-cn-v-2774c002/984c581341be494ab12e9195d8b9dd60.jpeg", "张碧晨《光的方向》(剪辑版) - 张碧晨")); + put(17, new MusicBean(17,"https://p11.douyinpic.com/aweme/200x200/tos-cn-v-2774c002/77790e0f66f64fb88934bf022f34c1dc.jpeg", "致00后的预防针 - 王以诺")); + put(18, new MusicBean(18,"https://p3.douyinpic.com/aweme/200x200/tos-cn-v-2774c002/7677e49b6a734b3bb2db8cc357351f5c.jpeg", "雪龙吟(剪辑版) - 张杰")); + put(19, new MusicBean(19,"https://p3.douyinpic.com/aweme/200x200/tos-cn-v-2774c002/b4c665dbf7234ebfa59e1cec6a5d9dbc.jpeg", "我们的爱 - 曹雨航")); + put(20, new MusicBean(20,"https://p9.douyinpic.com/aweme/200x200/tos-cn-v-2774c002/c8db6cd7a66b402f854bb547b757def0.jpeg", "老茧-剪辑版 - 简弘亦")); + put(21, new MusicBean(21,"https://p6.douyinpic.com/aweme/200x200/tos-cn-v-2774c002/cf8b3f3801924f049da1db34286572aa.jpeg", "Beautiful - INTO1-米卡")); + put(22, new MusicBean(22,"https://p3.douyinpic.com/aweme/200x200/tos-cn-v-2774c002/1cc8823cd51e4ee4b06b5ec65616afeb.jpeg", "天若有情 ((电视剧「锦绣未央」主题曲) - A-Lin")); + put(23, new MusicBean(23,"https://p3.douyinpic.com/aweme/200x200/tos-cn-v-2774c002/cd7d189e43cb4c59ac081a60571220ec.jpeg", "DO WHATEVER想做就做(剪辑版) - 卡西恩Cacien")); + put(24, new MusicBean(24,"https://p26.douyinpic.com/aweme/200x200/tos-cn-v-2774c002/62756bbdce8d46c9be06cac90813425e.jpeg", "平凡的一天 - 毛不易")); + put(25, new MusicBean(25,"https://p9.douyinpic.com/aweme/200x200/tos-cn-v-2774c002/cd0510692553442b80ca8006d6f326cd.jpeg", "我们啊(男版)片段2 - 三块木头")); + put(26, new MusicBean(26,"https://p26.douyinpic.com/aweme/200x200/tos-cn-v-2774c002/02011d6377e64bfcb35820795c6560cf.jpeg", "剑魂_鱼多余完整版已上线 - 鱼多余")); + put(27, new MusicBean(27,"https://p3.douyinpic.com/aweme/200x200/tos-cn-v-2774c002/c5dfad8371c54cd69986c9dc7a4bb325.jpeg", "最好的都给你(剪辑版) - 余佳运")); + put(28, new MusicBean(28,"https://p11.douyinpic.com/aweme/200x200/tos-cn-v-2774c002/1f5f7b1b48f0427fab2d28cfe9e3c009.jpeg", "微风吹(剪辑版) - 李润祺")); + put(29, new MusicBean(29,"https://p3.douyinpic.com/aweme/200x200/tos-cn-v-2774c002/5064ec1dc0d845419fea14ce792bed70.jpeg", "Celebrity - IU")); + put(30, new MusicBean(30,"https://p3.douyinpic.com/aweme/200x200/tos-cn-v-2774c002/23960b32a6b149e3b336b4ecd433246f.jpeg", "落在生命里的光 - 尹昔眠")); + }}; + + // 评论数据 + public static SparseArray CommentList = new SparseArray(){{ + put(1, new CommentBean(1, UserList.get(1), "超级鸡马体验超高难度地狱模式,大黄崩溃了")); + put(2, new CommentBean(2, UserList.get(2), "超级鸡马基友互坑时刻,失去信心的大黄")); + put(3, new CommentBean(3, UserList.get(3), "迷你世界无限套娃合西瓜,伙伴捣乱抢生意,那我走?")); + put(4, new CommentBean(4, UserList.get(4), "荒野求生出发雪山城堡,媳妇公主现身,名副其实三剑客")); + put(5, new CommentBean(5, UserList.get(5), "只只大冒险勇闯冰雪天敌,让我们荡起双桨,多米差点被红烧")); + put(6, new CommentBean(6, UserList.get(6), "迷你世界生存到极致就像开挂狼堡大升级!火柴盒秒变大别墅")); + put(7, new CommentBean(7, UserList.get(7), "迷你世界流沙来了快建房,建造基岩房,善心大发搭救伙伴?")); + put(8, new CommentBean(8, UserList.get(8), "方舟生存进化神奇宝贝61水晶洞穴对抗死亡蠕虫,寻获团结神器")); + put(9, new CommentBean(9, UserList.get(9), "2021年值得入住的民宿,有生之年一定要去“睡”一次!")); + put(10, new CommentBean(10, UserList.get(10), "国内最美的热气球景点,你们去过吗?")); + put(11, new CommentBean(11, UserList.get(11), "每个月最适合旅行你过的地方?你真的去对啦吗!")); + put(12, new CommentBean(12, UserList.get(12), "没有去过香格里拉,怎知世界的纯净,云南最值得打卡的地方!")); + put(13, new CommentBean(13, UserList.get(13), "西双版纳4天3晚游才人均不到一千?这份攻略你可要收好了!")); + put(14, new CommentBean(14, UserList.get(14), "有种冰雪童话,叫冬天的哈尔滨!")); + put(15, new CommentBean(15, UserList.get(15), "iPad Pro 2021款12.9英寸黑白颜色对比。")); + put(16, new CommentBean(16, UserList.get(16), "想要主动降噪与好音质,2021年适合iPhone的真无线蓝牙耳机怎么选?")); + put(17, new CommentBean(17, UserList.get(17), "首个进入太空的生物,为什么要选择一只流浪狗呢?")); + put(18, new CommentBean(18, UserList.get(18), "同样是鲤鱼,为什么黄河鲤鱼更贵呢?")); + put(19, new CommentBean(19, UserList.get(19), "肉被切开后,为什么表面会跳动呢?")); + put(20, new CommentBean(20, UserList.get(20), "为什么椰子里面会有水呢?")); + put(21, new CommentBean(21, UserList.get(21), "为什么工人要往水泥里加白糖呢?")); + put(22, new CommentBean(22, UserList.get(22), "科学家为什么不敢把火星土壤带回地球呢?")); + put(23, new CommentBean(23, UserList.get(23), "有气囊的鼻托你见过吗?")); + put(24, new CommentBean(24, UserList.get(24), "我做的红酒雪梨,每次上桌不到1分钟就被抢光,思虑再三,决定把方法发出来,希望学会的能给我个❤️")); + put(25, new CommentBean(25, UserList.get(25), "的新吃法!真的太好吃了!全麦欧包更适合做主食哦!")); + put(26, new CommentBean(26, UserList.get(26), "月旨期放心吃,吃肉肉掉肉肉")); + put(27, new CommentBean(27, UserList.get(27), "用茶代替水做出来的红烧肉,肥而不腻,隔壁老王都说好吃!")); + put(28, new CommentBean(28, UserList.get(28), "塞尔达传说来到王城遗址,塞尔达公主为我举行授勋仪式")); + put(29, new CommentBean(29, UserList.get(29), "塞尔达传说用火把点燃哈特诺之塔,我得到了四大部落的位置")); + put(30, new CommentBean(30, UserList.get(30), "翼龙历险记打败会喷火的龙皇后,5只小翼龙宝宝出生了")); + }}; + + // 随机用户视频 + public static SparseArray> UserVideo = new SparseArray>(){{ + Random rand = new Random(); + for(int i = 0; i < UserList.size(); i++) { + int key = UserList.keyAt(i); + List list = new ArrayList<>(); + int getI = rand.nextInt(10); + int getS = rand.nextInt(20) + 10; + for(int o = getI; o < getS; o++) { + list.add(VideoList.get(VideoList.keyAt(o))); + } + put(key, list); + } + }}; + + public static class UserBean { + public int id; + public String name; + public String icon; + public String bg; + public String city; + public int age; + public int sex; + public String text; + public int praise; + public int follow; + public int fans; + public boolean isFollow = false; + UserBean(int id, String name, String icon, String bg, String city, int age, int sex, String text) { + Random rand = new Random(); + this.id = id; + this.name = name; + this.icon = icon; + this.bg = bg; + this.city = city; + this.age = age; + this.sex = sex; + this.text = text; + praise = rand.nextInt(100000); + follow = rand.nextInt(100000); + fans = rand.nextInt(100000); + } + public String getPraise() { + return Common.ParseNum(praise); + } + public String getFollow() { + return Common.ParseNum(follow); + } + public String getFans() { + return Common.ParseNum(fans); + } + } + + public static class VideoBean { + public int id; + public String img; + public String text; + public String src; + public int favCount; + public int sayCount; + public int shareCount; + public boolean isFav = false; + VideoBean(int id, String img, String text, String src) { + Random rand = new Random(); + this.id = id; + this.img = img; + this.text = text; + this.src = src; + favCount = rand.nextInt(100000); + sayCount = rand.nextInt(100000); + shareCount = rand.nextInt(100000); + } + public String getFavCount() { + return Common.ParseNum(favCount); + } + public String getSayCount() { + return Common.ParseNum(sayCount); + } + public String getShareCount() { + return Common.ParseNum(shareCount); + } + } + + public static class MusicBean { + public int id; + public String icon; + public String text; + MusicBean(int id, String icon, String text) { + this.id = id; + this.icon = icon; + this.text = text; + } + } + + public static class CommentBean { + public int id; + public UserBean user; + public String text; + public String time; + public int favCount; + CommentBean(int id, UserBean user, String text) { + Random rand = new Random(); + this.id = id; + this.user = user; + this.text = text; + this.time = (rand.nextInt(59) + 1) + (rand.nextInt(2) == 0 ? "小时" : "分钟") + "前"; + favCount = rand.nextInt(100000); + } + public String getFavCount() { + return Common.ParseNum(favCount); + } + } + +} diff --git a/app/src/main/java/cn/leaqi/drawerapp/Views/MarqueView.java b/app/src/main/java/cn/leaqi/drawerapp/Views/MarqueView.java new file mode 100644 index 0000000..57dbd47 --- /dev/null +++ b/app/src/main/java/cn/leaqi/drawerapp/Views/MarqueView.java @@ -0,0 +1,45 @@ +package cn.leaqi.drawerapp.Views; + +import android.content.Context; +import android.text.TextUtils; +import android.util.AttributeSet; + +import androidx.appcompat.widget.AppCompatTextView; + +/** + * TextView 文本滚动 + */ +public class MarqueView extends AppCompatTextView { + + private boolean isFocused = false; + + public MarqueView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + Init(); + } + + public MarqueView(Context context, AttributeSet attrs) { + super(context, attrs); + Init(); + } + + public MarqueView(Context context) { + super(context); + Init(); + } + + public void Init() { + setSingleLine(true); + setEllipsize(TextUtils.TruncateAt.MARQUEE); + } + + public void setFocused(boolean focused) { + isFocused = focused; + requestLayout(); + } + + @Override + public boolean isFocused() { + return isFocused; + } +} \ No newline at end of file diff --git a/app/src/main/java/cn/leaqi/drawerapp/Views/NewGridView.java b/app/src/main/java/cn/leaqi/drawerapp/Views/NewGridView.java new file mode 100644 index 0000000..1c98f2c --- /dev/null +++ b/app/src/main/java/cn/leaqi/drawerapp/Views/NewGridView.java @@ -0,0 +1,30 @@ +package cn.leaqi.drawerapp.Views; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.GridView; + +/** + * GridView 嵌套滚动 + */ +public class NewGridView extends GridView { + + public NewGridView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public NewGridView(Context context) { + super(context); + } + + public NewGridView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); + super.onMeasure(widthMeasureSpec, expandSpec); + } + +} \ No newline at end of file diff --git a/app/src/main/java/cn/leaqi/drawerapp/Views/RadiusImage.java b/app/src/main/java/cn/leaqi/drawerapp/Views/RadiusImage.java new file mode 100644 index 0000000..4030d5e --- /dev/null +++ b/app/src/main/java/cn/leaqi/drawerapp/Views/RadiusImage.java @@ -0,0 +1,126 @@ +package cn.leaqi.drawerapp.Views; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.RectF; +import android.util.AttributeSet; + +import androidx.appcompat.widget.AppCompatImageView; + +import cn.leaqi.drawerapp.R; + +/** + * ImageView 图片圆角 + */ +public class RadiusImage extends AppCompatImageView { + + private int leftTopRadius = 0; + private int rightTopRadius = 0; + private int rightBottomRadius = 0; + private int leftBottomRadius = 0; + + private Paint paint; + private Paint paint2; + + public RadiusImage(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + init(context, attrs); + } + + public RadiusImage(Context context, AttributeSet attrs) { + super(context, attrs); + init(context, attrs); + } + + public RadiusImage(Context context) { + super(context); + init(context, null); + } + + private void init(Context context, AttributeSet attrs) { + if (attrs != null) { + final TypedArray attrArr = context.obtainStyledAttributes(attrs, R.styleable.RadiusImage); + int allRadius = attrArr.getDimensionPixelSize(R.styleable.RadiusImage_radius, 0); + if(allRadius > 0){ + leftTopRadius = allRadius; + rightTopRadius = allRadius; + leftBottomRadius = allRadius; + rightBottomRadius = allRadius; + } + attrArr.recycle(); + } + + paint = new Paint(); + paint.setColor(Color.WHITE); + paint.setAntiAlias(true); + paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); + + paint2 = new Paint(); + paint2.setXfermode(null); + } + + @Override + public void draw(Canvas canvas) { + try { + Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888); + Canvas canvas2 = new Canvas(bitmap); + super.draw(canvas2); + if(leftTopRadius > 0)drawLeftTop(canvas2); + if(rightTopRadius > 0)drawRightTop(canvas2); + if(leftBottomRadius > 0)drawLeftBottom(canvas2); + if(rightBottomRadius > 0)drawRightBottom(canvas2); + canvas.drawBitmap(bitmap, 0, 0, paint2); + bitmap.recycle(); + } catch (IllegalArgumentException e){ + e.printStackTrace(); + } + } + + private void drawLeftTop(Canvas canvas) { + Path path = new Path(); + path.moveTo(0, leftTopRadius); + path.lineTo(0, 0); + path.lineTo(leftTopRadius, 0); + path.arcTo(new RectF(0, 0, leftTopRadius * 2, leftTopRadius * 2), -90, -90); + path.close(); + canvas.drawPath(path, paint); + } + + private void drawRightTop(Canvas canvas) { + Path path = new Path(); + path.moveTo(getWidth(), rightTopRadius); + path.lineTo(getWidth(), 0); + path.lineTo(getWidth() - rightTopRadius, 0); + path.arcTo(new RectF(getWidth() - rightTopRadius * 2, 0, getWidth(), rightTopRadius * 2), -90, 90); + path.close(); + canvas.drawPath(path, paint); + } + + private void drawLeftBottom(Canvas canvas) { + Path path = new Path(); + path.moveTo(0, getHeight() - leftBottomRadius); + path.lineTo(0, getHeight()); + path.lineTo(leftBottomRadius, getHeight()); + path.arcTo(new RectF(0, getHeight() - leftBottomRadius * 2, leftBottomRadius * 2, getHeight()), 90, 90); + path.close(); + canvas.drawPath(path, paint); + } + + private void drawRightBottom(Canvas canvas) { + Path path = new Path(); + path.moveTo(getWidth() - rightBottomRadius, getHeight()); + path.lineTo(getWidth(), getHeight()); + path.lineTo(getWidth(), getHeight() - rightBottomRadius); + path.arcTo(new RectF(getWidth() - rightBottomRadius * 2, getHeight() - rightBottomRadius * 2, getWidth(), getHeight()), -0, 90); + path.close(); + canvas.drawPath(path, paint); + } + +} \ No newline at end of file diff --git a/app/src/main/java/cn/leaqi/drawerapp/Views/TopBar.java b/app/src/main/java/cn/leaqi/drawerapp/Views/TopBar.java new file mode 100644 index 0000000..ddee7a3 --- /dev/null +++ b/app/src/main/java/cn/leaqi/drawerapp/Views/TopBar.java @@ -0,0 +1,225 @@ +package cn.leaqi.drawerapp.Views; + +import android.app.Activity; +import android.content.Context; +import android.graphics.Color; +import android.os.Build; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.TextView; + +import cn.leaqi.drawerapp.R; +import cn.leaqi.drawerapp.Utils.Common; + +/** + * 布局头部处理类 + */ +public class TopBar { + private Context mContext; + private Activity mActivity; + + private int statusHeight = 0; + private View topBar; + private View topStatus; + private View topHead; + private TextView topText; + private View topLeft; + private View topRight; + private View topLeftIcon; + private View topRightIcon; + private TextView topRightText; + + public interface OnTopClickListener{ + void onClick(View view); + } + + public TopBar(Context context) { + mContext = context; + mActivity = ((Activity)mContext); + topBar = mActivity.findViewById(R.id.top_bar); + topStatus = mActivity.findViewById(R.id.top_status); + topHead = mActivity.findViewById(R.id.top_head); + topText = mActivity.findViewById(R.id.top_text); + topLeft = mActivity.findViewById(R.id.top_left); + topRight = mActivity.findViewById(R.id.top_right); + topLeftIcon = mActivity.findViewById(R.id.top_left_icon); + topRightIcon = mActivity.findViewById(R.id.top_right_icon); + topRightText = mActivity.findViewById(R.id.top_right_text); + setStatusBar(true); + } + + public TopBar(Context context, boolean isStatus) { + mContext = context; + mActivity = ((Activity)mContext); + if (isStatus) { + topStatus = mActivity.findViewById(R.id.top_status); + } + setStatusBar(isStatus); + } + + private void setStatusBar(boolean isStatus){ + try { + Window window = mActivity.getWindow(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + setStatusTop(isStatus); + window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); + window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); + window.setStatusBarColor(Color.TRANSPARENT); + }else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + setStatusTop(isStatus); + window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); + window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void setNavigationBar() { + Window window = mActivity.getWindow(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + window.setNavigationBarColor(Color.BLACK); + } + } + + private void setStatusTop(boolean isStatus){ + try { + int resourceId = mContext.getResources().getIdentifier("status_bar_height", "dimen", "android"); + if (resourceId > 0) { + statusHeight = mContext.getResources().getDimensionPixelSize(resourceId); + } + if (statusHeight == 0) { + statusHeight = Common.dipToPx(mContext, 25); + } + //System.out.println("StatusHeight : " + statusHeight + " - SDK_INT : " + Build.VERSION.SDK_INT); + if (isStatus && topStatus != null) { + ViewGroup.LayoutParams params = topStatus.getLayoutParams(); + params.height = statusHeight; + topStatus.setLayoutParams(params); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void setTitle(String title){ + topText.setText(title); + } + + public void setLeftIcon(int image) { + setLeftIcon(image, true); + } + + public void setLeftIcon(int image, boolean isAnim) { + topLeftIcon.setBackgroundResource(image); + if (isAnim) Common.animScale(topLeftIcon, 200); + } + + public void setRightIcon(int image) { + setRightIcon(image, true); + } + + public void setRightIcon(int image, boolean isAnim) { + topRightIcon.setBackgroundResource(image); + if (isAnim) Common.animScale(topRightIcon, 200); + } + + public void showLeft(int image, final OnTopClickListener listener){ + setLeftIcon(image, false); + if (topLeft.getVisibility() == View.GONE) { + topLeft.setVisibility(View.VISIBLE); + } + if(listener != null){ + topLeft.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + listener.onClick(view); + } + }); + } + } + + public void showRight(int image, final OnTopClickListener listener){ + setRightIcon(image, false); + if (topRight.getVisibility() == View.GONE) { + topRight.setVisibility(View.VISIBLE); + } + if(listener != null){ + topRight.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + listener.onClick(view); + } + }); + } + } + + public void setRightText(String text){ + setRightText(text, null); + } + + public void setRightText(String text, final OnTopClickListener listener){ + if (topRightText.getVisibility() == View.GONE) { + topRightText.setVisibility(View.VISIBLE); + } + topRightText.setText(text); + if(listener != null){ + topRightText.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + listener.onClick(view); + } + }); + } + } + + public void showLeftBack() { + showLeft(R.mipmap.icon_back, new TopBar.OnTopClickListener() { + @Override + public void onClick(View view) { + mActivity.finish(); + } + }); + } + + public void radiusBar() { + topHead.setBackgroundResource(R.drawable.radius_status); + if (topStatus.getVisibility() == View.VISIBLE) { + topStatus.setVisibility(View.INVISIBLE); + } + } + + public void normalBar() { + topHead.setBackgroundResource(R.color.colorPrimary); + if (topStatus.getVisibility() == View.INVISIBLE) { + topStatus.setVisibility(View.VISIBLE); + } + } + + public void setBarAlpha(float alpha) { + topBar.setAlpha(alpha); + } + + public int getWidth() { + return topBar.getMeasuredWidth(); + } + + public int getHeight() { + return topBar.getMeasuredHeight(); + } + + public int getStatusHeight() { + return statusHeight; + } + + public View getTopLeftIcon() { + return topLeftIcon; + } + + public View getTopRightIcon() { + return topRightIcon; + } +} diff --git a/app/src/main/java/cn/leaqi/drawerapp/Views/TouchView.java b/app/src/main/java/cn/leaqi/drawerapp/Views/TouchView.java new file mode 100644 index 0000000..dcac269 --- /dev/null +++ b/app/src/main/java/cn/leaqi/drawerapp/Views/TouchView.java @@ -0,0 +1,54 @@ +package cn.leaqi.drawerapp.Views; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.widget.LinearLayout; + +/** + * 布局触摸缩小 + */ +public class TouchView extends LinearLayout { + + public TouchView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + init(context, attrs); + } + + public TouchView(Context context, AttributeSet attrs) { + super(context, attrs); + init(context, attrs); + } + + public TouchView(Context context) { + super(context); + init(context, null); + } + + private void init(Context context, AttributeSet attrs) { + setClickable(true); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + if (ev.getAction() == MotionEvent.ACTION_DOWN) { + setScaleX(0.8f); + setScaleY(0.8f); + return true; + } + return super.onInterceptTouchEvent(ev); + } + + + @Override + public boolean onTouchEvent(MotionEvent ev) { + switch (ev.getAction()) { + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + setScaleX(1f); + setScaleY(1f); + } + return super.onTouchEvent(ev); + } + +} diff --git a/app/src/main/java/cn/leaqi/drawerapp/Views/UserComment.java b/app/src/main/java/cn/leaqi/drawerapp/Views/UserComment.java new file mode 100644 index 0000000..9f8c304 --- /dev/null +++ b/app/src/main/java/cn/leaqi/drawerapp/Views/UserComment.java @@ -0,0 +1,251 @@ +package cn.leaqi.drawerapp.Views; + +import android.content.Context; +import android.graphics.Color; +import android.graphics.Rect; +import android.text.Editable; +import android.text.TextWatcher; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewTreeObserver; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import cn.leaqi.drawerapp.R; +import cn.leaqi.drawerapp.Utils.Common; +import cn.leaqi.drawerapp.Utils.Config; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Random; + +/** + * 视频布局用户评论类 + */ +public class UserComment implements View.OnClickListener { + private Context mContext; + private RecyclerView mainList; + private ListAdapter listAdapter; + private List listData = new ArrayList<>(); + + private View parent; + private View itemSend; + private View sendIcon; + private EditText sendVal; + private View sendAt; + private View sendBq; + private View sendSubmit; + + private int keyboardHeight = 0; + + public UserComment(Context context, View view) { + mContext = context; + parent = view; + mainList = parent.findViewById(R.id.itemComment); + itemSend = parent.findViewById(R.id.itemSend); + sendIcon = parent.findViewById(R.id.send_icon); + sendVal = parent.findViewById(R.id.send_val); + sendAt = parent.findViewById(R.id.send_at); + sendBq = parent.findViewById(R.id.send_bq); + sendSubmit = parent.findViewById(R.id.send_submit); + sendIcon.setOnClickListener(this); + sendAt.setOnClickListener(this); + sendBq.setOnClickListener(this); + sendSubmit.setOnClickListener(this); + AppInit(); + } + + @Override + public void onClick(View view) { + if (view == sendIcon) { + Common.showToast("拍视频"); + } else if (view == sendAt) { + Common.showToast("艾特"); + } else if (view == sendBq) { + Common.showToast("表情"); + } else if (view == sendSubmit) { + // 发布评论 + final String getVal = sendVal.getText().toString(); + if (getVal.length() > 0) { + Common.showToast("发布成功"); + Common.hideInput(mContext); + sendVal.setText(""); + listData.add(0, new ItemBean(getVal)); + listAdapter.notifyItemInserted(0); + mainList.scrollToPosition(0); + } + } + } + + private void AppInit() { + listAdapter = new ListAdapter(mContext, R.layout.comment_item, listData); + mainList.setLayoutManager(new LinearLayoutManager(mContext)); + mainList.setAdapter(listAdapter); + + sendVal.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { } + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { } + @Override + public void afterTextChanged(Editable editable) { + if (editable.toString().length() > 0) { + sendSubmit.setVisibility(View.VISIBLE); + } else { + sendSubmit.setVisibility(View.GONE); + } + } + }); + + parent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener(){ + @Override + public void onGlobalLayout() { + Rect rect = new Rect(); + parent.getWindowVisibleDisplayFrame(rect); + int getHeight = parent.getHeight() - rect.bottom; + if (keyboardHeight != getHeight) { + keyboardHeight = getHeight; + RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) itemSend.getLayoutParams(); + lp.bottomMargin = getHeight; + itemSend.setLayoutParams(lp); + } + } + }); + } + + public void setData() { + for (int i = 1; i < Config.CommentList.size() + 1; i++) { + Config.CommentBean item = Config.CommentList.get(i); + listData.add(new ItemBean(item.user.icon, item.user.name, item.text, item.time, item.favCount)); + } + Collections.shuffle(listData); + listAdapter.notifyDataSetChanged(); + } + + private class ItemBean { + int src = -1; + String icon; + String name; + String text; + String time; + int dig; + boolean isDig = false; + + private ItemBean(String i, String n, String s, String t, int d) { + icon = i; + name = n; + text = s; + time = t; + dig = d; + } + + private ItemBean(String t) { + src = R.mipmap.icon; + name = "我"; + text = t; + time = "刚刚"; + dig = 0; + } + + private String getDigParse() { + return Common.ParseNum(dig); + } + } + + private class ListAdapter extends RecyclerView.Adapter { + private int layout; + private LayoutInflater inflater; + private List list; + + + private ListAdapter(Context context, int resource, List objects) { + layout = resource; + inflater = LayoutInflater.from(context); + list = objects; + } + + @NonNull + @Override + public ListViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View addView = inflater.inflate(layout, parent, false); + return new ListViewHolder(addView); + } + + @Override + public void onBindViewHolder(@NonNull ListViewHolder holder, int position) { + ItemBean item = list.get(position); + if (item.src != -1) { + // 新增的评论使用默认头像 + holder.itemIcon.setImageResource(item.src); + } else { + // 加载评论用户头像 + Common.setHttpImage(holder.itemIcon, item.icon, R.mipmap.icon_user); + } + holder.itemTitle.setText(item.name); // 用户名称 + holder.itemText.setText(item.text); // 评论内容 + holder.itemTime.setText(item.time); // 评论时间 + // 评论点赞 + holder.itemDigIcon.setImageResource(item.isDig ? R.mipmap.icon_dig_cur : R.mipmap.icon_dig_def); + holder.itemDigNum.setVisibility(item.dig == 0 ? View.GONE : View.VISIBLE); + holder.itemDigNum.setTextColor(Color.parseColor(item.isDig ? "#FC2E5D" : "#888888")); + holder.itemDigNum.setText(item.getDigParse()); + } + + @Override + public int getItemCount() { + return list.size(); + } + + private class ListViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + ImageView itemIcon; + TextView itemTitle; + TextView itemText; + TextView itemTime; + View itemDigBox; + ImageView itemDigIcon; + TextView itemDigNum; + + private ListViewHolder(View view) { + super(view); + itemIcon = view.findViewById(R.id.item_icon); + itemTitle = view.findViewById(R.id.item_title); + itemText = view.findViewById(R.id.item_text); + itemTime = view.findViewById(R.id.item_time); + itemDigBox = view.findViewById(R.id.item_dig_box); + itemDigIcon = view.findViewById(R.id.item_dig_icon); + itemDigNum = view.findViewById(R.id.item_dig_num); + itemIcon.setOnClickListener(this); + itemTitle.setOnClickListener(this); + itemDigBox.setOnClickListener(this); + } + + @Override + public void onClick(View view) { + int position = getAdapterPosition(); + ItemBean item = list.get(position); + if (view == itemIcon || view == itemTitle) { + Common.showToast(item.name); + } else if (view == itemDigBox) { + // 点击评论点赞 + item.isDig = !item.isDig; + item.dig = item.isDig ? item.dig + 1 : item.dig - 1; + itemDigIcon.setImageResource(item.isDig ? R.mipmap.icon_dig_cur : R.mipmap.icon_dig_def); + itemDigNum.setVisibility(item.dig == 0 ? View.GONE : View.VISIBLE); + itemDigNum.setTextColor(Color.parseColor(item.isDig ? "#FC2E5D" : "#888888")); + itemDigNum.setText(item.getDigParse()); + } + } + + } + + } + +} \ No newline at end of file diff --git a/app/src/main/java/cn/leaqi/drawerapp/Views/UserHome.java b/app/src/main/java/cn/leaqi/drawerapp/Views/UserHome.java new file mode 100644 index 0000000..23b8f5e --- /dev/null +++ b/app/src/main/java/cn/leaqi/drawerapp/Views/UserHome.java @@ -0,0 +1,265 @@ +package cn.leaqi.drawerapp.Views; + +import android.app.Activity; +import android.content.Context; +import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.GridView; +import android.widget.ImageView; +import android.widget.ScrollView; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import com.google.android.material.tabs.TabLayout; +import cn.leaqi.drawerapp.R; +import cn.leaqi.drawerapp.Utils.Common; +import cn.leaqi.drawerapp.Utils.Config; +import cn.leaqi.drawer.SwipeDrawer; +import cn.leaqi.drawer.OnDrawerState; + +import java.util.ArrayList; +import java.util.List; + +/** + * 视频布局用户主页类 + */ +public class UserHome implements View.OnClickListener { + private Context mContext; + private Activity mActivity; + private SwipeDrawer homeDrawer; + private SwipeDrawer infoDrawer; + private TabLayout homeTab; + private ScrollView homeScroll; + private ImageView homeBg; + private ImageView homeIcon; + private TextView homeName; + private TextView homeId; + private TextView homeText; + private TextView homeAge; + private ImageView homeSex; + private TextView homeCity; + private TextView numPraise; + private TextView numFollow; + private TextView numFans; + private View homeFollow; + private View homeCancel; + + private List tabList = new ArrayList(){{ + add("作品"); + add("喜欢"); + }}; + + private List listData = new ArrayList<>(); + private ListAdapter listAdapter = null; + + private Config.UserBean userInfo; + + public UserHome(Context context) { + mContext = context; + mActivity = ((Activity)mContext); + homeDrawer = mActivity.findViewById(R.id.homeDrawer); + infoDrawer = mActivity.findViewById(R.id.infoDrawer); + homeTab = mActivity.findViewById(R.id.homeTab); + homeScroll = mActivity.findViewById(R.id.homeScroll); + homeBg = mActivity.findViewById(R.id.homeBg); + homeIcon = mActivity.findViewById(R.id.homeIcon); + homeName = mActivity.findViewById(R.id.homeName); + homeId = mActivity.findViewById(R.id.homeId); + homeText = mActivity.findViewById(R.id.homeText); + homeAge = mActivity.findViewById(R.id.homeAge); + homeSex = mActivity.findViewById(R.id.homeSex); + homeCity = mActivity.findViewById(R.id.homeCity); + numPraise = mActivity.findViewById(R.id.numPraise); + numFollow = mActivity.findViewById(R.id.numFollow); + numFans = mActivity.findViewById(R.id.numFans); + homeFollow = mActivity.findViewById(R.id.homeFollow); + homeCancel = mActivity.findViewById(R.id.homeCancel); + AppInit(); + ListData(); + } + + @Override + public void onClick(View view) { + int getId = view.getId(); + switch (getId) { + case R.id.homeBack : // 点击左上角返回 + Common.sendKeyCode(KeyEvent.KEYCODE_BACK); + break; + case R.id.homeSet : // 点击右上角设置 + homeDrawer.openDrawer(SwipeDrawer.DIRECTION_BOTTOM); + break; + case R.id.homeClose : // 点击设置面板关闭按钮 + homeDrawer.closeDrawer(); + break; + case R.id.homeFollow : // 点击关注 + if (userInfo != null) { + userInfo.isFollow = true; + homeCancel.setVisibility(View.VISIBLE); + homeFollow.setVisibility(View.GONE); + Common.showToast("已关注"); + } + break; + case R.id.homeCancel : // 点击取消关注 + if (userInfo != null) { + userInfo.isFollow = false; + homeCancel.setVisibility(View.GONE); + homeFollow.setVisibility(View.VISIBLE); + Common.showToast("取消关注"); + } + break; + case R.id.homeShare : // 点击设置面板分享 + Common.showToast("分享"); + homeDrawer.closeDrawer(); + break; + case R.id.homeMsg : // 点击设置面板聊天 + Common.showToast("聊天"); + homeDrawer.closeDrawer(); + break; + case R.id.homeWarn : // 点击设置面板举报 + Common.showToast("举报"); + homeDrawer.closeDrawer(); + break; + case R.id.homeBlack : // 点击设置面板举报 + Common.showToast("拉黑"); + homeDrawer.closeDrawer(); + break; + } + } + + private void AppInit() { + final View homeBg = mActivity.findViewById(R.id.homeBg); + final View homeBack = mActivity.findViewById(R.id.homeBack); + final View homeSet = mActivity.findViewById(R.id.homeSet); + final View homeClose = mActivity.findViewById(R.id.homeClose); + final View homeShare = mActivity.findViewById(R.id.homeShare); + final View homeMsg = mActivity.findViewById(R.id.homeMsg); + final View homeWarn = mActivity.findViewById(R.id.homeWarn); + final View homeBlack = mActivity.findViewById(R.id.homeBlack); + homeFollow.setOnClickListener(this); + homeCancel.setOnClickListener(this); + homeBack.setOnClickListener(this); + homeSet.setOnClickListener(this); + homeClose.setOnClickListener(this); + homeShare.setOnClickListener(this); + homeMsg.setOnClickListener(this); + homeWarn.setOnClickListener(this); + homeBlack.setOnClickListener(this); + createTab(); + + infoDrawer.setOnDrawerState(new OnDrawerState() { + @Override + public void onStart(int type) { } + @Override + public void onMove(int type, float progress) { + // 主页顶部下拉背景放大缩小 + progress *= 0.5; + homeBg.setScaleX(1 + progress); + homeBg.setScaleY(1 + progress); + } + @Override + public void onOpen(int type) { } + @Override + public void onClose(int type) { } + @Override + public void onCancel(int type) { } + }); + } + + // 更新主页数据 + public void upHome(Config.UserBean info) { + homeCancel.setVisibility(info.isFollow ? View.VISIBLE : View.GONE); + homeFollow.setVisibility(info.isFollow ? View.GONE : View.VISIBLE); + if (userInfo != info) { + userInfo = info; + homeScroll.scrollTo(0, 0); // scroll 回到顶部 + homeName.setText(userInfo.name); // 用户名称 + homeId.setText(("账号: " + (100000 + userInfo.id))); // 用户ID + homeText.setText(userInfo.text); // 用户简介 + homeAge.setText((userInfo.age + "岁")); // 用户年龄 + homeCity.setText(userInfo.city); // 用户城市 + numPraise.setText(userInfo.getPraise()); // 获赞数量 + numFollow.setText(userInfo.getFollow()); // 关注数量 + numFans.setText(userInfo.getFans()); // 粉丝数量 + homeTab.getTabAt(0).select(); + // 设置用户性别图标 + if (userInfo.sex > 0) { + homeSex.setVisibility(View.VISIBLE); + homeSex.setImageResource(userInfo.sex == 1 ? R.mipmap.sex_1 : R.mipmap.sex_2); + } else { + homeSex.setVisibility(View.GONE); + } + Common.setHttpImage(homeBg, userInfo.bg); // 用户主页背景图 + Common.setHttpImage(homeIcon, userInfo.icon, R.mipmap.icon_user); // 用户头像 + SetList(); + } + } + + private void createTab() { + for (int i = 0; i < tabList.size(); i++) { + homeTab.addTab(homeTab.newTab().setText(tabList.get(i))); + } + homeTab.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { + @Override + public void onTabSelected(TabLayout.Tab tab) { } + @Override + public void onTabUnselected(TabLayout.Tab tab) { } + @Override + public void onTabReselected(TabLayout.Tab tab) { } + }); + } + + private void SetList() { + listData.clear(); + listData.addAll(Config.UserVideo.get(userInfo.id)); + homeTab.getTabAt(0).setText(tabList.get(0) + (listData.size() > 0 ? " " + listData.size() : "")); + listAdapter.notifyDataSetChanged(); + } + + private void ListData() { + final GridView homeGrid = mActivity.findViewById(R.id.homeGrid); + listAdapter = new ListAdapter(mActivity, R.layout.home_item, listData); + homeGrid.setAdapter(listAdapter); + } + + private class ListAdapter extends ArrayAdapter{ + private int layout; + private LayoutInflater inflater; + private List list; + + private ListAdapter(Context context, int resource, List objects) { + super(context, resource, objects); + layout = resource; + inflater = LayoutInflater.from(context); + list = objects; + } + @NonNull + public View getView(int position, View convertView, @NonNull ViewGroup parent) { + View view; + ViewHolder viewHolder; + if (convertView == null) { + view = inflater.inflate(layout, null); + viewHolder = new ViewHolder(); + viewHolder.itemImg = view.findViewById(R.id.itemImg); + viewHolder.title = view.findViewById(R.id.itemTitle); + view.setTag(viewHolder); + } else { + view = convertView; + viewHolder = (ViewHolder) view.getTag(); + } + Config.VideoBean item = list.get(position); + viewHolder.title.setText(item.getFavCount()); + Common.setHttpImage(viewHolder.itemImg, item.img); + return view; + } + + private class ViewHolder { + ImageView itemImg; + TextView title; + } + } + +} diff --git a/app/src/main/java/cn/leaqi/drawerapp/Views/UserInfo.java b/app/src/main/java/cn/leaqi/drawerapp/Views/UserInfo.java new file mode 100644 index 0000000..cbe2317 --- /dev/null +++ b/app/src/main/java/cn/leaqi/drawerapp/Views/UserInfo.java @@ -0,0 +1,76 @@ +package cn.leaqi.drawerapp.Views; + +import android.app.Activity; +import android.content.Context; +import android.view.View; +import android.view.ViewGroup; + +import cn.leaqi.drawerapp.R; +import cn.leaqi.drawerapp.Utils.Common; +import cn.leaqi.drawer.SwipeDrawer; +import cn.leaqi.drawer.OnDrawerState; + +/** + * 右侧边栏用户菜单操作类 + */ +public class UserInfo implements View.OnClickListener { + private Context mContext; + private Activity mActivity; + + + public UserInfo(Context context) { + mContext = context; + mActivity = ((Activity)mContext); + AppInit(); + } + + private void AppInit() { + final SwipeDrawer userInfo = mActivity.findViewById(R.id.userInfo); + final View infoTopIcon = mActivity.findViewById(R.id.infoTopIcon); + final View infoTopTitle = mActivity.findViewById(R.id.infoTopTitle); + final ViewGroup listItem1 = mActivity.findViewById(R.id.listItem1); + final ViewGroup listItem2 = mActivity.findViewById(R.id.listItem2); + final ViewGroup listItem3 = mActivity.findViewById(R.id.listItem3); + + userInfo.setOnDrawerState(new OnDrawerState() { + @Override + public void onStart(int type) { } + @Override + public void onMove(int type, float progress) { + if (type == SwipeDrawer.DIRECTION_TOP) { + infoTopIcon.setRotation(progress * 360); + progress *= 0.2; + infoTopIcon.setScaleX(1 + progress); + infoTopIcon.setScaleY(1 + progress); + infoTopTitle.setScaleX(1 + progress); + infoTopTitle.setScaleY(1 + progress); + } + } + @Override + public void onOpen(int type) { } + @Override + public void onClose(int type) { } + @Override + public void onCancel(int type) { } + }); + + for (int i = 0; i < listItem1.getChildCount(); i++) { + View view = listItem1.getChildAt(i); + view.setOnClickListener(this); + } + for (int i = 0; i < listItem2.getChildCount(); i++) { + View view = listItem2.getChildAt(i); + view.setOnClickListener(this); + } + for (int i = 0; i < listItem3.getChildCount(); i++) { + View view = listItem3.getChildAt(i); + view.setOnClickListener(this); + } + } + + @Override + public void onClick(View view) { + String getText = (String) view.getTag(); + Common.showToast(getText); + } +} diff --git a/app/src/main/java/cn/leaqi/drawerapp/Views/UserMenu.java b/app/src/main/java/cn/leaqi/drawerapp/Views/UserMenu.java new file mode 100644 index 0000000..fe5b613 --- /dev/null +++ b/app/src/main/java/cn/leaqi/drawerapp/Views/UserMenu.java @@ -0,0 +1,39 @@ +package cn.leaqi.drawerapp.Views; + +import android.app.Activity; +import android.content.Context; +import android.view.View; +import android.view.ViewGroup; + +import cn.leaqi.drawerapp.R; +import cn.leaqi.drawerapp.Utils.Common; + +/** + * 左侧边栏用户菜单操作类 + */ +public class UserMenu implements View.OnClickListener { + private Context mContext; + private Activity mActivity; + + + public UserMenu(Context context) { + mContext = context; + mActivity = ((Activity)mContext); + AppInit(); + } + + private void AppInit() { + final ViewGroup listItem = mActivity.findViewById(R.id.listItem); + + for (int i = 0; i < listItem.getChildCount(); i++) { + View view = listItem.getChildAt(i); + view.setOnClickListener(this); + } + } + + @Override + public void onClick(View view) { + String getText = (String) view.getTag(); + Common.showToast(getText); + } +} diff --git a/app/src/main/java/cn/leaqi/drawerapp/Views/UserShare.java b/app/src/main/java/cn/leaqi/drawerapp/Views/UserShare.java new file mode 100644 index 0000000..a05ead8 --- /dev/null +++ b/app/src/main/java/cn/leaqi/drawerapp/Views/UserShare.java @@ -0,0 +1,46 @@ +package cn.leaqi.drawerapp.Views; + +import android.app.Activity; +import android.content.Context; +import android.view.View; +import android.view.ViewGroup; + +import cn.leaqi.drawerapp.R; +import cn.leaqi.drawerapp.Utils.Common; +import cn.leaqi.drawer.SwipeDrawer; + +/** + * 视频布局用户分享类 + */ +public class UserShare implements View.OnClickListener { + private Context mContext; + private Activity mActivity; + private SwipeDrawer rootDrawer; + + public UserShare(Context context) { + mContext = context; + mActivity = ((Activity)mContext); + rootDrawer = mActivity.findViewById(R.id.rootDrawer); + AppInit(); + } + + private void AppInit() { + final ViewGroup shareBox1 = mActivity.findViewById(R.id.shareBox1); + final ViewGroup shareBox2 = mActivity.findViewById(R.id.shareBox2); + for (int i = 0; i < shareBox1.getChildCount(); i++) { + View view = shareBox1.getChildAt(i); + view.setOnClickListener(this); + } + for (int i = 0; i < shareBox2.getChildCount(); i++) { + View view = shareBox2.getChildAt(i); + view.setOnClickListener(this); + } + } + + @Override + public void onClick(View view) { + String getText = (String) view.getTag(); + Common.showToast(getText); + rootDrawer.closeDrawer(); + } +} \ No newline at end of file diff --git a/app/src/main/java/cn/leaqi/drawerapp/Views/VideoPlay.java b/app/src/main/java/cn/leaqi/drawerapp/Views/VideoPlay.java new file mode 100644 index 0000000..9db618b --- /dev/null +++ b/app/src/main/java/cn/leaqi/drawerapp/Views/VideoPlay.java @@ -0,0 +1,324 @@ +package cn.leaqi.drawerapp.Views; + +import android.content.Context; +import android.content.res.TypedArray; +import android.media.MediaPlayer; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.animation.AlphaAnimation; +import android.view.animation.Animation; +import android.view.animation.AnimationSet; +import android.view.animation.ScaleAnimation; +import android.widget.SeekBar; +import android.widget.VideoView; + +import cn.leaqi.drawerapp.R; +import cn.leaqi.drawer.SwipeDrawer; + +import java.util.ArrayList; +import java.util.List; + +/** + * 自定义VideoView视频播放器 + */ +public class VideoPlay extends VideoView implements MediaPlayer.OnErrorListener,View.OnClickListener { + + private static final List lastPlay = new ArrayList<>(); + + private boolean init = false; + private boolean drag = false; + + private boolean isPlay = false; + + private int loadId = -1; + private int playId = -1; + private int pauseId = -1; + private int seekId = -1; + private View loadView = null; + private View playView = null; + private View pauseView = null; + private SeekBar seekView = null; + private OnPlayState onPlayState = null; + + public interface OnPlayState { + void onStart(VideoPlay view); + void onPlay(VideoPlay view); + void onStop(VideoPlay view); + void onError(VideoPlay view); + } + + public VideoPlay(Context context) { + super(context); + Init(context, null); + } + + public VideoPlay(Context context, AttributeSet attrs) { + super(context, attrs); + Init(context, attrs); + } + + public VideoPlay(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + Init(context, attrs); + } + + private void Init(Context context, AttributeSet attrs) { + if (attrs != null) { + final TypedArray attrArr = context.obtainStyledAttributes(attrs, R.styleable.VideoPlay); + playId = attrArr.getResourceId(R.styleable.VideoPlay_playId, playId); + pauseId = attrArr.getResourceId(R.styleable.VideoPlay_pauseId, pauseId); + seekId = attrArr.getResourceId(R.styleable.VideoPlay_seekId, seekId); + loadId = attrArr.getResourceId(R.styleable.VideoPlay_loadId, loadId); + attrArr.recycle(); + } + setOnErrorListener(this); + setOnClickListener(this); + setOnPreparedListener(new MediaPlayer.OnPreparedListener() { + @Override + public void onPrepared(MediaPlayer mediaPlayer) { + isPlay = true; + loadAnim(false); + if (onPlayState != null) onPlayState.onPlay(VideoPlay.this); + } + }); + setOnCompletionListener(new MediaPlayer.OnCompletionListener() { + @Override + public void onCompletion(MediaPlayer mediaPlayer) { + mediaPlayer.start(); + mediaPlayer.setLooping(true); + } + }); + } + + public void setOnPlayState(OnPlayState call) { + onPlayState = call; + } + + private void upProgress() { + final int duration = getDuration(); + if (seekView != null) { + seekView.setMax(duration); + new Thread() { + @Override + public void run() { + try { + while (isPlaying() && !drag) { + /*int current = getCurrentPosition(); + int progress = Math.round(((float) current / duration) * 100); + System.out.println("current : " + current + " - " + progress);*/ + seekView.post(new Runnable() { + @Override + public void run() { + if (drag) return; + seekView.setProgress(getCurrentPosition()); + } + }); + sleep(500); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + }.start(); + } + } + + private void upViews(boolean play) { + if (play) { + if(playView != null) playView.setVisibility(GONE); + if(pauseView != null) pauseView.setVisibility(VISIBLE); + } else { + if(playView != null) playView.setVisibility(VISIBLE); + if(pauseView != null) pauseView.setVisibility(GONE); + } + } + + private void loadAnim(boolean bool) { + if (loadView != null) { + if (bool) { + ScaleAnimation scale = new ScaleAnimation(0.3f, 1f, 1f, 1f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); + scale.setRepeatCount(-1); + AlphaAnimation alpha = new AlphaAnimation(1f, 0.3f); + alpha.setRepeatCount(-1); + AnimationSet anim = new AnimationSet(true); + anim.addAnimation(scale); + anim.addAnimation(alpha); + anim.setDuration(300); + loadView.startAnimation(anim); + loadView.setVisibility(VISIBLE); + } else { + loadView.clearAnimation(); + loadView.setVisibility(GONE); + } + } + if (seekView != null) { + if (bool) { + seekView.setVisibility(GONE); + } else { + seekView.setVisibility(VISIBLE); + } + } + } + + public static void setViewAlpha(float alpha) { + if (lastPlay.size() > 0) { + for (VideoPlay view : lastPlay) { + if (view.seekView != null) { + view.seekView.setAlpha(alpha); + } + if (view.playView != null) { + view.playView.setAlpha(alpha); + } + if (view.pauseView != null) { + view.pauseView.setAlpha(alpha); + } + } + } + } + + @Override + public void start() { + if (lastPlay.indexOf(this) == -1) lastPlay.add(this); + super.start(); + upProgress(); + upViews(true); + if (isPlay) { + if (onPlayState != null) onPlayState.onPlay(this); + } else { + loadAnim(true); + if (onPlayState != null) onPlayState.onStart(this); + } + } + + @Override + public void pause() { + super.pause(); + upViews(false); + if (onPlayState != null) onPlayState.onStop(this); + } + + @Override + public void resume() { + if (lastPlay.indexOf(this) == -1) lastPlay.add(this); + super.resume(); + upProgress(); + upViews(true); + if (onPlayState != null) onPlayState.onPlay(this); + } + + @Override + public void stopPlayback() { + super.stopPlayback(); + } + + @Override + public void onClick(View view) { + if (view == pauseView) { + if (isPlaying()) { + pause(); + } + } else if (view == playView) { + start(); + } + } + + @Override + public boolean onError(MediaPlayer mediaPlayer, int i, int i1) { + System.out.println("MediaPlayer : " + mediaPlayer + " - " + i + " - " + i1); + if (onPlayState != null) onPlayState.onPlay(this); + return true; + } + + /*@Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int width = getDefaultSize(0, widthMeasureSpec); + int height = getDefaultSize(0, heightMeasureSpec); + setMeasuredDimension(width, height); + }*/ + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + if (!init) { + View parent = (View) getParent(); + if (parent != null) { + View view; + if (playId != -1) { + view = parent.findViewById(playId); + if (view != null) { + playView = view; + playView.setOnClickListener(this); + } + } + if (pauseId != -1) { + view = parent.findViewById(pauseId); + if (view != null) { + pauseView = view; + pauseView.setVisibility(VISIBLE); + pauseView.setOnClickListener(this); + } + } + if (loadId != -1) { + view = parent.findViewById(loadId); + if (view != null) { + loadView = view; + loadAnim(true); + } + } + if (seekId != -1) { + view = parent.findViewById(seekId); + if (view instanceof SeekBar) { + seekView = (SeekBar) view; + seekView.setVisibility(GONE); + seekView.setOnTouchListener(new OnTouchListener() { + @Override + public boolean onTouch(View view, MotionEvent ev) { + switch (ev.getAction()) { + case MotionEvent.ACTION_DOWN: + SwipeDrawer.setAllIntercept(true); + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + SwipeDrawer.setAllIntercept(false); + break; + } + return false; + } + }); + seekView.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int i, boolean b) { + if (b) { + seekTo(i); + } + } + + @Override + public void onStartTrackingTouch(final SeekBar seekBar) { + drag = true; + seekBar.setScaleX(2f); + seekBar.setScaleY(2f); + } + + @Override + public void onStopTrackingTouch(final SeekBar seekBar) { + drag = false; + seekBar.setScaleX(1f); + seekBar.setScaleY(1f); + upProgress(); + } + }); + } + } + } + init = true; + } + } + + @Override + protected void onDetachedFromWindow() { + if (lastPlay.indexOf(this) >= 0) lastPlay.remove(this); + super.onDetachedFromWindow(); + } +} diff --git a/app/src/main/res/drawable/fixed_btn_select.xml b/app/src/main/res/drawable/fixed_btn_select.xml new file mode 100644 index 0000000..75cbc94 --- /dev/null +++ b/app/src/main/res/drawable/fixed_btn_select.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/load_anim.xml b/app/src/main/res/drawable/load_anim.xml new file mode 100644 index 0000000..e38c550 --- /dev/null +++ b/app/src/main/res/drawable/load_anim.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/menu_color.xml b/app/src/main/res/drawable/menu_color.xml new file mode 100644 index 0000000..2c47d58 --- /dev/null +++ b/app/src/main/res/drawable/menu_color.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/drawable/menu_item.xml b/app/src/main/res/drawable/menu_item.xml new file mode 100644 index 0000000..ac5bd31 --- /dev/null +++ b/app/src/main/res/drawable/menu_item.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/radius_add.xml b/app/src/main/res/drawable/radius_add.xml new file mode 100644 index 0000000..92c90b0 --- /dev/null +++ b/app/src/main/res/drawable/radius_add.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/radius_bg.xml b/app/src/main/res/drawable/radius_bg.xml new file mode 100644 index 0000000..326ee22 --- /dev/null +++ b/app/src/main/res/drawable/radius_bg.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/radius_bg_top.xml b/app/src/main/res/drawable/radius_bg_top.xml new file mode 100644 index 0000000..446199a --- /dev/null +++ b/app/src/main/res/drawable/radius_bg_top.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/radius_border.xml b/app/src/main/res/drawable/radius_border.xml new file mode 100644 index 0000000..f24702e --- /dev/null +++ b/app/src/main/res/drawable/radius_border.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/radius_cancel.xml b/app/src/main/res/drawable/radius_cancel.xml new file mode 100644 index 0000000..afc71bc --- /dev/null +++ b/app/src/main/res/drawable/radius_cancel.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/radius_follow.xml b/app/src/main/res/drawable/radius_follow.xml new file mode 100644 index 0000000..7c8faee --- /dev/null +++ b/app/src/main/res/drawable/radius_follow.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/radius_grey_top.xml b/app/src/main/res/drawable/radius_grey_top.xml new file mode 100644 index 0000000..c8bb726 --- /dev/null +++ b/app/src/main/res/drawable/radius_grey_top.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/radius_grid_item.xml b/app/src/main/res/drawable/radius_grid_item.xml new file mode 100644 index 0000000..2ef741c --- /dev/null +++ b/app/src/main/res/drawable/radius_grid_item.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/radius_icon.xml b/app/src/main/res/drawable/radius_icon.xml new file mode 100644 index 0000000..c951946 --- /dev/null +++ b/app/src/main/res/drawable/radius_icon.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/radius_so.xml b/app/src/main/res/drawable/radius_so.xml new file mode 100644 index 0000000..c2bed9c --- /dev/null +++ b/app/src/main/res/drawable/radius_so.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/radius_status.xml b/app/src/main/res/drawable/radius_status.xml new file mode 100644 index 0000000..63b1ad3 --- /dev/null +++ b/app/src/main/res/drawable/radius_status.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/radius_tags.xml b/app/src/main/res/drawable/radius_tags.xml new file mode 100644 index 0000000..fc05e64 --- /dev/null +++ b/app/src/main/res/drawable/radius_tags.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/radius_value.xml b/app/src/main/res/drawable/radius_value.xml new file mode 100644 index 0000000..b6c92f1 --- /dev/null +++ b/app/src/main/res/drawable/radius_value.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/radius_white.xml b/app/src/main/res/drawable/radius_white.xml new file mode 100644 index 0000000..e5cd0b6 --- /dev/null +++ b/app/src/main/res/drawable/radius_white.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/radius_white_top.xml b/app/src/main/res/drawable/radius_white_top.xml new file mode 100644 index 0000000..73df44b --- /dev/null +++ b/app/src/main/res/drawable/radius_white_top.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/seek_layer.xml b/app/src/main/res/drawable/seek_layer.xml new file mode 100644 index 0000000..1d21b2d --- /dev/null +++ b/app/src/main/res/drawable/seek_layer.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/seek_thumb.xml b/app/src/main/res/drawable/seek_thumb.xml new file mode 100644 index 0000000..c4b8b45 --- /dev/null +++ b/app/src/main/res/drawable/seek_thumb.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/seek_video_layer.xml b/app/src/main/res/drawable/seek_video_layer.xml new file mode 100644 index 0000000..45f5e6a --- /dev/null +++ b/app/src/main/res/drawable/seek_video_layer.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/seek_video_thumb.xml b/app/src/main/res/drawable/seek_video_thumb.xml new file mode 100644 index 0000000..8f2b258 --- /dev/null +++ b/app/src/main/res/drawable/seek_video_thumb.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_demo1.xml b/app/src/main/res/layout/activity_demo1.xml new file mode 100644 index 0000000..2d3fe7d --- /dev/null +++ b/app/src/main/res/layout/activity_demo1.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_demo10.xml b/app/src/main/res/layout/activity_demo10.xml new file mode 100644 index 0000000..e29ed26 --- /dev/null +++ b/app/src/main/res/layout/activity_demo10.xml @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_demo11.xml b/app/src/main/res/layout/activity_demo11.xml new file mode 100644 index 0000000..9e84ff7 --- /dev/null +++ b/app/src/main/res/layout/activity_demo11.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_demo12.xml b/app/src/main/res/layout/activity_demo12.xml new file mode 100644 index 0000000..5725660 --- /dev/null +++ b/app/src/main/res/layout/activity_demo12.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_demo13.xml b/app/src/main/res/layout/activity_demo13.xml new file mode 100644 index 0000000..250ef23 --- /dev/null +++ b/app/src/main/res/layout/activity_demo13.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_demo14.xml b/app/src/main/res/layout/activity_demo14.xml new file mode 100644 index 0000000..073d3bb --- /dev/null +++ b/app/src/main/res/layout/activity_demo14.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_demo2.xml b/app/src/main/res/layout/activity_demo2.xml new file mode 100644 index 0000000..5aaf11f --- /dev/null +++ b/app/src/main/res/layout/activity_demo2.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_demo3.xml b/app/src/main/res/layout/activity_demo3.xml new file mode 100644 index 0000000..8a34a1c --- /dev/null +++ b/app/src/main/res/layout/activity_demo3.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_demo4.xml b/app/src/main/res/layout/activity_demo4.xml new file mode 100644 index 0000000..843a54e --- /dev/null +++ b/app/src/main/res/layout/activity_demo4.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_demo5.xml b/app/src/main/res/layout/activity_demo5.xml new file mode 100644 index 0000000..942d2ae --- /dev/null +++ b/app/src/main/res/layout/activity_demo5.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_demo6.xml b/app/src/main/res/layout/activity_demo6.xml new file mode 100644 index 0000000..8d98d26 --- /dev/null +++ b/app/src/main/res/layout/activity_demo6.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_demo7.xml b/app/src/main/res/layout/activity_demo7.xml new file mode 100644 index 0000000..3b50530 --- /dev/null +++ b/app/src/main/res/layout/activity_demo7.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_demo8.xml b/app/src/main/res/layout/activity_demo8.xml new file mode 100644 index 0000000..4994f92 --- /dev/null +++ b/app/src/main/res/layout/activity_demo8.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_demo9.xml b/app/src/main/res/layout/activity_demo9.xml new file mode 100644 index 0000000..548eda5 --- /dev/null +++ b/app/src/main/res/layout/activity_demo9.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..d9fd19f --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/btn_item.xml b/app/src/main/res/layout/btn_item.xml new file mode 100644 index 0000000..196a9b6 --- /dev/null +++ b/app/src/main/res/layout/btn_item.xml @@ -0,0 +1,9 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/comment_item.xml b/app/src/main/res/layout/comment_item.xml new file mode 100644 index 0000000..385b30b --- /dev/null +++ b/app/src/main/res/layout/comment_item.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/grid_item.xml b/app/src/main/res/layout/grid_item.xml new file mode 100644 index 0000000..55b48a2 --- /dev/null +++ b/app/src/main/res/layout/grid_item.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/grid_text.xml b/app/src/main/res/layout/grid_text.xml new file mode 100644 index 0000000..b2abf34 --- /dev/null +++ b/app/src/main/res/layout/grid_text.xml @@ -0,0 +1,17 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/home_item.xml b/app/src/main/res/layout/home_item.xml new file mode 100644 index 0000000..5e0d6fe --- /dev/null +++ b/app/src/main/res/layout/home_item.xml @@ -0,0 +1,37 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/home_tab_item.xml b/app/src/main/res/layout/home_tab_item.xml new file mode 100644 index 0000000..a748b83 --- /dev/null +++ b/app/src/main/res/layout/home_tab_item.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_so.xml b/app/src/main/res/layout/item_so.xml new file mode 100644 index 0000000..cc9662c --- /dev/null +++ b/app/src/main/res/layout/item_so.xml @@ -0,0 +1,31 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/list_btn.xml b/app/src/main/res/layout/list_btn.xml new file mode 100644 index 0000000..fc2d542 --- /dev/null +++ b/app/src/main/res/layout/list_btn.xml @@ -0,0 +1,15 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/list_icon.xml b/app/src/main/res/layout/list_icon.xml new file mode 100644 index 0000000..b881313 --- /dev/null +++ b/app/src/main/res/layout/list_icon.xml @@ -0,0 +1,23 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/list_item.xml b/app/src/main/res/layout/list_item.xml new file mode 100644 index 0000000..be21c79 --- /dev/null +++ b/app/src/main/res/layout/list_item.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/main_load.xml b/app/src/main/res/layout/main_load.xml new file mode 100644 index 0000000..c6418ba --- /dev/null +++ b/app/src/main/res/layout/main_load.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/tab_item.xml b/app/src/main/res/layout/tab_item.xml new file mode 100644 index 0000000..9191e1b --- /dev/null +++ b/app/src/main/res/layout/tab_item.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/top_bar.xml b/app/src/main/res/layout/top_bar.xml new file mode 100644 index 0000000..5ff730f --- /dev/null +++ b/app/src/main/res/layout/top_bar.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/user_comment.xml b/app/src/main/res/layout/user_comment.xml new file mode 100644 index 0000000..3077f70 --- /dev/null +++ b/app/src/main/res/layout/user_comment.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/user_home.xml b/app/src/main/res/layout/user_home.xml new file mode 100644 index 0000000..1589afe --- /dev/null +++ b/app/src/main/res/layout/user_home.xml @@ -0,0 +1,255 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/user_info.xml b/app/src/main/res/layout/user_info.xml new file mode 100644 index 0000000..b49736f --- /dev/null +++ b/app/src/main/res/layout/user_info.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/user_list.xml b/app/src/main/res/layout/user_list.xml new file mode 100644 index 0000000..786c140 --- /dev/null +++ b/app/src/main/res/layout/user_list.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/user_menu.xml b/app/src/main/res/layout/user_menu.xml new file mode 100644 index 0000000..45794fc --- /dev/null +++ b/app/src/main/res/layout/user_menu.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/user_share.xml b/app/src/main/res/layout/user_share.xml new file mode 100644 index 0000000..20aff6f --- /dev/null +++ b/app/src/main/res/layout/user_share.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/video_item.xml b/app/src/main/res/layout/video_item.xml new file mode 100644 index 0000000..a4e819e --- /dev/null +++ b/app/src/main/res/layout/video_item.xml @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/video_page.xml b/app/src/main/res/layout/video_page.xml new file mode 100644 index 0000000..d9a7656 --- /dev/null +++ b/app/src/main/res/layout/video_page.xml @@ -0,0 +1,31 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/view_page.xml b/app/src/main/res/layout/view_page.xml new file mode 100644 index 0000000..18ebc75 --- /dev/null +++ b/app/src/main/res/layout/view_page.xml @@ -0,0 +1,16 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-xhdpi/bg.jpg b/app/src/main/res/mipmap-xhdpi/bg.jpg new file mode 100644 index 0000000..c970cc5 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/bg.jpg differ diff --git a/app/src/main/res/mipmap-xhdpi/cover_load.png b/app/src/main/res/mipmap-xhdpi/cover_load.png new file mode 100644 index 0000000..206e0df Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/cover_load.png differ diff --git a/app/src/main/res/mipmap-xhdpi/cover_more.png b/app/src/main/res/mipmap-xhdpi/cover_more.png new file mode 100644 index 0000000..b406f49 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/cover_more.png differ diff --git a/app/src/main/res/mipmap-xhdpi/follow_add.png b/app/src/main/res/mipmap-xhdpi/follow_add.png new file mode 100644 index 0000000..a8250d1 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/follow_add.png differ diff --git a/app/src/main/res/mipmap-xhdpi/follow_ok.png b/app/src/main/res/mipmap-xhdpi/follow_ok.png new file mode 100644 index 0000000..bc9ced8 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/follow_ok.png differ diff --git a/app/src/main/res/mipmap-xhdpi/home_black.png b/app/src/main/res/mipmap-xhdpi/home_black.png new file mode 100644 index 0000000..dcf6637 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/home_black.png differ diff --git a/app/src/main/res/mipmap-xhdpi/home_msg.png b/app/src/main/res/mipmap-xhdpi/home_msg.png new file mode 100644 index 0000000..781943d Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/home_msg.png differ diff --git a/app/src/main/res/mipmap-xhdpi/home_share.png b/app/src/main/res/mipmap-xhdpi/home_share.png new file mode 100644 index 0000000..23dcce9 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/home_share.png differ diff --git a/app/src/main/res/mipmap-xhdpi/home_warn.png b/app/src/main/res/mipmap-xhdpi/home_warn.png new file mode 100644 index 0000000..a03d5ca Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/home_warn.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon.png b/app/src/main/res/mipmap-xhdpi/icon.png new file mode 100644 index 0000000..fc374f6 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_add.png b/app/src/main/res/mipmap-xhdpi/icon_add.png new file mode 100644 index 0000000..72a0241 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_add.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_back.png b/app/src/main/res/mipmap-xhdpi/icon_back.png new file mode 100644 index 0000000..d3a7fa0 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_back.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_bhcs.png b/app/src/main/res/mipmap-xhdpi/icon_bhcs.png new file mode 100644 index 0000000..5fac9eb Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_bhcs.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_bhcs_1.png b/app/src/main/res/mipmap-xhdpi/icon_bhcs_1.png new file mode 100644 index 0000000..733154c Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_bhcs_1.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_bottom.png b/app/src/main/res/mipmap-xhdpi/icon_bottom.png new file mode 100644 index 0000000..228a15e Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_bottom.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_bottom_black.png b/app/src/main/res/mipmap-xhdpi/icon_bottom_black.png new file mode 100644 index 0000000..3d2fa46 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_bottom_black.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_close.png b/app/src/main/res/mipmap-xhdpi/icon_close.png new file mode 100644 index 0000000..5508b6e Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_close.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_close_black.png b/app/src/main/res/mipmap-xhdpi/icon_close_black.png new file mode 100644 index 0000000..c1cae39 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_close_black.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_close_white.png b/app/src/main/res/mipmap-xhdpi/icon_close_white.png new file mode 100644 index 0000000..4e3973a Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_close_white.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_complete.png b/app/src/main/res/mipmap-xhdpi/icon_complete.png new file mode 100644 index 0000000..11239fe Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_complete.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_cwtd.png b/app/src/main/res/mipmap-xhdpi/icon_cwtd.png new file mode 100644 index 0000000..ac6655a Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_cwtd.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_cwtd_1.png b/app/src/main/res/mipmap-xhdpi/icon_cwtd_1.png new file mode 100644 index 0000000..20e07f6 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_cwtd_1.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_dig_cur.png b/app/src/main/res/mipmap-xhdpi/icon_dig_cur.png new file mode 100644 index 0000000..ed60bf3 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_dig_cur.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_dig_def.png b/app/src/main/res/mipmap-xhdpi/icon_dig_def.png new file mode 100644 index 0000000..2e6ae3d Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_dig_def.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_down.png b/app/src/main/res/mipmap-xhdpi/icon_down.png new file mode 100644 index 0000000..885b7c1 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_down.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_ewm.png b/app/src/main/res/mipmap-xhdpi/icon_ewm.png new file mode 100644 index 0000000..631e280 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_ewm.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_fav.png b/app/src/main/res/mipmap-xhdpi/icon_fav.png new file mode 100644 index 0000000..70a5a67 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_fav.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_fav_cur.png b/app/src/main/res/mipmap-xhdpi/icon_fav_cur.png new file mode 100644 index 0000000..3945e86 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_fav_cur.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_hqly.png b/app/src/main/res/mipmap-xhdpi/icon_hqly.png new file mode 100644 index 0000000..5637824 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_hqly.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_hqly_1.png b/app/src/main/res/mipmap-xhdpi/icon_hqly_1.png new file mode 100644 index 0000000..7830f86 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_hqly_1.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_hssy.png b/app/src/main/res/mipmap-xhdpi/icon_hssy.png new file mode 100644 index 0000000..645aa49 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_hssy.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_hssy_1.png b/app/src/main/res/mipmap-xhdpi/icon_hssy_1.png new file mode 100644 index 0000000..0b90030 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_hssy_1.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_jdyd.png b/app/src/main/res/mipmap-xhdpi/icon_jdyd.png new file mode 100644 index 0000000..72efb9a Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_jdyd.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_jdyd_1.png b/app/src/main/res/mipmap-xhdpi/icon_jdyd_1.png new file mode 100644 index 0000000..9a7840a Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_jdyd_1.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_jzfw.png b/app/src/main/res/mipmap-xhdpi/icon_jzfw.png new file mode 100644 index 0000000..efc66b4 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_jzfw.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_jzfw_1.png b/app/src/main/res/mipmap-xhdpi/icon_jzfw_1.png new file mode 100644 index 0000000..e308ed2 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_jzfw_1.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_left.png b/app/src/main/res/mipmap-xhdpi/icon_left.png new file mode 100644 index 0000000..2ce8b9b Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_left.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_left_black.png b/app/src/main/res/mipmap-xhdpi/icon_left_black.png new file mode 100644 index 0000000..1374851 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_left_black.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_load.png b/app/src/main/res/mipmap-xhdpi/icon_load.png new file mode 100644 index 0000000..d43e548 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_load.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_lrmr.png b/app/src/main/res/mipmap-xhdpi/icon_lrmr.png new file mode 100644 index 0000000..29a6a16 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_lrmr.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_lrmr_1.png b/app/src/main/res/mipmap-xhdpi/icon_lrmr_1.png new file mode 100644 index 0000000..5a90ddb Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_lrmr_1.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_machine.png b/app/src/main/res/mipmap-xhdpi/icon_machine.png new file mode 100644 index 0000000..6207709 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_machine.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_menu.png b/app/src/main/res/mipmap-xhdpi/icon_menu.png new file mode 100644 index 0000000..bbf1f55 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_menu.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_more.png b/app/src/main/res/mipmap-xhdpi/icon_more.png new file mode 100644 index 0000000..7470dcc Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_more.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_music.png b/app/src/main/res/mipmap-xhdpi/icon_music.png new file mode 100644 index 0000000..cc3e4d9 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_music.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_note.png b/app/src/main/res/mipmap-xhdpi/icon_note.png new file mode 100644 index 0000000..c14a93f Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_note.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_over.png b/app/src/main/res/mipmap-xhdpi/icon_over.png new file mode 100644 index 0000000..ef86da5 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_over.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_play.png b/app/src/main/res/mipmap-xhdpi/icon_play.png new file mode 100644 index 0000000..232d81d Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_play.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_re.png b/app/src/main/res/mipmap-xhdpi/icon_re.png new file mode 100644 index 0000000..71e0206 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_re.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_read.png b/app/src/main/res/mipmap-xhdpi/icon_read.png new file mode 100644 index 0000000..35accf1 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_read.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_right.png b/app/src/main/res/mipmap-xhdpi/icon_right.png new file mode 100644 index 0000000..e58896c Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_right.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_right_black.png b/app/src/main/res/mipmap-xhdpi/icon_right_black.png new file mode 100644 index 0000000..0492410 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_right_black.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_say.png b/app/src/main/res/mipmap-xhdpi/icon_say.png new file mode 100644 index 0000000..8b8d47b Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_say.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_search.png b/app/src/main/res/mipmap-xhdpi/icon_search.png new file mode 100644 index 0000000..83d4b80 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_search.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_set.png b/app/src/main/res/mipmap-xhdpi/icon_set.png new file mode 100644 index 0000000..654e5fa Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_set.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_share.png b/app/src/main/res/mipmap-xhdpi/icon_share.png new file mode 100644 index 0000000..6151fbd Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_share.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_sjhc.png b/app/src/main/res/mipmap-xhdpi/icon_sjhc.png new file mode 100644 index 0000000..7ce1b7e Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_sjhc.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_sjhc_1.png b/app/src/main/res/mipmap-xhdpi/icon_sjhc_1.png new file mode 100644 index 0000000..5aad576 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_sjhc_1.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_so.png b/app/src/main/res/mipmap-xhdpi/icon_so.png new file mode 100644 index 0000000..678b0d6 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_so.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_top.png b/app/src/main/res/mipmap-xhdpi/icon_top.png new file mode 100644 index 0000000..8208e92 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_top.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_top_black.png b/app/src/main/res/mipmap-xhdpi/icon_top_black.png new file mode 100644 index 0000000..5e49257 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_top_black.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_up.png b/app/src/main/res/mipmap-xhdpi/icon_up.png new file mode 100644 index 0000000..1422f20 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_up.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_user.png b/app/src/main/res/mipmap-xhdpi/icon_user.png new file mode 100644 index 0000000..83fd016 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_user.png differ diff --git a/app/src/main/res/mipmap-xhdpi/icon_xin.png b/app/src/main/res/mipmap-xhdpi/icon_xin.png new file mode 100644 index 0000000..61e784b Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/icon_xin.png differ diff --git a/app/src/main/res/mipmap-xhdpi/load_1.png b/app/src/main/res/mipmap-xhdpi/load_1.png new file mode 100644 index 0000000..7405707 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/load_1.png differ diff --git a/app/src/main/res/mipmap-xhdpi/load_10.png b/app/src/main/res/mipmap-xhdpi/load_10.png new file mode 100644 index 0000000..0d8cc49 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/load_10.png differ diff --git a/app/src/main/res/mipmap-xhdpi/load_11.png b/app/src/main/res/mipmap-xhdpi/load_11.png new file mode 100644 index 0000000..3c9bacf Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/load_11.png differ diff --git a/app/src/main/res/mipmap-xhdpi/load_12.png b/app/src/main/res/mipmap-xhdpi/load_12.png new file mode 100644 index 0000000..553d1d7 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/load_12.png differ diff --git a/app/src/main/res/mipmap-xhdpi/load_13.png b/app/src/main/res/mipmap-xhdpi/load_13.png new file mode 100644 index 0000000..8889550 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/load_13.png differ diff --git a/app/src/main/res/mipmap-xhdpi/load_14.png b/app/src/main/res/mipmap-xhdpi/load_14.png new file mode 100644 index 0000000..3177520 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/load_14.png differ diff --git a/app/src/main/res/mipmap-xhdpi/load_15.png b/app/src/main/res/mipmap-xhdpi/load_15.png new file mode 100644 index 0000000..6c9e3cd Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/load_15.png differ diff --git a/app/src/main/res/mipmap-xhdpi/load_16.png b/app/src/main/res/mipmap-xhdpi/load_16.png new file mode 100644 index 0000000..efee392 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/load_16.png differ diff --git a/app/src/main/res/mipmap-xhdpi/load_17.png b/app/src/main/res/mipmap-xhdpi/load_17.png new file mode 100644 index 0000000..90f68af Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/load_17.png differ diff --git a/app/src/main/res/mipmap-xhdpi/load_18.png b/app/src/main/res/mipmap-xhdpi/load_18.png new file mode 100644 index 0000000..59e5477 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/load_18.png differ diff --git a/app/src/main/res/mipmap-xhdpi/load_19.png b/app/src/main/res/mipmap-xhdpi/load_19.png new file mode 100644 index 0000000..2f3548c Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/load_19.png differ diff --git a/app/src/main/res/mipmap-xhdpi/load_2.png b/app/src/main/res/mipmap-xhdpi/load_2.png new file mode 100644 index 0000000..544f0f3 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/load_2.png differ diff --git a/app/src/main/res/mipmap-xhdpi/load_20.png b/app/src/main/res/mipmap-xhdpi/load_20.png new file mode 100644 index 0000000..c458462 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/load_20.png differ diff --git a/app/src/main/res/mipmap-xhdpi/load_21.png b/app/src/main/res/mipmap-xhdpi/load_21.png new file mode 100644 index 0000000..db694be Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/load_21.png differ diff --git a/app/src/main/res/mipmap-xhdpi/load_22.png b/app/src/main/res/mipmap-xhdpi/load_22.png new file mode 100644 index 0000000..b8f47ff Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/load_22.png differ diff --git a/app/src/main/res/mipmap-xhdpi/load_3.png b/app/src/main/res/mipmap-xhdpi/load_3.png new file mode 100644 index 0000000..837ea6c Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/load_3.png differ diff --git a/app/src/main/res/mipmap-xhdpi/load_4.png b/app/src/main/res/mipmap-xhdpi/load_4.png new file mode 100644 index 0000000..dee22af Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/load_4.png differ diff --git a/app/src/main/res/mipmap-xhdpi/load_5.png b/app/src/main/res/mipmap-xhdpi/load_5.png new file mode 100644 index 0000000..54362c9 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/load_5.png differ diff --git a/app/src/main/res/mipmap-xhdpi/load_6.png b/app/src/main/res/mipmap-xhdpi/load_6.png new file mode 100644 index 0000000..499e8f8 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/load_6.png differ diff --git a/app/src/main/res/mipmap-xhdpi/load_7.png b/app/src/main/res/mipmap-xhdpi/load_7.png new file mode 100644 index 0000000..7653416 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/load_7.png differ diff --git a/app/src/main/res/mipmap-xhdpi/load_8.png b/app/src/main/res/mipmap-xhdpi/load_8.png new file mode 100644 index 0000000..bf67caf Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/load_8.png differ diff --git a/app/src/main/res/mipmap-xhdpi/load_9.png b/app/src/main/res/mipmap-xhdpi/load_9.png new file mode 100644 index 0000000..4ae02f0 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/load_9.png differ diff --git a/app/src/main/res/mipmap-xhdpi/pull_back.png b/app/src/main/res/mipmap-xhdpi/pull_back.png new file mode 100644 index 0000000..3894de0 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/pull_back.png differ diff --git a/app/src/main/res/mipmap-xhdpi/pull_rider.png b/app/src/main/res/mipmap-xhdpi/pull_rider.png new file mode 100644 index 0000000..bb21c7b Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/pull_rider.png differ diff --git a/app/src/main/res/mipmap-xhdpi/pull_sun.png b/app/src/main/res/mipmap-xhdpi/pull_sun.png new file mode 100644 index 0000000..6b2efe9 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/pull_sun.png differ diff --git a/app/src/main/res/mipmap-xhdpi/pull_wheel.png b/app/src/main/res/mipmap-xhdpi/pull_wheel.png new file mode 100644 index 0000000..6c81438 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/pull_wheel.png differ diff --git a/app/src/main/res/mipmap-xhdpi/radius_back.png b/app/src/main/res/mipmap-xhdpi/radius_back.png new file mode 100644 index 0000000..7d3ebf7 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/radius_back.png differ diff --git a/app/src/main/res/mipmap-xhdpi/radius_set.png b/app/src/main/res/mipmap-xhdpi/radius_set.png new file mode 100644 index 0000000..162db62 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/radius_set.png differ diff --git a/app/src/main/res/mipmap-xhdpi/seek_cur.png b/app/src/main/res/mipmap-xhdpi/seek_cur.png new file mode 100644 index 0000000..b5847e3 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/seek_cur.png differ diff --git a/app/src/main/res/mipmap-xhdpi/seek_def.png b/app/src/main/res/mipmap-xhdpi/seek_def.png new file mode 100644 index 0000000..321585d Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/seek_def.png differ diff --git a/app/src/main/res/mipmap-xhdpi/seek_video_cur.png b/app/src/main/res/mipmap-xhdpi/seek_video_cur.png new file mode 100644 index 0000000..1e37dec Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/seek_video_cur.png differ diff --git a/app/src/main/res/mipmap-xhdpi/seek_video_def.png b/app/src/main/res/mipmap-xhdpi/seek_video_def.png new file mode 100644 index 0000000..cc1563a Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/seek_video_def.png differ diff --git a/app/src/main/res/mipmap-xhdpi/send_at.png b/app/src/main/res/mipmap-xhdpi/send_at.png new file mode 100644 index 0000000..1ed84da Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/send_at.png differ diff --git a/app/src/main/res/mipmap-xhdpi/send_bq.png b/app/src/main/res/mipmap-xhdpi/send_bq.png new file mode 100644 index 0000000..53e110e Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/send_bq.png differ diff --git a/app/src/main/res/mipmap-xhdpi/send_icon.png b/app/src/main/res/mipmap-xhdpi/send_icon.png new file mode 100644 index 0000000..aa77aab Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/send_icon.png differ diff --git a/app/src/main/res/mipmap-xhdpi/send_submit.png b/app/src/main/res/mipmap-xhdpi/send_submit.png new file mode 100644 index 0000000..ef6dd6d Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/send_submit.png differ diff --git a/app/src/main/res/mipmap-xhdpi/sex_1.png b/app/src/main/res/mipmap-xhdpi/sex_1.png new file mode 100644 index 0000000..d397ed0 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/sex_1.png differ diff --git a/app/src/main/res/mipmap-xhdpi/sex_2.png b/app/src/main/res/mipmap-xhdpi/sex_2.png new file mode 100644 index 0000000..1902bc4 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/sex_2.png differ diff --git a/app/src/main/res/mipmap-xhdpi/share_and.png b/app/src/main/res/mipmap-xhdpi/share_and.png new file mode 100644 index 0000000..bc53892 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/share_and.png differ diff --git a/app/src/main/res/mipmap-xhdpi/share_code.png b/app/src/main/res/mipmap-xhdpi/share_code.png new file mode 100644 index 0000000..56601e6 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/share_code.png differ diff --git a/app/src/main/res/mipmap-xhdpi/share_down.png b/app/src/main/res/mipmap-xhdpi/share_down.png new file mode 100644 index 0000000..1ce4c70 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/share_down.png differ diff --git a/app/src/main/res/mipmap-xhdpi/share_edit.png b/app/src/main/res/mipmap-xhdpi/share_edit.png new file mode 100644 index 0000000..6045729 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/share_edit.png differ diff --git a/app/src/main/res/mipmap-xhdpi/share_link.png b/app/src/main/res/mipmap-xhdpi/share_link.png new file mode 100644 index 0000000..1951777 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/share_link.png differ diff --git a/app/src/main/res/mipmap-xhdpi/share_no.png b/app/src/main/res/mipmap-xhdpi/share_no.png new file mode 100644 index 0000000..0013071 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/share_no.png differ diff --git a/app/src/main/res/mipmap-xhdpi/share_pyq.png b/app/src/main/res/mipmap-xhdpi/share_pyq.png new file mode 100644 index 0000000..1136570 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/share_pyq.png differ diff --git a/app/src/main/res/mipmap-xhdpi/share_qq.png b/app/src/main/res/mipmap-xhdpi/share_qq.png new file mode 100644 index 0000000..0da6733 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/share_qq.png differ diff --git a/app/src/main/res/mipmap-xhdpi/share_qz.png b/app/src/main/res/mipmap-xhdpi/share_qz.png new file mode 100644 index 0000000..e963c44 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/share_qz.png differ diff --git a/app/src/main/res/mipmap-xhdpi/share_relay.png b/app/src/main/res/mipmap-xhdpi/share_relay.png new file mode 100644 index 0000000..d164807 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/share_relay.png differ diff --git a/app/src/main/res/mipmap-xhdpi/share_send.png b/app/src/main/res/mipmap-xhdpi/share_send.png new file mode 100644 index 0000000..d254041 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/share_send.png differ diff --git a/app/src/main/res/mipmap-xhdpi/share_wb.png b/app/src/main/res/mipmap-xhdpi/share_wb.png new file mode 100644 index 0000000..c8a5e62 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/share_wb.png differ diff --git a/app/src/main/res/mipmap-xhdpi/share_wran.png b/app/src/main/res/mipmap-xhdpi/share_wran.png new file mode 100644 index 0000000..da9f75d Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/share_wran.png differ diff --git a/app/src/main/res/mipmap-xhdpi/share_wx.png b/app/src/main/res/mipmap-xhdpi/share_wx.png new file mode 100644 index 0000000..94810fc Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/share_wx.png differ diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml new file mode 100644 index 0000000..f8613e7 --- /dev/null +++ b/app/src/main/res/values/attrs.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..8731fcb --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,9 @@ + + + #00acf1 + #049AD6 + #E91E4D + #161722 + #555555 + #999999 + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..ac4a533 --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + DrawerApp + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..01ba5cb --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,399 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/xml/network_security_config.xml b/app/src/main/res/xml/network_security_config.xml new file mode 100644 index 0000000..dca93c0 --- /dev/null +++ b/app/src/main/res/xml/network_security_config.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..18f2562 --- /dev/null +++ b/build.gradle @@ -0,0 +1,23 @@ + +buildscript { + repositories { + google() + mavenCentral() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.5.2' + classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' + } +} + +allprojects { + repositories { + google() + mavenCentral() + maven { url "https://jitpack.io" } + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/drawer/build.gradle b/drawer/build.gradle new file mode 100644 index 0000000..6bb1aa4 --- /dev/null +++ b/drawer/build.gradle @@ -0,0 +1,23 @@ +apply plugin: 'com.android.library' +apply plugin: 'com.github.dcendents.android-maven' +group='com.github.Leaqi' +version='1.0' + +android { + compileSdkVersion 29 + buildToolsVersion "29.0.3" + + defaultConfig { + minSdkVersion 14 + targetSdkVersion 29 + versionCode 1 + versionName version + consumerProguardFiles 'consumer-rules.pro' + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } +} \ No newline at end of file diff --git a/drawer/consumer-rules.pro b/drawer/consumer-rules.pro new file mode 100644 index 0000000..e69de29 diff --git a/drawer/proguard-rules.pro b/drawer/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/drawer/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/drawer/src/main/AndroidManifest.xml b/drawer/src/main/AndroidManifest.xml new file mode 100644 index 0000000..1ab2970 --- /dev/null +++ b/drawer/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/drawer/src/main/java/cn/leaqi/drawer/AnimThread.java b/drawer/src/main/java/cn/leaqi/drawer/AnimThread.java new file mode 100644 index 0000000..a439be1 --- /dev/null +++ b/drawer/src/main/java/cn/leaqi/drawer/AnimThread.java @@ -0,0 +1,126 @@ +/* + Copyright 2022 Leaqi + + 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 cn.leaqi.drawer; + +import android.view.animation.AccelerateDecelerateInterpolator; +import android.view.animation.Interpolator; + +/** + * AnimThread by animation processing class + * Created by Leaqi. + * Github: https://github.com/Leaqi + */ +public class AnimThread extends Thread { + + private static int FPS = 100; + + private int setDuration; + private boolean isStop = false; + private boolean isEnd = false; + private boolean isAlive = true; + + private Interpolator animInterpolator; + + public AnimThread(int duration, Interpolator interpolator) { + setDuration = duration; + animInterpolator = interpolator == null ? new AccelerateDecelerateInterpolator() : interpolator; + onInit(); + start(); + } + + protected void onInit() {} + + protected void onEnd() {} + + protected void onUpdate(float value) {} + + public void setStop() { + isStop = true; + } + + public void setEnd() { + isEnd = true; + } + + public void setAlive() { + isAlive = false; + } + + public static void setFPS(int num) { + FPS = num; + } + + public boolean getStop() { + return isStop; + } + + public boolean getEnd() { + return isEnd; + } + + public boolean getAlive() { + return isAlive; + } + + public static int getFPS() { + return FPS; + } + + public float getInterpolation(float t) { + if (animInterpolator != null) { + return animInterpolator.getInterpolation(t); + } else { + return t; + } + } + + @Override + public void run() { + if (setDuration > 0) { + int sSleep = Math.round(1000 / FPS); + int iNum = 0; + float eNum = ((float) setDuration / 1000) * FPS; + float value = 0; + while (iNum < eNum) { + if (isEnd) break; + if (isStop) return; + try { + Thread.sleep(sSleep); + } catch (InterruptedException e) { + e.printStackTrace(); + } + value = getInterpolation(iNum / eNum); + onUpdate(value); + iNum++; + } + if (value < 1) { + onUpdate(1); + } + } else { + onUpdate(1); + } + onEnd(); + } + + public static boolean isThread(AnimThread thread) { + if (thread != null) { + return thread.getAlive() || thread.isAlive(); + } else { + return false; + } + } + +} diff --git a/drawer/src/main/java/cn/leaqi/drawer/DrawerHolder.java b/drawer/src/main/java/cn/leaqi/drawer/DrawerHolder.java new file mode 100644 index 0000000..5f19fca --- /dev/null +++ b/drawer/src/main/java/cn/leaqi/drawer/DrawerHolder.java @@ -0,0 +1,116 @@ +/* + Copyright 2022 Leaqi + + 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 cn.leaqi.drawer; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * The function of DrawerHolder is to save the state of SwipeDrawer + * Created by Leaqi. + * Github: https://github.com/Leaqi + */ +public class DrawerHolder implements OnDrawerSwitch { + + private Map listView = Collections.synchronizedMap(new HashMap()); + private Map listMap = Collections.synchronizedMap(new HashMap()); + + public void bindHolder(final SwipeDrawer view, final Object obj) { + try { + if (!listView.containsKey(view)) { + view.setOnDrawerSwitch(this); + } + listView.put(view, obj); + if (listMap.containsKey(obj)) { + final Integer getData = listMap.get(obj); + if (getData != null) { + if (view.getShow() && view.getDirection() != getData) { + view.closeDrawer(false, false); + } + view.openDrawer(getData, false, false); + } + } else { + if (view.getShow()) { + view.closeDrawer(false, false); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void delHolder(SwipeDrawer view) { + try { + if (listView.containsKey(view)) { + Object obj = listView.get(view); + if (obj == null) return; + listMap.remove(obj); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void clearHolder() { + try { + for (Map.Entry val : listView.entrySet()) { + val.getKey().forceClose(false); + } + listMap.clear(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void clearView() { + try { + listView.clear(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void clear() { + try { + clearHolder(); + listView.clear(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void onOpen(SwipeDrawer view) { + try { + if (listView.containsKey(view)) { + Object obj = listView.get(view); + if (obj == null) return; + if (!listMap.containsKey(obj)) { + listMap.put(obj, view.getDirection()); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void onClose(SwipeDrawer view) { + delHolder(view); + } + +} diff --git a/drawer/src/main/java/cn/leaqi/drawer/OnDrawerChange.java b/drawer/src/main/java/cn/leaqi/drawer/OnDrawerChange.java new file mode 100644 index 0000000..25184a8 --- /dev/null +++ b/drawer/src/main/java/cn/leaqi/drawer/OnDrawerChange.java @@ -0,0 +1,5 @@ +package cn.leaqi.drawer; + +public interface OnDrawerChange { + void onChange(SwipeDrawer view, int state, float progress); +} diff --git a/drawer/src/main/java/cn/leaqi/drawer/OnDrawerState.java b/drawer/src/main/java/cn/leaqi/drawer/OnDrawerState.java new file mode 100644 index 0000000..ec2bad6 --- /dev/null +++ b/drawer/src/main/java/cn/leaqi/drawer/OnDrawerState.java @@ -0,0 +1,9 @@ +package cn.leaqi.drawer; + +public interface OnDrawerState { + void onStart(int type); + void onMove(int type, float progress); + void onOpen(int type); + void onClose(int type); + void onCancel(int type); +} diff --git a/drawer/src/main/java/cn/leaqi/drawer/OnDrawerSwitch.java b/drawer/src/main/java/cn/leaqi/drawer/OnDrawerSwitch.java new file mode 100644 index 0000000..b5a857e --- /dev/null +++ b/drawer/src/main/java/cn/leaqi/drawer/OnDrawerSwitch.java @@ -0,0 +1,6 @@ +package cn.leaqi.drawer; + +public interface OnDrawerSwitch { + void onOpen(SwipeDrawer view); + void onClose(SwipeDrawer view); +} diff --git a/drawer/src/main/java/cn/leaqi/drawer/SwipeDrawer.java b/drawer/src/main/java/cn/leaqi/drawer/SwipeDrawer.java new file mode 100644 index 0000000..1953991 --- /dev/null +++ b/drawer/src/main/java/cn/leaqi/drawer/SwipeDrawer.java @@ -0,0 +1,1643 @@ +/* + Copyright 2022 Leaqi + + 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 cn.leaqi.drawer; + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.view.ViewParent; +import android.view.animation.AnimationUtils; +import android.view.animation.Interpolator; + +/** + * SwipeDrawer is an layout class + * Created by Leaqi. + * Github: https://github.com/Leaqi + */ +public class SwipeDrawer extends ViewGroup { + + public static final int MODE_DRAWER = 0; + public static final int MODE_COVER = 1; + public static final int MODE_FIXED = 2; + + public static final int DIRECTION_ORDER = -1; + public static final int DIRECTION_MAIN = 0; + public static final int DIRECTION_LEFT = 1; + public static final int DIRECTION_TOP = 2; + public static final int DIRECTION_RIGHT = 3; + public static final int DIRECTION_BOTTOM = 4; + + public static final int MASK_NONE = 0; + public static final int MASK_GENERAL = 1; + public static final int MASK_GRADUAL = 2; + + public static final int TYPE_VIEW = 0; + public static final int TYPE_SCROLL_Y = 1; + public static final int TYPE_SCROLL_X = 2; + + public static final int MAIN_OPEN_NONE = 0; + public static final int MAIN_OPEN_CLICK = 1; + public static final int MAIN_OPEN_INTERCEPT = 2; + + public static final int STATE_START = 0; + public static final int STATE_OPEN = 1; + public static final int STATE_CLOSE = 2; + public static final int STATE_PROGRESS = 3; + public static final int STATE_ANIM_OVER = 4; + public static final int STATE_CALL_OPEN = 5; + public static final int STATE_CALL_CLOSE = 6; + public static final int STATE_CANCEL = 7; + public static final int STATE_DRAG_INTO = 8; + public static final int STATE_DRAG_OUT = 9; + + private int open = 0; + private int mask = 0; + private int mode = 0; + private int leftMode = -1; + private int topMode = -1; + private int rightMode = -1; + private int bottomMode = -1; + private int lastMode = 0; + private int mainType = 0; + private int leftType = 0; + private int topType = 0; + private int rightType = 0; + private int bottomType = 0; + private int mainOpen = 0; + private int parentId = -1; + private int mainScrollId = -1; + private int leftScrollId = -1; + private int topScrollId = -1; + private int rightScrollId = -1; + private int bottomScrollId = -1; + private int mainId = -1; + private int leftId = -1; + private int topId = -1; + private int rightId = -1; + private int bottomId = -1; + private SwipeDrawer parentDrawer = null; + private ViewUtils mainScroll = null; + private ViewUtils leftScroll = null; + private ViewUtils topScroll = null; + private ViewUtils rightScroll = null; + private ViewUtils bottomScroll = null; + private ViewUtils mainLayout = null; + private ViewUtils leftLayout = null; + private ViewUtils topLayout = null; + private ViewUtils rightLayout = null; + private ViewUtils bottomLayout = null; + private View maskView = null; + private float shrinkRange = 5; + private int dragDamping = 10; + private int dragRange = 0; + private int maxDragSize = 0; + private int duration = 200; + private int maskColor = -2147483648; + private boolean leftDragOpen = true; + private boolean topDragOpen = true; + private boolean rightDragOpen = true; + private boolean bottomDragOpen = true; + private boolean showLayout = false; + private boolean autoClose = false; + private boolean maskClose = false; + private boolean dragClose = true; + private boolean scrollOuterDrag = false; + private static boolean allIntercept = false; + private static SwipeDrawer autoDrawer = null; + + private int downX = 0; + private int downY = 0; + private int downMs = 0; + + private boolean isInit = false; + private boolean isFinish = false; + private boolean isTouch = false; + private boolean isIntercept = false; + private boolean isShow = false; + private boolean arriveRange = false; + private boolean isArriveCall = false; + private int parentIntercept = 0; + private int inDirection = -1; + private float lastProgress = -1; + + private AnimThread animThread = null; + + private OnDrawerState onDrawerState = null; + private OnDrawerSwitch onDrawerSwitch = null; + private OnDrawerChange onDrawerChange = null; + private Interpolator animInterpolator = null; + + public SwipeDrawer(Context context) { + super(context); + attrInit(context, null); + } + + public SwipeDrawer(Context context, AttributeSet attrs) { + super(context, attrs); + attrInit(context, attrs); + } + + public SwipeDrawer(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + attrInit(context, attrs); + } + + private void attrInit(Context context, AttributeSet attr) { + if (attr != null) { + final TypedArray attrArr = context.obtainStyledAttributes(attr, R.styleable.SwipeDrawer); + open = attrArr.getInteger(R.styleable.SwipeDrawer_open, open); + int getMode = attrArr.getInteger(R.styleable.SwipeDrawer_mode, mode); + int getMask = attrArr.getInteger(R.styleable.SwipeDrawer_mask, mask); + int getLeftMode = attrArr.getInteger(R.styleable.SwipeDrawer_leftMode, leftMode); + int getTopMode = attrArr.getInteger(R.styleable.SwipeDrawer_topMode, topMode); + int getRightMode = attrArr.getInteger(R.styleable.SwipeDrawer_rightMode, rightMode); + int getBottomMode = attrArr.getInteger(R.styleable.SwipeDrawer_bottomMode, bottomMode); + int getMainType = attrArr.getInteger(R.styleable.SwipeDrawer_mainType, mainType); + int getLeftType = attrArr.getInteger(R.styleable.SwipeDrawer_leftType, leftType); + int getTopType = attrArr.getInteger(R.styleable.SwipeDrawer_topType, topType); + int getRightType = attrArr.getInteger(R.styleable.SwipeDrawer_rightType, rightType); + int getBottomType = attrArr.getInteger(R.styleable.SwipeDrawer_bottomType, bottomType); + int getMainOpen = attrArr.getInteger(R.styleable.SwipeDrawer_mainOpen, mainOpen); + float getShrinkRange = attrArr.getFloat(R.styleable.SwipeDrawer_shrinkRange, shrinkRange); + int getDragDamping = attrArr.getInteger(R.styleable.SwipeDrawer_dragDamping, dragDamping); + int getDragRange = attrArr.getDimensionPixelSize(R.styleable.SwipeDrawer_dragRange, dragRange); + int getMaxDragSize = attrArr.getDimensionPixelSize(R.styleable.SwipeDrawer_maxDragSize, maxDragSize); + int getDuration = attrArr.getInteger(R.styleable.SwipeDrawer_duration, duration); + int getMaskColor = attrArr.getColor(R.styleable.SwipeDrawer_maskColor, maskColor); + int getInterpolatorId = attrArr.getResourceId(R.styleable.SwipeDrawer_interpolator, -1); + leftDragOpen = attrArr.getBoolean(R.styleable.SwipeDrawer_leftDragOpen, leftDragOpen); + topDragOpen = attrArr.getBoolean(R.styleable.SwipeDrawer_topDragOpen, topDragOpen); + rightDragOpen = attrArr.getBoolean(R.styleable.SwipeDrawer_rightDragOpen, rightDragOpen); + bottomDragOpen = attrArr.getBoolean(R.styleable.SwipeDrawer_bottomDragOpen, bottomDragOpen); + showLayout = attrArr.getBoolean(R.styleable.SwipeDrawer_showLayout, showLayout); + autoClose = attrArr.getBoolean(R.styleable.SwipeDrawer_autoClose, autoClose); + maskClose = attrArr.getBoolean(R.styleable.SwipeDrawer_maskClose, maskClose); + dragClose = attrArr.getBoolean(R.styleable.SwipeDrawer_dragClose, dragClose); + scrollOuterDrag = attrArr.getBoolean(R.styleable.SwipeDrawer_scrollOuterDrag, scrollOuterDrag); + parentId = attrArr.getResourceId(R.styleable.SwipeDrawer_parentDrawer, parentId); + mainScrollId = attrArr.getResourceId(R.styleable.SwipeDrawer_mainScroll, mainScrollId); + leftScrollId = attrArr.getResourceId(R.styleable.SwipeDrawer_leftScroll, leftScrollId); + topScrollId = attrArr.getResourceId(R.styleable.SwipeDrawer_topScroll, topScrollId); + rightScrollId = attrArr.getResourceId(R.styleable.SwipeDrawer_rightScroll, rightScrollId); + bottomScrollId = attrArr.getResourceId(R.styleable.SwipeDrawer_bottomScroll, bottomScrollId); + mainId = attrArr.getResourceId(R.styleable.SwipeDrawer_mainLayout, mainId); + leftId = attrArr.getResourceId(R.styleable.SwipeDrawer_leftLayout, leftId); + topId = attrArr.getResourceId(R.styleable.SwipeDrawer_topLayout, topId); + rightId = attrArr.getResourceId(R.styleable.SwipeDrawer_rightLayout, rightId); + bottomId = attrArr.getResourceId(R.styleable.SwipeDrawer_bottomLayout, bottomId); + if (getMode == MODE_DRAWER || getMode == MODE_COVER || getMode == MODE_FIXED) mode = getMode; + if (getLeftMode == MODE_DRAWER || getLeftMode == MODE_COVER || getLeftMode == MODE_FIXED) leftMode = getLeftMode; + if (getTopMode == MODE_DRAWER || getTopMode == MODE_COVER || getTopMode == MODE_FIXED) topMode = getTopMode; + if (getRightMode == MODE_DRAWER || getRightMode == MODE_COVER || getRightMode == MODE_FIXED) rightMode = getRightMode; + if (getBottomMode == MODE_DRAWER || getBottomMode == MODE_COVER || getBottomMode == MODE_FIXED) bottomMode = getBottomMode; + setMask(getMask); + setMainType(getMainType); + setLeftType(getLeftType); + setTopType(getTopType); + setRightType(getRightType); + setBottomType(getBottomType); + setMainOpen(getMainOpen); + setShrinkRange(getShrinkRange); + setDragDamping(getDragDamping); + setDragRange(getDragRange); + setMaxDragSize(getMaxDragSize); + setMaskColor(getMaskColor); + setDuration(getDuration); + if (getInterpolatorId != -1) { + animInterpolator = AnimationUtils.loadInterpolator(getContext(), getInterpolatorId); + } + attrArr.recycle(); + } + } + + public void setMode(int type) { + if (isShow) return; + if (type == MODE_DRAWER || type == MODE_COVER || type == MODE_FIXED) { + mode = type; + checkTouch(); + updateLayout(); + } + } + + public void setLeftMode(int type) { + if (isShow) return; + if (type == MODE_DRAWER || type == MODE_COVER || type == MODE_FIXED) { + leftMode = type; + checkTouch(); + updateLayout(); + } + } + + public void setRightMode(int type) { + if (isShow) return; + if (type == MODE_DRAWER || type == MODE_COVER || type == MODE_FIXED) { + rightMode = type; + checkTouch(); + updateLayout(); + } + } + + public void setTopMode(int type) { + if (isShow) return; + if (type == MODE_DRAWER || type == MODE_COVER || type == MODE_FIXED) { + topMode = type; + checkTouch(); + updateLayout(); + } + } + + public void setBottomMode(int type) { + if (isShow) return; + if (type == MODE_DRAWER || type == MODE_COVER || type == MODE_FIXED) { + bottomMode = type; + checkTouch(); + updateLayout(); + } + } + + public void setMask(int type) { + if (type == MASK_NONE || type == MASK_GENERAL || type == MASK_GRADUAL) { + mask = type; + checkTouch(); + requestLayout(); + } + } + + public void setMainType(int type) { + if (type == TYPE_VIEW || type == TYPE_SCROLL_Y || type == TYPE_SCROLL_X) { + mainType = type; + } + } + + public void setLeftType(int type) { + if (type == TYPE_VIEW || type == TYPE_SCROLL_Y || type == TYPE_SCROLL_X) { + leftType = type; + } + } + + public void setTopType(int type) { + if (type == TYPE_VIEW || type == TYPE_SCROLL_Y || type == TYPE_SCROLL_X) { + topType = type; + } + } + + public void setRightType(int type) { + if (type == TYPE_VIEW || type == TYPE_SCROLL_Y || type == TYPE_SCROLL_X) { + rightType = type; + } + } + + public void setBottomType(int type) { + if (type == TYPE_VIEW || type == TYPE_SCROLL_Y || type == TYPE_SCROLL_X) { + bottomType = type; + } + } + + public void setMainOpen(int type) { + if (type == MAIN_OPEN_NONE || type == MAIN_OPEN_CLICK || type == MAIN_OPEN_INTERCEPT) { + mainOpen = type; + } + } + + public void setShrinkRange(float num) { + if (num < 0) num = 0; + shrinkRange = num; + } + + public void setDragDamping(int num) { + if (num < 0 || num > 10) num = 10; + dragDamping = num; + } + + public void setDragRange(int num) { + if (num < -1) num = -1; + dragRange = num; + } + + public void setMaxDragSize(int num) { + if (num < 0) num = 0; + maxDragSize = num; + } + + public void setDuration(int ms) { + if (ms < 0) return; + duration = ms; + } + + public void setLeftDragOpen(boolean bool) { + leftDragOpen = bool; + } + + public void setTopDragOpen(boolean bool) { + topDragOpen = bool; + } + + public void setRightDragOpen(boolean bool) { + rightDragOpen = bool; + } + + public void setBottomDragOpen(boolean bool) { + bottomDragOpen = bool; + } + + public void setShowLayout(boolean bool) { + showLayout = bool; + } + + public void setAutoClose(boolean bool) { + autoClose = bool; + } + + public void setMaskClose(boolean bool) { + maskClose = bool; + } + + public void setMaskColor(int color) { + maskColor = color; + if (maskView != null) { + maskView.setBackgroundColor(maskColor); + } + } + + public void setDragClose(boolean bool) { + dragClose = bool; + } + + public void setScrollOuterDrag(boolean bool) { + scrollOuterDrag = bool; + } + + public void setParentDrawer(final int id) { + new Thread(new Runnable() { + @Override + public void run() { + try { + ViewParent view = SwipeDrawer.this; + while ((view = view.getParent()) != null) { + if (view instanceof SwipeDrawer) { + if (((SwipeDrawer) view).getId() == id) { + parentDrawer = (SwipeDrawer) view; + break; + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + }).start(); + } + + public void setParentDrawer(SwipeDrawer view) { + if (view == null) return; + parentDrawer = view; + } + + public void setMainScroll(int id) { + setMainScroll(findViewById(id)); + } + + public void setMainScroll(View view) { + if (view != null) { + mainScroll = new ViewUtils(view, DIRECTION_MAIN, true); + requestLayout(); + } + } + + public void setLeftScroll(int id) { + setLeftScroll(findViewById(id)); + } + + public void setLeftScroll(View view) { + if (view != null) { + leftScroll = new ViewUtils(view, DIRECTION_LEFT, true); + requestLayout(); + } + } + + public void setTopScroll(int id) { + setTopScroll(findViewById(id)); + } + + public void setTopScroll(View view) { + if (view != null) { + topScroll = new ViewUtils(view, DIRECTION_TOP, true); + requestLayout(); + } + } + + public void setRightScroll(int id) { + setRightScroll(findViewById(id)); + } + + public void setRightScroll(View view) { + if (view != null) { + rightScroll = new ViewUtils(view, DIRECTION_RIGHT, true); + requestLayout(); + } + } + + public void setBottomScroll(int id) { + setBottomScroll(findViewById(id)); + } + + public void setBottomScroll(View view) { + if (view != null) { + bottomScroll = new ViewUtils(view, DIRECTION_BOTTOM, true); + requestLayout(); + } + } + + public void setMainLayout(int id) { + setMainLayout(findViewById(id)); + } + + public void setMainLayout(View view) { + if (isShow) return; + if (view != null) { + mainLayout = new ViewUtils(view, DIRECTION_MAIN, true); + checkTouch(); + requestLayout(); + } + } + + public void setLeftLayout(int id) { + setLeftLayout(findViewById(id)); + } + + public void setLeftLayout(View view) { + if (isShow) return; + if (view != null) { + leftLayout = new ViewUtils(view, DIRECTION_LEFT, true); + checkTouch(); + requestLayout(); + } + } + + public void setTopLayout(int id) { + setTopLayout(findViewById(id)); + } + + public void setTopLayout(View view) { + if (isShow) return; + if (view != null) { + topLayout = new ViewUtils(view, DIRECTION_TOP, true); + checkTouch(); + requestLayout(); + } + } + + public void setRightLayout(int id) { + setRightLayout(findViewById(id)); + } + + public void setRightLayout(View view) { + if (isShow) return; + if (view != null) { + rightLayout = new ViewUtils(view, DIRECTION_RIGHT, true); + checkTouch(); + requestLayout(); + } + } + + public void setBottomLayout(int id) { + setBottomLayout(findViewById(id)); + } + + public void setBottomLayout(View view) { + if (isShow) return; + if (view != null) { + bottomLayout = new ViewUtils(view, DIRECTION_BOTTOM, true); + checkTouch(); + requestLayout(); + } + } + + public void setMainScale(float scale) { + if (isTouch) { + mainLayout.setScale(scale); + } + } + + public void setMainRotation(float rotation) { + if (isTouch) { + mainLayout.setRotation(rotation); + } + } + + public boolean setIntercept(boolean intercept) { + return setIntercept(DIRECTION_LEFT, intercept) || setIntercept(DIRECTION_TOP, intercept) || setIntercept(DIRECTION_RIGHT, intercept)|| setIntercept(DIRECTION_BOTTOM, intercept); + } + + public boolean setIntercept(View view, boolean intercept) { + int type = getDirection(view); + return setIntercept(type, intercept); + } + + public boolean setIntercept(int type, boolean intercept) { + ViewUtils utils = getViewUtils(type); + if (utils != null) { + utils.intercept = intercept; + } + return utils != null; + } + + public void setOnDrawerState(OnDrawerState listener) { + onDrawerState = listener; + } + + public void setOnDrawerSwitch(OnDrawerSwitch listener) { + onDrawerSwitch = listener; + } + + public void setOnDrawerChange(OnDrawerChange listener) { + onDrawerChange = listener; + } + + public void setInterpolator(Interpolator interpolator) { + animInterpolator = interpolator; + } + + public static void setAllIntercept(boolean bool) { + allIntercept = bool; + } + + public static boolean getAllIntercept() { + return allIntercept; + } + + public static SwipeDrawer getParentDrawer(View view) { + try { + if (view != null) { + ViewParent parent = view.getParent(); + while (parent != null) { + if (parent instanceof SwipeDrawer) { + return (SwipeDrawer) parent; + } else { + parent = parent.getParent(); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public int getMode() { + return mode; + } + + public int getLeftMode() { + return leftMode; + } + + public int getTopMode() { + return topMode; + } + + public int getRightMode() { + return rightMode; + } + + public int getBottomMode() { + return bottomMode; + } + + public int getMask() { + return mask; + } + + public View getMaskView() { + return maskView; + } + + public View getMainView() { + return mainLayout == null ? null : mainLayout.view; + } + + public View getLeftView() { + return leftLayout == null ? null : leftLayout.view; + } + + public View getTopView() { + return topLayout == null ? null : topLayout.view; + } + + public View getRightView() { + return rightLayout == null ? null : rightLayout.view; + } + + public View getBottomView() { + return bottomLayout == null ? null : bottomLayout.view; + } + + public int getMainType() { + return mainType; + } + + public int getLeftType() { + return leftType; + } + + public int getTopType() { + return topType; + } + + public int getRightType() { + return rightType; + } + + public int getBottomType() { + return bottomType; + } + + public int getMainOpen() { + return mainOpen; + } + + public float getShrinkRange() { + return shrinkRange; + } + + public int getDragDamping() { + return dragDamping; + } + + public int getDragRange() { + return dragRange; + } + + public int getMaxDragSize() { + return maxDragSize; + } + + public int getDuration() { + return duration; + } + + public boolean getLeftDragOpen() { + return leftDragOpen; + } + + public boolean getTopDragOpen() { + return topDragOpen; + } + + public boolean getRightDragOpen() { + return rightDragOpen; + } + + public boolean getBottomDragOpen() { + return bottomDragOpen; + } + + public boolean getShowLayout() { + return showLayout; + } + + public boolean getAutoClose() { + return autoClose; + } + + public boolean getMaskClose() { + return maskClose; + } + + public boolean getScrollOuterDrag() { + return scrollOuterDrag; + } + + public boolean getIntercept() { + return isIntercept; + } + + public boolean getShow() { + return isShow; + } + + public boolean getArriveRange() { + return arriveRange; + } + + public int getDirection() { + return inDirection; + } + + public int getMaskColor() { + return maskColor; + } + + + public int getDirection(View view) { + if (mainLayout != null) { + if (view == mainLayout.view) return DIRECTION_MAIN; + } + if (leftLayout != null) { + if (view == leftLayout.view) return DIRECTION_LEFT; + } + if (topLayout != null) { + if (view == topLayout.view) return DIRECTION_TOP; + } + if (rightLayout != null) { + if (view == rightLayout.view) return DIRECTION_RIGHT; + } + if (bottomLayout != null) { + if (view == bottomLayout.view) return DIRECTION_BOTTOM; + } + return DIRECTION_ORDER; + } + + public int getDirectionMode(int type) { + if (type == DIRECTION_LEFT && leftMode != -1) { + return leftMode; + } else if (type == DIRECTION_TOP && topMode != -1) { + return topMode; + } else if (type == DIRECTION_RIGHT && rightMode != -1) { + return rightMode; + } else if (type == DIRECTION_BOTTOM && bottomMode != -1) { + return bottomMode; + } + return mode; + } + + public ViewUtils getViewUtils(int type) { + if (type == DIRECTION_MAIN && mainLayout != null) { + return mainLayout; + } else if (type == DIRECTION_LEFT && leftLayout != null) { + return leftLayout; + } else if (type == DIRECTION_TOP && topLayout != null) { + return topLayout; + } else if (type == DIRECTION_RIGHT && rightLayout != null) { + return rightLayout; + } else if (type == DIRECTION_BOTTOM && bottomLayout != null) { + return bottomLayout; + } + return null; + } + + public ViewUtils getScrollUtils(int type) { + if (type == DIRECTION_MAIN && mainScroll != null) { + return mainScroll; + } else if (type == DIRECTION_LEFT && leftScroll != null) { + return leftScroll; + } else if (type == DIRECTION_TOP && topScroll != null) { + return topScroll; + } else if (type == DIRECTION_RIGHT && rightScroll != null) { + return rightScroll; + } else if (type == DIRECTION_BOTTOM && bottomScroll != null) { + return bottomScroll; + } + return null; + } + + public void openDrawer(int type) { + openDrawer(type, true, true); + } + + public void openDrawer(int type, boolean anim) { + openDrawer(type, anim, true); + } + + public void openDrawer(int type, boolean anim, boolean call) { + if (isShow || AnimThread.isThread(animThread)) return; + ViewUtils viewUtils = getViewUtils(type); + if (viewUtils != null) { + if (!isInit) { + open = type; + return; + } + inDirection = type; + if (getDirectionMode(inDirection) == MODE_COVER) { + mainLayout.setFront(); + requestMask(true); + viewUtils.setFront(); + } else { + viewUtils.setFront(); + requestMask(true); + mainLayout.setFront(); + } + isShow = true; + if (onDrawerChange != null) onDrawerChange.onChange(this, STATE_CALL_OPEN, 0); + checkView(); + animRecovery(true, anim, call); + if (call) onOpen(); + if (mask == MASK_GENERAL) { + progressMask(1f); + } + } + } + + public void closeDrawer() { + closeDrawer(inDirection, true, true); + } + + public void closeDrawer(boolean anim) { + closeDrawer(inDirection, anim, true); + } + + public void closeDrawer(boolean anim, boolean call) { + closeDrawer(inDirection, anim, call); + } + + public void closeDrawer(int type) { + closeDrawer(type, true, true); + } + + public void closeDrawer(int type, boolean anim) { + closeDrawer(type, anim, true); + } + + public void closeDrawer(int type, boolean anim, boolean call) { + if (!isShow || type != inDirection || AnimThread.isThread(animThread)) return; + ViewUtils viewUtils = getViewUtils(type); + if (viewUtils != null) { + inDirection = type; + isShow = false; + if (onDrawerChange != null) onDrawerChange.onChange(this, STATE_CALL_CLOSE, 0); + checkView(); + animRecovery(false, anim, call); + if (call) onClose(); + if (mask == MASK_GENERAL) { + progressMask(0f); + } + } + } + + public void forceClose(boolean anim) { + forceClose(anim, true); + } + + public void forceClose(boolean anim, boolean call) { + if (isShow) { + if (AnimThread.isThread(animThread)) { + animThread.setStop(); + animThread.setAlive(); + } + isShow = false; + if (onDrawerChange != null) onDrawerChange.onChange(this, STATE_CALL_CLOSE, 0); + checkView(); + animRecovery(false, anim, call); + if (call) onClose(); + if (mask == MASK_GENERAL) { + progressMask(0f); + } + } + } + + public void toggleDrawer(int type) { + toggleDrawer(type, true, true); + } + + public void toggleDrawer(int type, boolean anim) { + toggleDrawer(type, anim, true); + } + + public void toggleDrawer(int type, boolean anim, boolean call) { + if (isShow) { + closeDrawer(type, anim, call); + } else { + openDrawer(type, anim, call); + } + } + + public void updateLayout() { + lastMode = 0; + requestLayout(); + } + + public void updateSize(boolean isAll) { + if (mainScroll != null) mainScroll.Update(isAll); + if (leftScroll != null) leftScroll.Update(isAll); + if (topScroll != null) topScroll.Update(isAll); + if (rightScroll != null) rightScroll.Update(isAll); + if (bottomScroll != null) bottomScroll.Update(isAll); + if (mainLayout != null) mainLayout.Update(isAll); + if (leftLayout != null) leftLayout.Update(isAll); + if (topLayout != null) topLayout.Update(isAll); + if (rightLayout != null) rightLayout.Update(isAll); + if (bottomLayout != null) bottomLayout.Update(isAll); + } + + private void setParentIntercept(int intercept, boolean isAll) { + //System.out.println("setParentIntercept : " + intercept + " - " + isAll); + try { + if (parentDrawer != null) { + SwipeDrawer view = parentDrawer; + view.parentIntercept = intercept; + if (isAll) { + while ((view = view.parentDrawer) != null) { + view.parentIntercept = intercept; + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void progressMask(float alpha) { + if (maskView != null) { + maskView.setAlpha(alpha); + } + } + + private void requestMask(boolean bool) { + if (maskView != null) { + if (bool) { + maskView.bringToFront(); + maskView.setVisibility(VISIBLE); + } else { + maskView.setAlpha(0f); + maskView.setVisibility(GONE); + } + } + } + + private void requestIntercept() { + try { + ViewParent parent = getParent(); + if (parent != null) { + parent.requestDisallowInterceptTouchEvent(true); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + private int[] getLocation() { + int[] location = new int[2]; + getLocationOnScreen(location); + return location; + } + + private boolean isScrollType(int type) { + final boolean isLeft = type == DIRECTION_LEFT; + final boolean isTop = type == DIRECTION_TOP; + final boolean isRight = type == DIRECTION_RIGHT; + final boolean isBottom = type == DIRECTION_BOTTOM; + boolean bool = true; + ViewUtils viewUtils; + if (isShow) { + viewUtils = getScrollUtils(type); + if (viewUtils != null) { + if (isTop && !viewUtils.isScrollBottom()) bool = false; + if (isBottom && !viewUtils.isScrollTop()) bool = false; + if (isLeft && !viewUtils.isScrollRight()) bool = false; + if (isRight && !viewUtils.isScrollLeft()) bool = false; + } else { + int setType = 0; + if (isTop) setType = topType; + if (isBottom) setType = bottomType; + if (isLeft) setType = leftType; + if (isRight) setType = rightType; + viewUtils = getViewUtils(type); + if (viewUtils != null) { + if (setType == TYPE_SCROLL_Y) { + if (isTop && !viewUtils.isScrollBottom()) bool = false; + if (isBottom && !viewUtils.isScrollTop()) bool = false; + } else if (setType == TYPE_SCROLL_X) { + if (isLeft && !viewUtils.isScrollRight()) bool = false; + if (isRight && !viewUtils.isScrollLeft()) bool = false; + } + } + } + } else { + viewUtils = getScrollUtils(DIRECTION_MAIN); + if (viewUtils != null) { + if (isTop && !viewUtils.isScrollTop()) bool = false; + if (isBottom && !viewUtils.isScrollBottom()) bool = false; + if (isLeft && !viewUtils.isScrollLeft()) bool = false; + if (isRight && !viewUtils.isScrollRight()) bool = false; + } else { + viewUtils = getViewUtils(DIRECTION_MAIN); + if (mainType == TYPE_SCROLL_Y) { + if (isTop && !viewUtils.isScrollTop()) bool = false; + if (isBottom && !viewUtils.isScrollBottom()) bool = false; + } else if (mainType == TYPE_SCROLL_X) { + if (isLeft && !viewUtils.isScrollLeft()) bool = false; + if (isRight && !viewUtils.isScrollRight()) bool = false; + } + } + } + if (viewUtils != null && scrollOuterDrag) { + if (!viewUtils.isActionDown(downX, downY, getLocation())) { + bool = true; + } + } + return bool; + } + + private ViewUtils getIntercept(int shiftX, int shiftY) { + if (leftLayout != null && ((isShow && inDirection == DIRECTION_LEFT && shiftX < 0 && Math.abs(shiftX) > Math.abs(shiftY)) || (!isShow && leftDragOpen && shiftX > Math.abs(shiftY)))) { + if (leftLayout.intercept && isScrollType(DIRECTION_LEFT) && (isShow || dragRange == 0 || dragRange >= downX)) { + return leftLayout; + } + } + if (rightLayout != null && ((!isShow && rightDragOpen && shiftX < 0 && Math.abs(shiftX) > Math.abs(shiftY)) || (isShow && inDirection == DIRECTION_RIGHT && shiftX > Math.abs(shiftY)))) { + if (rightLayout.intercept && isScrollType(DIRECTION_RIGHT) && (isShow || dragRange == 0 || dragRange >= (mainLayout.width - downX))) { + return rightLayout; + } + } + if (topLayout != null && ((isShow && inDirection == DIRECTION_TOP && shiftY < 0 && Math.abs(shiftY) > Math.abs(shiftX)) || (!isShow && topDragOpen && shiftY > Math.abs(shiftX)))) { + if (topLayout.intercept && isScrollType(DIRECTION_TOP) && (isShow || dragRange == 0 || dragRange >= downY)) { + return topLayout; + } + } + if (bottomLayout != null && ((!isShow && bottomDragOpen && shiftY < 0 && Math.abs(shiftY) > Math.abs(shiftX)) || (isShow && inDirection == DIRECTION_BOTTOM && shiftY > Math.abs(shiftX)))) { + if (bottomLayout.intercept && isScrollType(DIRECTION_BOTTOM) && (isShow || dragRange == 0 || dragRange >= (mainLayout.height - downY))) { + return bottomLayout; + } + } + setParentIntercept(0, false); + return null; + } + + private void animRecovery(final boolean bool, final boolean anim, final boolean call) { + if (!isTouch) return; + final ViewUtils viewUtils = getViewUtils(inDirection); + if (viewUtils == null) return; + int getMode = getDirectionMode(inDirection); + final boolean isDrawer = getMode == MODE_DRAWER; + final boolean isFixed = getMode == MODE_FIXED; + final boolean isCover = getMode == MODE_COVER; + final boolean isLeft = inDirection == DIRECTION_LEFT; + final boolean isTop = inDirection == DIRECTION_TOP; + final boolean isRight = inDirection == DIRECTION_RIGHT; + final boolean isBottom = inDirection == DIRECTION_BOTTOM; + int setNum = isLeft || isRight ? (isLeft ? leftLayout.width : -rightLayout.width) : (isTop ? topLayout.height : -bottomLayout.height); + int oldNum = isLeft || isRight ? mainLayout.left : mainLayout.top; + if (isCover) { + if (isLeft) oldNum = viewUtils.width + viewUtils.left; + if (isRight) oldNum = viewUtils.left - mainLayout.width; + if (isTop) oldNum = viewUtils.height + viewUtils.top; + if (isBottom) oldNum = viewUtils.top - mainLayout.height; + } + final int oldValue = oldNum; + final int setValue = (bool ? setNum : 0) - oldValue; + isIntercept = false; + if (anim && duration > 0) { + animThread = new AnimThread(duration, animInterpolator) { + @Override + protected void onUpdate(final float value) { + post(new Runnable() { + @Override + public void run() { + if (getStop()) return; + int newValue = (int) Math.ceil(setValue * value); + if (isLeft || isRight) { + if (isDrawer || isFixed) mainLayout.setLeft(oldValue + newValue); + if (isDrawer || isCover) + viewUtils.setLeft(oldValue + newValue + (isLeft ? -viewUtils.width : mainLayout.width)); + } else if (isTop || isBottom) { + if (isDrawer || isFixed) mainLayout.setTop(oldValue + newValue); + if (isDrawer || isCover) + viewUtils.setTop(oldValue + newValue + (isTop ? -viewUtils.height : mainLayout.height)); + } + float progress = (float) Math.abs(oldValue + newValue) / (isLeft || isRight ? viewUtils.width : viewUtils.height); + if (lastProgress != progress) { + if (onDrawerState != null && call) { + onDrawerState.onMove(inDirection, progress); + } + if (onDrawerChange != null && call) { + onDrawerChange.onChange(SwipeDrawer.this, STATE_PROGRESS, progress); + } + lastProgress = progress; + } + if (mask == MASK_GRADUAL) { + progressMask(progress); + } + if (value >= 1) { + setStop(); + setAlive(); + if (!isShow) { + requestMask(false); + } + if (onDrawerChange != null && call) { + onDrawerChange.onChange(SwipeDrawer.this, STATE_ANIM_OVER, 0); + } + } + } + }); + } + }; + } else { + if (AnimThread.isThread(animThread)) { + animThread.setStop(); + animThread.setAlive(); + } + if (isLeft || isRight) { + if (isDrawer || isFixed) mainLayout.setLeft(oldValue + setValue); + if (isDrawer || isCover) viewUtils.setLeft(oldValue + setValue + (isLeft ? -viewUtils.width : mainLayout.width)); + } else if (isTop || isBottom) { + if (isDrawer || isFixed) mainLayout.setTop(oldValue + setValue); + if (isDrawer || isCover) viewUtils.setTop(oldValue + setValue + (isTop ? -viewUtils.height : mainLayout.height)); + } + progressMask(isShow ? 1f : 0f); + if (!isShow) { + requestMask(false); + } + if (onDrawerChange != null && call) { + onDrawerChange.onChange(SwipeDrawer.this, STATE_ANIM_OVER, 0); + } + } + if (isShow && autoClose) autoDrawer = this; + } + + private void onOpen() { + if (isShow) { + if (onDrawerState != null) onDrawerState.onOpen(inDirection); + if (onDrawerSwitch != null) onDrawerSwitch.onOpen(this); + if (onDrawerChange != null) onDrawerChange.onChange(this, STATE_OPEN, 0); + } + } + + private void onClose() { + if (!isShow) { + if (onDrawerState != null) onDrawerState.onClose(inDirection); + if (onDrawerSwitch != null) onDrawerSwitch.onClose(this); + if (onDrawerChange != null) onDrawerChange.onChange(this, STATE_CLOSE, 0); + } + } + + private void cacheDrawer(boolean anim) { + try { + if (autoClose && autoDrawer != null && autoDrawer != this) { + autoDrawer.forceClose(anim); + autoDrawer = null; + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void checkView() { + if (showLayout) return; + if (leftLayout != null) leftLayout.setVisibility(inDirection == leftLayout.type); + if (topLayout != null) topLayout.setVisibility(inDirection == topLayout.type); + if (rightLayout != null) rightLayout.setVisibility(inDirection == rightLayout.type); + if (bottomLayout != null) bottomLayout.setVisibility(inDirection == bottomLayout.type); + } + + private void checkMask() { + if (mask != MASK_NONE) { + if (maskView == null) { + View view = null; + try { + view = new View(getContext()); + view.setAlpha(0f); + view.setVisibility(GONE); + view.setBackgroundColor(maskColor); + addView(view, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + } catch (Exception e) { + e.printStackTrace(); + } + if (view != null) maskView = view; + } + } else { + if (maskView != null) { + removeView(maskView); + maskView = null; + mainLayout.setMask(null); + } + } + } + + private void checkTouch() { + if (isFinish) { + checkMask(); + checkView(); + isTouch = mainLayout != null && (leftLayout != null || topLayout != null || rightLayout != null || bottomLayout != null); + if (isTouch) { + mainLayout.setFront(); + if (maskView != null) { + mainLayout.setMask(maskView); + maskView.setLayoutParams(mainLayout.view.getLayoutParams()); + } + } + } + } + + private boolean checkIntercept(MotionEvent ev) { + if (isIntercept) return false; + if (AnimThread.isThread(animThread)) return true; + if (!isShow && dragRange == -1) { + setParentIntercept(0, false); + return false; + } + int getX = (int) ev.getX(); + int getY = (int) ev.getY(); + int shiftX = getX - downX; + int shiftY = getY - downY; + ViewUtils viewUtils = getIntercept(shiftX, shiftY); + if (isShow && (mainOpen == MAIN_OPEN_CLICK || mainOpen == MAIN_OPEN_INTERCEPT)) { + ViewUtils showUtils = getViewUtils(inDirection); + if (showUtils != null && viewUtils == null) { + if (maskView != null) { + requestIntercept(); + return false; + }else if (!showUtils.isActionDown(downX, downY, getLocation())) { + return true; + } + } + } + if (!isIntercept && !AnimThread.isThread(animThread) && viewUtils != null) { + downX = getX; + downY = getY; + isIntercept = true; + inDirection = viewUtils.type; + checkView(); + if (getDirectionMode(inDirection) == MODE_COVER) { + mainLayout.setFront(); + requestMask(true); + viewUtils.setFront(); + } else { + viewUtils.setFront(); + requestMask(true); + mainLayout.setFront(); + } + if (onDrawerState != null) onDrawerState.onStart(inDirection); + if (onDrawerChange != null) onDrawerChange.onChange(this, STATE_START, 0); + requestIntercept(); + } + return false; + } + + + private void checkRange(ViewUtils viewUtils, boolean isCover, boolean isLeft, boolean isRight, boolean isTop, boolean isBottom) { + if (shrinkRange == 0) { + arriveRange = false; + } else { + int viewSize = isLeft || isRight ? viewUtils.width : viewUtils.height; + int mainSize = Math.abs(isLeft || isRight ? mainLayout.left : mainLayout.top); + if (isCover) { + if (isLeft) mainSize = viewUtils.width + viewUtils.left; + if (isRight) mainSize = mainLayout.width - viewUtils.left; + if (isTop) mainSize = viewUtils.height + viewUtils.top; + if (isBottom) mainSize = mainLayout.height - viewUtils.top; + } + if (isShow) mainSize = viewSize - mainSize; + arriveRange = mainSize >= Math.round(viewSize / shrinkRange); + } + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + setClickable(true); + if (getChildCount() > 1) { + View view; + if (mainScrollId != -1) { + if ((view = findViewById(mainScrollId)) != null) mainScroll = new ViewUtils(view, DIRECTION_MAIN); + } + if (leftScrollId != -1) { + if ((view = findViewById(leftScrollId)) != null) leftScroll = new ViewUtils(view, DIRECTION_LEFT); + } + if (topScrollId != -1) { + if ((view = findViewById(topScrollId)) != null) topScroll = new ViewUtils(view, DIRECTION_TOP); + } + if (rightScrollId != -1) { + if ((view = findViewById(rightScrollId)) != null) rightScroll = new ViewUtils(view, DIRECTION_RIGHT); + } + if (bottomScrollId != -1) { + if ((view = findViewById(bottomScrollId)) != null) bottomScroll = new ViewUtils(view, DIRECTION_BOTTOM); + } + if (mainId != -1) { + if ((view = findViewById(mainId)) != null) mainLayout = new ViewUtils(view, DIRECTION_MAIN); + } + if (leftId != -1) { + if ((view = findViewById(leftId)) != null) leftLayout = new ViewUtils(view, DIRECTION_LEFT); + } + if (topId != -1) { + if ((view = findViewById(topId)) != null) topLayout = new ViewUtils(view, DIRECTION_TOP); + } + if (rightId != -1) { + if ((view = findViewById(rightId)) != null) rightLayout = new ViewUtils(view, DIRECTION_RIGHT); + } + if (bottomId != -1) { + if ((view = findViewById(bottomId)) != null) bottomLayout = new ViewUtils(view, DIRECTION_BOTTOM); + } + if (mainLayout == null) { + for (int i = 0; i < getChildCount(); i++) { + View child = getChildAt(i); + if (getDirection(child) == DIRECTION_ORDER && child != maskView) { + mainLayout = new ViewUtils(child, DIRECTION_MAIN); + break; + } + } + } + isFinish = true; + checkTouch(); + } + } + + @Override + public boolean canScrollVertically(int direction) { + if (direction == -1) { + if (topLayout == null) return false; + return !(isShow && inDirection != DIRECTION_BOTTOM); + } else if (direction == 1) { + if (bottomLayout == null) return false; + return !(isShow && inDirection != DIRECTION_TOP); + } else { + return super.canScrollVertically(direction); + } + } + + @Override + public boolean canScrollHorizontally(int direction) { + if (direction == -1) { + if (leftLayout == null) return false; + return !(isShow && inDirection != DIRECTION_RIGHT); + } else if (direction == 1) { + if (rightLayout == null) return false; + return !(isShow && inDirection != DIRECTION_LEFT); + } else { + return super.canScrollHorizontally(direction); + } + } + + @Override + public boolean performClick() { + return super.performClick(); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + if (!isTouch || (!dragClose && isShow) || (parentIntercept == 1 && !isShow) || parentIntercept == 2 || allIntercept) return super.onInterceptTouchEvent(ev); + int getX = (int) ev.getX(); + int getY = (int) ev.getY(); + int getMs = (int) ev.getEventTime(); + switch (ev.getAction()) { + case MotionEvent.ACTION_DOWN: + downX = getX; + downY = getY; + downMs = getMs; + cacheDrawer(true); + setParentIntercept(1, true); + if (isShow && mainOpen == MAIN_OPEN_INTERCEPT) { + if (maskView != null) { + requestIntercept(); + setParentIntercept(2, true); + } else { + ViewUtils showUtils = getViewUtils(inDirection); + if (showUtils != null) { + if (!showUtils.isActionDown(downX, downY, getLocation())) { + return true; + } + } + } + } + break; + case MotionEvent.ACTION_MOVE: + if (checkIntercept(ev)) { + requestIntercept(); + return true; + } + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + int getMoveX = Math.abs(getX - downX); + int getMoveY = Math.abs(getY - downY); + if (!isIntercept && (getMs - downMs) < ViewConfiguration.getLongPressTimeout() && getMoveX < 3 && getMoveY < 3){ + boolean isClose = false; + if (isShow && maskClose && maskView != null) { + ViewUtils showUtils = getViewUtils(inDirection); + if (showUtils != null) { + if (!showUtils.isActionDown(downX, downY, getLocation())) { + closeDrawer(); + isClose = true; + } + } + } + if (!isClose) { + performClick(); + } + } + isIntercept = false; + setParentIntercept(0, true); + break; + } + return isIntercept; + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + if (!isTouch || (!dragClose && isShow) || (parentIntercept == 1 && !isShow) || parentIntercept == 2 || allIntercept) return super.onTouchEvent(ev); + int getX = (int) ev.getX(); + int getY = (int) ev.getY(); + int getMs = (int) ev.getEventTime(); + int getMode = getDirectionMode(inDirection); + boolean isDrawer = getMode == MODE_DRAWER; + boolean isFixed = getMode == MODE_FIXED; + boolean isCover = getMode == MODE_COVER; + boolean isLeft = inDirection == DIRECTION_LEFT; + boolean isTop = inDirection == DIRECTION_TOP; + boolean isRight = inDirection == DIRECTION_RIGHT; + boolean isBottom = inDirection == DIRECTION_BOTTOM; + switch (ev.getAction()) { + case MotionEvent.ACTION_MOVE: + if (checkIntercept(ev)) { + requestIntercept(); + return true; + } + if (isIntercept) { + int shiftX = getX - downX; + int shiftY = getY - downY; + ViewUtils viewUtils = getViewUtils(inDirection); + if (viewUtils != null) { + int moveSize = isLeft || isRight ? shiftX : shiftY; + int viewSize = isLeft || isRight ? viewUtils.width : viewUtils.height; + int mainSize = isLeft || isRight ? mainLayout.width : mainLayout.height; + int newSize = maxDragSize > 0 && !isShow ? maxDragSize : viewSize; + if (dragDamping > 0 && dragDamping < 10) moveSize *= (float)dragDamping / 10; + if ((((isLeft || isTop) && ((isShow && moveSize > 0) || (!isShow && moveSize < 0)))) || (((isRight || isBottom) && ((isShow && moveSize < 0) || (!isShow && moveSize > 0))))) moveSize = 0; + if (Math.abs(moveSize) > newSize) moveSize = (isShow && (isLeft || isTop)) || (!isShow && (isRight || isBottom)) ? -newSize : newSize; + if (isShow) { + if (isLeft || isRight) { + if (isDrawer || isFixed) mainLayout.setRight(moveSize + mainSize + (isLeft ? viewSize : -viewSize)); + if (isDrawer || isCover) viewUtils.setRight(moveSize + (isLeft ? viewSize : mainSize)); + } else if (isTop || isBottom) { + if (isDrawer || isFixed) mainLayout.setBottom(moveSize + mainSize + (isTop ? viewSize : -viewSize)); + if (isDrawer || isCover) viewUtils.setBottom(moveSize + (isTop ? viewSize : mainSize)); + } + } else { + if (isLeft || isRight) { + if (isDrawer || isFixed) mainLayout.setLeft(moveSize); + if (isDrawer || isCover) viewUtils.setLeft(moveSize + (isLeft ? -viewSize : mainSize)); + } else if (isTop || isBottom) { + if (isDrawer || isFixed) mainLayout.setTop(moveSize); + if (isDrawer || isCover) viewUtils.setTop(moveSize + (isTop ? -viewSize : mainSize)); + } + } + checkRange(viewUtils, isCover, isLeft, isRight, isTop, isBottom); + float progress = (float) Math.abs(moveSize) / (isLeft || isRight ? viewUtils.width : viewUtils.height); + if (lastProgress != progress) { + if (onDrawerState != null) onDrawerState.onMove(inDirection, isShow ? (1 - progress) : progress); + if (onDrawerChange != null) onDrawerChange.onChange(this, STATE_PROGRESS, isShow ? (1 - progress) : progress); + lastProgress = progress; + } + if (onDrawerChange != null) { + if (arriveRange) { + if (!isArriveCall) { + onDrawerChange.onChange(this, STATE_DRAG_INTO, 0); + isArriveCall = true; + } + } else { + if (isArriveCall) { + onDrawerChange.onChange(this, STATE_DRAG_OUT, 0); + isArriveCall = false; + } + } + } + if (mask == MASK_GRADUAL) { + progressMask(isShow ? (1 - progress) : progress); + } + requestIntercept(); + } + } + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + if (isIntercept) { + ViewUtils viewUtils = getViewUtils(inDirection); + if (viewUtils != null) { + checkRange(viewUtils, isCover, isLeft, isRight, isTop, isBottom); + if (shrinkRange == 0) { + animRecovery(isShow, true, true); + if (onDrawerState != null) onDrawerState.onCancel(inDirection); + if (onDrawerChange != null) onDrawerChange.onChange(this, STATE_CANCEL, 0); + } else if (arriveRange) { + isShow = !isShow; + animRecovery(isShow, true, true); + if (isShow) { + onOpen(); + } else { + onClose(); + } + if (mask == MASK_GENERAL) { + progressMask(isShow ? 1f : 0f); + } + } else { + animRecovery(isShow, true, true); + if (onDrawerState != null) onDrawerState.onCancel(inDirection); + if (onDrawerChange != null) onDrawerChange.onChange(this, STATE_CANCEL, 0); + } + } + isIntercept = false; + setParentIntercept(0, true); + } else { + int getMoveX = Math.abs(getX - downX); + int getMoveY = Math.abs(getY - downY); + if ((getMs - downMs) < ViewConfiguration.getLongPressTimeout() && getMoveX < 3 && getMoveY < 3) performClick(); + } + break; + } + if (!isIntercept) super.onTouchEvent(ev); + return true; + } + + @Override + protected void onDetachedFromWindow() { + cacheDrawer(false); + super.onDetachedFromWindow(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int setWidth = MeasureSpec.getSize(widthMeasureSpec); + int setHeight = 0; + int heightMode = MeasureSpec.getMode(heightMeasureSpec); + for (int i = 0; i < getChildCount(); i++) { + View view = getChildAt(i); + if (view.getVisibility() != GONE) { + view.setClickable(true); + measureChild(view, widthMeasureSpec, heightMeasureSpec); + setHeight = Math.max(setHeight, view.getMeasuredHeight()); + } + } + if (heightMode == MeasureSpec.EXACTLY) { + setHeight = MeasureSpec.getSize(heightMeasureSpec); + } + setMeasuredDimension(setWidth, setHeight); + updateSize(false); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + for (int i = 0; i < getChildCount(); i++) { + View view = getChildAt(i); + if (view.getVisibility() != GONE) { + if ((view.getLeft() == 0 && view.getTop() == 0 && view.getRight() == 0 && view.getBottom() == 0) || lastMode != mode) { + int setLeft = 0; + int setTop = 0; + int setRight = view.getMeasuredWidth(); + int setBottom = view.getMeasuredHeight(); + if (isTouch) { + int getDirection = getDirection(view); + int getMode = getDirectionMode(getDirection); + if (getMode == MODE_DRAWER || getMode == MODE_COVER) { + if (getDirection == DIRECTION_LEFT) { + setLeft = -setRight; + setRight = 0; + } else if (getDirection == DIRECTION_RIGHT) { + setLeft = mainLayout.width; + setRight += setLeft; + } else if (getDirection == DIRECTION_TOP) { + setTop = -setBottom; + setBottom = 0; + } else if (getDirection == DIRECTION_BOTTOM) { + setTop = mainLayout.height; + setBottom += setTop; + } + } else { + if (getDirection == DIRECTION_RIGHT) { + setLeft = getMeasuredWidth() - setRight; + setRight = getMeasuredWidth(); + } else if (getDirection == DIRECTION_BOTTOM) { + setTop = getMeasuredHeight() - setBottom; + setBottom = getMeasuredHeight(); + } + } + } + view.layout(setLeft, setTop, setRight, setBottom); + } else { + view.layout(view.getLeft(), view.getTop(), view.getRight(), view.getBottom()); + } + } + } + updateSize(true); + if (!isInit) { + isInit = true; + } + if (open > 0) { + openDrawer(open, false, false); + open = 0; + } + if (lastMode != mode) { + lastMode = mode; + } + if (parentId != -1) { + setParentDrawer(parentId); + parentId = -1; + } + } + +} diff --git a/drawer/src/main/java/cn/leaqi/drawer/ViewUtils.java b/drawer/src/main/java/cn/leaqi/drawer/ViewUtils.java new file mode 100644 index 0000000..f753167 --- /dev/null +++ b/drawer/src/main/java/cn/leaqi/drawer/ViewUtils.java @@ -0,0 +1,169 @@ +/* + Copyright 2022 Leaqi + + 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 cn.leaqi.drawer; + +import android.view.View; + +/** + * ViewUtils is an view operation class + * Created by Leaqi. + * Github: https://github.com/Leaqi + */ +public class ViewUtils { + View view = null; + View mask = null; + int type = -1; + int width = 0; + int height = 0; + int left = 0; + int top = 0; + int right = 0; + int bottom = 0; + int paddingLeft = 0; + int paddingTop = 0; + int paddingRight = 0; + int paddingBottom = 0; + boolean intercept = true; + + ViewUtils(View v, int t) { + view = v; + type = t; + } + + ViewUtils(View v, int t, boolean u) { + view = v; + type = t; + Update(u); + } + + void Update(boolean isAll) { + width = view.getMeasuredWidth(); + height = view.getMeasuredHeight(); + if (isAll) { + left = view.getLeft(); + top = view.getTop(); + right = view.getRight(); + bottom = view.getBottom(); + paddingLeft = view.getPaddingLeft(); + paddingTop = view.getPaddingTop(); + paddingRight = view.getPaddingRight(); + paddingBottom = view.getPaddingBottom(); + } + } + + void setMask(View view) { + mask = view; + } + + void setScale(float scale) { + view.setScaleX(scale); + view.setScaleY(scale); + if (mask != null) { + mask.setScaleX(scale); + mask.setScaleY(scale); + } + } + + void setRotation(float rotation) { + view.setRotation(rotation); + if (mask != null) { + mask.setRotation(rotation); + } + } + + void setLeft(int l) { + left = l; + view.setLeft(left); + right = l + width; + view.setRight(right); + upMask(); + } + + void setTop(int t) { + top = t; + view.setTop(top); + bottom = t + height; + view.setBottom(bottom); + upMask(); + } + + void setRight(int r) { + right = r; + view.setRight(right); + left = r - width; + view.setLeft(left); + upMask(); + } + + void setBottom(int b) { + bottom = b; + view.setBottom(bottom); + top = b - height; + view.setTop(top); + upMask(); + } + + void setVisibility(boolean show) { + view.setVisibility(show ? View.VISIBLE : View.INVISIBLE); + } + + void setFront() { + view.bringToFront(); + if (mask != null) { + mask.bringToFront(); + } + } + + void upMask(){ + if (mask != null) { + mask.setLeft(left); + mask.setRight(right); + mask.setTop(top); + mask.setBottom(bottom); + } + } + + boolean isScrollLeft() { + return !view.canScrollHorizontally(-1); + } + + boolean isScrollTop() { + return !view.canScrollVertically(-1); + } + + boolean isScrollRight() { + return !view.canScrollHorizontally(1); + } + + boolean isScrollBottom() { + return !view.canScrollVertically(1); + } + + + boolean isActionDown(int downX, int downY, int[] location) { + int[] iLocation = getLocation(); + int getX = iLocation[0] - location[0]; + int getY = iLocation[1] - location[1]; + return downX > getX && downY > getY && downX < (getX + width) && downY < (getY + height); + } + + int[] getLocation() { + int[] location = new int[2]; + view.getLocationOnScreen(location); + return location; + } + +} \ No newline at end of file diff --git a/drawer/src/main/res/values/attrs.xml b/drawer/src/main/res/values/attrs.xml new file mode 100644 index 0000000..34ab430 --- /dev/null +++ b/drawer/src/main/res/values/attrs.xml @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/drawer/src/main/res/values/strings.xml b/drawer/src/main/res/values/strings.xml new file mode 100644 index 0000000..2215c24 --- /dev/null +++ b/drawer/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + SwipeDrawer + diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..199d16e --- /dev/null +++ b/gradle.properties @@ -0,0 +1,20 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx1536m +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Automatically convert third-party libraries to use AndroidX +android.enableJetifier=true + diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..f6b961f Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..22c78d7 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Mon Mar 07 16:21:38 CST 2022 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..cccdd3d --- /dev/null +++ b/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..f955316 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..b982df1 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,2 @@ +include ':app', ':drawer' +rootProject.name='DrawerApp'