├── .github
├── FUNDING.yml
└── workflows
│ └── issue_check.yml
├── .gitignore
├── .idea
├── copyright
│ ├── profiles_settings.xml
│ └── xuexiang.xml
└── gradle.xml
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle
├── channel
├── debug.jks
├── multiple-channel.gradle
├── proguard-rules.pro
├── src
│ ├── androidTest
│ │ └── java
│ │ │ └── com
│ │ │ └── xuexiang
│ │ │ └── templateproject
│ │ │ └── ExampleInstrumentedTest.kt
│ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── assets
│ │ │ ├── protocol
│ │ │ │ ├── account_protocol.txt
│ │ │ │ └── privacy_protocol.txt
│ │ │ └── tips.json
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── xuexiang
│ │ │ │ └── templateproject
│ │ │ │ ├── MyApp.kt
│ │ │ │ ├── activity
│ │ │ │ ├── LoginActivity.kt
│ │ │ │ ├── MainActivity.kt
│ │ │ │ └── SplashActivity.kt
│ │ │ │ ├── adapter
│ │ │ │ ├── base
│ │ │ │ │ ├── broccoli
│ │ │ │ │ │ ├── BroccoliRecyclerAdapter.kt
│ │ │ │ │ │ └── BroccoliSimpleDelegateAdapter.kt
│ │ │ │ │ └── delegate
│ │ │ │ │ │ ├── BaseDelegateAdapter.kt
│ │ │ │ │ │ ├── SimpleDelegateAdapter.kt
│ │ │ │ │ │ ├── SingleDelegateAdapter.kt
│ │ │ │ │ │ └── XDelegateAdapter.kt
│ │ │ │ └── entity
│ │ │ │ │ └── NewInfo.kt
│ │ │ │ ├── core
│ │ │ │ ├── BaseActivity.kt
│ │ │ │ ├── BaseContainerFragment.kt
│ │ │ │ ├── BaseFragment.kt
│ │ │ │ ├── BaseSimpleListFragment.kt
│ │ │ │ ├── SimpleListAdapter.kt
│ │ │ │ ├── XPageTransferActivity.kt
│ │ │ │ ├── http
│ │ │ │ │ ├── api
│ │ │ │ │ │ └── ApiService.kt
│ │ │ │ │ ├── callback
│ │ │ │ │ │ ├── NoTipCallBack.kt
│ │ │ │ │ │ ├── TipCallBack.kt
│ │ │ │ │ │ └── TipProgressLoadingCallBack.kt
│ │ │ │ │ ├── entity
│ │ │ │ │ │ └── TipInfo.kt
│ │ │ │ │ ├── loader
│ │ │ │ │ │ ├── IProgressLoaderFactory.kt
│ │ │ │ │ │ ├── MiniLoadingDialogLoader.kt
│ │ │ │ │ │ ├── MiniProgressLoaderFactory.kt
│ │ │ │ │ │ └── ProgressLoader.kt
│ │ │ │ │ └── subscriber
│ │ │ │ │ │ ├── NoTipRequestSubscriber.kt
│ │ │ │ │ │ ├── TipProgressLoadingSubscriber.kt
│ │ │ │ │ │ └── TipRequestSubscriber.kt
│ │ │ │ └── webview
│ │ │ │ │ ├── AgentWebActivity.kt
│ │ │ │ │ ├── AgentWebFragment.kt
│ │ │ │ │ ├── BaseWebViewFragment.kt
│ │ │ │ │ ├── FragmentKeyDown.kt
│ │ │ │ │ ├── LollipopFixedWebView.kt
│ │ │ │ │ ├── MiddlewareChromeClient.kt
│ │ │ │ │ ├── MiddlewareWebViewClient.kt
│ │ │ │ │ ├── UIController.kt
│ │ │ │ │ ├── WebLayout.kt
│ │ │ │ │ ├── WebViewInterceptDialog.kt
│ │ │ │ │ └── XPageWebViewFragment.kt
│ │ │ │ ├── fragment
│ │ │ │ ├── news
│ │ │ │ │ ├── GridItemFragment.kt
│ │ │ │ │ └── NewsFragment.kt
│ │ │ │ ├── other
│ │ │ │ │ ├── AboutFragment.kt
│ │ │ │ │ ├── LoginFragment.kt
│ │ │ │ │ ├── ServiceProtocolFragment.kt
│ │ │ │ │ └── SettingsFragment.kt
│ │ │ │ ├── profile
│ │ │ │ │ └── ProfileFragment.kt
│ │ │ │ └── trending
│ │ │ │ │ └── TrendingFragment.kt
│ │ │ │ ├── utils
│ │ │ │ ├── DemoDataProvider.kt
│ │ │ │ ├── MMKVUtils.kt
│ │ │ │ ├── RandomUtils.kt
│ │ │ │ ├── SettingUtils.kt
│ │ │ │ ├── TokenUtils.kt
│ │ │ │ ├── Utils.kt
│ │ │ │ ├── sdkinit
│ │ │ │ │ ├── ANRWatchDogInit.kt
│ │ │ │ │ ├── UMengInit.kt
│ │ │ │ │ ├── XBasicLibInit.kt
│ │ │ │ │ └── XUpdateInit.kt
│ │ │ │ ├── service
│ │ │ │ │ └── JsonSerializationService.kt
│ │ │ │ └── update
│ │ │ │ │ ├── CustomUpdateDownloader.kt
│ │ │ │ │ ├── CustomUpdateFailureListener.kt
│ │ │ │ │ ├── CustomUpdateParser.kt
│ │ │ │ │ ├── UpdateTipDialog.kt
│ │ │ │ │ └── XHttpUpdateHttpServiceImpl.kt
│ │ │ │ └── widget
│ │ │ │ ├── GuideTipsDialog.kt
│ │ │ │ └── MaterialFooter.kt
│ │ └── res
│ │ │ ├── color
│ │ │ └── selector_round_button_main_theme_color.xml
│ │ │ ├── drawable-hdpi
│ │ │ ├── ic_comment.png
│ │ │ ├── ic_praise.png
│ │ │ ├── ic_splash_app_logo_xui.png
│ │ │ └── ic_splash_company_logo.png
│ │ │ ├── drawable-v17
│ │ │ └── xui_config_bg_splash.xml
│ │ │ ├── drawable-v21
│ │ │ └── xui_config_bg_splash.xml
│ │ │ ├── drawable-v24
│ │ │ └── ic_launcher_foreground.xml
│ │ │ ├── drawable-xxxhdpi
│ │ │ ├── ic_web_back.png
│ │ │ ├── ic_web_close.png
│ │ │ └── ic_web_more.png
│ │ │ ├── drawable
│ │ │ ├── bg_dialog_common_tip_corner_white.xml
│ │ │ ├── ic_action_close_white.xml
│ │ │ ├── ic_default_head.xml
│ │ │ ├── ic_launcher_background.xml
│ │ │ ├── ic_login_close.xml
│ │ │ ├── ic_logo_app.xml
│ │ │ ├── ic_menu_about.xml
│ │ │ ├── ic_menu_about_white.xml
│ │ │ ├── ic_menu_issues.xml
│ │ │ ├── ic_menu_news.xml
│ │ │ ├── ic_menu_notifications.xml
│ │ │ ├── ic_menu_person.xml
│ │ │ ├── ic_menu_privacy.xml
│ │ │ ├── ic_menu_search.xml
│ │ │ ├── ic_menu_settings.xml
│ │ │ ├── ic_menu_star.xml
│ │ │ ├── ic_menu_trending.xml
│ │ │ ├── ic_password.xml
│ │ │ ├── ic_phone.xml
│ │ │ ├── icon_arrow_right_grey.xml
│ │ │ └── img_guide_tip_top.xml
│ │ │ ├── layout
│ │ │ ├── activity_agent_web.xml
│ │ │ ├── activity_main.xml
│ │ │ ├── adapter_common_grid_item.xml
│ │ │ ├── adapter_item_simple_list_2.xml
│ │ │ ├── adapter_news_card_view_list_item.xml
│ │ │ ├── adapter_title_item.xml
│ │ │ ├── dialog_guide_tips.xml
│ │ │ ├── fragment_about.xml
│ │ │ ├── fragment_agentweb.xml
│ │ │ ├── fragment_grid_item.xml
│ │ │ ├── fragment_login.xml
│ │ │ ├── fragment_news.xml
│ │ │ ├── fragment_profile.xml
│ │ │ ├── fragment_pulldown_web.xml
│ │ │ ├── fragment_service_protocol.xml
│ │ │ ├── fragment_settings.xml
│ │ │ ├── fragment_trending.xml
│ │ │ ├── include_head_view_banner.xml
│ │ │ ├── include_navigation_header.xml
│ │ │ ├── include_toolbar_web.xml
│ │ │ ├── layout_main_content.xml
│ │ │ └── layout_news_card_item.xml
│ │ │ ├── menu
│ │ │ ├── menu_drawer.xml
│ │ │ ├── menu_main.xml
│ │ │ ├── menu_navigation_bottom.xml
│ │ │ └── menu_toolbar_web.xml
│ │ │ ├── mipmap-anydpi-v26
│ │ │ ├── ic_launcher.xml
│ │ │ └── ic_launcher_round.xml
│ │ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ │ ├── values
│ │ │ ├── arrays.xml
│ │ │ ├── colors.xml
│ │ │ ├── dimens.xml
│ │ │ ├── strings.xml
│ │ │ ├── styles.xml
│ │ │ └── styles_widget.xml
│ │ │ └── xml
│ │ │ └── network_security_config.xml
│ └── test
│ │ └── java
│ │ └── com
│ │ └── xuexiang
│ │ └── templateproject
│ │ └── ExampleUnitTest.kt
└── x-library.gradle
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── versions.gradle
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | custom: https://gitee.com/xuexiangjys/Resource/blob/master/doc/sponsor.md
4 |
--------------------------------------------------------------------------------
/.github/workflows/issue_check.yml:
--------------------------------------------------------------------------------
1 | name: No Free usage issue checker # Action名字。可以自定义
2 |
3 | on:
4 | issues:
5 | types: [opened, reopened] # 在issue打开和重新打开时调用
6 |
7 | jobs:
8 | build:
9 | runs-on: ubuntu-latest
10 |
11 | steps:
12 | - uses: actions/checkout@v2
13 | - name: Check issue actor # 步骤名字。可以自定义。
14 | uses: fluttercandies/no-free-usage-action@v1.0.1
15 | with:
16 | token: ${{ secrets.GITHUB_TOKEN }} # 由GitHub提供的临时Token,必须在此处进行传递,且必须为这个值。
17 | forked: '--no-forked'
18 | words: To support our project, please file the issue after you starred the repo. Thanks! 🙂
19 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /LocalRepository
4 | /keystores
5 | /local.properties
6 | /.idea/caches
7 | /.idea/codeStyles
8 | /.idea/inspectionProfiles
9 | /.idea/libraries
10 | /.idea/dictionaries
11 | /.idea/markdown-navigator
12 | /.idea/*.xml
13 | .DS_Store
14 | /build
15 | /captures
16 | .externalNativeBuild
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/copyright/xuexiang.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
18 |
19 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/channel:
--------------------------------------------------------------------------------
1 | # 美团
2 | meituan
3 | # 三星
4 | samsungapps
5 | # 小米
6 | xiaomi
7 | # 91助手
8 | 91com
9 | # 魅族
10 | meizu
11 | # 豌豆荚
12 | wandou
13 | # Google Play
14 | googleplay
15 | # 百度
16 | baidu
17 | # 360
18 | 360cn
19 | # 应用宝
20 | myapp
21 | # 华为
22 | huawei
23 | # 蒲公英
24 | pgyer
25 | github
--------------------------------------------------------------------------------
/app/debug.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xuexiangjys/TemplateAppProject-kotlin/551bef56697c628628d42a857db37658c7670f8d/app/debug.jks
--------------------------------------------------------------------------------
/app/multiple-channel.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'walle'
2 |
3 | walle {
4 | // 指定渠道包的输出路径
5 | apkOutputFolder = new File("${project.buildDir}/outputs/channels")
6 | // 定制渠道包的APK的文件名称
7 | apkFileNameFormat = '${appName}-${packageName}-${channel}-${buildType}-v${versionName}-${versionCode}-${buildTime}.apk'
8 | // 渠道配置文件
9 | channelFile = new File("${project.getProjectDir()}/channel")
10 | }
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/xuexiang/templateproject/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.xuexiang.templateproject
2 |
3 | import androidx.test.ext.junit.runners.AndroidJUnit4
4 | import androidx.test.platform.app.InstrumentationRegistry
5 | import org.junit.Assert
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | /**
10 | * Instrumented test, which will execute on an Android device.
11 | *
12 | * @see [Testing documentation](http://d.android.com/tools/testing)
13 | */
14 | @RunWith(AndroidJUnit4::class)
15 | class ExampleInstrumentedTest {
16 | @Test
17 | fun useAppContext() {
18 | // Context of the app under test.
19 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
20 | Assert.assertEquals("com.xuexiang.templateproject", appContext.packageName)
21 | }
22 | }
--------------------------------------------------------------------------------
/app/src/main/assets/protocol/privacy_protocol.txt:
--------------------------------------------------------------------------------
1 | ####尊重并保护所有使用服务用户的个人隐私权。为了给您提供更准确、更有个性化的 服务,####会按照本隐私权政策的规定使用和披露您的个人信息。但####将以高 度的勤勉、审慎义务对待这些信息。除本隐私权政策另有规定外,在未征得您事先许可的情况下 ,####不会将这些信息对外披露或向第三方提供。####会不时更新本隐私权政策 。 您在同意####服务使用协议之时,即视为您已经同意本隐私权政策全部内容。本隐私 权政策属于####服务使用协议不可分割的一部分。
2 |
3 |
4 | 1. 适用范围
5 |
6 | a) 在您注册####帐号时,您根据####要求提供的个人注册信息;
7 |
8 | b) 在您使用####网络服务,或访问####平台网页时,####自动接收并记 录的您的浏览器和计算机上的信息,包括但不限于您的IP地址、浏览器的类型、使用的语言、访 问日期和时间、软硬件特征信息及您需求的网页记录等数据;
9 |
10 | c) ####通过合法途径从商业伙伴处取得的用户个人数据。
11 |
12 | 您了解并同意,以下信息不适用本隐私权政策:
13 |
14 | a) 您在使用####平台提供的搜索服务时输入的关键字信息;
15 |
16 | b) ####收集到的您在####发布的有关信息数据,包括但不限于参与活动、成交 信息及评价详情;
17 |
18 | c) 违反法律规定或违反####规则行为及####已对您采取的措施。
19 |
20 | 2. 信息使用
21 |
22 | a) ####不会向任何无关第三方提供、出售、出租、分享或交易您的个人信息,除非事先 得到您的许可,或该第三方和####(含####关联公司)单独或共同为您提供服务 ,且在该服务结束后,其将被禁止访问包括其以前能够访问的所有这些资料。
23 |
24 | b) ####亦不允许任何第三方以任何手段收集、编辑、出售或者无偿传播您的个人信息。 任何####平台用户如从事上述活动,一经发现,####有权立即终止与该用户的服 务协议。
25 |
26 | c) 为服务用户的目的,####可能通过使用您的个人信息,向您提供您感兴趣的信息,包 括但不限于向您发出产品和服务信息,或者与####合作伙伴共享信息以便他们向您发送 有关其产品和服务的信息(后者需要您的事先同意)。
27 |
28 | 3. 信息披露 在如下情况下,####将依据您的个人意愿或法律的规定全部或部分的披露您的个人信息 :
29 |
30 | a) 经您事先同意,向第三方披露;
31 |
32 | b) 为提供您所要求的产品和服务,而必须和第三方分享您的个人信息;
33 |
34 | c) 根据法律的有关规定,或者行政或司法机构的要求,向第三方或者行政、司法机构披露;
35 |
36 | d) 如您出现违反中国有关法律、法规或者####服务协议或相关规则的情况,需要向第三 方披露;
37 |
38 | e) 如您是适格的知识产权投诉人并已提起投诉,应被投诉人要求,向被投诉人披露,以便双方 处理可能的权利纠纷;
39 |
40 | f) 在####平台上创建的某一交易中,如交易任何一方履行或部分履行了交易义务并提出 信息披露请求的,####有权决定向该用户提供其交易对方的联络方式等必要信息,以促 成交易的完成或纠纷的解决。
41 |
42 | g) 其它####根据法律、法规或者网站政策认为合适的披露。
43 |
44 | 4. 信息存储和交换 ####收集的有关您的信息和资料将保存在####及(或)其关联公司的服务器上, 这些信息和资料可能传送至您所在国家、地区或####收集信息和资料所在地的境外并在 境外被访问、存储和展示。
45 |
46 | 5. Cookie的使用
47 |
48 | a) 在您未拒绝接受cookies的情况下,####会在您的计算机上设定或取用cookies ,以便您能登录或使用依赖于cookies的####平台服务或功能。####使用cookies 可为您提供更加周到的个性化服务,包括推广服务。
49 |
50 | b) 您有权选择接受或拒绝接受cookies。 您可以通过修改浏览器设置的方式拒绝接受cookies。但如果您选择拒绝接受cookies,则您可能 无法登录或使用依赖于cookies的####网络服务或功能。
51 |
52 | c) 通过####所设cookies所取得的有关信息,将适用本政策。
53 |
54 | 6. 信息安全
55 |
56 | a) ####帐号均有安全保护功能,请妥善保管您的用户名及密码信息。####将通 过对用户密码进行加密等安全措施确保您的信息不丢失,不被滥用和变造。尽管有前述安全措施 ,但同时也请您注意在信息网络上不存在“完善的安全措施”。
57 |
58 | b) 在使用####网络服务进行网上交易时,您不可避免的要向交易对方或潜在的交易对方 披露自己的个人信息,如联络方式或者邮政地址。请您妥善保护自己的个人信息,仅在必要的情 形下向他人提供。如您发现自己的个人信息泄密,尤其是####用户名及密码发生泄露, 请您立即联络####客服,以便####采取相应措施。
59 |
60 | 7. 接入的第三方SDK说明
61 |
62 | a) 友盟统计SDK(com.umeng)
63 | 使用目的: 统计应用运营数据
64 | 使用范围: 应用运营数据统计
65 |
66 | 8. 敏感信息收集说明
67 | 我们的产品集成友盟+SDK,友盟+SDK需要收集您的设备Mac地址、唯一设备识别码(IMEI/android ID/IDFA/OPENUDID/GUID、SIM 卡 IMSI 信息)以提供统计分析服务,并通过地理位置校准报表数据准确性,提供基础反作弊能力。
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/app/src/main/assets/tips.json:
--------------------------------------------------------------------------------
1 | {
2 | "Code": 0,
3 | "Data": [
4 | {
5 | "title": "微信公众号",
6 | "content": "获取更多资讯内容,欢迎微信搜索公众号:「我的Android开源之旅」"
7 | },
8 | {
9 | "title": "关于作者",
10 | "content": "点击关注作者,了解最新动态!
Github
\n知乎
\n掘金
简书
\n思否
\n哔哩哔哩
\n今日头条"
11 | },
12 | {
13 | "title": "赞助作者",
14 | "content": "你的打赏是我维护的动力,点击此处支持我吧!"
15 | },
16 | {
17 | "title": "QQ交流群",
18 | "content": "XUI开源交流1号群
XUI开源交流2号群
AndroidGitHub开源交流群
XUpdate官方交流群"
19 | }
20 | ]
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/java/com/xuexiang/templateproject/MyApp.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 | package com.xuexiang.templateproject
18 |
19 | import android.app.Application
20 | import android.content.Context
21 | import androidx.multidex.MultiDex
22 | import com.xuexiang.templateproject.utils.sdkinit.XBasicLibInit
23 | import com.xuexiang.templateproject.utils.sdkinit.XUpdateInit
24 | import com.xuexiang.templateproject.utils.sdkinit.UMengInit
25 | import com.xuexiang.templateproject.utils.sdkinit.ANRWatchDogInit
26 |
27 | /**
28 | * @author xuexiang
29 | * @since 2018/11/7 下午1:12
30 | */
31 | class MyApp : Application() {
32 | override fun attachBaseContext(base: Context) {
33 | super.attachBaseContext(base)
34 | //解决4.x运行崩溃的问题
35 | MultiDex.install(this)
36 | }
37 |
38 | override fun onCreate() {
39 | super.onCreate()
40 | initLibs()
41 | }
42 |
43 | /**
44 | * 初始化基础库
45 | */
46 | private fun initLibs() {
47 | // X系列基础库初始化
48 | XBasicLibInit.init(this)
49 | // 版本更新初始化
50 | XUpdateInit.init(this)
51 | // 运营统计数据
52 | UMengInit.init(this)
53 | // ANR监控
54 | ANRWatchDogInit.init()
55 | }
56 |
57 | companion object {
58 | /**
59 | * @return 当前app是否是调试开发模式
60 | */
61 | val isDebug: Boolean
62 | get() = BuildConfig.DEBUG
63 | }
64 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/xuexiang/templateproject/activity/LoginActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 | package com.xuexiang.templateproject.activity
18 |
19 | import android.os.Bundle
20 | import android.view.KeyEvent
21 | import androidx.viewbinding.ViewBinding
22 | import com.xuexiang.templateproject.core.BaseActivity
23 | import com.xuexiang.templateproject.fragment.other.LoginFragment
24 | import com.xuexiang.xui.utils.KeyboardUtils
25 | import com.xuexiang.xui.utils.StatusBarUtils
26 | import com.xuexiang.xutil.display.Colors
27 |
28 | /**
29 | * 登录页面
30 | *
31 | * @author xuexiang
32 | * @since 2019-11-17 22:21
33 | */
34 | class LoginActivity : BaseActivity() {
35 | override fun onCreate(savedInstanceState: Bundle?) {
36 | super.onCreate(savedInstanceState)
37 | openPage(LoginFragment::class.java, intent.extras)
38 | }
39 |
40 | override val isSupportSlideBack = false
41 |
42 | override fun initStatusBarStyle() {
43 | StatusBarUtils.initStatusBarStyle(this, false, Colors.WHITE)
44 | }
45 |
46 | override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
47 | return KeyboardUtils.onDisableBackKeyDown(keyCode) && super.onKeyDown(keyCode, event)
48 | }
49 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/xuexiang/templateproject/activity/SplashActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 | package com.xuexiang.templateproject.activity
18 |
19 | import android.view.KeyEvent
20 | import com.xuexiang.templateproject.R
21 | import com.xuexiang.templateproject.utils.SettingUtils.isAgreePrivacy
22 | import com.xuexiang.templateproject.utils.TokenUtils.hasToken
23 | import com.xuexiang.templateproject.utils.Utils.showPrivacyDialog
24 | import com.xuexiang.xui.utils.KeyboardUtils
25 | import com.xuexiang.xui.widget.activity.BaseSplashActivity
26 | import com.xuexiang.xui.widget.dialog.materialdialog.DialogAction
27 | import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
28 | import com.xuexiang.xutil.app.ActivityUtils
29 | import me.jessyan.autosize.internal.CancelAdapt
30 |
31 | /**
32 | * 启动页【无需适配屏幕大小】
33 | *
34 | * @author xuexiang
35 | * @since 2019-06-30 17:32
36 | */
37 | class SplashActivity : BaseSplashActivity(), CancelAdapt {
38 | override fun getSplashDurationMillis(): Long {
39 | return 500
40 | }
41 |
42 | /**
43 | * activity启动后的初始化
44 | */
45 | override fun onCreateActivity() {
46 | initSplashView(R.drawable.xui_config_bg_splash)
47 | startSplash(false)
48 | }
49 |
50 | /**
51 | * 启动页结束后的动作
52 | */
53 | override fun onSplashFinished() {
54 | if (isAgreePrivacy) {
55 | loginOrGoMainPage()
56 | } else {
57 | showPrivacyDialog(this) { dialog: MaterialDialog, which: DialogAction? ->
58 | dialog.dismiss()
59 | isAgreePrivacy = true
60 | loginOrGoMainPage()
61 | }
62 | }
63 | }
64 |
65 | private fun loginOrGoMainPage() {
66 | if (hasToken()) {
67 | ActivityUtils.startActivity(MainActivity::class.java)
68 | } else {
69 | ActivityUtils.startActivity(LoginActivity::class.java)
70 | }
71 | finish()
72 | }
73 |
74 | /**
75 | * 菜单、返回键响应
76 | */
77 | override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
78 | return KeyboardUtils.onDisableBackKeyDown(keyCode) && super.onKeyDown(keyCode, event)
79 | }
80 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/xuexiang/templateproject/adapter/base/broccoli/BroccoliRecyclerAdapter.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 | package com.xuexiang.templateproject.adapter.base.broccoli
18 |
19 | import android.view.View
20 | import com.xuexiang.xui.adapter.recyclerview.BaseRecyclerAdapter
21 | import com.xuexiang.xui.adapter.recyclerview.RecyclerViewHolder
22 | import com.xuexiang.xui.adapter.recyclerview.XRecyclerAdapter
23 | import me.samlss.broccoli.Broccoli
24 | import java.util.*
25 |
26 | /**
27 | * 使用Broccoli占位的基础适配器
28 | *
29 | * @author XUE
30 | * @since 2019/4/8 16:33
31 | */
32 | abstract class BroccoliRecyclerAdapter(collection: Collection?) :
33 | BaseRecyclerAdapter(collection) {
34 | /**
35 | * 是否已经加载成功
36 | */
37 | private var mHasLoad = false
38 | private val mBroccoliMap: MutableMap = HashMap()
39 | override fun bindData(holder: RecyclerViewHolder, position: Int, item: T) {
40 | var broccoli = mBroccoliMap[holder.itemView]
41 | if (broccoli == null) {
42 | broccoli = Broccoli()
43 | mBroccoliMap[holder.itemView] = broccoli
44 | }
45 | if (mHasLoad) {
46 | broccoli.removeAllPlaceholders()
47 | onBindData(holder, item, position)
48 | } else {
49 | onBindBroccoli(holder, broccoli)
50 | broccoli.show()
51 | }
52 | }
53 |
54 | /**
55 | * 绑定控件
56 | *
57 | * @param holder
58 | * @param model
59 | * @param position
60 | */
61 | protected abstract fun onBindData(holder: RecyclerViewHolder?, model: T, position: Int)
62 |
63 | /**
64 | * 绑定占位控件
65 | *
66 | * @param broccoli
67 | */
68 | protected abstract fun onBindBroccoli(holder: RecyclerViewHolder?, broccoli: Broccoli?)
69 | override fun refresh(collection: Collection): XRecyclerAdapter<*, *> {
70 | mHasLoad = true
71 | return super.refresh(collection)
72 | }
73 |
74 | /**
75 | * 资源释放,防止内存泄漏
76 | */
77 | fun recycle() {
78 | for (broccoli in mBroccoliMap.values) {
79 | broccoli.removeAllPlaceholders()
80 | }
81 | mBroccoliMap.clear()
82 | clear()
83 | }
84 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/xuexiang/templateproject/adapter/base/broccoli/BroccoliSimpleDelegateAdapter.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2021 xuexiangjys(xuexiangjys@163.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 | package com.xuexiang.templateproject.adapter.base.broccoli
18 |
19 | import android.view.View
20 | import com.alibaba.android.vlayout.LayoutHelper
21 | import com.xuexiang.templateproject.adapter.base.delegate.SimpleDelegateAdapter
22 | import com.xuexiang.templateproject.adapter.base.delegate.XDelegateAdapter
23 | import com.xuexiang.xui.adapter.recyclerview.RecyclerViewHolder
24 | import me.samlss.broccoli.Broccoli
25 |
26 | /**
27 | * 使用Broccoli占位的基础适配器
28 | *
29 | * @author xuexiang
30 | * @since 2021/1/9 4:52 PM
31 | */
32 | abstract class BroccoliSimpleDelegateAdapter : SimpleDelegateAdapter {
33 | /**
34 | * 是否已经加载成功
35 | */
36 | private var mHasLoad = false
37 | private val mBroccoliMap: MutableMap = HashMap()
38 |
39 | constructor(layoutId: Int, layoutHelper: LayoutHelper) : super(layoutId, layoutHelper)
40 | constructor(layoutId: Int, layoutHelper: LayoutHelper, list: Collection?) : super(
41 | layoutId,
42 | layoutHelper,
43 | list
44 | )
45 |
46 | constructor(layoutId: Int, layoutHelper: LayoutHelper, data: Array?) : super(
47 | layoutId,
48 | layoutHelper,
49 | data
50 | )
51 |
52 | override fun bindData(holder: RecyclerViewHolder, position: Int, item: T) {
53 | var broccoli = mBroccoliMap[holder.itemView]
54 | if (broccoli == null) {
55 | broccoli = Broccoli()
56 | mBroccoliMap[holder.itemView] = broccoli
57 | }
58 | if (mHasLoad) {
59 | broccoli.removeAllPlaceholders()
60 | onBindData(holder, item, position)
61 | } else {
62 | onBindBroccoli(holder, broccoli)
63 | broccoli.show()
64 | }
65 | }
66 |
67 | /**
68 | * 绑定控件
69 | *
70 | * @param holder
71 | * @param model
72 | * @param position
73 | */
74 | protected abstract fun onBindData(holder: RecyclerViewHolder, model: T, position: Int)
75 |
76 | /**
77 | * 绑定占位控件
78 | *
79 | * @param holder
80 | * @param broccoli
81 | */
82 | protected abstract fun onBindBroccoli(holder: RecyclerViewHolder, broccoli: Broccoli)
83 |
84 | override fun refresh(collection: Collection?): XDelegateAdapter<*, *> {
85 | mHasLoad = true
86 | return super.refresh(collection)
87 | }
88 |
89 | /**
90 | * 资源释放,防止内存泄漏
91 | */
92 | fun recycle() {
93 | for (broccoli in mBroccoliMap.values) {
94 | broccoli.removeAllPlaceholders()
95 | }
96 | mBroccoliMap.clear()
97 | clear()
98 | }
99 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/xuexiang/templateproject/adapter/base/delegate/BaseDelegateAdapter.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 xuexiangjys(xuexiangjys@163.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 | package com.xuexiang.templateproject.adapter.base.delegate
18 |
19 | import android.view.ViewGroup
20 | import com.xuexiang.xui.adapter.recyclerview.RecyclerViewHolder
21 |
22 | /**
23 | * 通用的DelegateAdapter适配器
24 | *
25 | * @author xuexiang
26 | * @since 2020/3/20 12:44 AM
27 | */
28 | abstract class BaseDelegateAdapter : XDelegateAdapter {
29 | constructor() : super() {}
30 | constructor(list: Collection?) : super(list) {}
31 | constructor(data: Array?) : super(data) {}
32 |
33 | /**
34 | * 适配的布局
35 | *
36 | * @param viewType
37 | * @return
38 | */
39 | protected abstract fun getItemLayoutId(viewType: Int): Int
40 | override fun getViewHolder(parent: ViewGroup, viewType: Int): RecyclerViewHolder {
41 | return RecyclerViewHolder(inflateView(parent, getItemLayoutId(viewType)))
42 | }
43 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/xuexiang/templateproject/adapter/base/delegate/SimpleDelegateAdapter.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 xuexiangjys(xuexiangjys@163.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 | package com.xuexiang.templateproject.adapter.base.delegate
18 |
19 | import com.alibaba.android.vlayout.LayoutHelper
20 |
21 | /**
22 | * 简易DelegateAdapter适配器
23 | *
24 | * @author xuexiang
25 | * @since 2020/3/20 12:55 AM
26 | */
27 | abstract class SimpleDelegateAdapter : BaseDelegateAdapter {
28 | private var mLayoutId: Int
29 | private var mLayoutHelper: LayoutHelper
30 |
31 | constructor(layoutId: Int, layoutHelper: LayoutHelper) : super() {
32 | mLayoutId = layoutId
33 | mLayoutHelper = layoutHelper
34 | }
35 |
36 | constructor(layoutId: Int, layoutHelper: LayoutHelper, list: Collection?) : super(list) {
37 | mLayoutId = layoutId
38 | mLayoutHelper = layoutHelper
39 | }
40 |
41 | constructor(layoutId: Int, layoutHelper: LayoutHelper, data: Array?) : super(data) {
42 | mLayoutId = layoutId
43 | mLayoutHelper = layoutHelper
44 | }
45 |
46 | override fun getItemLayoutId(viewType: Int): Int {
47 | return mLayoutId
48 | }
49 |
50 | override fun onCreateLayoutHelper(): LayoutHelper {
51 | return mLayoutHelper
52 | }
53 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/xuexiang/templateproject/adapter/base/delegate/SingleDelegateAdapter.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 xuexiangjys(xuexiangjys@163.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 | package com.xuexiang.templateproject.adapter.base.delegate
18 |
19 | import android.view.LayoutInflater
20 | import android.view.View
21 | import android.view.ViewGroup
22 | import androidx.annotation.LayoutRes
23 | import com.alibaba.android.vlayout.DelegateAdapter
24 | import com.alibaba.android.vlayout.LayoutHelper
25 | import com.alibaba.android.vlayout.layout.SingleLayoutHelper
26 | import com.xuexiang.xui.adapter.recyclerview.RecyclerViewHolder
27 |
28 | /**
29 | * 单独布局的DelegateAdapter
30 | *
31 | * @author xuexiang
32 | * @since 2020/3/20 1:04 AM
33 | */
34 | abstract class SingleDelegateAdapter(private val mLayoutId: Int) :
35 | DelegateAdapter.Adapter() {
36 | override fun onCreateLayoutHelper(): LayoutHelper {
37 | return SingleLayoutHelper()
38 | }
39 |
40 | /**
41 | * 加载布局获取控件
42 | *
43 | * @param parent 父布局
44 | * @param layoutId 布局ID
45 | * @return
46 | */
47 | protected fun inflateView(parent: ViewGroup, @LayoutRes layoutId: Int): View {
48 | return LayoutInflater.from(parent.context).inflate(layoutId, parent, false)
49 | }
50 |
51 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerViewHolder {
52 | return RecyclerViewHolder(inflateView(parent, mLayoutId))
53 | }
54 |
55 | override fun getItemCount(): Int {
56 | return 1
57 | }
58 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/xuexiang/templateproject/core/BaseContainerFragment.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019 xuexiangjys(xuexiangjys@163.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *
16 | */
17 | package com.xuexiang.templateproject.core
18 |
19 | import android.content.res.Configuration
20 | import android.view.View
21 | import android.view.ViewGroup
22 | import android.widget.AdapterView
23 | import com.umeng.analytics.MobclickAgent
24 | import com.xuexiang.xaop.annotation.SingleClick
25 | import com.xuexiang.xpage.base.XPageContainerListFragment
26 | import com.xuexiang.xui.widget.actionbar.TitleBar
27 | import com.xuexiang.xui.widget.actionbar.TitleUtils
28 | import java.util.*
29 |
30 | /**
31 | * 修改列表样式为主副标题显示
32 | *
33 | * @author xuexiang
34 | * @since 2018/11/22 上午11:26
35 | */
36 | abstract class BaseContainerFragment : XPageContainerListFragment() {
37 | override fun initPage() {
38 | initTitle()
39 | initViews()
40 | initListeners()
41 | }
42 |
43 | private fun initTitle(): TitleBar {
44 | return TitleUtils.addTitleBarDynamic(
45 | toolbarContainer,
46 | pageTitle
47 | ) { popToBack() }
48 | }
49 |
50 | override fun initData() {
51 | mSimpleData = initSimpleData(mSimpleData)
52 | val data: MutableList