第一次提交
|
@ -0,0 +1,9 @@
|
|||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/workspace.xml
|
||||
/.idea/libraries
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
/.idea
|
|
@ -0,0 +1,66 @@
|
|||
# Android普遍存在的问题
|
||||
|
||||
> 这些问题已经在模板项目中已经被修复好了,具体修复过程如下
|
||||
|
||||
#### 修复 Button 在Android 5.1 之后英文字符串自动大写的问题
|
||||
|
||||
> 给 Button 添加如下属性即可,模板工程已经把该属性封装到Style中,直接引用style="@style/ButtonStyle"即可
|
||||
|
||||
android:textAllCaps="false"
|
||||
|
||||
#### 修复 Button 在设置状态选择器后仍然残留按压阴影的问题
|
||||
|
||||
> 给 Button 设置样式如下即可,模板工程已经把该属性封装到Style中,直接引用style="@style/ButtonStyle"即可
|
||||
|
||||
style="Widget.AppCompat.Button.Borderless"
|
||||
|
||||
#### 修复某些低配置机型启动页停留在白屏的时间比较长的问题
|
||||
|
||||
> 某些低配置机型上出现该问题比较明显,如果配置好的机型则看不出来,添加一个透明的Activity主题样式
|
||||
|
||||
<!-- 解决启动页白屏的问题 -->
|
||||
<style name="LauncherTheme" parent="AppTheme">
|
||||
<item name="android:windowIsTranslucent">true</item>
|
||||
<item name="android:windowBackground">@android:color/transparent</item>
|
||||
</style>
|
||||
|
||||
> 在清单文件中给启动页的Activity设置主题样式
|
||||
|
||||
<!-- 启动页面(因为使用了LauncherTheme,所以不要给这个Activity设置screenOrientation属性,会导致崩溃) -->
|
||||
<activity
|
||||
android:name=".ui.activity.LauncherActivity"
|
||||
android:theme="@style/LauncherTheme">
|
||||
|
||||
<!-- 程序入口 -->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
|
||||
</activity>
|
||||
|
||||
> 还有一点需要特别注意,Android 8.0 及之后不允许透明主题的Activity设置屏幕方向,所以请不要给Activity设置该属性,否则会导致崩溃
|
||||
|
||||
#### 修复某些机型在 WebView 长按时布局被顶下来的问题
|
||||
|
||||
> 这个问题在只要界面有 WebView 的情况才会发生,在 Android 5.1 经过测试,在 WebView 中长按选择复制文字时,会显示一个类似于 Actionbar 的控件,但是这个东西叫做ActionMode,会将当前 Activity 所在布局顶下去,这时会和我们项目中的标题栏出现冲突,类似于一个界面同时出现了两个标题栏的效果,解决的方法很简单,就是让出现的 ActionMode 悬浮在 Activity上,这样就把项目中的标题栏遮挡住了,不会出现那种类似一个界面出现两种标题栏的效果,当 WebView 取消长按复制文字后,ActionMode也会随之消失
|
||||
|
||||
> 如何让 ActionMode 悬浮在 Activity 上呢?其实很简单,在 Application 主题中加入以下属性
|
||||
|
||||
<!-- ActionMode覆盖Actionbar,不顶下来 -->
|
||||
<item name="windowActionModeOverlay">true</item>
|
||||
<item name="android:windowContentOverlay">@null</item>
|
||||
<!-- ActionMode的颜色 -->
|
||||
<item name="actionModeBackground">@color/colorPrimary</item>
|
||||
|
||||
#### 修复 任务栈中 首页Activity 被重复启动的问题
|
||||
|
||||
> 这个问题导致是因为LauncherActivity作为APP的第一个界面,销毁后没有保存任务栈的状态,导致我们在桌面上启动的时候系统误认为当前启动LauncherActivity的任务栈已经被销毁,所以重新创建了新的任务栈并且跳转到LauncherActivity,最终导致用户从桌面点击APP图标时,总是跳转到LauncherActivity而不是HomeActivity
|
||||
|
||||
<!-- 主页界面 -->
|
||||
<activity
|
||||
android:name=".ui.activity.HomeActivity"
|
||||
android:alwaysRetainTaskState="true"
|
||||
android:launchMode="singleTop" />
|
|
@ -0,0 +1,202 @@
|
|||
|
||||
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 [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
|
@ -0,0 +1,68 @@
|
|||
# 项目介绍
|
||||
|
||||
## Module 介绍
|
||||
|
||||
> 这里的项目 Module 关系十分简单,只有两个:
|
||||
|
||||
* app:关于 APP 功能实现的业务逻辑代码,集成了一些常用的框架
|
||||
|
||||
* baselibrary:只存放关于技术实现的代码,不集成任何框架
|
||||
|
||||
> 本项目基于最新的 Android SDK 28 编译,[点击此处查看配置](build.gradle),最低安装要求为 Android 4.0
|
||||
|
||||
> 其中 Android Studio 的版本为3.2,Gradle的版本为 4.4
|
||||
|
||||
targetSdkVersion = 28
|
||||
compileSdkVersion = 28
|
||||
buildToolsVersion = '28.0.0'
|
||||
|
||||
## Activity关系
|
||||
|
||||
> 模板项目中的Activity有三层继承关系,Fragment 和 Application 继承关系也是雷同,这里不再赘述
|
||||
|
||||
* [BaseActivity](baselibrary/src/main/java/com/hjq/baselibrary/base/BaseActivity.java):继承至AppCompatActivity,主要做一些简单的代码封装
|
||||
|
||||
* [UIActivity](app/src/main/java/com/hjq/demo/common/UIActivity.java):继承至BaseActivity,主要加入了界面侧滑和状态栏沉浸式
|
||||
|
||||
* [CommonActivity](app/src/main/java/com/hjq/demo/common/CommonActivity.java):继承至UIActivity,主要实现项目中的业务逻辑代码
|
||||
|
||||
## View 样式
|
||||
|
||||
* 普通的圆角 Button 样式:style="@style/ButtonStyle"
|
||||
|
||||
* 普通不带圆角 Button 样式:style="@style/RectButtonStyle"
|
||||
|
||||
* 普通 EditText 样式:style="@style/EditTextStyle"
|
||||
|
||||
* 普通的水平分割线 View 样式:style="@style/HorizontalLineStyle"
|
||||
|
||||
* 普通的垂直分割线 View 样式:style="@style/VerticalLineStyle"
|
||||
|
||||
## View 使用
|
||||
|
||||
> 具体用法可以[点击此处查看示例](app/src/main/res/layout/fragment_test_b.xml)
|
||||
|
||||
![](picture/2.png)
|
||||
|
||||
## 框架使用
|
||||
|
||||
> 具体用法可以[点击此处查看示例](app/src/main/res/layout/fragment_test_c.xml)
|
||||
|
||||
![](picture/3.png)
|
||||
|
||||
## 友盟多渠道打包
|
||||
|
||||
> 具体配置可以[点击此处查看](app/build.gradle)
|
||||
|
||||
![](picture/flavors_1.jpg)
|
||||
|
||||
![](picture/flavors_2.jpg)
|
||||
|
||||
![](picture/flavors_3.jpg)
|
||||
|
||||
> 使用友盟多渠道统计时需要[更换清单文件中的key](app/src/main/AndroidManifest.xml)
|
||||
|
||||
<!-- 友盟统计 -->
|
||||
<meta-data
|
||||
android:name="UMENG_APPKEY"
|
||||
android:value="XXXXXXXXXXXXXXXXXXXXXXXX" /><!-- 要注意更换key -->
|
|
@ -0,0 +1,89 @@
|
|||
# 模板工程
|
||||
|
||||
> 当我们日复一日年复一年的搬砖的时候,你是否曾想过提升一下开发效率,如果一个模板的项目摆在你的面前,你还会选择自己搭架构么
|
||||
|
||||
> 但是做出一个好的模板项目并非易事,有多少人愿意选择去做,还有多少人选择努力去做好,可能寥寥无几,但是你今天看到的,正是你所想要的,一个真正能解决你开发新项目时最大痛点的模板工程,你不需要再麻木 Copy 原有旧项目的代码,只需改动少量代码就能得到想要的效果,你会发现开发新项目其实是一件很快乐的事
|
||||
|
||||
> 已经正式投入公司新项目开发多时,暂时没有其他毛病,[点击此处下载Demo](https://raw.githubusercontent.com/getActivity/AndroidProject/master/AndroidProject.apk)
|
||||
|
||||
![](picture/0.png)
|
||||
|
||||
![](picture/1.gif)
|
||||
|
||||
![](picture/2.png)
|
||||
|
||||
![](picture/3.png)
|
||||
|
||||
![](picture/4.png)
|
||||
|
||||
![](picture/5.png)
|
||||
|
||||
![](picture/6.png)
|
||||
|
||||
![](picture/7.png)
|
||||
|
||||
![](picture/8.png)
|
||||
|
||||
## 集成框架
|
||||
|
||||
* 状态栏沉浸:[https://github.com/gyf-dev/ImmersionBar](https://github.com/gyf-dev/ImmersionBar)
|
||||
|
||||
* 侧滑功能:[https://github.com/bingoogolapple/BGASwipeBackLayout-Android](https://github.com/bingoogolapple/BGASwipeBackLayout-Android)
|
||||
|
||||
* 权限请求框架:[https://github.com/getActivity/XXPermissions](https://github.com/getActivity/XXPermissions)
|
||||
|
||||
* 标题栏:[https://github.com/getActivity/TitleBar](https://github.com/getActivity/TitleBar)
|
||||
|
||||
* 吐司工具类:[https://github.com/getActivity/ToastUtils](https://github.com/getActivity/ToastUtils)
|
||||
|
||||
* 圆形的ImageView:[https://github.com/hdodenhof/CircleImageView](https://github.com/hdodenhof/CircleImageView)
|
||||
|
||||
* ButterKnife注解:[https://github.com/JakeWharton/butterknife](https://github.com/JakeWharton/butterknife)
|
||||
|
||||
#### 模板项目亮点,[查看详细](ProjectDetails.md)
|
||||
|
||||
* APP用户体验:已经集成界面侧滑以及状态栏沉浸框架
|
||||
|
||||
* 必备优秀框架:危险权限处理,标题栏控件,吐司工具类,圆形ImageView
|
||||
|
||||
* 常用页面模板:启动界面,主页界面,登录界面,注册界面,关于界面,浏览器界面
|
||||
|
||||
* 集成友盟统计:集成友盟统计,并且加入了友盟多渠道打包,在发布release包时可选择渠道包
|
||||
|
||||
* 常用自定义View:圆形ImageView,验证码点击倒计时View,带清除按钮的EditText,正方形的FrameLayout、LinearLayout、RelativeLayout、ImageView
|
||||
|
||||
* 界面样式规范:项目的严格按照 Material Design 设计进行配色,统一和规范Button和EditText控件样式
|
||||
|
||||
* 代码注释规范:代码严格按照谷歌级规范来做,如需寻找友盟相关的代码,全局搜索 "友盟" 即可,任何一处不关于原生的 API 都有非常完善的注释
|
||||
|
||||
#### 修复Android普遍存在的问题,[查看详细](AndroidBug.md)
|
||||
|
||||
* 修复 Button 在Android 5.1 之后英文字符串自动大写的问题
|
||||
|
||||
* 修复 Button 在设置状态选择器后仍然残留按压阴影的问题
|
||||
|
||||
* 修复某些低配置机型启动页停留在白屏的时间比较长的问题
|
||||
|
||||
* 修复某些机型在 WebView 长按时布局被顶下来的问题
|
||||
|
||||
* 修复 任务栈中 首页Activity 被重复启动的问题
|
||||
|
||||
#### Android技术讨论Q群:78797078
|
||||
|
||||
## License
|
||||
|
||||
```text
|
||||
Copyright 2018 Huang Jinqun
|
||||
|
||||
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.
|
||||
```
|
|
@ -0,0 +1 @@
|
|||
/build
|
|
@ -0,0 +1,93 @@
|
|||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion rootProject.ext.compileSdkVersion
|
||||
buildToolsVersion rootProject.ext.buildToolsVersion
|
||||
defaultConfig {
|
||||
applicationId "com.hjq.demo"
|
||||
minSdkVersion 14
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 10
|
||||
versionName "1.0"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
// 不显示Log
|
||||
buildConfigField "boolean", "LOG_DEBUG", "false"
|
||||
// 移除无用的resource文件,前提minifyEnabled必须打开
|
||||
shrinkResources true
|
||||
// ZipAlign优化
|
||||
zipAlignEnabled true
|
||||
// 设置混淆
|
||||
minifyEnabled true
|
||||
//加载默认混淆配置涵
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
|
||||
debug {
|
||||
//ZipAlign优化
|
||||
zipAlignEnabled false
|
||||
//设置混淆
|
||||
minifyEnabled false
|
||||
//加载默认混淆配置涵
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
flavorDimensions "default"//这个名字貌似随便取,也可以有多个,总之一定要有
|
||||
//多渠道打包
|
||||
productFlavors {
|
||||
kuan {} //酷安
|
||||
tencent {} //应用宝
|
||||
baidu {} //百度
|
||||
xiaomi {} //小米
|
||||
huawei {} //华为
|
||||
qihu {} //360
|
||||
|
||||
productFlavors.all { flavor ->
|
||||
flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api fileTree(include: ['*.jar'], dir: 'libs')
|
||||
api project(':baselibrary')
|
||||
// 示例:添加一个 aar 包
|
||||
//api(name: 'password_dialog', ext: 'aar')
|
||||
|
||||
api "com.android.support:appcompat-v7:$rootProject.ext.supportLibraryVersion"
|
||||
api "com.android.support:design:$rootProject.ext.supportLibraryVersion"
|
||||
api "com.android.support:support-v4:$rootProject.ext.supportLibraryVersion"
|
||||
api "com.android.support:cardview-v7:$rootProject.ext.supportLibraryVersion"
|
||||
api "com.android.support.constraint:constraint-layout:$rootProject.ext.constraintlayoutVersion"
|
||||
|
||||
// 状态栏沉浸:https://github.com/gyf-dev/ImmersionBar
|
||||
api 'com.gyf.barlibrary:barlibrary:2.3.0'
|
||||
// 侧滑功能:https://github.com/bingoogolapple/BGASwipeBackLayout-Android
|
||||
api 'cn.bingoogolapple:bga-swipebacklayout:1.1.9@aar'
|
||||
|
||||
// 权限请求框架:https://github.com/getActivity/XXPermissions
|
||||
api 'com.hjq:xxpermissions:5.2'
|
||||
// 标题栏:https://github.com/getActivity/TitleBar
|
||||
api 'com.hjq:titlebar:3.2'
|
||||
// 吐司工具类:https://github.com/getActivity/ToastUtils
|
||||
api 'com.hjq:toast:2.5'
|
||||
|
||||
// 圆形的ImageView:https://github.com/hdodenhof/CircleImageView
|
||||
api 'de.hdodenhof:circleimageview:2.2.0'
|
||||
|
||||
// ButterKnife注解库:https://github.com/JakeWharton/butterknife
|
||||
api "com.jakewharton:butterknife:$rootProject.ext.butterknifeVersion"
|
||||
annotationProcessor "com.jakewharton:butterknife-compiler:$rootProject.ext.butterknifeVersion"
|
||||
|
||||
// 友盟统计
|
||||
compileOnly 'com.umeng.analytics:analytics:6.1.4'
|
||||
}
|
||||
|
||||
repositories {
|
||||
flatDir {
|
||||
dirs 'libs' //就是你放aar的目录地址
|
||||
}
|
||||
}
|
|
@ -0,0 +1,225 @@
|
|||
#指定代码的压缩级别
|
||||
-optimizationpasses 5
|
||||
|
||||
#包明不混合大小写
|
||||
-dontusemixedcaseclassnames
|
||||
|
||||
#不去忽略非公共的库类
|
||||
-dontskipnonpubliclibraryclasses
|
||||
|
||||
#优化 不优化输入的类文件
|
||||
-dontoptimize
|
||||
|
||||
#预校验
|
||||
-dontpreverify
|
||||
|
||||
#混淆时是否记录日志
|
||||
-verbose
|
||||
|
||||
# 混淆时所采用的算法
|
||||
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
|
||||
|
||||
#保护注解
|
||||
-keepattributes *Annotation*
|
||||
|
||||
# 保持哪些类不被混淆
|
||||
-keep public class * extends android.app.Fragment
|
||||
-keep public class * extends android.app.Activity
|
||||
-keep public class * extends android.app.Application
|
||||
-keep public class * extends android.app.Service
|
||||
-keep public class * extends android.content.BroadcastReceiver
|
||||
-keep public class * extends android.content.ContentProvider
|
||||
-keep public class * extends android.app.backup.BackupAgentHelper
|
||||
-keep public class * extends android.preference.Preference
|
||||
-keep public class com.android.vending.licensing.ILicensingService
|
||||
#如果有引用v4包可以添加下面这行
|
||||
-keep public class * extends android.support.v4.app.Fragment
|
||||
|
||||
|
||||
#忽略警告
|
||||
-ignorewarning
|
||||
|
||||
#####################记录生成的日志数据,gradle build时在本项目根目录输出################
|
||||
|
||||
#apk 包内所有 class 的内部结构
|
||||
-dump class_files.txt
|
||||
#未混淆的类和成员
|
||||
-printseeds seeds.txt
|
||||
#列出从 apk 中删除的代码
|
||||
-printusage unused.txt
|
||||
#混淆前后的映射
|
||||
-printmapping mapping.txt
|
||||
|
||||
#####################记录生成的日志数据,gradle build时 在本项目根目录输出-end################
|
||||
|
||||
|
||||
################混淆保护自己项目的部分代码以及引用的第三方jar包library#########################
|
||||
#-libraryjars libs/umeng-analytics-v5.2.4.jar
|
||||
#-libraryjars libs/alipaysdk.jar
|
||||
#-libraryjars libs/alipaysecsdk.jar
|
||||
#-libraryjars libs/alipayutdid.jar
|
||||
#-libraryjars libs/wup-1.0.0-SNAPSHOT.jar
|
||||
#-libraryjars libs/weibosdkcore.jar
|
||||
|
||||
|
||||
#三星应用市场需要添加:sdk-v1.0.0.jar,look-v1.0.1.jar
|
||||
#-libraryjars libs/sdk-v1.0.0.jar
|
||||
#-libraryjars libs/look-v1.0.1.jar
|
||||
|
||||
#我是以libaray的形式引用了一个图片加载框架,如果不想混淆 keep 掉
|
||||
-keep class com.nostra13.universalimageloader.** { *; }
|
||||
|
||||
#友盟
|
||||
-keep class com.umeng.**{*;}
|
||||
|
||||
#支付宝
|
||||
-keep class com.alipay.android.app.IAliPay{*;}
|
||||
-keep class com.alipay.android.app.IAlixPay{*;}
|
||||
-keep class com.alipay.android.app.IRemoteServiceCallback{*;}
|
||||
-keep class com.alipay.android.app.lib.ResourceMap{*;}
|
||||
|
||||
|
||||
#信鸽推送
|
||||
-keep class com.tencent.android.tpush.** {* ;}
|
||||
-keep class com.tencent.mid.** {* ;}
|
||||
|
||||
|
||||
#自己项目特殊处理代码
|
||||
|
||||
#忽略警告
|
||||
-dontwarn com.veidy.mobile.common.**
|
||||
#保留一个完整的包
|
||||
-keep class com.veidy.mobile.common.** {
|
||||
*;
|
||||
}
|
||||
|
||||
-keep class com.veidy.activity.login.WebLoginActivity{*;}
|
||||
-keep class com.veidy.activity.UserInfoFragment{*;}
|
||||
-keep class com.veidy.activity.HomeFragmentActivity{*;}
|
||||
-keep class com.veidy.activity.CityActivity{*;}
|
||||
-keep class com.veidy.activity.ClinikActivity{*;}
|
||||
|
||||
#如果引用了v4或者v7包
|
||||
-dontwarn android.support.**
|
||||
|
||||
############混淆保护自己项目的部分代码以及引用的第三方jar包library-end##################
|
||||
|
||||
-keep public class * extends android.view.View {
|
||||
public <init>(android.content.Context);
|
||||
public <init>(android.content.Context, android.util.AttributeSet);
|
||||
public <init>(android.content.Context, android.util.AttributeSet, int);
|
||||
public void set*(...);
|
||||
}
|
||||
|
||||
#保持 native 方法不被混淆
|
||||
-keepclasseswithmembernames class * {
|
||||
native <methods>;
|
||||
}
|
||||
|
||||
#保持自定义控件类不被混淆
|
||||
-keepclasseswithmembers class * {
|
||||
public <init>(android.content.Context, android.util.AttributeSet);
|
||||
}
|
||||
|
||||
#保持自定义控件类不被混淆
|
||||
-keepclasseswithmembers class * {
|
||||
public <init>(android.content.Context, android.util.AttributeSet, int);
|
||||
}
|
||||
#保持自定义控件类不被混淆
|
||||
-keepclassmembers class * extends android.app.Activity {
|
||||
public void *(android.view.View);
|
||||
}
|
||||
|
||||
#保持 Parcelable 不被混淆
|
||||
-keep class * implements android.os.Parcelable {
|
||||
public static final android.os.Parcelable$Creator *;
|
||||
}
|
||||
|
||||
#保持 Serializable 不被混淆
|
||||
-keepnames class * implements java.io.Serializable
|
||||
|
||||
#保持 Serializable 不被混淆并且enum 类也不被混淆
|
||||
-keepclassmembers class * implements java.io.Serializable {
|
||||
static final long serialVersionUID;
|
||||
private static final java.io.ObjectStreamField[] serialPersistentFields;
|
||||
!static !transient <fields>;
|
||||
!private <fields>;
|
||||
!private <methods>;
|
||||
private void writeObject(java.io.ObjectOutputStream);
|
||||
private void readObject(java.io.ObjectInputStream);
|
||||
java.lang.Object writeReplace();
|
||||
java.lang.Object readResolve();
|
||||
}
|
||||
|
||||
#保持枚举 enum 类不被混淆 如果混淆报错,建议直接使用上面的 -keepclassmembers class * implements java.io.Serializable即可
|
||||
#-keepclassmembers enum * {
|
||||
# public static **[] values();
|
||||
# public static ** valueOf(java.lang.String);
|
||||
#}
|
||||
|
||||
-keepclassmembers class * {
|
||||
public void *ButtonClicked(android.view.View);
|
||||
}
|
||||
|
||||
#不混淆资源类
|
||||
-keepclassmembers class **.R$* {
|
||||
public static <fields>;
|
||||
}
|
||||
|
||||
#避免混淆泛型 如果混淆报错建议关掉
|
||||
#–keepattributes Signature
|
||||
|
||||
#移除log 测试了下没有用还是建议自己定义一个开关控制是否输出日志
|
||||
#-assumenosideeffects class android.util.Log {
|
||||
# public static boolean isLoggable(java.lang.String, int);
|
||||
# public static int v(...);
|
||||
# public static int i(...);
|
||||
# public static int w(...);
|
||||
# public static int d(...);
|
||||
# public static int e(...);
|
||||
#}
|
||||
|
||||
# webview + js
|
||||
-keepattributes *JavascriptInterface*
|
||||
# keep 使用 webview 的类
|
||||
-keepclassmembers class com.veidy.activity.WebViewActivity {
|
||||
public *;
|
||||
}
|
||||
# keep 使用 webview 的类的所有的内部类
|
||||
-keepclassmembers class com.veidy.activity.WebViewActivity$*{
|
||||
*;
|
||||
}
|
||||
|
||||
# 不混淆WebChromeClient中的openFileChooser方法
|
||||
-keepclassmembers class * extends android.webkit.WebChromeClient{
|
||||
public void openFileChooser(...);
|
||||
}
|
||||
|
||||
#友盟统计
|
||||
-keepclassmembers class * {
|
||||
public <init> (org.json.JSONObject);
|
||||
}
|
||||
|
||||
#极光推送
|
||||
-dontoptimize
|
||||
-dontpreverify
|
||||
|
||||
-dontwarn cn.jpush.**
|
||||
-keep class cn.jpush.** { *; }
|
||||
-keep class * extends cn.jpush.android.helpers.JPushMessageReceiver { *; }
|
||||
|
||||
-dontwarn cn.jiguang.**
|
||||
-keep class cn.jiguang.** { *; }
|
||||
|
||||
# support-v7-appcompat
|
||||
-keep public class android.support.v7.widget.** { *; }
|
||||
-keep public class android.support.v7.internal.widget.** { *; }
|
||||
-keep public class android.support.v7.internal.view.menu.** { *; }
|
||||
-keep public class * extends android.support.v4.view.ActionProvider {
|
||||
public <init>(android.content.Context);
|
||||
}
|
||||
# support-design
|
||||
-dontwarn android.support.design.**
|
||||
-keep class android.support.design.** { *; }
|
||||
-keep interface android.support.design.** { *; }
|
||||
-keep public class android.support.design.R$* { *; }
|
|
@ -0,0 +1,80 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.hjq.demo">
|
||||
|
||||
<!-- 外部存储读写权限 -->
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
|
||||
<!-- 拍照权限 -->
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
|
||||
<!-- 联网权限 -->
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<!-- 友盟统计 -->
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
|
||||
<application
|
||||
android:name=".common.CommonApplication"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher"
|
||||
android:theme="@style/AppTheme">
|
||||
|
||||
<!-- 友盟统计 -->
|
||||
<meta-data
|
||||
android:name="UMENG_APPKEY"
|
||||
android:value="XXXXXXXXXXXXXXXXXXXXXXXX" /><!-- 要注意更换key -->
|
||||
|
||||
<!-- 友盟多渠道打包 -->
|
||||
<meta-data
|
||||
android:name="UMENG_CHANNEL"
|
||||
android:value="${UMENG_CHANNEL_VALUE}" />
|
||||
|
||||
<!-- 启动页面(因为使用了LauncherTheme,所以不要给这个Activity设置screenOrientation属性,会导致崩溃) -->
|
||||
<activity
|
||||
android:name=".ui.activity.LauncherActivity"
|
||||
android:theme="@style/LauncherTheme">
|
||||
|
||||
<!-- 程序入口 -->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
|
||||
</activity>
|
||||
|
||||
<!-- 主页界面 -->
|
||||
<activity
|
||||
android:name=".ui.activity.HomeActivity"
|
||||
android:alwaysRetainTaskState="true"
|
||||
android:launchMode="singleTop" />
|
||||
|
||||
<!-- 登录界面 -->
|
||||
<activity
|
||||
android:name=".ui.activity.LoginActivity"
|
||||
android:launchMode="singleTop" />
|
||||
|
||||
<!-- 注册界面 -->
|
||||
<activity
|
||||
android:name=".ui.activity.RegisterActivity"
|
||||
android:launchMode="singleTop" />
|
||||
|
||||
<!-- 关于界面 -->
|
||||
<activity
|
||||
android:name=".ui.activity.AboutActivity"
|
||||
android:launchMode="singleTop" />
|
||||
|
||||
<!-- 浏览器界面 -->
|
||||
<activity
|
||||
android:name=".ui.activity.WebActivity"
|
||||
android:launchMode="singleTop" />
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
|
@ -0,0 +1,132 @@
|
|||
package com.hjq.demo.common;
|
||||
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.view.View;
|
||||
|
||||
import com.hjq.bar.OnTitleBarListener;
|
||||
import com.hjq.bar.TitleBar;
|
||||
import com.umeng.analytics.MobclickAgent;
|
||||
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.Unbinder;
|
||||
|
||||
/**
|
||||
* author : HJQ
|
||||
* github : https://github.com/getActivity/AndroidProject
|
||||
* time : 2018/10/18
|
||||
* desc : 项目中的Activity基类
|
||||
*/
|
||||
public abstract class CommonActivity extends UIActivity
|
||||
implements OnTitleBarListener {
|
||||
|
||||
private Unbinder mButterKnife;//View注解
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
|
||||
//初始化标题栏的监听
|
||||
if (getTitleBarId() > 0) {
|
||||
if (findViewById(getTitleBarId()) instanceof TitleBar) {
|
||||
((TitleBar) findViewById(getTitleBarId())).setOnTitleBarListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
mButterKnife = ButterKnife.bind(this);
|
||||
|
||||
initOrientation();
|
||||
|
||||
super.init();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化横竖屏方向,会和 LauncherTheme 主题样式有冲突,注意不要同时使用
|
||||
*/
|
||||
protected void initOrientation() {
|
||||
//如果没有指定屏幕方向,则默认为竖屏
|
||||
if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置标题栏的标题
|
||||
*/
|
||||
@Override
|
||||
public void setTitle(int titleId) {
|
||||
setTitle(getText(titleId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置标题栏的标题
|
||||
*/
|
||||
@Override
|
||||
public void setTitle(CharSequence title) {
|
||||
super.setTitle(title);
|
||||
TitleBar titleBar = getTitleBar();
|
||||
if (titleBar != null) {
|
||||
titleBar.setTitle(title);
|
||||
}
|
||||
}
|
||||
|
||||
protected TitleBar getTitleBar() {
|
||||
if (getTitleBarId() > 0 && findViewById(getTitleBarId()) instanceof TitleBar) {
|
||||
return findViewById(getTitleBarId());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean statusBarDarkFont() {
|
||||
//返回true表示黑色字体
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link OnTitleBarListener}
|
||||
*/
|
||||
|
||||
/**
|
||||
* 标题栏左边的View被点击了
|
||||
*/
|
||||
@Override
|
||||
public void onLeftClick(View v) {
|
||||
onBackPressed();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 标题栏中间的View被点击了
|
||||
*/
|
||||
@Override
|
||||
public void onTitleClick(View v) {}
|
||||
|
||||
/**
|
||||
* 标题栏右边的View被点击了
|
||||
*/
|
||||
@Override
|
||||
public void onRightClick(View v) {}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
// 手动统计页面
|
||||
MobclickAgent.onPageStart(getClass().getSimpleName());
|
||||
// 友盟统计
|
||||
MobclickAgent.onResume(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
// 手动统计页面,必须保证 onPageEnd 在 onPause 之前调用,因为SDK会在 onPause 中保存onPageEnd统计到的页面数据
|
||||
MobclickAgent.onPageEnd(getClass().getSimpleName());
|
||||
// 友盟统计
|
||||
MobclickAgent.onPause(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mButterKnife != null) mButterKnife.unbind();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package com.hjq.demo.common;
|
||||
|
||||
import com.hjq.toast.ToastUtils;
|
||||
import com.umeng.analytics.MobclickAgent;
|
||||
|
||||
/**
|
||||
* author : HJQ
|
||||
* github : https://github.com/getActivity/AndroidProject
|
||||
* time : 2018/10/18
|
||||
* desc : 项目中的Activity基类
|
||||
*/
|
||||
public class CommonApplication extends UIApplication {
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
// 初始化吐司工具类
|
||||
ToastUtils.init(getApplicationContext());
|
||||
|
||||
// 友盟统计
|
||||
MobclickAgent.setScenarioType(getApplicationContext(), MobclickAgent.EScenarioType.E_UM_NORMAL);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package com.hjq.demo.common;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.umeng.analytics.MobclickAgent;
|
||||
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.Unbinder;
|
||||
|
||||
/**
|
||||
* author : HJQ
|
||||
* github : https://github.com/getActivity/AndroidProject
|
||||
* time : 2018/10/18
|
||||
* desc : 项目中Fragment懒加载基类
|
||||
*/
|
||||
public abstract class CommonLazyFragment extends UILazyFragment {
|
||||
|
||||
private Unbinder mButterKnife;// View注解
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View view = super.onCreateView(inflater, container, savedInstanceState);
|
||||
mButterKnife = ButterKnife.bind(this, view);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
// 友盟统计
|
||||
MobclickAgent.onResume(getContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
// 友盟统计
|
||||
MobclickAgent.onPause(getContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
mButterKnife.unbind();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,173 @@
|
|||
package com.hjq.demo.common;
|
||||
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.gyf.barlibrary.ImmersionBar;
|
||||
import com.hjq.baselibrary.base.BaseActivity;
|
||||
import com.hjq.demo.R;
|
||||
|
||||
import cn.bingoogolapple.swipebacklayout.BGASwipeBackHelper;
|
||||
|
||||
/**
|
||||
* author : HJQ
|
||||
* github : https://github.com/getActivity/AndroidProject
|
||||
* time : 2018/10/18
|
||||
* desc : 支持沉浸式和侧滑的Activity基类(默认开启沉浸式状态栏和侧滑功能)
|
||||
*/
|
||||
public abstract class UIActivity extends BaseActivity
|
||||
implements BGASwipeBackHelper.Delegate, ViewTreeObserver.OnGlobalLayoutListener {
|
||||
|
||||
private ImmersionBar mImmersionBar;//状态栏沉浸
|
||||
private BGASwipeBackHelper mSwipeBackHelper;//侧滑返回
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
// 在 super.onCreate(savedInstanceState) 之前调用该方法
|
||||
initSwipeBackFinish();
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
public void init(){
|
||||
|
||||
//初始化沉浸式状态栏
|
||||
if (isStatusBarEnabled()) {
|
||||
statusBarConfig().init();
|
||||
}
|
||||
|
||||
//设置标题栏
|
||||
if (getTitleBarId() > 0) {
|
||||
ImmersionBar.setTitleBar(this, findViewById(getTitleBarId()));
|
||||
}
|
||||
initView();
|
||||
initData();
|
||||
}
|
||||
|
||||
public BGASwipeBackHelper getSwipeBackHelper() {
|
||||
return mSwipeBackHelper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化滑动返回。在 super.onCreate(savedInstanceState) 之前调用该方法
|
||||
*/
|
||||
private void initSwipeBackFinish() {
|
||||
mSwipeBackHelper = new BGASwipeBackHelper(this, this);
|
||||
|
||||
// 「必须在 Application 的 onCreate 方法中执行 BGASwipeBackHelper.init 来初始化滑动返回」
|
||||
// 下面几项可以不配置,这里只是为了讲述接口用法。
|
||||
|
||||
// 设置滑动返回是否可用。默认值为 true
|
||||
mSwipeBackHelper.setSwipeBackEnable(true);
|
||||
// 设置是否仅仅跟踪左侧边缘的滑动返回。默认值为 true
|
||||
mSwipeBackHelper.setIsOnlyTrackingLeftEdge(true);
|
||||
// 设置是否是微信滑动返回样式。默认值为 true
|
||||
mSwipeBackHelper.setIsWeChatStyle(true);
|
||||
// 设置阴影资源 id。默认值为 R.drawable.bga_sbl_shadow
|
||||
mSwipeBackHelper.setShadowResId(R.drawable.bga_sbl_shadow);
|
||||
// 设置是否显示滑动返回的阴影效果。默认值为 true
|
||||
mSwipeBackHelper.setIsNeedShowShadow(true);
|
||||
// 设置阴影区域的透明度是否根据滑动的距离渐变。默认值为 true
|
||||
mSwipeBackHelper.setIsShadowAlphaGradient(true);
|
||||
// 设置触发释放后自动滑动返回的阈值,默认值为 0.3f
|
||||
mSwipeBackHelper.setSwipeBackThreshold(0.3f);
|
||||
// 设置底部导航条是否悬浮在内容上,默认值为 false
|
||||
mSwipeBackHelper.setIsNavigationBarOverlap(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link BGASwipeBackHelper.Delegate}
|
||||
*/
|
||||
|
||||
/**
|
||||
* 是否支持滑动返回。这里在父类中默认返回 true 来支持滑动返回,如果某个界面不想支持滑动返回则重写该方法返回 false 即可
|
||||
*/
|
||||
@Override
|
||||
public boolean isSupportSwipeBack() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 正在滑动返回
|
||||
*
|
||||
* @param slideOffset 从 0 到 1
|
||||
*/
|
||||
@Override
|
||||
public void onSwipeBackLayoutSlide(float slideOffset) {}
|
||||
|
||||
/**
|
||||
* 没达到滑动返回的阈值,取消滑动返回动作,回到默认状态
|
||||
*/
|
||||
@Override
|
||||
public void onSwipeBackLayoutCancel() {}
|
||||
|
||||
/**
|
||||
* 滑动返回执行完毕,销毁当前 Activity
|
||||
*/
|
||||
@Override
|
||||
public void onSwipeBackLayoutExecuted() {
|
||||
mSwipeBackHelper.swipeBackward();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
// 正在滑动返回的时候取消返回按钮事件
|
||||
if (mSwipeBackHelper.isSliding()) {
|
||||
return;
|
||||
}
|
||||
mSwipeBackHelper.backward();
|
||||
super.onBackPressed();
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否使用沉浸式状态栏
|
||||
*/
|
||||
public boolean isStatusBarEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取状态栏沉浸的配置对象
|
||||
*/
|
||||
public ImmersionBar getStatusBarConfig() {
|
||||
return mImmersionBar;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化沉浸式状态栏
|
||||
*/
|
||||
private ImmersionBar statusBarConfig() {
|
||||
//在BaseActivity里初始化
|
||||
mImmersionBar = ImmersionBar.with(this)
|
||||
.statusBarDarkFont(statusBarDarkFont()) //默认状态栏字体颜色为黑色
|
||||
.keyboardEnable(false, WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN
|
||||
| WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN); //解决软键盘与底部输入框冲突问题,默认为false,还有一个重载方法,可以指定软键盘mode
|
||||
//必须设置View树布局变化监听,否则软键盘无法顶上去,还有模式必须是SOFT_INPUT_ADJUST_PAN
|
||||
getWindow().getDecorView().getViewTreeObserver().addOnGlobalLayoutListener(this);
|
||||
return mImmersionBar;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ViewTreeObserver.OnGlobalLayoutListener}
|
||||
*/
|
||||
@Override
|
||||
public void onGlobalLayout() {}//不用写任何方法
|
||||
|
||||
/**
|
||||
* 获取状态栏字体颜色
|
||||
*/
|
||||
public boolean statusBarDarkFont() {
|
||||
//返回false表示白色字体
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mImmersionBar != null) mImmersionBar.destroy();
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
getWindow().getDecorView().getViewTreeObserver().removeOnGlobalLayoutListener(this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package com.hjq.demo.common;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
import cn.bingoogolapple.swipebacklayout.BGASwipeBackHelper;
|
||||
|
||||
/**
|
||||
* author : HJQ
|
||||
* github : https://github.com/getActivity/AndroidProject
|
||||
* time : 2018/10/18
|
||||
* desc : 支持侧滑的UIApplication基类
|
||||
*/
|
||||
public abstract class UIApplication extends Application {
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
/**
|
||||
* 必须在 Application 的 onCreate 方法中执行 BGASwipeBackHelper.init 来初始化滑动返回
|
||||
* 第一个参数:应用程序上下文
|
||||
* 第二个参数:如果发现滑动返回后立即触摸界面时应用崩溃,请把该界面里比较特殊的 View 的 class 添加到该集合中,目前在库中已经添加了 WebView 和 SurfaceView
|
||||
*/
|
||||
BGASwipeBackHelper.init(this, null);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
package com.hjq.demo.common;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.view.View;
|
||||
|
||||
import com.gyf.barlibrary.ImmersionBar;
|
||||
import com.hjq.baselibrary.base.BaseLazyFragment;
|
||||
|
||||
/**
|
||||
* author : HJQ
|
||||
* github : https://github.com/getActivity/AndroidProject
|
||||
* time : 2018/10/18
|
||||
* desc : 支持沉浸式Fragment懒加载基类(默认不开启沉浸式)
|
||||
*/
|
||||
public abstract class UILazyFragment extends BaseLazyFragment {
|
||||
|
||||
private ImmersionBar mImmersionBar;//状态栏沉浸
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
//初始化沉浸式状态栏
|
||||
if (isVisibleToUser() && isStatusBarEnabled() && isLazyLoad()) {
|
||||
statusBarConfig().init();
|
||||
}
|
||||
|
||||
//设置标题栏
|
||||
if (!isLazyLoad() && getTitleBarId() > 0) {
|
||||
ImmersionBar.setTitleBar(mActivity, view.findViewById(getTitleBarId()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否在Fragment使用沉浸式
|
||||
*/
|
||||
public boolean isStatusBarEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取状态栏沉浸的配置对象
|
||||
*/
|
||||
protected ImmersionBar getStatusBarConfig() {
|
||||
return mImmersionBar;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化沉浸式
|
||||
*/
|
||||
private ImmersionBar statusBarConfig() {
|
||||
//在BaseActivity里初始化
|
||||
mImmersionBar = ImmersionBar.with(this)
|
||||
.statusBarDarkFont(statusBarDarkFont()) //默认状态栏字体颜色为黑色
|
||||
.keyboardEnable(true); //解决软键盘与底部输入框冲突问题,默认为false,还有一个重载方法,可以指定软键盘mode
|
||||
return mImmersionBar;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取状态栏字体颜色
|
||||
*/
|
||||
protected boolean statusBarDarkFont() {
|
||||
//返回true表示黑色字体
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mImmersionBar != null) mImmersionBar.destroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUserVisibleHint(boolean isVisibleToUser) {
|
||||
super.setUserVisibleHint(isVisibleToUser);
|
||||
if (isVisibleToUser && isStatusBarEnabled() && isLazyLoad()) {
|
||||
// 重新初始化状态栏
|
||||
statusBarConfig().init();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package com.hjq.demo.ui.activity;
|
||||
|
||||
import com.hjq.demo.R;
|
||||
import com.hjq.demo.common.CommonActivity;
|
||||
|
||||
/**
|
||||
* author : HJQ
|
||||
* github : https://github.com/getActivity/AndroidProject
|
||||
* time : 2018/10/18
|
||||
* desc : 关于界面
|
||||
*/
|
||||
public class AboutActivity extends CommonActivity {
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.activity_about;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getTitleBarId() {
|
||||
return R.id.tb_about_title;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initView() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initData() {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package com.hjq.demo.ui.activity;
|
||||
|
||||
import com.hjq.demo.R;
|
||||
import com.hjq.demo.common.CommonActivity;
|
||||
|
||||
/**
|
||||
* author : HJQ
|
||||
* github : https://github.com/getActivity/AndroidProject
|
||||
* time : 2018/10/18
|
||||
* desc : 可进行拷贝的副本
|
||||
*/
|
||||
public class CopyActivity extends CommonActivity {
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.activity_copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getTitleBarId() {
|
||||
return R.id.tb_copy_title;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initView() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initData() {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
package com.hjq.demo.ui.activity;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.design.widget.BottomNavigationView;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import com.hjq.demo.R;
|
||||
import com.hjq.demo.common.CommonActivity;
|
||||
import com.hjq.demo.ui.adapter.HomeViewPagerAdapter;
|
||||
import com.hjq.baselibrary.utils.OnClickUtils;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
/**
|
||||
* author : HJQ
|
||||
* github : https://github.com/getActivity/AndroidProject
|
||||
* time : 2018/10/18
|
||||
* desc : 主页界面
|
||||
*/
|
||||
public class HomeActivity extends CommonActivity implements
|
||||
ViewPager.OnPageChangeListener, BottomNavigationView.OnNavigationItemSelectedListener {
|
||||
|
||||
@BindView(R.id.vp_home_pager)
|
||||
ViewPager mViewPager;
|
||||
@BindView(R.id.bv_home_navigation)
|
||||
BottomNavigationView mBottomNavigationView;
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.activity_home;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getTitleBarId() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initView() {
|
||||
// 限制页面数量
|
||||
mViewPager.setOffscreenPageLimit(4);
|
||||
mViewPager.addOnPageChangeListener(this);
|
||||
|
||||
// 不使用图标默认变色
|
||||
mBottomNavigationView.setItemIconTintList(null);
|
||||
mBottomNavigationView.setOnNavigationItemSelectedListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initData() {
|
||||
mViewPager.setAdapter(new HomeViewPagerAdapter(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link ViewPager.OnPageChangeListener}
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
switch (position) {
|
||||
case 0:
|
||||
mBottomNavigationView.setSelectedItemId(R.id.menu_home);
|
||||
break;
|
||||
case 1:
|
||||
mBottomNavigationView.setSelectedItemId(R.id.home_found);
|
||||
break;
|
||||
case 2:
|
||||
mBottomNavigationView.setSelectedItemId(R.id.home_message);
|
||||
break;
|
||||
case 3:
|
||||
mBottomNavigationView.setSelectedItemId(R.id.home_me);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) {}
|
||||
|
||||
/**
|
||||
* {@link BottomNavigationView.OnNavigationItemSelectedListener}
|
||||
*/
|
||||
|
||||
@Override
|
||||
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.menu_home:
|
||||
mViewPager.setCurrentItem(0);
|
||||
return true;
|
||||
case R.id.home_found:
|
||||
mViewPager.setCurrentItem(1);
|
||||
return true;
|
||||
case R.id.home_message:
|
||||
mViewPager.setCurrentItem(2);
|
||||
return true;
|
||||
case R.id.home_me:
|
||||
mViewPager.setCurrentItem(3);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (OnClickUtils.isOnDoubleClick()) {
|
||||
//移动到上一个任务栈,避免侧滑引起的不良反应
|
||||
moveTaskToBack(false);
|
||||
getWindow().getDecorView().postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
//销毁掉当前界面
|
||||
finish();
|
||||
}
|
||||
}, 300);
|
||||
} else {
|
||||
ToastUtils.show(getResources().getString(R.string.home_exit_hint));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
mViewPager.removeOnPageChangeListener(this);
|
||||
mViewPager.setAdapter(null);
|
||||
mBottomNavigationView.setOnNavigationItemSelectedListener(null);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportSwipeBack() {
|
||||
// 不使用侧滑功能
|
||||
return !super.isSupportSwipeBack();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,160 @@
|
|||
package com.hjq.demo.ui.activity;
|
||||
|
||||
import android.view.animation.AlphaAnimation;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.RotateAnimation;
|
||||
import android.view.animation.ScaleAnimation;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.gyf.barlibrary.BarHide;
|
||||
import com.hjq.demo.R;
|
||||
import com.hjq.demo.common.CommonActivity;
|
||||
import com.hjq.permissions.OnPermission;
|
||||
import com.hjq.permissions.Permission;
|
||||
import com.hjq.permissions.XXPermissions;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
/**
|
||||
* author : HJQ
|
||||
* github : https://github.com/getActivity/AndroidProject
|
||||
* time : 2018/10/18
|
||||
* desc : 启动界面
|
||||
*/
|
||||
public class LauncherActivity extends CommonActivity
|
||||
implements OnPermission, Animation.AnimationListener {
|
||||
|
||||
@BindView(R.id.iv_launcher_bg)
|
||||
ImageView mImageView;
|
||||
@BindView(R.id.iv_launcher_icon)
|
||||
ImageView mIconView;
|
||||
@BindView(R.id.iv_launcher_name)
|
||||
TextView mTextView;
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.activity_launcher;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getTitleBarId() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initView() {
|
||||
//初始化动画
|
||||
initStartAnim();
|
||||
//设置状态栏和导航栏参数
|
||||
getStatusBarConfig()
|
||||
.fullScreen(true)//有导航栏的情况下,activity全屏显示,也就是activity最下面被导航栏覆盖,不写默认非全屏
|
||||
.hideBar(BarHide.FLAG_HIDE_STATUS_BAR)//隐藏状态栏
|
||||
.transparentNavigationBar()//透明导航栏,不写默认黑色(设置此方法,fullScreen()方法自动为true)
|
||||
.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initData() {}
|
||||
|
||||
private static final int ANIM_TIME = 1000;
|
||||
|
||||
/**
|
||||
* 启动动画
|
||||
*/
|
||||
private void initStartAnim() {
|
||||
// 渐变展示启动屏
|
||||
AlphaAnimation aa = new AlphaAnimation(0.4f, 1.0f);
|
||||
aa.setDuration(ANIM_TIME * 2);
|
||||
aa.setAnimationListener(this);
|
||||
mImageView.startAnimation(aa);
|
||||
|
||||
ScaleAnimation sa = new ScaleAnimation(0, 1, 0, 1, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
|
||||
sa.setDuration(ANIM_TIME);
|
||||
mIconView.startAnimation(sa);
|
||||
|
||||
RotateAnimation ra = new RotateAnimation(180, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
|
||||
ra.setDuration(ANIM_TIME);
|
||||
mTextView.startAnimation(ra);
|
||||
}
|
||||
|
||||
private void requestFilePermission() {
|
||||
XXPermissions.with(this)
|
||||
.permission(Permission.Group.STORAGE)
|
||||
.request(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link OnPermission}
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void hasPermission(List<String> granted, boolean isAll) {
|
||||
startActivity(HomeActivity.class);
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
//禁用返回键
|
||||
//super.onBackPressed();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestart() {
|
||||
super.onRestart();
|
||||
if (XXPermissions.isHasPermission(LauncherActivity.this, Permission.Group.STORAGE)) {
|
||||
hasPermission(null, true);
|
||||
}else {
|
||||
requestFilePermission();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportSwipeBack() {
|
||||
//不使用侧滑功能
|
||||
return !super.isSupportSwipeBack();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void noPermission(List<String> denied, boolean quick) {
|
||||
if (quick) {
|
||||
ToastUtils.show("没有权限访问文件,请手动授予权限");
|
||||
XXPermissions.gotoPermissionSettings(LauncherActivity.this, true);
|
||||
}else {
|
||||
ToastUtils.show("请先授予文件读写权限");
|
||||
getWindow().getDecorView().postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
requestFilePermission();
|
||||
}
|
||||
}, 2000);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Animation.AnimationListener}
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void onAnimationStart(Animation animation) {}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animation animation) {
|
||||
requestFilePermission();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationRepeat(Animation animation) {}
|
||||
|
||||
|
||||
@Override
|
||||
protected void initOrientation() {
|
||||
//Android 8.0踩坑记录:Only fullscreen opaque activities can request orientation
|
||||
// https://www.jianshu.com/p/d0d907754603
|
||||
//super.initOrientation();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
package com.hjq.demo.ui.activity;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
|
||||
import com.hjq.baselibrary.utils.TextInputHelper;
|
||||
import com.hjq.demo.R;
|
||||
import com.hjq.demo.common.CommonActivity;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
/**
|
||||
* author : HJQ
|
||||
* github : https://github.com/getActivity/AndroidProject
|
||||
* time : 2018/10/18
|
||||
* desc : 登录界面
|
||||
*/
|
||||
public class LoginActivity extends CommonActivity
|
||||
implements View.OnClickListener {
|
||||
|
||||
@BindView(R.id.et_login_phone)
|
||||
EditText mPhoneView;
|
||||
@BindView(R.id.et_login_password)
|
||||
EditText mPasswordView;
|
||||
@BindView(R.id.btn_login_commit)
|
||||
Button mCommitView;
|
||||
|
||||
private TextInputHelper mTextInputHelper;
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.activity_login;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getTitleBarId() {
|
||||
return R.id.tb_login_bar;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initView() {
|
||||
mCommitView.setOnClickListener(this);
|
||||
mTextInputHelper = new TextInputHelper(mCommitView, false);
|
||||
mTextInputHelper.addViews(mPhoneView, mPasswordView);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initData() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRightClick(View v) {
|
||||
// 跳转到注册界面
|
||||
startActivity(RegisterActivity.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
mTextInputHelper.removeViews();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupportSwipeBack() {
|
||||
//不使用侧滑功能
|
||||
return !super.isSupportSwipeBack();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link View.OnClickListener}
|
||||
*/
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v == mCommitView) {
|
||||
if (mPhoneView.getText().toString().length() != 11) {
|
||||
ToastUtils.show(getResources().getString(R.string.phone_input_error));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
package com.hjq.demo.ui.activity;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
|
||||
import com.hjq.baselibrary.utils.TextInputHelper;
|
||||
import com.hjq.demo.R;
|
||||
import com.hjq.demo.common.CommonActivity;
|
||||
import com.hjq.baselibrary.widget.CountdownView;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
/**
|
||||
* author : HJQ
|
||||
* github : https://github.com/getActivity/AndroidProject
|
||||
* time : 2018/10/18
|
||||
* desc : 注册界面
|
||||
*/
|
||||
public class RegisterActivity extends CommonActivity
|
||||
implements View.OnClickListener {
|
||||
|
||||
@BindView(R.id.et_register_phone)
|
||||
EditText mPhoneView;
|
||||
@BindView(R.id.cv_register_countdown)
|
||||
CountdownView mCountdownView;
|
||||
|
||||
@BindView(R.id.et_register_code)
|
||||
EditText mCodeView;
|
||||
|
||||
@BindView(R.id.et_register_password1)
|
||||
EditText mPasswordView1;
|
||||
@BindView(R.id.et_register_password2)
|
||||
EditText mPasswordView2;
|
||||
|
||||
@BindView(R.id.btn_register_commit)
|
||||
Button mCommitView;
|
||||
|
||||
private TextInputHelper mTextInputHelper;
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.activity_register;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getTitleBarId() {
|
||||
return R.id.tb_register_bar;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initView() {
|
||||
mCountdownView.setOnClickListener(this);
|
||||
mCommitView.setOnClickListener(this);
|
||||
|
||||
mTextInputHelper = new TextInputHelper(mCommitView, false);
|
||||
mTextInputHelper.addViews(mPhoneView, mCodeView, mPasswordView1, mPasswordView2);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initData() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link View.OnClickListener}
|
||||
*/
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v == mCountdownView) { //获取验证码
|
||||
|
||||
if (mPhoneView.getText().toString().length() != 11) {
|
||||
ToastUtils.show(getResources().getString(R.string.phone_input_error));
|
||||
return;
|
||||
}
|
||||
|
||||
ToastUtils.show(getResources().getString(R.string.countdown_code_send_succeed));
|
||||
|
||||
}else if (v == mCommitView) { //提交注册
|
||||
|
||||
if (mPhoneView.getText().toString().length() != 11) {
|
||||
ToastUtils.show(getResources().getString(R.string.phone_input_error));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mPasswordView1.getText().toString().equals(mPasswordView2.getText().toString())) {
|
||||
ToastUtils.show(getResources().getString(R.string.two_password_input_error));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
mTextInputHelper.removeViews();
|
||||
super.onDestroy();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
package com.hjq.demo.ui.activity;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.net.http.SslError;
|
||||
import android.os.Build;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.webkit.SslErrorHandler;
|
||||
import android.webkit.WebChromeClient;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
import com.hjq.baselibrary.utils.WebViewLifecycleUtils;
|
||||
import com.hjq.demo.R;
|
||||
import com.hjq.demo.common.CommonActivity;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
/**
|
||||
* author : HJQ
|
||||
* github : https://github.com/getActivity/AndroidProject
|
||||
* time : 2018/10/18
|
||||
* desc : 浏览器界面
|
||||
*/
|
||||
public class WebActivity extends CommonActivity {
|
||||
|
||||
@BindView(R.id.pb_web_progress)
|
||||
ProgressBar mProgressBar;
|
||||
@BindView(R.id.wv_web_view)
|
||||
WebView mWebView;
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.activity_web;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getTitleBarId() {
|
||||
return R.id.tb_web_title;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initView() {
|
||||
// 不显示滚动条
|
||||
mWebView.setVerticalScrollBarEnabled(false);
|
||||
mWebView.setHorizontalScrollBarEnabled(false);
|
||||
|
||||
WebSettings settings = mWebView.getSettings();
|
||||
//允许文件访问
|
||||
settings.setAllowFileAccess(true);
|
||||
//支持javaScript
|
||||
settings.setJavaScriptEnabled(true);
|
||||
//允许网页定位
|
||||
settings.setGeolocationEnabled(true);
|
||||
//允许保存密码
|
||||
settings.setSavePassword(true);
|
||||
|
||||
//支持播放gif动画
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
|
||||
settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
|
||||
}
|
||||
|
||||
//解决Android 5.0上Webview默认不允许加载Http与Https混合内容
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
//两者都可以
|
||||
settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
|
||||
}
|
||||
|
||||
//加快HTML网页加载完成的速度,等页面finish再加载图片
|
||||
if(Build.VERSION.SDK_INT >= 19) {
|
||||
settings.setLoadsImagesAutomatically(true);
|
||||
} else {
|
||||
settings.setLoadsImagesAutomatically(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initData() {
|
||||
mWebView.setWebViewClient(new MyWebViewClient());
|
||||
mWebView.setWebChromeClient(new MyWebChromeClient());
|
||||
mWebView.loadUrl("https://github.com/getActivity/AndroidProject");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLeftClick(View v) {
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK && mWebView.canGoBack()) {
|
||||
// 后退网页并且拦截该事件
|
||||
mWebView.goBack();
|
||||
return true;
|
||||
}
|
||||
return super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
WebViewLifecycleUtils.onResume(mWebView);
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
WebViewLifecycleUtils.onPause(mWebView);
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
WebViewLifecycleUtils.onDestroy(mWebView);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
private class MyWebViewClient extends WebViewClient {
|
||||
|
||||
//网页加载错误时回调,这个方法会在onPageFinished之前调用
|
||||
@Override
|
||||
public void onReceivedError(WebView view, int errorCode, String description, final String failingUrl) {
|
||||
|
||||
}
|
||||
|
||||
//开始加载网页
|
||||
@Override
|
||||
public void onPageStarted(final WebView view, final String url, Bitmap favicon) {
|
||||
mProgressBar.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
//完成加载网页
|
||||
@Override
|
||||
public void onPageFinished(WebView view, String url) {
|
||||
mProgressBar.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
|
||||
//super.onReceivedSslError(view, handler, error);注意一定要去除这行代码,否则设置无效。
|
||||
// handler.cancel();// Android默认的处理方式
|
||||
handler.proceed();// 接受所有网站的证书
|
||||
// handleMessage(Message msg);// 进行其他处理
|
||||
}
|
||||
|
||||
//跳转到其他链接
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, final String url) {
|
||||
|
||||
String scheme = Uri.parse(url).getScheme();
|
||||
if (scheme != null) {
|
||||
scheme = scheme.toLowerCase();
|
||||
}
|
||||
if ("http".equals(scheme) || "https".equals(scheme)) {
|
||||
mWebView.loadUrl(url);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private class MyWebChromeClient extends WebChromeClient {
|
||||
|
||||
//收到网页标题
|
||||
@Override
|
||||
public void onReceivedTitle(WebView view, String title) {
|
||||
if (title != null) {
|
||||
setTitle(title);
|
||||
}
|
||||
}
|
||||
|
||||
//收到加载进度变化
|
||||
@Override
|
||||
public void onProgressChanged(WebView view, int newProgress) {
|
||||
mProgressBar.setProgress(newProgress);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package com.hjq.demo.ui.adapter;
|
||||
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
|
||||
import com.hjq.demo.common.CommonLazyFragment;
|
||||
import com.hjq.baselibrary.base.BaseFragmentPagerAdapter;
|
||||
import com.hjq.demo.ui.fragment.TestFragmentA;
|
||||
import com.hjq.demo.ui.fragment.TestFragmentC;
|
||||
import com.hjq.demo.ui.fragment.TestFragmentB;
|
||||
import com.hjq.demo.ui.fragment.TestFragmentD;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* author : HJQ
|
||||
* github : https://github.com/getActivity/AndroidProject
|
||||
* time : 2018/10/18
|
||||
* desc : 主页界面 ViewPager + Fragment 适配器
|
||||
*/
|
||||
public final class HomeViewPagerAdapter extends BaseFragmentPagerAdapter<CommonLazyFragment> {
|
||||
|
||||
public HomeViewPagerAdapter(FragmentActivity activity) {
|
||||
super(activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init(FragmentManager fm, List<CommonLazyFragment> list) {
|
||||
list.add(TestFragmentA.newInstance());
|
||||
list.add(TestFragmentB.newInstance());
|
||||
list.add(TestFragmentC.newInstance());
|
||||
list.add(TestFragmentD.newInstance());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package com.hjq.demo.ui.fragment;
|
||||
|
||||
import com.hjq.demo.R;
|
||||
import com.hjq.demo.common.CommonLazyFragment;
|
||||
|
||||
/**
|
||||
* author : HJQ
|
||||
* github : https://github.com/getActivity/AndroidProject
|
||||
* time : 2018/10/18
|
||||
* desc : 可进行拷贝的副本
|
||||
*/
|
||||
public class CopyFragment extends CommonLazyFragment {
|
||||
|
||||
public static CopyFragment newInstance() {
|
||||
return new CopyFragment();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getTitleBarId() {
|
||||
return R.id.tb_copy_bar;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initView() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initData() {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
package com.hjq.demo.ui.fragment;
|
||||
|
||||
import android.support.design.widget.AppBarLayout;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.gyf.barlibrary.ImmersionBar;
|
||||
import com.hjq.bar.TitleBar;
|
||||
import com.hjq.demo.R;
|
||||
import com.hjq.demo.common.CommonLazyFragment;
|
||||
import com.hjq.demo.widget.XCollapsingToolbarLayout;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
/**
|
||||
* author : HJQ
|
||||
* github : https://github.com/getActivity/AndroidProject
|
||||
* time : 2018/10/18
|
||||
* desc : 项目炫酷效果示例
|
||||
*/
|
||||
public class TestFragmentA extends CommonLazyFragment
|
||||
implements XCollapsingToolbarLayout.OnScrimsListener {
|
||||
|
||||
@BindView(R.id.abl_test_bar)
|
||||
AppBarLayout mAppBarLayout;
|
||||
@BindView(R.id.ctl_test_bar)
|
||||
XCollapsingToolbarLayout mCollapsingToolbarLayout;
|
||||
@BindView(R.id.t_test_title)
|
||||
Toolbar mToolbar;
|
||||
@BindView(R.id.tb_test_bar)
|
||||
TitleBar mTitleBar;
|
||||
|
||||
@BindView(R.id.tv_test_address)
|
||||
TextView mAddressView;
|
||||
@BindView(R.id.tv_test_search)
|
||||
TextView mSearchView;
|
||||
|
||||
public static TestFragmentA newInstance() {
|
||||
return new TestFragmentA();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_test_a;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getTitleBarId() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initView() {
|
||||
ImmersionBar.setTitleBar(getSupportActivity(), mToolbar);
|
||||
ImmersionBar.setTitleBar(getSupportActivity(), mTitleBar);
|
||||
|
||||
//设置渐变监听
|
||||
mCollapsingToolbarLayout.setOnScrimsListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initData() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStatusBarEnabled() {
|
||||
// 使用沉浸式状态栏
|
||||
return !super.isStatusBarEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean statusBarDarkFont() {
|
||||
return mCollapsingToolbarLayout.isScrimsShown();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link XCollapsingToolbarLayout.OnScrimsListener}
|
||||
*/
|
||||
@Override
|
||||
public void onScrimsStateChange(boolean shown) {
|
||||
if (shown) {
|
||||
mAddressView.setTextColor(getResources().getColor(R.color.black));
|
||||
mSearchView.setBackgroundResource(R.drawable.bg_home_search_bar_gray);
|
||||
getStatusBarConfig().statusBarDarkFont(true).init();
|
||||
}else {
|
||||
mAddressView.setTextColor(getResources().getColor(R.color.white));
|
||||
mSearchView.setBackgroundResource(R.drawable.bg_home_search_bar_transparent);
|
||||
getStatusBarConfig().statusBarDarkFont(false).init();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package com.hjq.demo.ui.fragment;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import com.hjq.baselibrary.widget.CountdownView;
|
||||
import com.hjq.demo.R;
|
||||
import com.hjq.demo.common.CommonLazyFragment;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
/**
|
||||
* author : HJQ
|
||||
* github : https://github.com/getActivity/AndroidProject
|
||||
* time : 2018/10/18
|
||||
* desc : 项目自定义控件展示
|
||||
*/
|
||||
public class TestFragmentB extends CommonLazyFragment
|
||||
implements View.OnClickListener {
|
||||
|
||||
@BindView(R.id.cv_test_countdown)
|
||||
CountdownView mCountdownView;
|
||||
|
||||
public static TestFragmentB newInstance() {
|
||||
return new TestFragmentB();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_test_b;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getTitleBarId() {
|
||||
return R.id.tb_test_c_bar;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initView() {
|
||||
mCountdownView.setOnClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initData() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link View.OnClickListener}
|
||||
*/
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v == mCountdownView) {
|
||||
ToastUtils.show(getResources().getString(R.string.countdown_code_send_succeed));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStatusBarEnabled() {
|
||||
// 使用沉浸式状态栏
|
||||
return !super.isStatusBarEnabled();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
package com.hjq.demo.ui.fragment;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
|
||||
import com.hjq.demo.R;
|
||||
import com.hjq.demo.common.CommonLazyFragment;
|
||||
import com.hjq.demo.common.UIActivity;
|
||||
import com.hjq.permissions.OnPermission;
|
||||
import com.hjq.permissions.Permission;
|
||||
import com.hjq.permissions.XXPermissions;
|
||||
import com.hjq.toast.ToastUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
/**
|
||||
* author : HJQ
|
||||
* github : https://github.com/getActivity/AndroidProject
|
||||
* time : 2018/10/18
|
||||
* desc : 项目框架使用示例
|
||||
*/
|
||||
public class TestFragmentC extends CommonLazyFragment
|
||||
implements View.OnClickListener {
|
||||
|
||||
@BindView(R.id.btn_test_toast)
|
||||
Button mToastView;
|
||||
@BindView(R.id.btn_test_permission)
|
||||
Button mPermissionView;
|
||||
@BindView(R.id.btn_test_state_black)
|
||||
Button mStateBlackView;
|
||||
@BindView(R.id.btn_test_state_white)
|
||||
Button mStateWhiteView;
|
||||
@BindView(R.id.btn_test_swipe_enabled)
|
||||
Button mSwipeEnabledView;
|
||||
@BindView(R.id.btn_test_swipe_disable)
|
||||
Button mSwipeDisableView;
|
||||
|
||||
public static TestFragmentC newInstance() {
|
||||
return new TestFragmentC();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_test_c;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getTitleBarId() {
|
||||
return R.id.tb_test_b_bar;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initView() {
|
||||
mToastView.setOnClickListener(this);
|
||||
mPermissionView.setOnClickListener(this);
|
||||
mStateBlackView.setOnClickListener(this);
|
||||
mStateWhiteView.setOnClickListener(this);
|
||||
mSwipeEnabledView.setOnClickListener(this);
|
||||
mSwipeDisableView.setOnClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initData() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStatusBarEnabled() {
|
||||
// 使用沉浸式状态栏
|
||||
return !super.isStatusBarEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link View.OnClickListener}
|
||||
*/
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v == mToastView) {
|
||||
ToastUtils.show("我是吐司");
|
||||
}else if (v == mPermissionView) {
|
||||
XXPermissions.with(getSupportActivity())
|
||||
//.constantRequest() //可设置被拒绝后继续申请,直到用户授权或者永久拒绝
|
||||
//.permission(Permission.SYSTEM_ALERT_WINDOW, Permission.REQUEST_INSTALL_PACKAGES) //支持请求6.0悬浮窗权限8.0请求安装权限
|
||||
.permission(Permission.CAMERA) //不指定权限则自动获取清单中的危险权限
|
||||
.request(new OnPermission() {
|
||||
|
||||
@Override
|
||||
public void hasPermission(List<String> granted, boolean isAll) {
|
||||
if (isAll) {
|
||||
ToastUtils.show("获取权限成功");
|
||||
}else {
|
||||
ToastUtils.show("获取权限成功,部分权限未正常授予");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void noPermission(List<String> denied, boolean quick) {
|
||||
if(quick) {
|
||||
ToastUtils.show("被永久拒绝授权,请手动授予权限");
|
||||
//如果是被永久拒绝就跳转到应用权限系统设置页面
|
||||
XXPermissions.gotoPermissionSettings(getSupportActivity());
|
||||
}else {
|
||||
ToastUtils.show("获取权限失败");
|
||||
}
|
||||
}
|
||||
});
|
||||
}else if (v == mStateBlackView) {
|
||||
UIActivity activity = (UIActivity) getSupportActivity();
|
||||
activity.getStatusBarConfig().statusBarDarkFont(true).init();
|
||||
}else if (v == mStateWhiteView) {
|
||||
UIActivity activity = (UIActivity) getSupportActivity();
|
||||
activity.getStatusBarConfig().statusBarDarkFont(false).init();
|
||||
}else if (v == mSwipeEnabledView) {
|
||||
UIActivity activity = (UIActivity) getSupportActivity();
|
||||
activity.getSwipeBackHelper().setSwipeBackEnable(true);
|
||||
ToastUtils.show("当前界面不会生效,其他界面调用才会有效果");
|
||||
}else if (v == mSwipeDisableView) {
|
||||
UIActivity activity = (UIActivity) getSupportActivity();
|
||||
activity.getSwipeBackHelper().setSwipeBackEnable(false);
|
||||
ToastUtils.show("当前界面不会生效,其他界面调用才会有效果");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
package com.hjq.demo.ui.fragment;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
|
||||
import com.hjq.demo.R;
|
||||
import com.hjq.demo.common.CommonLazyFragment;
|
||||
import com.hjq.demo.ui.activity.AboutActivity;
|
||||
import com.hjq.demo.ui.activity.LoginActivity;
|
||||
import com.hjq.demo.ui.activity.RegisterActivity;
|
||||
import com.hjq.demo.ui.activity.WebActivity;
|
||||
|
||||
import butterknife.BindView;
|
||||
|
||||
/**
|
||||
* author : HJQ
|
||||
* github : https://github.com/getActivity/AndroidProject
|
||||
* time : 2018/10/18
|
||||
* desc : 项目界面跳转示例
|
||||
*/
|
||||
public class TestFragmentD extends CommonLazyFragment
|
||||
implements View.OnClickListener {
|
||||
|
||||
@BindView(R.id.btn_test_login)
|
||||
Button mLoginView;
|
||||
@BindView(R.id.btn_test_register)
|
||||
Button mRegisterView;
|
||||
@BindView(R.id.btn_test_about)
|
||||
Button mAboutView;
|
||||
@BindView(R.id.btn_test_browser)
|
||||
Button mBrowserView;
|
||||
|
||||
public static TestFragmentD newInstance() {
|
||||
return new TestFragmentD();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.fragment_test_d;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getTitleBarId() {
|
||||
return R.id.tb_test_d_bar;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initView() {
|
||||
mLoginView.setOnClickListener(this);
|
||||
mRegisterView.setOnClickListener(this);
|
||||
mAboutView.setOnClickListener(this);
|
||||
mBrowserView.setOnClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initData() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link View.OnClickListener}
|
||||
*/
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v == mLoginView) {
|
||||
startActivity(LoginActivity.class);
|
||||
}else if (v == mRegisterView) {
|
||||
startActivity(RegisterActivity.class);
|
||||
}else if (v == mAboutView) {
|
||||
startActivity(AboutActivity.class);
|
||||
}else if (v == mBrowserView) {
|
||||
startActivity(WebActivity.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStatusBarEnabled() {
|
||||
// 使用沉浸式状态栏
|
||||
return !super.isStatusBarEnabled();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
package com.hjq.demo.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.design.widget.CollapsingToolbarLayout;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
/**
|
||||
* author : HJQ
|
||||
* github : https://github.com/getActivity/AndroidProject
|
||||
* time : 2018/10/18
|
||||
* desc : 支持监听渐变的CollapsingToolbarLayout
|
||||
*/
|
||||
public class XCollapsingToolbarLayout extends CollapsingToolbarLayout {
|
||||
|
||||
private OnScrimsListener mListener; // 渐变监听
|
||||
private boolean isScrimsShown; // 当前渐变状态
|
||||
|
||||
public XCollapsingToolbarLayout(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public XCollapsingToolbarLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public XCollapsingToolbarLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScrimsShown(boolean shown, boolean animate) {
|
||||
super.setScrimsShown(shown, true);
|
||||
// 判断渐变状态是否改变了
|
||||
if (isScrimsShown != shown) {
|
||||
// 如果是就记录并且回调监听器
|
||||
isScrimsShown = shown;
|
||||
if (mListener != null) {
|
||||
mListener.onScrimsStateChange(isScrimsShown);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前的渐变状态
|
||||
*/
|
||||
public boolean isScrimsShown() {
|
||||
return isScrimsShown;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置CollapsingToolbarLayout渐变监听
|
||||
*/
|
||||
public void setOnScrimsListener(OnScrimsListener l) {
|
||||
mListener = l;
|
||||
}
|
||||
|
||||
/**
|
||||
* CollapsingToolbarLayout渐变监听器
|
||||
*/
|
||||
public interface OnScrimsListener {
|
||||
|
||||
/**
|
||||
* 渐变状态变化
|
||||
*
|
||||
* @param shown 渐变开关
|
||||
*/
|
||||
void onScrimsStateChange(boolean shown);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#f4f4f4"/>
|
||||
<corners android:radius="@dimen/space_40"/>
|
||||
</shape>
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<corners android:radius="@dimen/space_40"/>
|
||||
|
||||
<stroke
|
||||
android:width="1px"
|
||||
android:color="#DDDDDD" />
|
||||
</shape>
|
|
@ -0,0 +1,26 @@
|
|||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:id="@android:id/background">
|
||||
<shape>
|
||||
<corners android:radius="@dimen/space_20" />
|
||||
<gradient
|
||||
android:angle="270"
|
||||
android:centerColor="#E6E6E6"
|
||||
android:endColor="#E6E6E6"
|
||||
android:startColor="#E6E6E6" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:id="@android:id/progress">
|
||||
<clip>
|
||||
<shape>
|
||||
<corners android:radius="@dimen/space_20" />
|
||||
<gradient
|
||||
android:centerColor="@color/colorAccent"
|
||||
android:endColor="@color/colorAccent"
|
||||
android:startColor="@color/colorAccent" />
|
||||
|
||||
</shape>
|
||||
</clip>
|
||||
</item>
|
||||
|
||||
</layer-list>
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- 按压状态 -->
|
||||
<item android:drawable="@mipmap/tab_ico_found" android:state_checked="true" />
|
||||
|
||||
<!-- 默认状态 -->
|
||||
<item android:drawable="@mipmap/tab_ico_found_off" />
|
||||
|
||||
</selector>
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- 按压状态 -->
|
||||
<item android:drawable="@mipmap/tab_ico_home" android:state_checked="true" />
|
||||
|
||||
<!-- 默认状态 -->
|
||||
<item android:drawable="@mipmap/tab_ico_home_off" />
|
||||
|
||||
</selector>
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- 按压状态 -->
|
||||
<item android:drawable="@mipmap/tab_ico_me" android:state_checked="true" />
|
||||
|
||||
<!-- 默认状态 -->
|
||||
<item android:drawable="@mipmap/tab_ico_me_off" />
|
||||
|
||||
</selector>
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- 按压状态 -->
|
||||
<item android:drawable="@mipmap/tab_ico_message" android:state_checked="true" />
|
||||
|
||||
<!-- 默认状态 -->
|
||||
<item android:drawable="@mipmap/tab_ico_message_off" />
|
||||
|
||||
</selector>
|
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 默认圆角按钮样式 -->
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- 按钮禁用状态 -->
|
||||
<item android:state_enabled="false">
|
||||
<shape android:shape="rectangle">
|
||||
<corners android:radius="@dimen/button_round_size" />
|
||||
<solid android:color="@color/colorButtonDisable" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<!-- 按钮按压状态 -->
|
||||
<item android:state_pressed="true">
|
||||
<shape android:shape="rectangle">
|
||||
<corners android:radius="@dimen/button_round_size" />
|
||||
<solid android:color="@color/colorButtonPressed" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<!-- 按钮默认状态 -->
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<corners android:radius="@dimen/button_round_size" />
|
||||
<solid android:color="@color/colorAccent" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
</selector>
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 不带圆角按钮样式 -->
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- 按钮禁用状态 -->
|
||||
<item android:drawable="@color/colorButtonDisable" android:state_enabled="false" />
|
||||
|
||||
<!-- 按钮按压状态 -->
|
||||
<item android:drawable="@color/colorButtonPressed" android:state_pressed="true" />
|
||||
|
||||
<!-- 按钮默认状态 -->
|
||||
<item android:drawable="@color/colorAccent" />
|
||||
|
||||
</selector>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:drawable="@color/black10" android:state_pressed="true" />
|
||||
<item android:drawable="@color/black10" android:state_selected="true" />
|
||||
<item android:drawable="@color/transparent" />
|
||||
|
||||
</selector>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item android:drawable="@color/black10" android:state_pressed="true" />
|
||||
<item android:drawable="@color/black10" android:state_selected="true" />
|
||||
<item android:drawable="@color/white" />
|
||||
|
||||
</selector>
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<!-- 选中状态 -->
|
||||
<item android:color="#000000" android:state_checked="true" />
|
||||
|
||||
<!-- 默认状态 -->
|
||||
<item android:color="#a4a4a4" />
|
||||
|
||||
</selector>
|
|
@ -0,0 +1,60 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical"
|
||||
tools:context=".ui.activity.AboutActivity">
|
||||
|
||||
<com.hjq.bar.TitleBar
|
||||
android:id="@+id/tb_about_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:title="@string/about_text" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="@dimen/space_200"
|
||||
android:layout_height="@dimen/space_200"
|
||||
android:layout_marginTop="@dimen/space_80"
|
||||
android:layout_marginBottom="@dimen/space_80"
|
||||
android:src="@mipmap/ic_logo" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/app_name"
|
||||
android:textColor="#222222"
|
||||
android:textSize="@dimen/font_size_32px" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/space_60"
|
||||
android:autoLink="all"
|
||||
android:gravity="center_horizontal"
|
||||
android:lineSpacingExtra="@dimen/space_20"
|
||||
android:text="Github地址\nhttps://github.com/getActivity/AndroidProject"
|
||||
android:textColor="#222222"
|
||||
android:textSize="@dimen/font_size_28px" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/space_40"
|
||||
android:layout_marginBottom="@dimen/space_40"
|
||||
android:text="@string/about_copyright"
|
||||
android:textColor="#BDBDBD"
|
||||
android:textSize="@dimen/font_size_28px" />
|
||||
|
||||
</LinearLayout>
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
tools:context=".ui.activity.CopyActivity">
|
||||
|
||||
<com.hjq.bar.TitleBar
|
||||
android:id="@+id/tb_copy_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:title="标题" />
|
||||
|
||||
</LinearLayout>
|
|
@ -0,0 +1,25 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
tools:context=".ui.activity.HomeActivity">
|
||||
|
||||
<com.hjq.baselibrary.widget.NoScrollViewPager
|
||||
android:id="@+id/vp_home_pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<android.support.design.widget.BottomNavigationView
|
||||
android:id="@+id/bv_home_navigation"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/white"
|
||||
app:itemTextColor="@drawable/txt_home_bottom_nav_selector"
|
||||
app:labelVisibilityMode="labeled"
|
||||
app:menu="@menu/menu_home_bottom_nav" />
|
||||
|
||||
</LinearLayout>
|
|
@ -0,0 +1,40 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
tools:context=".ui.activity.LauncherActivity">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_launcher_bg"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="fitXY"
|
||||
android:src="@mipmap/bg_launcher" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginBottom="@dimen/space_100"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_launcher_icon"
|
||||
android:layout_width="@dimen/space_400"
|
||||
android:layout_height="@dimen/space_400"
|
||||
android:src="@mipmap/ic_logo" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/iv_launcher_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/space_100"
|
||||
android:text="@string/app_name"
|
||||
android:textColor="@color/white90"
|
||||
android:textSize="@dimen/font_size_40px" />
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
|
@ -0,0 +1,84 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/white"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical"
|
||||
tools:context=".ui.activity.LoginActivity">
|
||||
|
||||
<com.hjq.bar.TitleBar
|
||||
android:id="@+id/tb_login_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/space_100"
|
||||
app:bar_style="transparent"
|
||||
app:color_right="@color/colorAccent"
|
||||
app:icon_back="false"
|
||||
app:title=""
|
||||
app:title_right="@string/login_register" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="@dimen/space_200"
|
||||
android:layout_height="@dimen/space_200"
|
||||
android:layout_margin="@dimen/space_60"
|
||||
android:src="@mipmap/ic_logo" />
|
||||
|
||||
<com.hjq.baselibrary.widget.ClearEditText
|
||||
android:id="@+id/et_login_phone"
|
||||
style="@style/EditTextStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/space_80"
|
||||
android:layout_marginTop="@dimen/space_20"
|
||||
android:layout_marginRight="@dimen/space_80"
|
||||
android:hint="@string/login_phone_input_hint"
|
||||
android:inputType="phone"
|
||||
android:maxLength="11"
|
||||
android:maxLines="1" />
|
||||
|
||||
<View
|
||||
style="@style/HorizontalLineStyle"
|
||||
android:layout_marginLeft="@dimen/space_80"
|
||||
android:layout_marginRight="@dimen/space_80" />
|
||||
|
||||
<com.hjq.baselibrary.widget.ClearEditText
|
||||
android:id="@+id/et_login_password"
|
||||
style="@style/EditTextStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/space_80"
|
||||
android:layout_marginTop="@dimen/space_40"
|
||||
android:layout_marginRight="@dimen/space_80"
|
||||
android:hint="@string/login_password_input_hint"
|
||||
android:inputType="textPassword"
|
||||
android:maxLength="20"
|
||||
android:maxLines="1" />
|
||||
|
||||
<View
|
||||
style="@style/HorizontalLineStyle"
|
||||
android:layout_marginLeft="@dimen/space_80"
|
||||
android:layout_marginRight="@dimen/space_80" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_login_forget"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="right"
|
||||
android:layout_marginLeft="@dimen/space_80"
|
||||
android:layout_marginTop="@dimen/space_30"
|
||||
android:layout_marginRight="@dimen/space_120"
|
||||
android:text="@string/login_forget"
|
||||
android:textColor="@color/colorAccent" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_login_commit"
|
||||
style="@style/ButtonStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/space_80"
|
||||
android:layout_marginTop="@dimen/space_60"
|
||||
android:layout_marginRight="@dimen/space_80"
|
||||
android:text="@string/login_text" />
|
||||
</LinearLayout>
|
|
@ -0,0 +1,130 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/white"
|
||||
android:orientation="vertical"
|
||||
tools:context=".ui.activity.RegisterActivity">
|
||||
|
||||
<com.hjq.bar.TitleBar
|
||||
android:id="@+id/tb_register_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/space_100"
|
||||
app:bar_style="transparent"
|
||||
app:color_left="@color/colorAccent"
|
||||
app:icon_back="false"
|
||||
app:title=""
|
||||
app:title_left="@string/register_login" />
|
||||
|
||||
<android.support.v4.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="@dimen/space_80"
|
||||
android:layout_marginRight="@dimen/space_80"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/space_40"
|
||||
android:text="@string/register_text"
|
||||
android:textColor="@color/black60"
|
||||
android:textSize="@dimen/font_size_46px" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/space_40"
|
||||
android:text="@string/register_hint"
|
||||
android:textColor="@color/black20"
|
||||
android:textSize="@dimen/font_size_28px" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ll_register_edit1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/space_60"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_register_phone"
|
||||
style="@style/EditTextStyle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:hint="@string/register_phone_input_hint"
|
||||
android:inputType="phone"
|
||||
android:maxLength="11"
|
||||
android:maxLines="1" />
|
||||
|
||||
<com.hjq.baselibrary.widget.CountdownView
|
||||
android:id="@+id/cv_register_countdown"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/space_20"
|
||||
android:text="@string/register_send_code"
|
||||
android:textColor="@color/colorAccent" />
|
||||
</LinearLayout>
|
||||
|
||||
<View style="@style/HorizontalLineStyle" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_register_code"
|
||||
style="@style/EditTextStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/space_40"
|
||||
android:hint="@string/register_code_input_hint"
|
||||
android:inputType="number"
|
||||
android:maxLength="8"
|
||||
android:maxLines="1" />
|
||||
|
||||
<View style="@style/HorizontalLineStyle" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_register_password1"
|
||||
style="@style/EditTextStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/space_40"
|
||||
android:hint="@string/register_password_input_hint1"
|
||||
android:inputType="textPassword"
|
||||
android:maxLength="20"
|
||||
android:maxLines="1" />
|
||||
|
||||
<View style="@style/HorizontalLineStyle" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_register_password2"
|
||||
style="@style/EditTextStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/space_40"
|
||||
android:hint="@string/register_password_input_hint2"
|
||||
android:inputType="textPassword"
|
||||
android:maxLength="20"
|
||||
android:maxLines="1" />
|
||||
|
||||
<View style="@style/HorizontalLineStyle" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_register_commit"
|
||||
style="@style/ButtonStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/space_60"
|
||||
android:text="@string/register_text" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.v4.widget.NestedScrollView>
|
||||
|
||||
</LinearLayout>
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
tools:context=".ui.activity.WebActivity">
|
||||
|
||||
<com.hjq.bar.TitleBar
|
||||
android:id="@+id/tb_web_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/pb_web_progress"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="3dip"
|
||||
android:progressDrawable="@drawable/bg_web_progress_bar"
|
||||
android:visibility="gone" />
|
||||
|
||||
<WebView
|
||||
android:id="@+id/wv_web_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</LinearLayout>
|
|
@ -0,0 +1,16 @@
|
|||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
tools:context=".ui.fragment.CopyFragment">
|
||||
|
||||
<com.hjq.bar.TitleBar
|
||||
android:id="@+id/tb_copy_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon_back="false"
|
||||
app:title="标题" />
|
||||
|
||||
</LinearLayout>
|
|
@ -0,0 +1,102 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ui.fragment.TestFragmentA">
|
||||
|
||||
<android.support.design.widget.AppBarLayout
|
||||
android:id="@+id/abl_test_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/white"
|
||||
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
|
||||
app:elevation="0dp">
|
||||
|
||||
<com.hjq.demo.widget.XCollapsingToolbarLayout
|
||||
android:id="@+id/ctl_test_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/space_512"
|
||||
app:contentScrim="@color/white"
|
||||
app:layout_scrollFlags="scroll|exitUntilCollapsed"
|
||||
app:scrimVisibleHeightTrigger="@dimen/space_240">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/space_300"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@mipmap/bg_launcher"
|
||||
app:layout_collapseMode="parallax" />
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:id="@+id/t_test_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?android:attr/actionBarSize"
|
||||
android:layout_marginRight="20dp"
|
||||
app:layout_collapseMode="pin" />
|
||||
|
||||
<com.hjq.bar.TitleBar
|
||||
android:id="@+id/tb_test_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?android:attr/actionBarSize"
|
||||
app:bar_style="transparent"
|
||||
app:color_title="@color/white"
|
||||
app:icon_back="false"
|
||||
app:layout_collapseMode="pin"
|
||||
app:line="false">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/space_20">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_test_address"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="@dimen/space_20"
|
||||
android:gravity="center_vertical"
|
||||
android:text="地区"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="@dimen/font_size_30px" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_test_search"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="@dimen/space_40"
|
||||
android:layout_marginRight="@dimen/space_100"
|
||||
android:background="@drawable/bg_home_search_bar_transparent"
|
||||
android:gravity="center"
|
||||
android:text="请输入搜索关键字"
|
||||
android:textColor="#a4a4a4"
|
||||
android:textSize="@dimen/font_size_28px" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.hjq.bar.TitleBar>
|
||||
|
||||
</com.hjq.demo.widget.XCollapsingToolbarLayout>
|
||||
|
||||
</android.support.design.widget.AppBarLayout>
|
||||
|
||||
<android.support.v4.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="@dimen/space_60"
|
||||
android:layout_marginRight="@dimen/space_60"
|
||||
android:orientation="vertical">
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.v4.widget.NestedScrollView>
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
|
@ -0,0 +1,184 @@
|
|||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
tools:context=".ui.fragment.TestFragmentB">
|
||||
|
||||
<com.hjq.bar.TitleBar
|
||||
android:id="@+id/tb_test_c_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon_back="false"
|
||||
app:title="@string/home_nav_found" />
|
||||
|
||||
<android.support.v4.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/colorAccent"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/space_40">
|
||||
|
||||
<de.hdodenhof.circleimageview.CircleImageView
|
||||
android:layout_width="@dimen/space_180"
|
||||
android:layout_height="@dimen/space_180"
|
||||
android:src="@mipmap/bg_launcher" />
|
||||
|
||||
<de.hdodenhof.circleimageview.CircleImageView
|
||||
android:layout_width="@dimen/space_180"
|
||||
android:layout_height="@dimen/space_180"
|
||||
android:layout_marginLeft="@dimen/space_40"
|
||||
android:src="@mipmap/ic_logo"
|
||||
app:civ_border_color="@color/white60"
|
||||
app:civ_border_width="@dimen/space_2" />
|
||||
|
||||
<de.hdodenhof.circleimageview.CircleImageView
|
||||
android:layout_width="@dimen/space_180"
|
||||
android:layout_height="@dimen/space_180"
|
||||
android:layout_marginLeft="@dimen/space_40"
|
||||
android:src="@mipmap/ic_logo"
|
||||
app:civ_border_color="@color/black60"
|
||||
app:civ_border_width="@dimen/space_2" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/space_30"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
style="@style/ButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="普通按钮" />
|
||||
|
||||
<Button
|
||||
style="@style/ButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/space_20"
|
||||
android:enabled="false"
|
||||
android:text="禁用了的按钮" />
|
||||
|
||||
<Button
|
||||
style="@style/RectButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/space_20"
|
||||
android:text="不带圆角的" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/space_80"
|
||||
android:layout_marginTop="@dimen/space_40"
|
||||
android:layout_marginRight="@dimen/space_80"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<EditText
|
||||
style="@style/EditTextStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:hint="请输入验证码" />
|
||||
|
||||
<com.hjq.baselibrary.widget.CountdownView
|
||||
android:id="@+id/cv_test_countdown"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="获取验证码" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<com.hjq.baselibrary.widget.ClearEditText
|
||||
style="@style/EditTextStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/space_80"
|
||||
android:layout_marginTop="@dimen/space_40"
|
||||
android:layout_marginRight="@dimen/space_80"
|
||||
android:text="这是一个带清除的按钮的EditText" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="@dimen/space_40"
|
||||
android:layout_marginRight="@dimen/space_20"
|
||||
android:layout_marginBottom="@dimen/space_20"
|
||||
android:text="这是一条华丽的分割线" />
|
||||
|
||||
<View style="@style/HorizontalLineStyle" />
|
||||
|
||||
<com.hjq.baselibrary.widget.square.SquareFrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/space_40"
|
||||
android:background="@color/colorButtonPressed">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:text="这是一个正方形的FrameLayout"
|
||||
android:textColor="@color/white" />
|
||||
|
||||
</com.hjq.baselibrary.widget.square.SquareFrameLayout>
|
||||
|
||||
<com.hjq.baselibrary.widget.square.SquareLinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/colorAccent"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:gravity="center_horizontal"
|
||||
android:text="这是一个正方形的LinearLayout"
|
||||
android:textColor="@color/white" />
|
||||
|
||||
</com.hjq.baselibrary.widget.square.SquareLinearLayout>
|
||||
|
||||
<com.hjq.baselibrary.widget.square.SquareRelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/colorButtonPressed">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:text="这是一个正方形的RelativeLayout"
|
||||
android:textColor="@color/white" />
|
||||
|
||||
</com.hjq.baselibrary.widget.square.SquareRelativeLayout>
|
||||
|
||||
<com.hjq.baselibrary.widget.square.SquareImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@mipmap/bg_launcher" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.v4.widget.NestedScrollView>
|
||||
|
||||
</LinearLayout>
|
|
@ -0,0 +1,78 @@
|
|||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
tools:context=".ui.fragment.TestFragmentC">
|
||||
|
||||
<com.hjq.bar.TitleBar
|
||||
android:id="@+id/tb_test_b_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon_back="false"
|
||||
app:title="@string/home_nav_message" />
|
||||
|
||||
<android.support.v4.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="@dimen/space_60"
|
||||
android:layout_marginRight="@dimen/space_60"
|
||||
android:orientation="vertical">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_test_toast"
|
||||
style="@style/ButtonStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/space_60"
|
||||
android:text="显示吐司" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_test_permission"
|
||||
style="@style/ButtonStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/space_60"
|
||||
android:text="请求权限" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_test_state_black"
|
||||
style="@style/ButtonStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/space_60"
|
||||
android:text="状态栏黑色字体" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_test_state_white"
|
||||
style="@style/ButtonStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/space_60"
|
||||
android:text="状态栏白色字体" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_test_swipe_enabled"
|
||||
style="@style/ButtonStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/space_60"
|
||||
android:text="开启界面侧滑" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_test_swipe_disable"
|
||||
style="@style/ButtonStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/space_60"
|
||||
android:text="关闭界面侧滑" />
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.v4.widget.NestedScrollView>
|
||||
|
||||
</LinearLayout>
|
|
@ -0,0 +1,63 @@
|
|||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
tools:context=".ui.fragment.TestFragmentD">
|
||||
|
||||
<com.hjq.bar.TitleBar
|
||||
android:id="@+id/tb_test_d_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon_back="false"
|
||||
app:title="@string/home_nav_me" />
|
||||
|
||||
<android.support.v4.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="@dimen/space_60"
|
||||
android:layout_marginRight="@dimen/space_60"
|
||||
android:orientation="vertical">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_test_login"
|
||||
style="@style/ButtonStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/space_60"
|
||||
android:text="点我进入登录界面" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_test_register"
|
||||
style="@style/ButtonStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/space_60"
|
||||
android:text="点我进入注册界面" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_test_about"
|
||||
style="@style/ButtonStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/space_60"
|
||||
android:text="点我进入关于界面" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_test_browser"
|
||||
style="@style/ButtonStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/space_60"
|
||||
android:text="点我进入浏览器界面" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.v4.widget.NestedScrollView>
|
||||
|
||||
</LinearLayout>
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_home"
|
||||
android:icon="@drawable/ic_selector_selectable_home_index"
|
||||
android:title="@string/home_nav_index"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/home_found"
|
||||
android:icon="@drawable/ic_selector_selectable_home_found"
|
||||
android:title="@string/home_nav_found"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/home_message"
|
||||
android:icon="@drawable/ic_selector_selectable_home_message"
|
||||
android:title="@string/home_nav_message"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/home_me"
|
||||
android:icon="@drawable/ic_selector_selectable_home_me"
|
||||
android:title="@string/home_nav_me"/>
|
||||
</menu>
|
After Width: | Height: | Size: 6.6 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 653 B |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 537 B |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 450 B |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 508 B |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 924 B |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 982 B |
After Width: | Height: | Size: 311 KiB |
After Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 190 KiB |
After Width: | Height: | Size: 6.4 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 1.3 KiB |
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
</resources>
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="windowBackground">#F4F4F4</color>
|
||||
<color name="colorPrimary">#FFFFFF</color>
|
||||
<color name="colorPrimaryDark">#000000</color>
|
||||
<color name="colorAccent">#5A8DDF</color>
|
||||
|
||||
<!-- 按钮按压时的颜色 -->
|
||||
<color name="colorButtonPressed">#1976d2</color>
|
||||
<!-- 按钮禁用时的颜色 -->
|
||||
<color name="colorButtonDisable">#DDDDDD</color>
|
||||
<!-- 分割线的颜色 -->
|
||||
<color name="colorLine">#ECECEC</color>
|
||||
</resources>
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<!-- 默认按钮的圆角大小 -->
|
||||
<dimen name="button_round_size">5dp</dimen>
|
||||
|
||||
<!-- 默认分割线的宽度或者高度 -->
|
||||
<dimen name="line_size">1px</dimen>
|
||||
|
||||
</resources>
|
|
@ -0,0 +1,37 @@
|
|||
<resources>
|
||||
<string name="app_name">模板工程</string>
|
||||
|
||||
<!-- 通用 -->
|
||||
<string name="countdown_code_send_succeed">验证码已发送,请注意查收</string>
|
||||
<string name="two_password_input_error">两次密码输入不一致,请重新输入</string>
|
||||
<string name="phone_input_error">手机号输入不正确</string>
|
||||
|
||||
<!-- 主页 -->
|
||||
<string name="home_exit_hint">再按一次退出</string>
|
||||
<string name="home_nav_index">首页</string>
|
||||
<string name="home_nav_found">发现</string>
|
||||
<string name="home_nav_message">消息</string>
|
||||
<string name="home_nav_me">我的</string>
|
||||
|
||||
<!-- 登录 -->
|
||||
<string name="login_register">注册</string>
|
||||
<string name="login_phone_input_hint">请输入手机号</string>
|
||||
<string name="login_password_input_hint">请输入密码</string>
|
||||
<string name="login_forget">忘记密码?</string>
|
||||
<string name="login_text">登录</string>
|
||||
|
||||
<!-- 注册 -->
|
||||
<string name="register_text">注册</string>
|
||||
<string name="register_hint">手机号仅用于登录和保护账号安全</string>
|
||||
<string name="register_login">登录</string>
|
||||
<string name="register_phone_input_hint">输入手机号码</string>
|
||||
<string name="register_code_input_hint">输入验证码</string>
|
||||
<string name="register_send_code">发送验证码</string>
|
||||
<string name="register_password_input_hint1">设置密码</string>
|
||||
<string name="register_password_input_hint2">再次输入密码</string>
|
||||
|
||||
<!-- 关于 -->
|
||||
<string name="about_text">关于我们</string>
|
||||
<string name="about_copyright">Copyright © 2018</string>
|
||||
|
||||
</resources>
|
|
@ -0,0 +1,67 @@
|
|||
<resources>
|
||||
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
<!-- 窗口背景颜色 -->
|
||||
<item name="android:windowBackground">@color/windowBackground</item>
|
||||
<!-- 应用的主要色调,actionBar默认使用该颜色,Toolbar导航栏的底色 -->
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<!-- 应用的主要暗色调,statusBarColor默认使用该颜色 -->
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<!-- 应用的强调色,CheckBox,RadioButton,SwitchCompat等一般控件的选中效果默认采用该颜色 -->
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
<!-- ActionMode覆盖Actionbar,不顶下来 -->
|
||||
<item name="windowActionModeOverlay">true</item>
|
||||
<item name="android:windowContentOverlay">@null</item>
|
||||
<!-- ActionMode的颜色 -->
|
||||
<item name="actionModeBackground">@color/colorPrimary</item>
|
||||
</style>
|
||||
|
||||
<!-- 解决启动页白屏的问题 -->
|
||||
<style name="LauncherTheme" parent="AppTheme">
|
||||
<item name="android:windowIsTranslucent">true</item>
|
||||
<item name="android:windowBackground">@android:color/transparent</item>
|
||||
</style>
|
||||
|
||||
<!-- 默认圆角按钮样式 -->
|
||||
<style name="ButtonStyle" parent="Widget.AppCompat.Button.Borderless">
|
||||
<item name="android:paddingLeft">@dimen/space_30</item>
|
||||
<item name="android:paddingRight">@dimen/space_30</item>
|
||||
<item name="android:textSize">@dimen/font_size_30px</item>
|
||||
<item name="android:textColor">@color/white90</item>
|
||||
<item name="android:gravity">center</item>
|
||||
<item name="android:background">@drawable/selector_button</item>
|
||||
<item name="android:foreground">@null</item>
|
||||
<item name="android:focusable">false</item>
|
||||
<!-- 解决 Android 5.1 及以上版本 Button 英文字符串自动变大写的问题 -->
|
||||
<item name="android:textAllCaps">false</item>
|
||||
</style>
|
||||
|
||||
<!-- 不带圆角按钮样式 -->
|
||||
<style name="RectButtonStyle" parent="ButtonStyle">
|
||||
<item name="android:background">@drawable/selector_button_rect</item>
|
||||
</style>
|
||||
|
||||
<!-- 默认文本框样式 -->
|
||||
<style name="EditTextStyle">
|
||||
<item name="android:background">@null</item>
|
||||
<item name="android:textSize">@dimen/font_size_30px</item>
|
||||
<item name="android:textColorHint">#A4A4A4</item>
|
||||
<item name="android:textColor">#333333</item>
|
||||
<item name="android:padding">@dimen/space_20</item>
|
||||
</style>
|
||||
|
||||
<!-- 默认水平分割线样式 -->
|
||||
<style name="HorizontalLineStyle">
|
||||
<item name="android:layout_width">match_parent</item>
|
||||
<item name="android:layout_height">1px</item>
|
||||
<item name="android:background">@color/colorLine</item>
|
||||
</style>
|
||||
|
||||
<!-- 默认垂直分割线样式 -->
|
||||
<style name="VerticalLineStyle">
|
||||
<item name="android:layout_width">1px</item>
|
||||
<item name="android:layout_height">match_parent</item>
|
||||
<item name="android:background">@color/colorLine</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
|
@ -0,0 +1 @@
|
|||
/build
|
|
@ -0,0 +1,55 @@
|
|||
//文件开头配置
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'com.novoda.bintray-release'
|
||||
|
||||
android {
|
||||
compileSdkVersion rootProject.ext.compileSdkVersion
|
||||
buildToolsVersion rootProject.ext.buildToolsVersion
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 14
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api "com.android.support:appcompat-v7:$rootProject.ext.supportLibraryVersion"
|
||||
api "com.android.support:design:$rootProject.ext.supportLibraryVersion"
|
||||
}
|
||||
|
||||
publish {
|
||||
userOrg = 'getactivity'//填写bintray用户名,注意大小写
|
||||
groupId = 'com.hjq'//定义的maven group id最终引用形式
|
||||
artifactId = 'formwork'//maven的artifact id
|
||||
version = '1.0'//maven 上发布版本号
|
||||
description = 'An advanced template project'//描述,自己定义
|
||||
website = "https://github.com/getActivity/AndroidProject"//项目在github中的地址
|
||||
}
|
||||
|
||||
tasks.withType(Javadoc) {//防止编码问题
|
||||
options.addStringOption('Xdoclint:none', '-quiet')
|
||||
options.addStringOption('encoding', 'UTF-8')
|
||||
options.addStringOption('charSet', 'UTF-8')
|
||||
}
|
||||
|
||||
task sourcesJar(type: Jar) {
|
||||
from android.sourceSets.main.java.srcDirs
|
||||
classifier = 'sources'
|
||||
}
|
||||
|
||||
task javadoc(type: Javadoc) {
|
||||
source = android.sourceSets.main.java.srcDirs
|
||||
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
|
||||
}
|
||||
|
||||
task javadocJar(type: Jar, dependsOn: javadoc) {
|
||||
classifier = 'javadoc'
|
||||
from javadoc.destinationDir
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives javadocJar
|
||||
archives sourcesJar
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in D:\SDK\Studio\sdk/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# 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
|
|
@ -0,0 +1 @@
|
|||
<manifest package="com.hjq.baselibrary" />
|
|
@ -0,0 +1,92 @@
|
|||
package com.hjq.baselibrary.base;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
|
||||
import com.hjq.baselibrary.utils.KeyboardUtils;
|
||||
|
||||
/**
|
||||
* author : HJQ
|
||||
* github : https://github.com/getActivity/AndroidProject
|
||||
* time : 2018/10/18
|
||||
* desc : Activity基类
|
||||
*/
|
||||
public abstract class BaseActivity extends AppCompatActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
if (getLayoutId() > 0) {
|
||||
setContentView(getLayoutId());
|
||||
}
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
public void init(){
|
||||
initView();
|
||||
initData();
|
||||
}
|
||||
|
||||
//引入布局
|
||||
protected abstract int getLayoutId();
|
||||
|
||||
//标题栏id,用于状态栏沉浸
|
||||
protected abstract int getTitleBarId();
|
||||
|
||||
//初始化控件
|
||||
protected abstract void initView();
|
||||
|
||||
//初始化数据
|
||||
protected abstract void initData();
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
// 隐藏软键盘,避免软键盘引发的内存泄露
|
||||
KeyboardUtils.hideKeyboard(getCurrentFocus());
|
||||
super.finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到其他Activity
|
||||
*
|
||||
* @param cls 目标Activity的Class
|
||||
*/
|
||||
public void startActivity(Class<?> cls) {
|
||||
startActivity(new Intent(this, cls));
|
||||
}
|
||||
|
||||
/**
|
||||
* 延迟执行某个任务
|
||||
*
|
||||
* @param action Runnable对象
|
||||
*/
|
||||
public boolean post(Runnable action) {
|
||||
return getWindow().getDecorView().post(action);
|
||||
}
|
||||
|
||||
/**
|
||||
* 延迟某个时间执行某个任务
|
||||
*
|
||||
* @param action Runnable对象
|
||||
* @param delayMillis 延迟的时间
|
||||
*/
|
||||
public boolean postDelayed(Runnable action, long delayMillis) {
|
||||
return getWindow().getDecorView().postDelayed(action, delayMillis);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除某个延迟任务
|
||||
* @param action Runnable对象
|
||||
*/
|
||||
public boolean removeCallbacks(Runnable action) {
|
||||
if(getWindow().getDecorView() != null) {
|
||||
return getWindow().getDecorView().removeCallbacks(action);
|
||||
}else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package com.hjq.baselibrary.base;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
* author : HJQ
|
||||
* github : https://github.com/getActivity/AndroidProject
|
||||
* time : 2018/10/18
|
||||
* desc : Activity中优化Handler基类
|
||||
*/
|
||||
public abstract class BaseActivityHandler<T extends Activity> extends Handler {
|
||||
|
||||
private final WeakReference<T> mActivity;
|
||||
|
||||
public BaseActivityHandler(T activity) {
|
||||
mActivity = new WeakReference<>(activity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断当前Handler是否可用
|
||||
*/
|
||||
public boolean isEnabled() {
|
||||
return mActivity.get() != null && !mActivity.get().isFinishing();
|
||||
}
|
||||
|
||||
/**
|
||||
* 在Activity销毁前移除所有的任务
|
||||
*/
|
||||
public void onDestroy() {
|
||||
//删除所有的回调函数和消息
|
||||
removeCallbacksAndMessages(null);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
package com.hjq.baselibrary.base;
|
||||
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentPagerAdapter;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* author : HJQ
|
||||
* github : https://github.com/getActivity/AndroidProject
|
||||
* time : 2018/10/18
|
||||
* desc : FragmentPagerAdapter基类
|
||||
*/
|
||||
public abstract class BaseFragmentPagerAdapter<T extends Fragment> extends FragmentPagerAdapter {
|
||||
|
||||
private List<T> mFragments = new ArrayList<>(); // Fragment集合
|
||||
|
||||
private T mCurrentFragment; // 当前显示的Fragment
|
||||
|
||||
/**
|
||||
* 在Activity中使用ViewPager适配器
|
||||
*/
|
||||
public BaseFragmentPagerAdapter(FragmentActivity activity) {
|
||||
this(activity.getSupportFragmentManager());
|
||||
}
|
||||
|
||||
/**
|
||||
* 在Fragment中使用ViewPager适配器
|
||||
*/
|
||||
public BaseFragmentPagerAdapter(Fragment fragment) {
|
||||
this(fragment.getChildFragmentManager());
|
||||
}
|
||||
|
||||
public BaseFragmentPagerAdapter(FragmentManager fm) {
|
||||
super(fm);
|
||||
init(fm, mFragments);
|
||||
}
|
||||
|
||||
//初始化Fragment
|
||||
protected abstract void init(FragmentManager fm, List<T> list);
|
||||
|
||||
@Override
|
||||
public T getItem(int position) {
|
||||
return mFragments.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mFragments.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPrimaryItem(ViewGroup container, int position, Object object) {
|
||||
if (getCurrentFragment() != object) {
|
||||
// 记录当前的Fragment对象
|
||||
mCurrentFragment = (T) object;
|
||||
}
|
||||
super.setPrimaryItem(container, position, object);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Fragment集合
|
||||
*/
|
||||
public List<T> getAllFragment() {
|
||||
return mFragments;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前的Fragment
|
||||
*/
|
||||
public T getCurrentFragment() {
|
||||
return mCurrentFragment;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,166 @@
|
|||
package com.hjq.baselibrary.base;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.IdRes;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* author : HJQ
|
||||
* github : https://github.com/getActivity/AndroidProject
|
||||
* time : 2018/10/18
|
||||
* desc : Fragment懒加载基类
|
||||
*/
|
||||
public abstract class BaseLazyFragment extends Fragment {
|
||||
|
||||
private boolean isLazyLoad = false;//是否已经懒加载
|
||||
private View mRootView;//根布局
|
||||
public Activity mActivity;//Activity对象
|
||||
|
||||
/**
|
||||
* 获得全局的,防止使用getActivity()为空
|
||||
*/
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
this.mActivity = (Activity) context;
|
||||
}
|
||||
|
||||
public Activity getSupportActivity() {
|
||||
return mActivity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
super.onCreateView(inflater, container, savedInstanceState);
|
||||
|
||||
if (mRootView == null && getLayoutId() > 0) {
|
||||
mRootView = inflater.inflate(getLayoutId(), null);
|
||||
}
|
||||
|
||||
ViewGroup parent = (ViewGroup) mRootView.getParent();
|
||||
if (parent != null) {
|
||||
parent.removeView(mRootView);
|
||||
}
|
||||
|
||||
return mRootView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView() {
|
||||
return mRootView;
|
||||
}
|
||||
|
||||
protected boolean isLazyLoad() {
|
||||
return isLazyLoad;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否在Fragment使用沉浸式
|
||||
*/
|
||||
protected boolean isStatusBarEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
mActivity = null;
|
||||
mRootView = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
if (isVisibleToUser && !isLazyLoad() && getView() != null) {
|
||||
isLazyLoad = true;
|
||||
init();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isVisibleToUser;
|
||||
|
||||
@Override
|
||||
public void setUserVisibleHint(boolean isVisibleToUser) {
|
||||
this.isVisibleToUser = isVisibleToUser;
|
||||
if (isVisibleToUser && !isLazyLoad() && getView() != null) {
|
||||
isLazyLoad = true;
|
||||
init();
|
||||
}
|
||||
super.setUserVisibleHint(isVisibleToUser);
|
||||
}
|
||||
|
||||
public boolean isVisibleToUser() {
|
||||
return isVisibleToUser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetach() {
|
||||
super.onDetach();
|
||||
//解决java.lang.IllegalStateException: Activity has been destroyed 的错误
|
||||
try {
|
||||
Field childFragmentManager = Fragment.class.getDeclaredField("mChildFragmentManager");
|
||||
childFragmentManager.setAccessible(true);
|
||||
childFragmentManager.set(this, null);
|
||||
} catch (NoSuchFieldException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void init() {
|
||||
initView();
|
||||
initData();
|
||||
}
|
||||
|
||||
//引入布局
|
||||
protected abstract int getLayoutId();
|
||||
|
||||
//标题栏id,用于状态栏沉浸
|
||||
protected abstract int getTitleBarId();
|
||||
|
||||
//初始化控件
|
||||
protected abstract void initView();
|
||||
|
||||
//初始化数据
|
||||
protected abstract void initData();
|
||||
|
||||
/**
|
||||
* 根据资源id获取一个View
|
||||
*/
|
||||
protected <T extends View> T findViewById(@IdRes int id) {
|
||||
return (T) getView().findViewById(id);
|
||||
}
|
||||
|
||||
protected <T extends View> T findActivityViewById(@IdRes int id) {
|
||||
return (T) mActivity.findViewById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到其他Activity
|
||||
*
|
||||
* @param cls 目标Activity的Class
|
||||
*/
|
||||
public void startActivity(Class<?> cls) {
|
||||
startActivity(new Intent(getContext(), cls));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fragment返回键被按下时回调
|
||||
*/
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
//默认不拦截按键事件,传递给Activity
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,205 @@
|
|||
package com.hjq.baselibrary.base;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.ColorInt;
|
||||
import android.support.annotation.DrawableRes;
|
||||
import android.support.annotation.IdRes;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* author : HJQ
|
||||
* github : https://github.com/getActivity/AndroidProject
|
||||
* time : 2018/10/18
|
||||
* desc : ListView适配器基类
|
||||
*/
|
||||
public abstract class BaseListViewAdapter<T, VH extends BaseListViewAdapter.ViewHolder> extends BaseAdapter {
|
||||
|
||||
private List<T> mDataSet;
|
||||
private Context mContext;
|
||||
|
||||
public BaseListViewAdapter(Context context) {
|
||||
this.mContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mDataSet == null ? 0 : mDataSet.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
ViewHolder holder;
|
||||
if (convertView == null) {
|
||||
holder = onCreateViewHolder(parent, getItemViewType(position));
|
||||
convertView = holder.getItemView();
|
||||
convertView.setTag(holder);
|
||||
} else {
|
||||
holder = (ViewHolder) convertView.getTag();
|
||||
}
|
||||
onBindViewHolder(holder, position);
|
||||
return holder.getItemView();
|
||||
}
|
||||
|
||||
public abstract ViewHolder onCreateViewHolder(ViewGroup parent, int viewType);
|
||||
|
||||
public abstract void onBindViewHolder(ViewHolder holder, int position);
|
||||
|
||||
/**
|
||||
* 设置新的数据
|
||||
*/
|
||||
public void setData(List<T> data) {
|
||||
mDataSet = data;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前数据
|
||||
*/
|
||||
public List<T> getData() {
|
||||
return mDataSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* 追加一些数据
|
||||
*/
|
||||
public void addData(List<T> data) {
|
||||
if (mDataSet != null) {
|
||||
mDataSet.addAll(data);
|
||||
} else {
|
||||
mDataSet = data;
|
||||
}
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空当前数据
|
||||
*/
|
||||
public void clearData() {
|
||||
//当前的数据不能为空
|
||||
if (mDataSet == null || mDataSet.size() == 0) return;
|
||||
|
||||
mDataSet.clear();
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某个位置上的数据
|
||||
*/
|
||||
@Override
|
||||
public T getItem(int position) {
|
||||
return mDataSet.get(position);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新某个位置上的数据
|
||||
*/
|
||||
public void setItem(int position, T item) {
|
||||
if (mDataSet == null) mDataSet = new ArrayList<>();
|
||||
mDataSet.set(position, item);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加单条数据
|
||||
*/
|
||||
public void addItem(T item) {
|
||||
addItem(mDataSet.size() - 1, item);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加单条数据
|
||||
*/
|
||||
public void addItem(int position, T item) {
|
||||
if (mDataSet == null) mDataSet = new ArrayList<>();
|
||||
|
||||
//如果是在for循环添加后要记得position++
|
||||
if (position < mDataSet.size()) {
|
||||
mDataSet.add(position, item);
|
||||
} else {
|
||||
mDataSet.add(item);
|
||||
}
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除单条数据
|
||||
*/
|
||||
public void removeItem(T item) {
|
||||
int index = mDataSet.indexOf(item);
|
||||
if (index != -1) {
|
||||
removeItem(index);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeItem(int position) {
|
||||
//如果是在for循环删除后要记得i--
|
||||
mDataSet.remove(position);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public Context getContext() {
|
||||
return mContext;
|
||||
}
|
||||
|
||||
public static class ViewHolder {
|
||||
|
||||
public final View itemView;
|
||||
|
||||
public ViewHolder(View itemView) {
|
||||
this.itemView = itemView;
|
||||
}
|
||||
|
||||
public final View getItemView() {
|
||||
return itemView;
|
||||
}
|
||||
|
||||
public final <T extends View> T findView(@IdRes int id) {
|
||||
return (T) itemView.findViewById(id);
|
||||
}
|
||||
|
||||
public final ViewHolder setText(@IdRes int id, String text) {
|
||||
if (text == null) text = "";
|
||||
View view = findView(id);
|
||||
if (view instanceof TextView) {
|
||||
((TextView) view).setText(text);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public final ViewHolder setVisibility(@IdRes int id, int visibility) {
|
||||
View view = findView(id);
|
||||
if (view != null) {
|
||||
view.setVisibility(visibility);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public final ViewHolder setColor(@IdRes int id, @ColorInt int color) {
|
||||
View view = findView(id);
|
||||
if (view instanceof TextView) {
|
||||
((TextView) view).setTextColor(color);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public final ViewHolder setImage(@IdRes int id, @DrawableRes int resID) {
|
||||
View view = findView(id);
|
||||
if (view instanceof ImageView) {
|
||||
((ImageView) view).setImageResource(resID);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,382 @@
|
|||
package com.hjq.baselibrary.base;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.ColorInt;
|
||||
import android.support.annotation.IdRes;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.hjq.baselibrary.listener.OnItemClickListener;
|
||||
import com.hjq.baselibrary.listener.OnItemLongClickListener;
|
||||
import com.hjq.baselibrary.listener.OnScrollingListener;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* author : HJQ
|
||||
* github : https://github.com/getActivity/AndroidProject
|
||||
* time : 2018/10/18
|
||||
* desc : RecyclerView适配器基类
|
||||
*/
|
||||
public abstract class BaseRecyclerViewAdapter<T, VH extends BaseRecyclerViewAdapter.ViewHolder>
|
||||
extends RecyclerView.Adapter<VH> {
|
||||
//列表数据
|
||||
private List<T> mDataSet;
|
||||
//当前列表的页码,默认为第一页,用于分页加载功能
|
||||
private int mPageNumber = 1;
|
||||
//是否是最后一页,默认为false,用于分页加载功能
|
||||
private boolean mLastPage;
|
||||
|
||||
//RecyclerView对象
|
||||
private RecyclerView mRecyclerView;
|
||||
//上下文对象,注意不要在构造函数中使用
|
||||
private Context mContext;
|
||||
|
||||
//标记对象
|
||||
private Object mTag;
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mDataSet == null ? 0 : mDataSet.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置新的数据
|
||||
*/
|
||||
public void setData(List<T> data) {
|
||||
mDataSet = data;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前数据
|
||||
*/
|
||||
public List<T> getData() {
|
||||
return mDataSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* 追加一些数据
|
||||
*/
|
||||
public void addData(List<T> data) {
|
||||
//追加的数据不能为空
|
||||
if (data == null || data.size() == 0) return;
|
||||
|
||||
if (mDataSet == null || mDataSet.size() == 0) {
|
||||
setData(data);
|
||||
}else {
|
||||
mDataSet.addAll(data);
|
||||
notifyItemRangeInserted(mDataSet.size() - data.size(), data.size());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空当前数据
|
||||
*/
|
||||
public void clearData() {
|
||||
//当前的数据不能为空
|
||||
if (mDataSet == null || mDataSet.size() == 0) return;
|
||||
|
||||
mDataSet.clear();
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某个位置上的数据
|
||||
*/
|
||||
public T getItem(int position) {
|
||||
return mDataSet.get(position);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新某个位置上的数据
|
||||
*/
|
||||
public void setItem(int position, T item) {
|
||||
if (mDataSet == null) mDataSet = new ArrayList<>();
|
||||
mDataSet.set(position, item);
|
||||
notifyItemChanged(position);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加单条数据
|
||||
*/
|
||||
public void addItem(T item) {
|
||||
addItem(mDataSet.size() - 1, item);
|
||||
}
|
||||
|
||||
public void addItem(int position, T item) {
|
||||
if (mDataSet == null) mDataSet = new ArrayList<>();
|
||||
|
||||
//如果是在for循环添加后要记得position++
|
||||
if (position < mDataSet.size()) {
|
||||
mDataSet.add(position, item);
|
||||
}else {
|
||||
mDataSet.add(item);
|
||||
position = mDataSet.size() - 1;
|
||||
}
|
||||
//告诉适配器添加数据的位置,会有动画效果
|
||||
notifyItemInserted(position);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除单条数据
|
||||
*/
|
||||
public void removeItem(T item) {
|
||||
int index = mDataSet.indexOf(item);
|
||||
if (index != -1) {
|
||||
removeItem(index);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeItem(int position) {
|
||||
//如果是在for循环删除后要记得i--
|
||||
mDataSet.remove(position);
|
||||
//告诉适配器删除数据的位置,会有动画效果
|
||||
notifyItemRemoved(position);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取RecyclerView对象,需要在setAdapter之后绑定
|
||||
*/
|
||||
public RecyclerView getRecyclerView() {
|
||||
return mRecyclerView;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上下文对象,注意不要在构造方法中调用
|
||||
*/
|
||||
public Context getContext() {
|
||||
return mContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果非要在构造方法中使用上下文对象,可以提前设置,否则只能setAdapter之后才能获取
|
||||
*/
|
||||
public void setContext(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前的页码
|
||||
*/
|
||||
public int getPageNumber() {
|
||||
return mPageNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置当前的页码
|
||||
*/
|
||||
public void setPageNumber(int pageNumber) {
|
||||
mPageNumber = pageNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前是否为最后一页
|
||||
*/
|
||||
public boolean isLastPage() {
|
||||
return mLastPage;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置是否为最后一页
|
||||
*/
|
||||
public void setLastPage(boolean lastPage) {
|
||||
mLastPage = lastPage;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取标记
|
||||
*/
|
||||
public Object getTag() {
|
||||
return mTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置标记
|
||||
*/
|
||||
public void setTag(Object tag) {
|
||||
mTag = tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 条目ViewHolder,需要子类ViewHolder继承
|
||||
*/
|
||||
public class ViewHolder extends RecyclerView.ViewHolder
|
||||
implements View.OnClickListener, View.OnLongClickListener {
|
||||
|
||||
public ViewHolder(ViewGroup parent, int layoutId) {
|
||||
this(LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false));
|
||||
}
|
||||
|
||||
public ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
//这里可以设置条目的监听事件
|
||||
itemView.setOnClickListener(this);
|
||||
itemView.setOnLongClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if(onItemClickListener != null) {
|
||||
onItemClickListener.onItemClick(v, getLayoutPosition());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onLongClick(View v) {
|
||||
if (onItemLongClickListener != null) {
|
||||
return onItemLongClickListener.onItemLongClick(v, getLayoutPosition());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public final <T extends View> T findView(@IdRes int id) {
|
||||
return (T) itemView.findViewById(id);
|
||||
}
|
||||
|
||||
public final ViewHolder setText(@IdRes int id, String text) {
|
||||
if (text == null) text = "";
|
||||
View view = findView(id);
|
||||
if (view instanceof TextView) {
|
||||
((TextView) view).setText(text);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public final ViewHolder setVisibility(@IdRes int id, int visibility) {
|
||||
View view = findView(id);
|
||||
if (view != null) {
|
||||
view.setVisibility(visibility);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public final ViewHolder setColor(@IdRes int id, @ColorInt int color) {
|
||||
View view = findView(id);
|
||||
if (view instanceof TextView) {
|
||||
((TextView) view).setTextColor(color);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public final ViewHolder setImage(@IdRes int id, int resID) {
|
||||
View view = findView(id);
|
||||
if (view instanceof ImageView) {
|
||||
((ImageView) view).setImageResource(resID);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
|
||||
mRecyclerView = recyclerView;
|
||||
if (mContext == null) {
|
||||
mContext = recyclerView.getContext();
|
||||
}
|
||||
//用户设置了滚动监听,需要给RecyclerView设置监听
|
||||
if (mScrollListener != null) {
|
||||
//添加滚动监听
|
||||
mRecyclerView.addOnScrollListener(mScrollListener);
|
||||
}
|
||||
//判断当前的布局管理器是否为空,如果为空则设置默认的布局管理器
|
||||
if (mRecyclerView.getLayoutManager() == null) {
|
||||
RecyclerView.LayoutManager manager = getDefaultLayoutManager(mContext);
|
||||
if (manager != null) {
|
||||
mRecyclerView.setLayoutManager(manager);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) {
|
||||
//移除滚动监听
|
||||
if (mScrollListener != null) {
|
||||
mRecyclerView.removeOnScrollListener(mScrollListener);
|
||||
}
|
||||
mRecyclerView = null;
|
||||
mContext = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取默认的布局摆放器
|
||||
*/
|
||||
public RecyclerView.LayoutManager getDefaultLayoutManager(Context context) {
|
||||
return new LinearLayoutManager(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置RecyclerView条目点击监听
|
||||
*/
|
||||
private OnItemClickListener onItemClickListener;
|
||||
public void setOnItemClickListener(OnItemClickListener l) {
|
||||
onItemClickListener = l;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置RecyclerView条目长按监听
|
||||
*/
|
||||
private OnItemLongClickListener onItemLongClickListener;
|
||||
public void setOnItemLongClickListener(OnItemLongClickListener l) {
|
||||
onItemLongClickListener = l;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置RecyclerView条目滚动监听
|
||||
*/
|
||||
private OnScrollingListener onScrollingListener;
|
||||
public void setOnScrollingListener(OnScrollingListener l) {
|
||||
onScrollingListener = l;
|
||||
|
||||
//如果当前已经有设置滚动监听,再次设置需要移除原有的监听器
|
||||
if (mScrollListener == null) {
|
||||
mScrollListener = new ScrollListener();
|
||||
}else {
|
||||
mRecyclerView.removeOnScrollListener(mScrollListener);
|
||||
}
|
||||
//用户设置了滚动监听,需要给RecyclerView设置监听
|
||||
if (mRecyclerView != null) {
|
||||
//添加滚动监听
|
||||
mRecyclerView.addOnScrollListener(mScrollListener);
|
||||
}
|
||||
}
|
||||
|
||||
//自定义滚动监听器
|
||||
private ScrollListener mScrollListener;
|
||||
|
||||
private class ScrollListener extends RecyclerView.OnScrollListener {
|
||||
|
||||
@Override
|
||||
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
|
||||
|
||||
if (onScrollingListener == null) return;
|
||||
|
||||
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
|
||||
|
||||
if (!recyclerView.canScrollVertically(1)) {
|
||||
//是否能向下滚动,false表示已经滚动到底部
|
||||
onScrollingListener.onScrollDown(recyclerView);
|
||||
}else if (!recyclerView.canScrollVertically(-1)) {
|
||||
//是否能向上滚动,false表示已经滚动到顶部
|
||||
onScrollingListener.onScrollTop(recyclerView);
|
||||
}
|
||||
|
||||
}else if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
|
||||
//正在滚动中
|
||||
onScrollingListener.onScrolling(recyclerView);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|