├── .gitignore ├── .idea ├── caches │ └── build_file_checksums.ser ├── codeStyles │ └── Project.xml ├── gradle.xml ├── markdown-navigator │ └── profiles_settings.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro ├── release │ ├── 始终_1.0.2_release.apk │ └── 始终_1.apk └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── zhangke │ │ └── shizhong │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── zhangke │ │ │ └── shizhong │ │ │ ├── common │ │ │ ├── APPConfig.java │ │ │ ├── ApiStores.java │ │ │ ├── AppClient.java │ │ │ ├── CustomFragmentPagerAdapter.java │ │ │ ├── NetWorkResponseListener.java │ │ │ └── SZApplication.java │ │ │ ├── contract │ │ │ ├── application │ │ │ │ └── IApplicationStatisticContract.java │ │ │ ├── plan │ │ │ │ ├── IClockPlanDetailContract.java │ │ │ │ ├── IEditPlanContract.java │ │ │ │ ├── IRationPlanDetailContract.java │ │ │ │ └── IShowPlanContract.java │ │ │ ├── poster │ │ │ │ ├── IInputNameContract.java │ │ │ │ ├── IShowMoviePosterContract.java │ │ │ │ ├── IShowMusicAlbumContract.java │ │ │ │ └── IShowMusicPosterContract.java │ │ │ └── todo │ │ │ │ ├── ICompletedTodoContract.java │ │ │ │ └── IShowTodoContract.java │ │ │ ├── db │ │ │ ├── ApplicationInfo.java │ │ │ ├── ApplicationInfoDao.java │ │ │ ├── ClockPlan.java │ │ │ ├── ClockPlanDao.java │ │ │ ├── ClockRecord.java │ │ │ ├── ClockRecordDao.java │ │ │ ├── DBManager.java │ │ │ ├── DaoMaster.java │ │ │ ├── DaoSession.java │ │ │ ├── RationPlan.java │ │ │ ├── RationPlanDao.java │ │ │ ├── RationRecord.java │ │ │ ├── RationRecordDao.java │ │ │ ├── Todo.java │ │ │ └── TodoDao.java │ │ │ ├── event │ │ │ ├── PlanChangedEvent.java │ │ │ ├── PlanSelectedEvent.java │ │ │ ├── PosterHideChangedEvent.java │ │ │ ├── ThemeChangedEvent.java │ │ │ └── TodoChangedEvent.java │ │ │ ├── model │ │ │ ├── other │ │ │ │ └── MonthSalaryEntity.java │ │ │ ├── plan │ │ │ │ ├── EditPlanDataEntity.java │ │ │ │ └── ShowPlanEntity.java │ │ │ ├── poster │ │ │ │ ├── DoubanSearchResultUserBean.java │ │ │ │ ├── GlideLoadBitmap.java │ │ │ │ ├── ILoadBitmap.java │ │ │ │ ├── InputNameModel.java │ │ │ │ ├── MoviePosterBean.java │ │ │ │ ├── MusicAlbumBean.java │ │ │ │ ├── MusicPosterBean.java │ │ │ │ ├── MusicSearchResultUserBean.java │ │ │ │ ├── ShowMoviePosterModel.java │ │ │ │ ├── ShowMusicAlbumModel.java │ │ │ │ ├── ShowMusicPosterModel.java │ │ │ │ └── UserBean.java │ │ │ └── todo │ │ │ │ └── ShowTodoEntity.java │ │ │ ├── page │ │ │ ├── application │ │ │ │ ├── ApplicationListAdapter.java │ │ │ │ ├── ApplicationStatisticsActivity.java │ │ │ │ └── SearchApplicationActivity.java │ │ │ ├── base │ │ │ │ ├── BaseActivity.java │ │ │ │ ├── BaseFragment.java │ │ │ │ ├── BaseRecyclerAdapter.java │ │ │ │ └── IBasePage.java │ │ │ ├── main │ │ │ │ ├── LaunchActivity.java │ │ │ │ ├── MainActivity.java │ │ │ │ └── SettingFragment.java │ │ │ ├── other │ │ │ │ ├── AboutActivity.java │ │ │ │ ├── MonthSalaryAdapter.java │ │ │ │ ├── QRCodeActivity.java │ │ │ │ ├── ShowQRCodeContentActivity.java │ │ │ │ ├── TaxCalculationActivity.java │ │ │ │ └── WifiInfoActivity.java │ │ │ ├── plan │ │ │ │ ├── AddPlanActivity.java │ │ │ │ ├── AddPlanFragment.java │ │ │ │ ├── ChoosePlanTypeFragment.java │ │ │ │ ├── ClockPlanDetailActivity.java │ │ │ │ ├── ClockPlanDetailAdapter.java │ │ │ │ ├── EditPlanActivity.java │ │ │ │ ├── RationPlanDetailActivity.java │ │ │ │ ├── RationPlanDetailAdapter.java │ │ │ │ ├── ShowPlanAdapter.java │ │ │ │ └── ShowPlanFragment.java │ │ │ ├── poster │ │ │ │ ├── InputNameActivity.java │ │ │ │ ├── MoviePosterAdapter.java │ │ │ │ ├── MusicAlbumAdapter.java │ │ │ │ ├── MusicPosterAdapter.java │ │ │ │ ├── SearchResultActivity.java │ │ │ │ ├── ShowMoviePosterActivity.java │ │ │ │ ├── ShowMusicAlbumActivity.java │ │ │ │ ├── ShowMusicPosterActivity.java │ │ │ │ └── UserAdapter.java │ │ │ └── todo │ │ │ │ ├── AddTodoActivity.java │ │ │ │ ├── CompletedTodoActivity.java │ │ │ │ ├── ShowTodoAdapter.java │ │ │ │ └── ShowTodoFragment.java │ │ │ ├── presenter │ │ │ ├── application │ │ │ │ └── ApplicationStatisticPresenterImpl.java │ │ │ ├── plan │ │ │ │ ├── ClockPlanDetailPresenter.java │ │ │ │ ├── EditPlanPresenterImpl.java │ │ │ │ ├── PlanHelper.java │ │ │ │ ├── RationPlanDetailPresenterImpl.java │ │ │ │ └── ShowPlanPresenterImpl.java │ │ │ ├── poster │ │ │ │ └── InputNamePresenter.java │ │ │ └── todo │ │ │ │ ├── CompletedTodoPresenterImpl.java │ │ │ │ └── ShowTodoPresenterImpl.java │ │ │ ├── service │ │ │ └── ProcessPlanService.java │ │ │ ├── util │ │ │ ├── ApplicationInfoUtil.java │ │ │ ├── CrashHandler.java │ │ │ ├── DateTimePickerHelper.java │ │ │ ├── DateUtils.java │ │ │ ├── FileUtils.java │ │ │ ├── GlideCircleTransform.java │ │ │ ├── HanziToPinyin.java │ │ │ ├── HttpObserver.java │ │ │ ├── HttpUtils.java │ │ │ ├── ISaveFileEngine.java │ │ │ ├── NumberFormatUtil.java │ │ │ ├── NumberUtil.java │ │ │ ├── PermissionUtil.java │ │ │ ├── PosterUtils.java │ │ │ ├── SaveFileEngine.java │ │ │ ├── SimpleTextWatcher.java │ │ │ ├── TaxHelper.java │ │ │ ├── ThemeUtils.java │ │ │ ├── ThreadPool.java │ │ │ ├── UiUtils.java │ │ │ └── WifiManage.java │ │ │ └── widget │ │ │ ├── CircleImageView.java │ │ │ ├── CountDownTextView.java │ │ │ ├── CustomAutoCompleteTextView.java │ │ │ ├── MultiItemLayoutManger.java │ │ │ ├── NoScrollViewPager.java │ │ │ ├── NumberProgressBar.java │ │ │ ├── PullToRefreshRecyclerView.java │ │ │ ├── RippleAnimationView.java │ │ │ ├── RoundProgressDialog.java │ │ │ ├── SemicircleProgressView.java │ │ │ └── SpacesItemDecoration.java │ └── res │ │ ├── anim │ │ ├── dialog_show_scale.xml │ │ ├── dismiss.xml │ │ ├── item_anim_right_to_left.xml │ │ ├── layout_anim_right_to_left.xml │ │ ├── right_to_left_in.xml │ │ ├── show.xml │ │ ├── slogan_01.xml │ │ └── slogan_02.xml │ │ ├── drawable │ │ ├── arrow_down.xml │ │ ├── common_btn_bg.xml │ │ ├── custom_progress_color.xml │ │ ├── svg_add.xml │ │ ├── svg_add_light.xml │ │ ├── svg_completed.xml │ │ ├── svg_delete.xml │ │ ├── svg_edit.xml │ │ ├── svg_edit_light.xml │ │ ├── svg_extend.xml │ │ ├── svg_home.xml │ │ ├── svg_search.xml │ │ ├── svg_todo.xml │ │ ├── tab_top_line.xml │ │ └── toolbar_bottom_line.xml │ │ ├── layout │ │ ├── activity_add_plan.xml │ │ ├── activity_add_todo.xml │ │ ├── activity_application_statistics.xml │ │ ├── activity_clock_plan_detail.xml │ │ ├── activity_complete_todo.xml │ │ ├── activity_edit_plan.xml │ │ ├── activity_input_name.xml │ │ ├── activity_launch.xml │ │ ├── activity_main.xml │ │ ├── activity_qr_code.xml │ │ ├── activity_ration_plan_detail.xml │ │ ├── activity_search_application.xml │ │ ├── activity_search_result.xml │ │ ├── activity_show_music_album.xml │ │ ├── activity_show_music_poster.xml │ │ ├── activity_show_qr_code_content.xml │ │ ├── activity_tax_calulation.xml │ │ ├── activity_wifi_info.xml │ │ ├── adapter_add_plan.xml │ │ ├── adapter_add_todo.xml │ │ ├── adapter_clock_plan_detail.xml │ │ ├── adapter_double_list.xml │ │ ├── adapter_month_salary.xml │ │ ├── adapter_movie_poster.xml │ │ ├── adapter_music_album_banner.xml │ │ ├── adapter_music_album_menu.xml │ │ ├── adapter_music_album_title.xml │ │ ├── adapter_ration_plan_detail.xml │ │ ├── adapter_search_result.xml │ │ ├── adapter_show_clock_plan.xml │ │ ├── adapter_show_ration_plan.xml │ │ ├── adapter_show_todo.xml │ │ ├── adapter_single_list.xml │ │ ├── dialog_add_period_plan.xml │ │ ├── dialog_clock.xml │ │ ├── dialog_poster_input_people_id.xml │ │ ├── dialog_ration_clock.xml │ │ ├── dialog_show_music_poster.xml │ │ ├── dialog_todo_option.xml │ │ ├── fragment_add_plan.xml │ │ ├── fragment_choose_plan_type.xml │ │ ├── fragment_setting.xml │ │ ├── fragment_show.xml │ │ ├── fragment_show_todo.xml │ │ ├── toolbar.xml │ │ └── view_pull_to_refresh_recycler.xml │ │ ├── menu │ │ ├── application_statistic_menu.xml │ │ ├── edit_menu.xml │ │ ├── plan_detail_menu.xml │ │ ├── search_application_menu.xml │ │ └── show_todo_menu.xml │ │ ├── mipmap-xhdpi │ │ ├── arrow.png │ │ ├── back_white.png │ │ ├── double_line.png │ │ ├── download.png │ │ ├── finish_date.png │ │ ├── logo.png │ │ ├── mine_icon.jpg │ │ ├── plan_current.png │ │ ├── plan_description.png │ │ ├── plan_name.png │ │ ├── plan_target.png │ │ ├── plan_unit.png │ │ ├── round_logo.png │ │ ├── sign_line.png │ │ ├── slogan01.png │ │ ├── slogan02.png │ │ └── start_date.png │ │ └── values │ │ ├── attrs.xml │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── zhangke │ └── shizhong │ ├── ExampleUnitTest.java │ └── util │ └── PosterUtilsTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── screenshots ├── clock_plan_detail.jpg ├── hunger.jpg ├── qrcode_for_account.jpg ├── qrcode_for_gsubscription.jpg ├── ration_plan_detail.jpg ├── setting.jpg ├── show_plan.jpg └── show_todo.jpg └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | -------------------------------------------------------------------------------- /.idea/caches/build_file_checksums.ser: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xZhangKe/ShiZhong/4474335bc38f2ba4d2343f0d52a93d985e764c26/.idea/caches/build_file_checksums.ser -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | 16 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/markdown-navigator/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 27 | 28 | 29 | 30 | 31 | 32 | 34 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 ZhangKe 2 | 3 | 996 License Version 1.0 (Draft) 4 | 5 | Permission is hereby granted to any individual or legal entity 6 | obtaining a copy of this licensed work (including the source code, 7 | documentation and/or related items, hereinafter collectively referred 8 | to as the "licensed work"), free of charge, to deal with the licensed 9 | work for any purpose, including without limitation, the rights to use, 10 | reproduce, modify, prepare derivative works of, distribute, publish 11 | and sublicense the licensed work, subject to the following conditions: 12 | 13 | 1. The individual or the legal entity must conspicuously display, 14 | without modification, this License and the notice on each redistributed 15 | or derivative copy of the Licensed Work. 16 | 17 | 2. The individual or the legal entity must strictly comply with all 18 | applicable laws, regulations, rules and standards of the jurisdiction 19 | relating to labor and employment where the individual is physically 20 | located or where the individual was born or naturalized; or where the 21 | legal entity is registered or is operating (whichever is stricter). In 22 | case that the jurisdiction has no such laws, regulations, rules and 23 | standards or its laws, regulations, rules and standards are 24 | unenforceable, the individual or the legal entity are required to 25 | comply with Core International Labor Standards. 26 | 27 | 3. The individual or the legal entity shall not induce or force its 28 | employee(s), whether full-time or part-time, or its independent 29 | contractor(s), in any methods, to agree in oral or written form, to 30 | directly or indirectly restrict, weaken or relinquish his or her 31 | rights or remedies under such laws, regulations, rules and standards 32 | relating to labor and employment as mentioned above, no matter whether 33 | such written or oral agreement are enforceable under the laws of the 34 | said jurisdiction, nor shall such individual or the legal entity 35 | limit, in any methods, the rights of its employee(s) or independent 36 | contractor(s) from reporting or complaining to the copyright holder or 37 | relevant authorities monitoring the compliance of the license about 38 | its violation(s) of the said license. 39 | 40 | THE LICENSED WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 41 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 42 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 43 | IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, 44 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 45 | OTHERWISE, ARISING FROM, OUT OF OR IN ANY WAY CONNECTION WITH THE 46 | LICENSED WORK OR THE USE OR OTHER DEALINGS IN THE LICENSED WORK. 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## ShiZhong 2 | 帮助制定及管理一些乱七八糟的计划,同时提供了几个并没什么用的小工具。 3 | 4 | [![996.icu](https://img.shields.io/badge/link-996.icu-red.svg)](https://996.icu) [![LICENSE](https://img.shields.io/badge/license-NPL%20(The%20996%20Prohibited%20License)-blue.svg)](https://github.com/996icu/996.ICU/blob/master/LICENSE) [![HitCount](http://hits.dwyl.io/0xZhangKe/ShiZhong.svg)](http://hits.dwyl.io/0xZhangKe/ShiZhong) 5 | 6 | ## 介绍 7 | 这是一个 Android 平台的 APP,项目基于 RxAndroid+Retrofit+Glide 开发,使用MVP架构(好像大家都喜欢这么写......)。 8 | 9 | 10 | 先看一下这个 APP 截图。 11 | ## 截图 12 | 13 | ![计划列表](screenshots/show_plan.jpg) 14 | 15 | 这个是首页。 16 | 17 | 18 | ![计划详情](screenshots/ration_plan_detail.jpg) 19 | 20 | 这个是定量计划的详情,我在 Material Design 官网上学(抄)的,一个买家秀一个卖家秀。 21 | 22 | 23 | ![计划详情](screenshots/clock_plan_detail.jpg) 24 | 25 | 这个是打卡计划的详情页面。 26 | 27 | 28 | ![TODO列表](screenshots/show_todo.jpg) 29 | 30 | 这个是 TODO 列表(市面上有一万个做 TODO 的 APP。。。),根据时间的紧急度做了颜色渐变。 31 | 32 | 33 | ![设置](screenshots/setting.jpg) 34 | 35 | 设置页面其实真的没啥好设置的。 36 | 37 | ## 技术点 38 | 这个破 APP 也没啥技术难点,挺简单的反正。 39 | 用的是 MVP 架构(真麻烦),里面也有几个 HTTP 接口,用的 RxAndroid+Retrofit,这俩加起来是真的好用,但是 Retrofit 的 baseURL 设置之后就不能更改,这个不太好我觉得,好在网上有很多解决方案,搜一下就有。 40 | 数据库 ORM 用的是 GreenDao。 41 | 代码总共也不多,写的还算是挺整洁的,注释啥的都有。 42 | 43 | ## 地址 44 | 我上架到酷安了,别的没上传,太麻烦了,国内一堆的市场。 45 | 46 | 酷安地址: 47 | https://www.coolapk.com/apk/199335 48 | 49 | 50 | 另外 APK 我也传到 Github 上了(记得点 star 啊): 51 | 52 | https://github.com/0xZhangKe/ShiZhong 53 | 54 | 还有啥问题欢迎给我提 issue,我会尽力改的。 55 | 56 | 如果觉得还不错的话,欢迎关注我的个人公众号,我会不定期发一些干货文章~ 57 | 58 | ![公众号](screenshots/qrcode_for_gsubscription.jpg) 59 | 60 | 也可以加我微信: 61 | 62 | ![公众号](screenshots/qrcode_for_account.jpg) 63 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'org.greenrobot.greendao' 3 | 4 | android { 5 | compileSdkVersion 27 6 | defaultConfig { 7 | applicationId "com.zhangke.shizhong" 8 | minSdkVersion 21 9 | targetSdkVersion 27 10 | versionCode 4 11 | versionName "1.0.3" 12 | multiDexEnabled = true 13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 14 | } 15 | compileOptions { 16 | sourceCompatibility JavaVersion.VERSION_1_8 17 | targetCompatibility JavaVersion.VERSION_1_8 18 | } 19 | buildTypes { 20 | release { 21 | minifyEnabled false 22 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 23 | } 24 | } 25 | packagingOptions { 26 | exclude 'META-INF/rxjava.properties' 27 | } 28 | } 29 | 30 | dependencies { 31 | implementation fileTree(dir: 'libs', include: ['*.jar']) 32 | implementation "com.android.support:appcompat-v7:$supportLibraryVersion" 33 | implementation "com.android.support:cardview-v7:$supportLibraryVersion" 34 | implementation "com.android.support:recyclerview-v7:$supportLibraryVersion" 35 | implementation "com.android.support:design:$supportLibraryVersion" 36 | implementation 'com.android.support:multidex:1.0.3' 37 | implementation 'com.android.support.constraint:constraint-layout:1.1.0' 38 | testImplementation 'junit:junit:4.12' 39 | testImplementation "org.mockito:mockito-core:2.13.0" 40 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 41 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 42 | annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1' 43 | implementation 'com.jakewharton:butterknife:8.8.1' 44 | implementation 'com.alibaba:fastjson:1.2.33' 45 | implementation 'org.greenrobot:eventbus:3.0.0' 46 | implementation 'com.github.bumptech.glide:glide:3.8.0' 47 | implementation 'io.reactivex.rxjava2:rxjava:2.0.1' 48 | implementation 'io.reactivex.rxjava2:rxandroid:2.0.1' 49 | implementation 'com.github.chrisbanes:PhotoView:2.0.0' 50 | implementation 'com.squareup.retrofit2:retrofit:2.4.0' 51 | implementation 'com.squareup.okhttp3:okhttp:3.10.0' 52 | implementation 'com.squareup.okhttp3:logging-interceptor:3.6.0' 53 | implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0' 54 | implementation 'com.squareup.retrofit2:converter-gson:2.3.0' 55 | implementation 'com.github.0xZhangKe:ZLog:3.0' 56 | implementation 'org.greenrobot:greendao:3.2.2' 57 | implementation 'com.haibin:calendarview:3.4.0' 58 | implementation 'com.github.0xZhangKe:QRCodeView:1.3' 59 | implementation 'me.drakeet.support:about:2.0.0' 60 | implementation 'me.drakeet.multitype:multitype:3.3.3' 61 | implementation 'me.drakeet.support:about-extension:2.0.0' 62 | implementation 'com.squareup.picasso:picasso:2.5.2' 63 | implementation 'com.umeng.sdk:common:1.5.0' 64 | implementation 'com.umeng.sdk:analytics:7.5.0' 65 | } 66 | 67 | greendao { 68 | schemaVersion 13 69 | daoPackage 'com.zhangke.shizhong.db' 70 | targetGenDir 'src/main/java' 71 | } 72 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -keep class com.zhangke.shizhong.MonthView { 23 | public (android.content.Context); 24 | } 25 | -keep class com.zhangke.shizhong.WeekBar { 26 | public (android.content.Context); 27 | } 28 | -keep class com.zhangke.shizhong.WeekView { 29 | public (android.content.Context); 30 | } 31 | -keep class com.umeng.** {*;} 32 | -keepclassmembers class * { 33 | public (org.json.JSONObject); 34 | } 35 | -keepclassmembers enum * { 36 | public static **[] values(); 37 | public static ** valueOf(java.lang.String); 38 | } -------------------------------------------------------------------------------- /app/release/始终_1.0.2_release.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xZhangKe/ShiZhong/4474335bc38f2ba4d2343f0d52a93d985e764c26/app/release/始终_1.0.2_release.apk -------------------------------------------------------------------------------- /app/release/始终_1.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xZhangKe/ShiZhong/4474335bc38f2ba4d2343f0d52a93d985e764c26/app/release/始终_1.apk -------------------------------------------------------------------------------- /app/src/androidTest/java/com/zhangke/shizhong/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.zhangke.shizhong", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 56 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/common/ApiStores.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.common; 2 | 3 | import com.zhangke.shizhong.model.poster.DoubanSearchResultUserBean; 4 | import com.zhangke.shizhong.model.poster.MusicSearchResultUserBean; 5 | import com.zhangke.shizhong.model.poster.MusicAlbumBean; 6 | import com.zhangke.shizhong.model.poster.MusicPosterBean; 7 | 8 | import io.reactivex.Observable; 9 | import okhttp3.ResponseBody; 10 | import retrofit2.Response; 11 | import retrofit2.http.GET; 12 | import retrofit2.http.Path; 13 | import retrofit2.http.Query; 14 | 15 | /** 16 | * Server 接口仓库 17 | * Created by ZhangKe on 2018/4/18. 18 | */ 19 | public interface ApiStores { 20 | 21 | /** 22 | * 搜索豆瓣用户 23 | * 24 | * @param q 用户名 25 | * @param start 页码 26 | */ 27 | @GET("j/search?cat=1005") 28 | Observable getMovieUsers(@Query("q") String q, @Query("start") int start); 29 | 30 | /** 31 | * 根据用户ID搜索标记的电影 32 | * 33 | * @param userId 用户ID 34 | * @param start 页码 35 | */ 36 | @GET("people/{userId}/collect?sort=time&rating=all&filter=all&mode=grid") 37 | Observable> getMoviePosters(@Path("userId") String userId, @Query("start") int start); 38 | 39 | /** 40 | * 搜索云音乐用户 41 | * 42 | * @param s 用户名 43 | */ 44 | @GET("cloudmusic/?type=search&search_type=1002") 45 | Observable getMusicUsers(@Query("s") String s); 46 | 47 | /** 48 | * 获取云音乐用户创建的歌单 49 | * 50 | * @param s 用户名 51 | */ 52 | @GET("cloudmusic/?type=search&search_type=1000") 53 | Observable getAlbumWithUser(@Query("s") String s); 54 | 55 | /** 56 | * 获取歌单中的歌曲列表 57 | * 58 | * @param id 歌单id 59 | */ 60 | @GET("cloudmusic/?type=playlist") 61 | Observable getMusicsWithAlbum(@Query("id") String id); 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/common/CustomFragmentPagerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.common; 2 | 3 | import android.support.v4.app.Fragment; 4 | import android.support.v4.app.FragmentManager; 5 | import android.support.v4.app.FragmentPagerAdapter; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | /** 11 | * 用于 ViewPager 的 Adapter 12 | * 13 | * Created by ZhangKe on 2017/11/15. 14 | */ 15 | 16 | public class CustomFragmentPagerAdapter extends FragmentPagerAdapter { 17 | 18 | private List fragmentList = new ArrayList<>(); 19 | 20 | public CustomFragmentPagerAdapter(FragmentManager fm, List fragmentList) { 21 | super(fm); 22 | this.fragmentList = fragmentList; 23 | } 24 | 25 | @Override 26 | public Fragment getItem(int position) { 27 | return fragmentList.get(position); 28 | } 29 | 30 | @Override 31 | public int getCount() { 32 | return fragmentList == null ? 0 : fragmentList.size(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/common/NetWorkResponseListener.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.common; 2 | 3 | /** 4 | * 网络请求响应监听接口 5 | *

6 | * Created by ZhangKe on 2018/4/18. 7 | */ 8 | 9 | public interface NetWorkResponseListener { 10 | 11 | interface OnSuccessResponse { 12 | void onSuccess(T response); 13 | } 14 | 15 | interface OnError { 16 | void onError(String cause); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/common/SZApplication.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.common; 2 | 3 | import android.content.Intent; 4 | import android.content.pm.ApplicationInfo; 5 | import android.support.multidex.MultiDexApplication; 6 | 7 | import com.umeng.analytics.MobclickAgent; 8 | import com.umeng.commonsdk.UMConfigure; 9 | import com.zhangke.shizhong.db.DBManager; 10 | import com.zhangke.shizhong.service.ProcessPlanService; 11 | import com.zhangke.shizhong.util.CrashHandler; 12 | import com.zhangke.shizhong.util.FileUtils; 13 | import com.zhangke.zlog.ZLog; 14 | 15 | /** 16 | * ApplicationInfo 17 | *

18 | * Created by ZhangKe on 2018/4/12. 19 | */ 20 | 21 | public class SZApplication extends MultiDexApplication { 22 | 23 | private static final String TAG = "ZLDApplication"; 24 | private static SZApplication application; 25 | 26 | @Override 27 | public void onCreate() { 28 | super.onCreate(); 29 | application = this; 30 | 31 | ZLog.Init(String.format("%s/log/", FileUtils.getDiskCacheDirPath(this))); 32 | 33 | DBManager.getInstance().init(this); 34 | 35 | if (debug()) { 36 | CrashHandler crashHandler = CrashHandler.getInstance(); 37 | crashHandler.init(this); 38 | } else { 39 | UMConfigure.init(this, UMConfigure.DEVICE_TYPE_PHONE, ""); 40 | UMConfigure.setLogEnabled(debug()); 41 | MobclickAgent.setScenarioType(this, MobclickAgent.EScenarioType.E_UM_NORMAL); 42 | } 43 | 44 | startService(new Intent(this, ProcessPlanService.class)); 45 | } 46 | 47 | public static SZApplication getInstance() { 48 | return application; 49 | } 50 | 51 | public static boolean debug() { 52 | try { 53 | ApplicationInfo info = getInstance().getApplicationInfo(); 54 | return (info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; 55 | } catch (Exception e) { 56 | return false; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/contract/application/IApplicationStatisticContract.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.contract.application; 2 | 3 | import com.zhangke.shizhong.db.ApplicationInfo; 4 | import com.zhangke.shizhong.page.base.IBasePage; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * APP统计 10 | * 11 | * Created by ZhangKe on 2018/4/26. 12 | */ 13 | 14 | public interface IApplicationStatisticContract { 15 | 16 | interface View extends IBasePage{ 17 | void notifyDataChanged(List list); 18 | void showTitleProgress(); 19 | void closeTitleProgress(); 20 | } 21 | 22 | interface Presenter{ 23 | /** 24 | * 是否显示系统APP 25 | */ 26 | void getApplication(boolean showSystem); 27 | 28 | void onDestroy(); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/contract/plan/IClockPlanDetailContract.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.contract.plan; 2 | 3 | import com.zhangke.shizhong.db.ClockPlan; 4 | import com.zhangke.shizhong.db.ClockRecord; 5 | import com.zhangke.shizhong.page.base.IBasePage; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * 打卡计划详情 11 | * 12 | * Created by ZhangKe on 2018/7/29. 13 | */ 14 | public interface IClockPlanDetailContract { 15 | 16 | interface View extends IBasePage{ 17 | void updateClockPlan(ClockPlan clockPlan); 18 | void notifyRecordChanged(List list); 19 | } 20 | 21 | interface Presenter{ 22 | void clearCache(); 23 | void update(String month); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/contract/plan/IEditPlanContract.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.contract.plan; 2 | 3 | import com.zhangke.shizhong.db.ClockPlan; 4 | import com.zhangke.shizhong.db.RationPlan; 5 | import com.zhangke.shizhong.model.plan.EditPlanDataEntity; 6 | import com.zhangke.shizhong.page.base.IBasePage; 7 | 8 | /** 9 | * 修改计划接口约束 10 | * 11 | * Created by ZhangKe on 2018/7/19. 12 | */ 13 | public interface IEditPlanContract { 14 | 15 | interface View extends IBasePage{ 16 | void showRationPlan(); 17 | void showClockPlan(); 18 | void fillRationPlanData(RationPlan plan); 19 | void fillClockPlanData(ClockPlan plan); 20 | 21 | } 22 | 23 | interface Presenter{ 24 | void initDate(long planId, int planType); 25 | void updatePlan(EditPlanDataEntity editData); 26 | void deletePeriod(); 27 | void deletePlan(); 28 | void onDestroy(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/contract/plan/IRationPlanDetailContract.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.contract.plan; 2 | 3 | import com.zhangke.shizhong.db.RationPlan; 4 | import com.zhangke.shizhong.db.RationRecord; 5 | import com.zhangke.shizhong.page.base.IBasePage; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * 定量计划详情 11 | * 12 | * Created by ZhangKe on 2018/7/26. 13 | */ 14 | public interface IRationPlanDetailContract { 15 | 16 | interface View extends IBasePage{ 17 | void fillRationPlanData(RationPlan rationPlan); 18 | void notifyDataChanged(List list); 19 | } 20 | 21 | interface Presenter{ 22 | void update(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/contract/plan/IShowPlanContract.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.contract.plan; 2 | 3 | import com.zhangke.shizhong.model.plan.ShowPlanEntity; 4 | import com.zhangke.shizhong.page.base.IBasePage; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * 显示计划界面的接口及业务逻辑约束类 10 | * 11 | * Created by ZhangKe on 2018/5/9. 12 | */ 13 | 14 | public interface IShowPlanContract { 15 | 16 | interface View extends IBasePage{ 17 | void notifyPlanDataChanged(List planList); 18 | } 19 | 20 | interface Presenter{ 21 | void getPlanData(); 22 | void onDestroy(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/contract/poster/IInputNameContract.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.contract.poster; 2 | 3 | import com.zhangke.shizhong.common.NetWorkResponseListener; 4 | import com.zhangke.shizhong.page.base.IBasePage; 5 | import com.zhangke.shizhong.model.poster.UserBean; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * 搜索姓名界面的接口 11 | *

12 | * Created by ZhangKe on 2018/4/17. 13 | */ 14 | 15 | public interface IInputNameContract { 16 | 17 | interface View extends IBasePage { 18 | 19 | void notifyUserListChanged(List list); 20 | 21 | /** 22 | * 关闭上拉加载进度框 23 | */ 24 | void closeLoadMoreView(); 25 | } 26 | 27 | interface Presenter { 28 | /** 29 | * 通过姓名搜索用户 30 | */ 31 | void searchUserFromName(String name); 32 | 33 | /** 34 | * 加载下一页 35 | */ 36 | void loadMore(); 37 | 38 | void clearUsers(); 39 | } 40 | 41 | interface Model { 42 | void reset(); 43 | void getDoubanUsers(String name, 44 | NetWorkResponseListener.OnSuccessResponse> successResponseListener, 45 | NetWorkResponseListener.OnError onErrorListener); 46 | void get163MusicUsers(String name, 47 | NetWorkResponseListener.OnSuccessResponse> successResponseListener, 48 | NetWorkResponseListener.OnError onErrorListener); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/contract/poster/IShowMoviePosterContract.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.contract.poster; 2 | 3 | import com.zhangke.shizhong.page.base.IBasePage; 4 | import com.zhangke.shizhong.model.poster.MoviePosterBean; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * 电影海报模块约束类 10 | *

11 | * Created by ZhangKe on 2018/4/22. 12 | */ 13 | 14 | public interface IShowMoviePosterContract { 15 | 16 | interface View extends IBasePage { 17 | /** 18 | * 通知 View 海报数据发生变化 19 | */ 20 | void notifyDataChanged(List list); 21 | } 22 | 23 | interface Model { 24 | /** 25 | * 根据 UserId 获取海报数据 26 | */ 27 | void getMoviePoster(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/contract/poster/IShowMusicAlbumContract.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.contract.poster; 2 | 3 | import com.zhangke.shizhong.page.base.IBasePage; 4 | import com.zhangke.shizhong.model.poster.MusicAlbumBean; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * 云音乐专辑约束接口 10 | * Created by ZhangKe on 2018/4/23. 11 | */ 12 | 13 | public interface IShowMusicAlbumContract { 14 | 15 | interface View extends IBasePage{ 16 | void notifyDataChanged(List list); 17 | } 18 | 19 | interface Model{ 20 | void getAlbum(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/contract/poster/IShowMusicPosterContract.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.contract.poster; 2 | 3 | import com.zhangke.shizhong.page.base.IBasePage; 4 | import com.zhangke.shizhong.model.poster.MusicPosterBean; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * 显示云音乐海报 10 | *

11 | * Created by ZhangKe on 2018/4/24. 12 | */ 13 | 14 | public interface IShowMusicPosterContract { 15 | 16 | interface View extends IBasePage { 17 | /** 18 | * 通知 View 海报数据发生变化 19 | */ 20 | void notifyDataChanged(List list); 21 | } 22 | 23 | interface Model { 24 | /** 25 | * 根据 UserId 获取海报数据 26 | */ 27 | void getMusicPoster(); 28 | 29 | /** 30 | * 下载图片 31 | */ 32 | void downloadImage(MusicPosterBean.PlaylistBean.TracksBean bean); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/contract/todo/ICompletedTodoContract.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.contract.todo; 2 | 3 | import com.zhangke.shizhong.model.todo.ShowTodoEntity; 4 | import com.zhangke.shizhong.page.base.IBasePage; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * 已完成的待办事项 10 | * 11 | * Created by ZhangKe on 2018/7/28. 12 | */ 13 | public interface ICompletedTodoContract { 14 | 15 | interface View extends IBasePage { 16 | void notifyTodoChanged(List todoList); 17 | } 18 | 19 | interface Presenter{ 20 | void update(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/contract/todo/IShowTodoContract.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.contract.todo; 2 | 3 | import com.zhangke.shizhong.db.Todo; 4 | import com.zhangke.shizhong.model.todo.ShowTodoEntity; 5 | import com.zhangke.shizhong.page.base.IBasePage; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * 待办事项 11 | *

12 | * Created by ZhangKe on 2018/7/23. 13 | */ 14 | public interface IShowTodoContract { 15 | 16 | interface View extends IBasePage{ 17 | void notifyTodoChanged(List todoList); 18 | } 19 | 20 | interface Presenter{ 21 | void update(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/db/ApplicationInfo.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.db; 2 | 3 | import android.graphics.drawable.Drawable; 4 | 5 | import org.greenrobot.greendao.annotation.Entity; 6 | import org.greenrobot.greendao.annotation.Id; 7 | import org.greenrobot.greendao.annotation.Transient; 8 | import org.greenrobot.greendao.annotation.Generated; 9 | 10 | /** 11 | * APP 数据实体 12 | * Created by ZhangKe on 2018/4/26. 13 | */ 14 | @Entity 15 | public class ApplicationInfo implements Comparable { 16 | 17 | private String appName; // 应用名 18 | @Id 19 | private String packageName; // 包名 20 | private String versionName; // 版本名 21 | private int versionCode = 0; // 版本号 22 | 23 | @Transient 24 | private Drawable appIcon = null; // 应用图标 25 | private String sortTarget; 26 | private boolean isSystemApp = false; 27 | 28 | @Generated(hash = 126628142) 29 | public ApplicationInfo() { 30 | } 31 | 32 | @Generated(hash = 1018086381) 33 | public ApplicationInfo(String appName, String packageName, String versionName, 34 | int versionCode, String sortTarget, boolean isSystemApp) { 35 | this.appName = appName; 36 | this.packageName = packageName; 37 | this.versionName = versionName; 38 | this.versionCode = versionCode; 39 | this.sortTarget = sortTarget; 40 | this.isSystemApp = isSystemApp; 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return appName + " , " + packageName + " ," + versionName + " ," + versionCode; 46 | } 47 | 48 | @Override 49 | public int compareTo(ApplicationInfo arg0) { 50 | return this.sortTarget.compareTo(arg0.sortTarget); 51 | } 52 | 53 | public Drawable getAppIcon() { 54 | return appIcon; 55 | } 56 | 57 | public void setAppIcon(Drawable appIcon) { 58 | this.appIcon = appIcon; 59 | } 60 | 61 | public String getAppName() { 62 | return this.appName; 63 | } 64 | 65 | public void setAppName(String appName) { 66 | this.appName = appName; 67 | } 68 | 69 | public String getPackageName() { 70 | return this.packageName; 71 | } 72 | 73 | public void setPackageName(String packageName) { 74 | this.packageName = packageName; 75 | } 76 | 77 | public String getVersionName() { 78 | return this.versionName; 79 | } 80 | 81 | public void setVersionName(String versionName) { 82 | this.versionName = versionName; 83 | } 84 | 85 | public int getVersionCode() { 86 | return this.versionCode; 87 | } 88 | 89 | public void setVersionCode(int versionCode) { 90 | this.versionCode = versionCode; 91 | } 92 | 93 | public String getSortTarget() { 94 | return this.sortTarget; 95 | } 96 | 97 | public void setSortTarget(String sortTarget) { 98 | this.sortTarget = sortTarget; 99 | } 100 | 101 | public boolean getIsSystemApp() { 102 | return this.isSystemApp; 103 | } 104 | 105 | public void setIsSystemApp(boolean isSystemApp) { 106 | this.isSystemApp = isSystemApp; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/db/ClockRecord.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.db; 2 | 3 | import org.greenrobot.greendao.annotation.Entity; 4 | import org.greenrobot.greendao.annotation.Id; 5 | import org.greenrobot.greendao.annotation.Generated; 6 | 7 | /** 8 | * 打卡计划的打卡记录 9 | * Created by ZhangKe on 2018/7/17. 10 | */ 11 | @Entity 12 | public class ClockRecord { 13 | 14 | @Id(autoincrement = true) 15 | private Long id; 16 | private Long parentPlanId; 17 | /** 18 | * 日期 19 | */ 20 | private String date; 21 | /** 22 | * 备注 23 | */ 24 | private String description; 25 | @Generated(hash = 1334261604) 26 | public ClockRecord(Long id, Long parentPlanId, String date, 27 | String description) { 28 | this.id = id; 29 | this.parentPlanId = parentPlanId; 30 | this.date = date; 31 | this.description = description; 32 | } 33 | @Generated(hash = 675671732) 34 | public ClockRecord() { 35 | } 36 | public Long getId() { 37 | return this.id; 38 | } 39 | public void setId(Long id) { 40 | this.id = id; 41 | } 42 | public Long getParentPlanId() { 43 | return this.parentPlanId; 44 | } 45 | public void setParentPlanId(Long parentPlanId) { 46 | this.parentPlanId = parentPlanId; 47 | } 48 | public String getDate() { 49 | return this.date; 50 | } 51 | public void setDate(String date) { 52 | this.date = date; 53 | } 54 | public String getDescription() { 55 | return this.description; 56 | } 57 | public void setDescription(String description) { 58 | this.description = description; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/db/DBManager.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.db; 2 | 3 | import android.content.Context; 4 | 5 | import com.zhangke.shizhong.common.SZApplication; 6 | 7 | /** 8 | * 数据库管理类 9 | *

10 | * Created by ZhangKe on 2018/4/26. 11 | */ 12 | 13 | public class DBManager { 14 | 15 | private static final String DB_NAME = "data.db"; 16 | private DaoSession daoSession; 17 | 18 | private static DBManager dbManager; 19 | 20 | public static DBManager getInstance() { 21 | if (dbManager == null) { 22 | synchronized (DBManager.class) { 23 | if (dbManager == null) { 24 | dbManager = new DBManager(); 25 | } 26 | } 27 | } 28 | return dbManager; 29 | } 30 | 31 | public void init(Context context) { 32 | DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(context, DB_NAME); 33 | 34 | DaoMaster daoMaster = new DaoMaster(helper.getWritableDatabase()); 35 | 36 | daoSession = daoMaster.newSession(); 37 | } 38 | 39 | public void clear(){ 40 | daoSession.clear(); 41 | } 42 | 43 | public ApplicationInfoDao getApplicationInfoDao() { 44 | return daoSession.getApplicationInfoDao(); 45 | } 46 | 47 | public RationPlanDao getRationPlanDao() { 48 | return daoSession.getRationPlanDao(); 49 | } 50 | 51 | public RationRecordDao getRationRecordDao(){ 52 | return daoSession.getRationRecordDao(); 53 | } 54 | 55 | public ClockPlanDao getClockPlanDao(){ 56 | return daoSession.getClockPlanDao(); 57 | } 58 | 59 | public ClockRecordDao getClockRecordDao(){ 60 | return daoSession.getClockRecordDao(); 61 | } 62 | 63 | public TodoDao getTodoDao(){ 64 | return daoSession.getTodoDao(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/db/RationRecord.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.db; 2 | 3 | import org.greenrobot.greendao.annotation.Entity; 4 | import org.greenrobot.greendao.annotation.Id; 5 | import org.greenrobot.greendao.annotation.Generated; 6 | 7 | /** 8 | * 短期计划实体 9 | *

10 | * Created by ZhangKe on 2018/5/9. 11 | */ 12 | 13 | @Entity 14 | public class RationRecord { 15 | 16 | @Id(autoincrement = true) 17 | private Long id; 18 | private Long parentPlanId; 19 | private String name; 20 | /** 21 | * 本次完成值 22 | */ 23 | private double value; 24 | /** 25 | * 日期 26 | */ 27 | private String date; 28 | @Generated(hash = 1133326716) 29 | public RationRecord(Long id, Long parentPlanId, String name, double value, 30 | String date) { 31 | this.id = id; 32 | this.parentPlanId = parentPlanId; 33 | this.name = name; 34 | this.value = value; 35 | this.date = date; 36 | } 37 | @Generated(hash = 1984267879) 38 | public RationRecord() { 39 | } 40 | public Long getId() { 41 | return this.id; 42 | } 43 | public void setId(Long id) { 44 | this.id = id; 45 | } 46 | public Long getParentPlanId() { 47 | return this.parentPlanId; 48 | } 49 | public void setParentPlanId(Long parentPlanId) { 50 | this.parentPlanId = parentPlanId; 51 | } 52 | public String getName() { 53 | return this.name; 54 | } 55 | public void setName(String name) { 56 | this.name = name; 57 | } 58 | public double getValue() { 59 | return this.value; 60 | } 61 | public void setValue(double value) { 62 | this.value = value; 63 | } 64 | public String getDate() { 65 | return this.date; 66 | } 67 | public void setDate(String date) { 68 | this.date = date; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/db/Todo.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.db; 2 | 3 | import org.greenrobot.greendao.annotation.Entity; 4 | import org.greenrobot.greendao.annotation.Id; 5 | import org.greenrobot.greendao.annotation.Generated; 6 | 7 | /** 8 | * 待做事项 9 | * 10 | * Created by ZhangKe on 2018/7/23. 11 | */ 12 | @Entity 13 | public class Todo { 14 | 15 | @Id(autoincrement = true) 16 | private Long id; 17 | private String title;//内容 18 | private String date;//日期时间 19 | private boolean completed;//是否已完成 20 | @Generated(hash = 81639775) 21 | public Todo(Long id, String title, String date, boolean completed) { 22 | this.id = id; 23 | this.title = title; 24 | this.date = date; 25 | this.completed = completed; 26 | } 27 | @Generated(hash = 1698043777) 28 | public Todo() { 29 | } 30 | public Long getId() { 31 | return this.id; 32 | } 33 | public void setId(Long id) { 34 | this.id = id; 35 | } 36 | public String getTitle() { 37 | return this.title; 38 | } 39 | public void setTitle(String title) { 40 | this.title = title; 41 | } 42 | public String getDate() { 43 | return this.date; 44 | } 45 | public void setDate(String date) { 46 | this.date = date; 47 | } 48 | public boolean getCompleted() { 49 | return this.completed; 50 | } 51 | public void setCompleted(boolean completed) { 52 | this.completed = completed; 53 | } 54 | 55 | 56 | 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/event/PlanChangedEvent.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.event; 2 | 3 | /** 4 | * 计划数据发生变化事件 5 | * Created by ZhangKe on 2018/5/19. 6 | */ 7 | public class PlanChangedEvent { 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/event/PlanSelectedEvent.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.event; 2 | 3 | /** 4 | * 计划类型选择完成后事件 5 | * Created by ZhangKe on 2018/7/17. 6 | */ 7 | public class PlanSelectedEvent { 8 | 9 | /** 10 | * 0-定量计划 11 | * 1-打卡计划 12 | */ 13 | private int planType; 14 | 15 | public PlanSelectedEvent(int planType) { 16 | this.planType = planType; 17 | } 18 | 19 | /** 20 | * 0-定量计划 21 | * 1-打卡计划 22 | */ 23 | public int getPlanType() { 24 | return planType; 25 | } 26 | 27 | /** 28 | * 0-定量计划 29 | * 1-打卡计划 30 | */ 31 | public void setPlanType(int planType) { 32 | this.planType = planType; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/event/PosterHideChangedEvent.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.event; 2 | 3 | /** 4 | * 海报功能开启状态发生变化事件 5 | * 6 | * Created by ZhangKe on 2018/8/2. 7 | */ 8 | public class PosterHideChangedEvent { 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/event/ThemeChangedEvent.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.event; 2 | 3 | /** 4 | * APP 日间/夜间发生改变事件 5 | * Created by ZhangKe on 2018/5/2. 6 | */ 7 | public class ThemeChangedEvent { 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/event/TodoChangedEvent.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.event; 2 | 3 | /** 4 | * 待办事项数据发生变化 5 | * 6 | * Created by ZhangKe on 2018/7/23. 7 | */ 8 | public class TodoChangedEvent { 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/model/other/MonthSalaryEntity.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.model.other; 2 | 3 | /** 4 | * Created by ZhangKe on 2019/3/15. 5 | */ 6 | public class MonthSalaryEntity { 7 | 8 | private int month; 9 | private double salary; 10 | 11 | public MonthSalaryEntity() { 12 | } 13 | 14 | public MonthSalaryEntity(int month) { 15 | this(month, 0.0); 16 | } 17 | 18 | public MonthSalaryEntity(int month, double salary) { 19 | this.month = month; 20 | this.salary = salary; 21 | } 22 | 23 | public int getMonth() { 24 | return month; 25 | } 26 | 27 | public void setMonth(int month) { 28 | this.month = month; 29 | } 30 | 31 | public double getSalary() { 32 | return salary; 33 | } 34 | 35 | public void setSalary(double salary) { 36 | this.salary = salary; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/model/plan/EditPlanDataEntity.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.model.plan; 2 | 3 | /** 4 | * 修改计划界面使用 5 | * Created by ZhangKe on 2018/7/20. 6 | */ 7 | public class EditPlanDataEntity { 8 | 9 | private String name; 10 | private String finishDate; 11 | private String description; 12 | private double target; 13 | private double current; 14 | private String unit; 15 | private boolean periodIsOpen; 16 | private double periodTarget; 17 | private int periodPlanType; 18 | 19 | public EditPlanDataEntity() { 20 | } 21 | 22 | public EditPlanDataEntity(String name, String finishDate, String description, double target, double current, String unit, boolean periodIsOpen, double periodTarget, int periodPlanType) { 23 | this.name = name; 24 | this.finishDate = finishDate; 25 | this.description = description; 26 | this.target = target; 27 | this.current = current; 28 | this.unit = unit; 29 | this.periodIsOpen = periodIsOpen; 30 | this.periodTarget = periodTarget; 31 | this.periodPlanType = periodPlanType; 32 | } 33 | 34 | public String getName() { 35 | return name; 36 | } 37 | 38 | public void setName(String name) { 39 | this.name = name; 40 | } 41 | 42 | public String getFinishDate() { 43 | return finishDate; 44 | } 45 | 46 | public void setFinishDate(String finishDate) { 47 | this.finishDate = finishDate; 48 | } 49 | 50 | public String getDescription() { 51 | return description; 52 | } 53 | 54 | public void setDescription(String description) { 55 | this.description = description; 56 | } 57 | 58 | public double getTarget() { 59 | return target; 60 | } 61 | 62 | public void setTarget(double target) { 63 | this.target = target; 64 | } 65 | 66 | public double getCurrent() { 67 | return current; 68 | } 69 | 70 | public void setCurrent(double current) { 71 | this.current = current; 72 | } 73 | 74 | public String getUnit() { 75 | return unit; 76 | } 77 | 78 | public void setUnit(String unit) { 79 | this.unit = unit; 80 | } 81 | 82 | public boolean isPeriodIsOpen() { 83 | return periodIsOpen; 84 | } 85 | 86 | public void setPeriodIsOpen(boolean periodIsOpen) { 87 | this.periodIsOpen = periodIsOpen; 88 | } 89 | 90 | public double getPeriodTarget() { 91 | return periodTarget; 92 | } 93 | 94 | public void setPeriodTarget(double periodTarget) { 95 | this.periodTarget = periodTarget; 96 | } 97 | 98 | public int getPeriodPlanType() { 99 | return periodPlanType; 100 | } 101 | 102 | public void setPeriodPlanType(int periodPlanType) { 103 | this.periodPlanType = periodPlanType; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/model/poster/DoubanSearchResultUserBean.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.model.poster; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * 豆瓣接口获取到的数据实体 7 | *

8 | * Created by ZhangKe on 2018/4/18. 9 | */ 10 | 11 | public class DoubanSearchResultUserBean { 12 | private int total; 13 | private int limit; 14 | private boolean more; 15 | private List items; 16 | 17 | public int getTotal() { 18 | return total; 19 | } 20 | 21 | public void setTotal(int total) { 22 | this.total = total; 23 | } 24 | 25 | public int getLimit() { 26 | return limit; 27 | } 28 | 29 | public void setLimit(int limit) { 30 | this.limit = limit; 31 | } 32 | 33 | public boolean isMore() { 34 | return more; 35 | } 36 | 37 | public void setMore(boolean more) { 38 | this.more = more; 39 | } 40 | 41 | public List getItems() { 42 | return items; 43 | } 44 | 45 | public void setItems(List items) { 46 | this.items = items; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/model/poster/GlideLoadBitmap.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.model.poster; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | import android.graphics.drawable.Drawable; 7 | import android.view.View; 8 | import android.widget.ImageView; 9 | 10 | import com.bumptech.glide.Glide; 11 | import com.bumptech.glide.load.engine.DiskCacheStrategy; 12 | import com.bumptech.glide.request.animation.GlideAnimation; 13 | import com.bumptech.glide.request.target.SimpleTarget; 14 | import com.zhangke.shizhong.util.ISaveFileEngine; 15 | 16 | import java.io.File; 17 | 18 | /** 19 | * 使用 Glide 下载图片 20 | * Created by ZhangKe on 2018/4/22. 21 | */ 22 | 23 | public class GlideLoadBitmap implements ILoadBitmap { 24 | 25 | private Context mContext; 26 | private ISaveFileEngine saveFileEngine; 27 | 28 | public GlideLoadBitmap(Context context, ISaveFileEngine saveFileEngine) { 29 | this.mContext = context; 30 | this.saveFileEngine = saveFileEngine; 31 | } 32 | 33 | @Override 34 | public void loadBitmapIntoImageView(final String url, 35 | final ImageView imageView, 36 | final File file) { 37 | if (file.exists()) { 38 | imageView.setImageBitmap(BitmapFactory.decodeFile(file.getPath())); 39 | } else { 40 | SimpleTarget target = new SimpleTarget() { 41 | @Override 42 | public void onResourceReady(Bitmap resource, GlideAnimation glideAnimation) { 43 | imageView.setImageBitmap(resource); 44 | saveFileEngine.addFile(file, resource); 45 | } 46 | 47 | @Override 48 | public void onLoadFailed(Exception e, Drawable errorDrawable) { 49 | super.onLoadFailed(e, errorDrawable); 50 | imageView.setVisibility(View.GONE); 51 | } 52 | }; 53 | Glide.with(mContext) 54 | .load(url) 55 | .asBitmap() 56 | .diskCacheStrategy(DiskCacheStrategy.NONE) 57 | .into(target); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/model/poster/ILoadBitmap.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.model.poster; 2 | 3 | import android.widget.ImageView; 4 | 5 | import java.io.File; 6 | 7 | /** 8 | * 加载图片工具接口 9 | * 10 | * Created by ZhangKe on 2018/4/22. 11 | */ 12 | 13 | public interface ILoadBitmap { 14 | 15 | /** 16 | * 下载指定图片到 ImageView 中,并把这个图片下载到本地磁盘 17 | * 18 | * @param file 将要保存的文件位置 19 | */ 20 | void loadBitmapIntoImageView(String url, 21 | ImageView imageView, 22 | File file); 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/model/poster/MoviePosterBean.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.model.poster; 2 | 3 | /** 4 | * 电影海报数据实体 5 | * Created by ZhangKe on 2018/4/22. 6 | */ 7 | 8 | public class MoviePosterBean { 9 | 10 | private String movieName; 11 | private String movieImageUrl; 12 | 13 | public MoviePosterBean() { 14 | } 15 | 16 | public MoviePosterBean(String movieName, String movieImageUrl) { 17 | this.movieName = movieName; 18 | this.movieImageUrl = movieImageUrl; 19 | } 20 | 21 | public String getMovieName() { 22 | return movieName; 23 | } 24 | 25 | public void setMovieName(String movieName) { 26 | this.movieName = movieName; 27 | } 28 | 29 | public String getMovieImageUrl() { 30 | return movieImageUrl; 31 | } 32 | 33 | public void setMovieImageUrl(String movieImageUrl) { 34 | this.movieImageUrl = movieImageUrl; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/model/todo/ShowTodoEntity.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.model.todo; 2 | 3 | import com.zhangke.shizhong.db.Todo; 4 | 5 | /** 6 | * 显示待办事项 7 | * 8 | * Created by ZhangKe on 2018/7/24. 9 | */ 10 | public class ShowTodoEntity { 11 | 12 | /** 13 | * 0-普通代办事项 14 | * 1-添加 15 | */ 16 | private int type = 0; 17 | /** 18 | * 紧急等级:1-6 19 | * 1-最低 20 | * 6-最高 21 | */ 22 | private int level; 23 | 24 | private Todo todo; 25 | 26 | public ShowTodoEntity() { 27 | } 28 | 29 | public ShowTodoEntity(int type, Todo todo) { 30 | this.type = type; 31 | this.todo = todo; 32 | } 33 | 34 | public int getType() { 35 | return type; 36 | } 37 | 38 | public void setType(int type) { 39 | this.type = type; 40 | } 41 | 42 | public int getLevel() { 43 | return level; 44 | } 45 | 46 | public void setLevel(int level) { 47 | this.level = level; 48 | } 49 | 50 | public Todo getTodo() { 51 | return todo; 52 | } 53 | 54 | public void setTodo(Todo todo) { 55 | this.todo = todo; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/page/application/ApplicationListAdapter.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.page.application; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.NonNull; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.ImageView; 9 | import android.widget.TextView; 10 | 11 | import com.zhangke.shizhong.R; 12 | import com.zhangke.shizhong.db.ApplicationInfo; 13 | import com.zhangke.shizhong.page.base.BaseRecyclerAdapter; 14 | 15 | import java.util.List; 16 | 17 | import butterknife.BindView; 18 | import butterknife.ButterKnife; 19 | 20 | /** 21 | * APP 列表 22 | *

23 | * Created by ZhangKe on 2018/4/26. 24 | */ 25 | 26 | public class ApplicationListAdapter extends BaseRecyclerAdapter { 27 | 28 | private boolean isSingleShow = true;//单排显示 29 | 30 | ApplicationListAdapter(Context context, List listData) { 31 | super(context, listData); 32 | } 33 | 34 | @NonNull 35 | @Override 36 | public AppInfoViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { 37 | return new AppInfoViewHolder( 38 | inflater.inflate( 39 | isSingleShow ? 40 | R.layout.adapter_single_list : 41 | R.layout.adapter_double_list, 42 | parent, 43 | false)); 44 | } 45 | 46 | @Override 47 | public void onBindViewHolder(@NonNull AppInfoViewHolder holder, int position) { 48 | ApplicationInfo info = listData.get(position); 49 | holder.tvDesc.setText(info.getPackageName()); 50 | holder.tvName.setText(info.getAppName()); 51 | holder.imgIcon.setImageDrawable(info.getAppIcon()); 52 | } 53 | 54 | class AppInfoViewHolder extends BaseRecyclerAdapter.ViewHolder { 55 | 56 | @BindView(R.id.img_icon) 57 | ImageView imgIcon; 58 | @BindView(R.id.tv_name) 59 | TextView tvName; 60 | @BindView(R.id.tv_desc) 61 | TextView tvDesc; 62 | 63 | AppInfoViewHolder(View itemView) { 64 | super(itemView); 65 | ButterKnife.bind(this, itemView); 66 | } 67 | } 68 | 69 | public void setSingleShow(boolean singleShow) { 70 | isSingleShow = singleShow; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/page/base/BaseRecyclerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.page.base; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * RecyclerAdapter 简化基类,支持 item 点击事件 12 | * Created by ZhangKe on 2018/4/18. 13 | */ 14 | 15 | public abstract class BaseRecyclerAdapter extends RecyclerView.Adapter { 16 | 17 | protected Context context; 18 | protected List

listData; 19 | protected LayoutInflater inflater; 20 | protected OnRecyclerItemClickListener onItemClickListener; 21 | 22 | public BaseRecyclerAdapter(Context context, List

listData) { 23 | this.context = context; 24 | this.listData = listData; 25 | 26 | inflater = LayoutInflater.from(context); 27 | } 28 | 29 | @Override 30 | public int getItemCount() { 31 | return listData == null ? 0 : listData.size(); 32 | } 33 | 34 | public void setOnItemClickListener(OnRecyclerItemClickListener onItemClickListener) { 35 | this.onItemClickListener = onItemClickListener; 36 | } 37 | 38 | public class ViewHolder extends RecyclerView.ViewHolder { 39 | public ViewHolder(final View itemView) { 40 | super(itemView); 41 | itemView.setOnClickListener(v -> { 42 | if (BaseRecyclerAdapter.this.onItemClickListener != null) { 43 | onItemClickListener.onItemClick(getAdapterPosition()); 44 | } 45 | }); 46 | } 47 | } 48 | 49 | public interface OnRecyclerItemClickListener { 50 | /** 51 | * @param position 点击 position 52 | */ 53 | void onItemClick(int position); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/page/base/IBasePage.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.page.base; 2 | 3 | import android.content.Context; 4 | import android.view.View; 5 | 6 | /** 7 | * BaseActivity 及 BaseFragment 必须提供的方法, 8 | * 这么做除了要统一 Activity 与 Fragment 之外,MVP 模式中也经常需要这么做。 9 | *

10 | * Created by ZhangKe on 2018/4/15. 11 | */ 12 | 13 | public interface IBasePage { 14 | 15 | //使用Intent传递数据时的参数 16 | String INTENT_ARG_01 = "intent_01"; 17 | String INTENT_ARG_02 = "intent_02"; 18 | String INTENT_ARG_03 = "intent_03"; 19 | String INTENT_ARG_04 = "intent_04"; 20 | String INTENT_ARG_05 = "intent_05"; 21 | 22 | void showRoundProgressDialog(); 23 | 24 | void showRoundProgressDialog(String msg); 25 | 26 | void closeRoundProgressDialog(); 27 | 28 | void showToastMessage(String msg); 29 | 30 | /** 31 | * 如果需要调用此方法,布局文件中必须包含 R.id.coordinator 控件 32 | */ 33 | void showNoActionSnackbar(String msg); 34 | 35 | Context getContext(); 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/page/main/LaunchActivity.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.page.main; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.os.Handler; 6 | import android.os.Looper; 7 | import android.support.annotation.Nullable; 8 | import android.view.View; 9 | import android.view.animation.AnimationUtils; 10 | import android.view.animation.DecelerateInterpolator; 11 | import android.view.animation.TranslateAnimation; 12 | import android.widget.ImageView; 13 | 14 | import com.zhangke.shizhong.R; 15 | import com.zhangke.shizhong.page.base.BaseActivity; 16 | import com.zhangke.shizhong.util.UiUtils; 17 | 18 | import butterknife.BindView; 19 | import butterknife.ButterKnife; 20 | 21 | /** 22 | * 启动页面 23 | *

24 | * Created by ZhangKe on 2018/7/29. 25 | */ 26 | public class LaunchActivity extends BaseActivity { 27 | 28 | @BindView(R.id.img_slogan_02) 29 | ImageView imgSlogan02; 30 | @BindView(R.id.img_slogan_01) 31 | ImageView imgSlogan01; 32 | 33 | @Override 34 | protected int getLayoutResId() { 35 | fullScreen(); 36 | return R.layout.activity_launch; 37 | } 38 | 39 | @Override 40 | protected void initView(@Nullable Bundle savedInstanceState) { 41 | ButterKnife.bind(this); 42 | 43 | final TranslateAnimation animation_01 = new TranslateAnimation(0, 0, 0, UiUtils.dip2px(this, 40)); 44 | final TranslateAnimation animation_02 = new TranslateAnimation(0, 0, 0, -UiUtils.dip2px(this, 40)); 45 | setupAnim(animation_01); 46 | setupAnim(animation_02); 47 | 48 | final Handler handler = new Handler(Looper.getMainLooper()); 49 | handler.postDelayed(()->{ 50 | imgSlogan01.setVisibility(View.VISIBLE); 51 | imgSlogan01.startAnimation(animation_01); 52 | handler.postDelayed(()->{ 53 | imgSlogan02.setVisibility(View.VISIBLE); 54 | imgSlogan02.startAnimation(animation_02); 55 | handler.postDelayed(()->{ 56 | startActivity(new Intent(LaunchActivity.this, MainActivity.class)); 57 | finish(); 58 | }, 1000); 59 | }, 400); 60 | }, 300); 61 | } 62 | 63 | private void setupAnim(TranslateAnimation anim){ 64 | anim.setDuration(400); 65 | anim.setFillAfter(true); 66 | anim.setRepeatCount(0); 67 | anim.setInterpolator(new DecelerateInterpolator()); 68 | } 69 | 70 | @Override 71 | protected boolean showImmersionWindowStatus() { 72 | return false; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/page/other/QRCodeActivity.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.page.other; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | import android.support.design.widget.CoordinatorLayout; 7 | import android.support.v7.widget.Toolbar; 8 | import android.view.View; 9 | 10 | import com.google.zxing.Result; 11 | import com.zhangke.qrcodeview.QRCodeView; 12 | import com.zhangke.shizhong.R; 13 | import com.zhangke.shizhong.page.base.BaseActivity; 14 | 15 | import butterknife.BindView; 16 | import butterknife.ButterKnife; 17 | 18 | /** 19 | * 二维码扫描页面 20 | *

21 | * Created by ZhangKe on 2018/8/1. 22 | */ 23 | public class QRCodeActivity extends BaseActivity { 24 | 25 | @BindView(R.id.toolbar) 26 | Toolbar toolbar; 27 | @BindView(R.id.qr_code) 28 | QRCodeView qrCode; 29 | 30 | @Override 31 | protected int getLayoutResId() { 32 | return R.layout.activity_qr_code; 33 | } 34 | 35 | @Override 36 | protected void initView(@Nullable Bundle savedInstanceState) { 37 | ButterKnife.bind(this); 38 | 39 | initToolbar(toolbar, "扫描二维码", true); 40 | 41 | qrCode.setOnQRCodeListener(result -> { 42 | Intent intent = new Intent(QRCodeActivity.this, ShowQRCodeContentActivity.class); 43 | intent.putExtra(INTENT_ARG_01, result.getText()); 44 | startActivity(intent); 45 | }); 46 | } 47 | 48 | @Override 49 | public void onResume() { 50 | super.onResume(); 51 | qrCode.startPreview(); 52 | } 53 | 54 | @Override 55 | public void onPause() { 56 | super.onPause(); 57 | qrCode.stopPreview(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/page/other/ShowQRCodeContentActivity.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.page.other; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | import android.support.design.widget.CoordinatorLayout; 7 | import android.support.v7.widget.Toolbar; 8 | import android.view.View; 9 | import android.widget.TextView; 10 | 11 | import com.zhangke.shizhong.R; 12 | import com.zhangke.shizhong.page.base.BaseActivity; 13 | 14 | import butterknife.BindView; 15 | import butterknife.ButterKnife; 16 | 17 | /** 18 | * 展示扫描到的二维码内容 19 | *

20 | * Created by ZhangKe on 2018/8/1. 21 | */ 22 | public class ShowQRCodeContentActivity extends BaseActivity { 23 | 24 | @BindView(R.id.toolbar) 25 | Toolbar toolbar; 26 | @BindView(R.id.tv_content) 27 | TextView tvContent; 28 | 29 | @Override 30 | protected int getLayoutResId() { 31 | return R.layout.activity_show_qr_code_content; 32 | } 33 | 34 | @Override 35 | protected void initView(@Nullable Bundle savedInstanceState) { 36 | ButterKnife.bind(this); 37 | 38 | initToolbar(toolbar, "内容", true); 39 | 40 | Intent intent = getIntent(); 41 | if(intent.hasExtra(INTENT_ARG_01)){ 42 | String text = intent.getStringExtra(INTENT_ARG_01); 43 | tvContent.setText(text); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/page/other/WifiInfoActivity.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.page.other; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v7.widget.Toolbar; 6 | import android.widget.TextView; 7 | 8 | import com.zhangke.shizhong.R; 9 | import com.zhangke.shizhong.page.base.BaseActivity; 10 | import com.zhangke.shizhong.util.WifiManage; 11 | 12 | import java.util.List; 13 | 14 | /** 15 | * 查看 wifi 密码 16 | * 17 | * Created by ZhangKe on 2018/8/1. 18 | */ 19 | public class WifiInfoActivity extends BaseActivity { 20 | 21 | private Toolbar toolbar; 22 | 23 | @Override 24 | protected int getLayoutResId() { 25 | return R.layout.activity_wifi_info; 26 | } 27 | 28 | @Override 29 | protected void initView(@Nullable Bundle savedInstanceState) { 30 | toolbar = findViewById(R.id.toolbar); 31 | 32 | initToolbar(toolbar, "查看 wifi 信息", true); 33 | 34 | TextView tvInfo = findViewById(R.id.tv_info); 35 | 36 | List list = WifiManage.readWifiInfo(); 37 | StringBuilder builder = new StringBuilder(); 38 | if(list != null && !list.isEmpty()){ 39 | for(WifiManage.WifiInfo info : list){ 40 | builder.append(info.toString()); 41 | builder.append("\n\n"); 42 | } 43 | }else{ 44 | builder.append("未获取到 wifi 信息,请检查是否允许 root 权限。"); 45 | } 46 | tvInfo.setText(builder.toString()); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/page/plan/AddPlanActivity.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.page.plan; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v4.app.Fragment; 6 | import android.support.v7.widget.Toolbar; 7 | 8 | import com.zhangke.shizhong.R; 9 | import com.zhangke.shizhong.common.CustomFragmentPagerAdapter; 10 | import com.zhangke.shizhong.event.PlanSelectedEvent; 11 | import com.zhangke.shizhong.page.base.BaseActivity; 12 | import com.zhangke.shizhong.widget.NoScrollViewPager; 13 | 14 | import org.greenrobot.eventbus.EventBus; 15 | import org.greenrobot.eventbus.Subscribe; 16 | import org.greenrobot.eventbus.ThreadMode; 17 | 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | 21 | import butterknife.BindView; 22 | import butterknife.ButterKnife; 23 | 24 | /** 25 | * 添加计划界面 26 | *

27 | * Created by ZhangKe on 2018/5/19. 28 | */ 29 | public class AddPlanActivity extends BaseActivity { 30 | 31 | @BindView(R.id.toolbar) 32 | Toolbar toolbar; 33 | @BindView(R.id.view_pager) 34 | NoScrollViewPager viewPager; 35 | 36 | @Override 37 | protected int getLayoutResId() { 38 | return R.layout.activity_add_plan; 39 | } 40 | 41 | @Override 42 | protected void initView(@Nullable Bundle savedInstanceState) { 43 | ButterKnife.bind(this); 44 | EventBus.getDefault().register(this); 45 | 46 | initToolbar(toolbar, "添加计划", true); 47 | 48 | List fragmentList = new ArrayList<>(); 49 | fragmentList.add(new ChoosePlanTypeFragment()); 50 | fragmentList.add(new AddPlanFragment()); 51 | 52 | CustomFragmentPagerAdapter fragmentPagerAdapter = new CustomFragmentPagerAdapter(getSupportFragmentManager(), fragmentList); 53 | 54 | viewPager.setAdapter(fragmentPagerAdapter); 55 | } 56 | 57 | @Subscribe(threadMode = ThreadMode.MAIN) 58 | public void onEventMainThread(PlanSelectedEvent event) { 59 | if(event.getPlanType() == -1) { 60 | viewPager.setCurrentItem(0); 61 | }else{ 62 | viewPager.setCurrentItem(1); 63 | } 64 | } 65 | 66 | @Override 67 | public void onBackPressed() { 68 | if(viewPager.getCurrentItem() == 1){ 69 | EventBus.getDefault().post(new PlanSelectedEvent(-1)); 70 | }else{ 71 | super.onBackPressed(); 72 | } 73 | } 74 | 75 | @Override 76 | protected void onDestroy() { 77 | EventBus.getDefault().unregister(this); 78 | super.onDestroy(); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/page/plan/ChoosePlanTypeFragment.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.page.plan; 2 | 3 | import android.support.v7.widget.Toolbar; 4 | import android.view.View; 5 | 6 | import com.zhangke.shizhong.R; 7 | import com.zhangke.shizhong.event.PlanSelectedEvent; 8 | import com.zhangke.shizhong.page.base.BaseFragment; 9 | 10 | import org.greenrobot.eventbus.EventBus; 11 | 12 | import butterknife.BindView; 13 | import butterknife.ButterKnife; 14 | import butterknife.OnClick; 15 | import butterknife.Unbinder; 16 | 17 | /** 18 | * 选择计划类型页面 19 | *

20 | * Created by ZhangKe on 2018/7/10. 21 | */ 22 | public class ChoosePlanTypeFragment extends BaseFragment { 23 | 24 | Unbinder unbinder; 25 | 26 | @Override 27 | protected int getLayoutResId() { 28 | return R.layout.fragment_choose_plan_type; 29 | } 30 | 31 | @Override 32 | protected void initView() { 33 | unbinder = ButterKnife.bind(this, rootView); 34 | 35 | } 36 | 37 | @OnClick(R.id.btn_ration_plan) 38 | public void openRationPlan(View view) { 39 | EventBus.getDefault().post(new PlanSelectedEvent(0)); 40 | } 41 | 42 | @OnClick(R.id.btn_clock_plan) 43 | public void openClockPlan(View view) { 44 | EventBus.getDefault().post(new PlanSelectedEvent(1)); 45 | } 46 | 47 | @Override 48 | public void onDestroyView() { 49 | super.onDestroyView(); 50 | unbinder.unbind(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/page/plan/ClockPlanDetailAdapter.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.page.plan; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.NonNull; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.TextView; 8 | 9 | import com.zhangke.shizhong.R; 10 | import com.zhangke.shizhong.db.ClockRecord; 11 | import com.zhangke.shizhong.page.base.BaseRecyclerAdapter; 12 | 13 | import java.util.List; 14 | 15 | import butterknife.BindView; 16 | import butterknife.ButterKnife; 17 | 18 | /** 19 | * 打卡计划详情页打卡记录列表 20 | *

21 | * Created by ZhangKe on 2018/7/29. 22 | */ 23 | public class ClockPlanDetailAdapter extends BaseRecyclerAdapter { 24 | 25 | public ClockPlanDetailAdapter(Context context, List listData) { 26 | super(context, listData); 27 | } 28 | 29 | @NonNull 30 | @Override 31 | public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { 32 | return new ViewHolder(inflater.inflate(R.layout.adapter_clock_plan_detail, parent, false)); 33 | } 34 | 35 | @Override 36 | public void onBindViewHolder(@NonNull ViewHolder holder, int position) { 37 | holder.tvDate.setText(listData.get(position).getDate()); 38 | holder.tvTitle.setText(listData.get(position).getDescription()); 39 | } 40 | 41 | class ViewHolder extends BaseRecyclerAdapter.ViewHolder { 42 | 43 | @BindView(R.id.tv_title) 44 | TextView tvTitle; 45 | @BindView(R.id.tv_date) 46 | TextView tvDate; 47 | 48 | public ViewHolder(View itemView) { 49 | super(itemView); 50 | ButterKnife.bind(this, itemView); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/page/plan/RationPlanDetailAdapter.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.page.plan; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.NonNull; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.TextView; 8 | 9 | import com.zhangke.shizhong.R; 10 | import com.zhangke.shizhong.db.RationRecord; 11 | import com.zhangke.shizhong.page.base.BaseRecyclerAdapter; 12 | 13 | import java.util.List; 14 | 15 | import butterknife.BindView; 16 | import butterknife.ButterKnife; 17 | 18 | /** 19 | * 定量计划打卡记录 20 | * Created by ZhangKe on 2018/7/26. 21 | */ 22 | public class RationPlanDetailAdapter extends BaseRecyclerAdapter { 23 | 24 | public RationPlanDetailAdapter(Context context, List listData) { 25 | super(context, listData); 26 | } 27 | 28 | @NonNull 29 | @Override 30 | public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { 31 | return new ViewHolder(inflater.inflate(R.layout.adapter_ration_plan_detail, parent, false)); 32 | } 33 | 34 | @Override 35 | public void onBindViewHolder(@NonNull ViewHolder holder, int position) { 36 | RationRecord record = listData.get(position); 37 | holder.tvTitle.setText(record.getName()); 38 | holder.tvTime.setText(record.getDate()); 39 | holder.tvValue.setText(String.valueOf(record.getValue())); 40 | } 41 | 42 | class ViewHolder extends BaseRecyclerAdapter.ViewHolder { 43 | 44 | @BindView(R.id.tv_title) 45 | TextView tvTitle; 46 | @BindView(R.id.tv_time) 47 | TextView tvTime; 48 | @BindView(R.id.tv_value) 49 | TextView tvValue; 50 | 51 | public ViewHolder(View itemView) { 52 | super(itemView); 53 | ButterKnife.bind(this, itemView); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/page/poster/InputNameActivity.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.page.poster; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | import android.support.v7.widget.Toolbar; 7 | import android.text.TextUtils; 8 | import android.view.View; 9 | import android.widget.Button; 10 | import android.widget.EditText; 11 | import android.widget.LinearLayout; 12 | 13 | import com.zhangke.shizhong.R; 14 | import com.zhangke.shizhong.page.base.BaseActivity; 15 | 16 | import butterknife.BindView; 17 | import butterknife.ButterKnife; 18 | import butterknife.OnClick; 19 | 20 | /** 21 | * 输入名字及展示搜索结果界面 22 | * Created by ZhangKe on 2018/4/15. 23 | */ 24 | 25 | public class InputNameActivity extends BaseActivity{ 26 | 27 | @BindView(R.id.toolbar) 28 | Toolbar toolbar; 29 | @BindView(R.id.ll_search) 30 | LinearLayout llSearch; 31 | @BindView(R.id.et_name) 32 | EditText etName; 33 | @BindView(R.id.btn_search) 34 | Button btnSearch; 35 | 36 | /** 37 | * 0-豆瓣电影海报 38 | * 1-云音乐封面 39 | */ 40 | private int type = 0; 41 | 42 | @Override 43 | protected int getLayoutResId() { 44 | return R.layout.activity_input_name; 45 | } 46 | 47 | @Override 48 | protected void initView(@Nullable Bundle savedInstanceState) { 49 | ButterKnife.bind(this); 50 | 51 | Intent intent = getIntent(); 52 | if (intent.hasExtra(INTENT_ARG_01)) { 53 | type = intent.getIntExtra(INTENT_ARG_01, type); 54 | } 55 | 56 | initToolbar(toolbar, type == 0 ? "豆瓣电影海报" : "云音乐封面", true); 57 | } 58 | 59 | @OnClick(R.id.btn_search) 60 | public void onViewClick(View view) { 61 | String name = etName.getText().toString(); 62 | if(TextUtils.isEmpty(name)){ 63 | showNoActionSnackbar("请输入用户名"); 64 | return; 65 | } 66 | Intent intent = new Intent(this, SearchResultActivity.class); 67 | intent.putExtra(INTENT_ARG_01, type); 68 | intent.putExtra(INTENT_ARG_02, etName.getText().toString()); 69 | startActivity(intent); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/page/poster/MoviePosterAdapter.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.page.poster; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.NonNull; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.ImageView; 8 | 9 | import com.zhangke.shizhong.R; 10 | import com.zhangke.shizhong.model.poster.ILoadBitmap; 11 | import com.zhangke.shizhong.model.poster.MoviePosterBean; 12 | import com.zhangke.shizhong.page.base.BaseRecyclerAdapter; 13 | import com.zhangke.shizhong.util.PosterUtils; 14 | 15 | import java.util.List; 16 | 17 | import butterknife.BindView; 18 | import butterknife.ButterKnife; 19 | 20 | /** 21 | * 电影海报展示 22 | * Created by ZhangKe on 2018/4/22. 23 | */ 24 | 25 | public class MoviePosterAdapter extends BaseRecyclerAdapter { 26 | 27 | private static final String TAG = "MoviePosterAdapter"; 28 | 29 | private ILoadBitmap loadBitmap; 30 | 31 | MoviePosterAdapter(Context context, 32 | List listData, 33 | ILoadBitmap loadBitmap) { 34 | super(context, listData); 35 | this.loadBitmap = loadBitmap; 36 | } 37 | 38 | @NonNull 39 | @Override 40 | public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { 41 | return new ViewHolder(inflater.inflate(R.layout.adapter_movie_poster, null)); 42 | } 43 | 44 | @Override 45 | public void onBindViewHolder(@NonNull ViewHolder holder, int position) { 46 | loadBitmap.loadBitmapIntoImageView( 47 | listData.get(position).getMovieImageUrl(), 48 | holder.imgView, 49 | PosterUtils.getMoviePosterFileWithName(listData.get(position).getMovieName())); 50 | } 51 | 52 | class ViewHolder extends BaseRecyclerAdapter.ViewHolder { 53 | 54 | @BindView(R.id.img_view) 55 | ImageView imgView; 56 | 57 | ViewHolder(View itemView) { 58 | super(itemView); 59 | ButterKnife.bind(this, itemView); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/page/poster/MusicPosterAdapter.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.page.poster; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.NonNull; 5 | import android.util.Log; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.ImageView; 9 | 10 | import com.bumptech.glide.Glide; 11 | import com.zhangke.shizhong.model.poster.MusicPosterBean; 12 | import com.zhangke.shizhong.page.base.BaseRecyclerAdapter; 13 | import com.zhangke.shizhong.util.UiUtils; 14 | 15 | import java.util.List; 16 | 17 | /** 18 | * 云音乐海报 19 | * Created by ZhangKe on 2018/4/24. 20 | */ 21 | 22 | public class MusicPosterAdapter extends BaseRecyclerAdapter { 23 | 24 | private static final String TAG = "MusicPosterAdapter"; 25 | 26 | private int itemViewHeight = 0; 27 | 28 | MusicPosterAdapter(Context context, 29 | List listData) { 30 | super(context, listData); 31 | 32 | itemViewHeight = UiUtils.getScreenWidth(context) / 4; 33 | } 34 | 35 | int createCount = 0; 36 | 37 | @NonNull 38 | @Override 39 | public MusicPosterAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { 40 | Log.d(TAG, String.format("onCreateViewHolder: 第%s次Create", ++createCount)); 41 | ImageView imageView = new ImageView(context); 42 | imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); 43 | ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 44 | ViewGroup.LayoutParams.WRAP_CONTENT); 45 | layoutParams.height = itemViewHeight; 46 | imageView.setLayoutParams(layoutParams); 47 | return new MusicPosterAdapter.ViewHolder(imageView); 48 | } 49 | 50 | int bindCount = 0; 51 | 52 | @Override 53 | public void onBindViewHolder(@NonNull MusicPosterAdapter.ViewHolder holder, int position) { 54 | MusicPosterBean.PlaylistBean.TracksBean item = listData.get(position); 55 | if (item.getAl() != null) { 56 | holder.imgView.setVisibility(View.VISIBLE); 57 | Glide.with(context) 58 | .load(item.getAl().getPicUrl()) 59 | .crossFade() 60 | .into(holder.imgView); 61 | }else{ 62 | holder.imgView.setVisibility(View.GONE); 63 | } 64 | 65 | Log.d(TAG, String.format("onBindViewHolder: 第%s次Bind", ++bindCount)); 66 | } 67 | 68 | class ViewHolder extends BaseRecyclerAdapter.ViewHolder { 69 | 70 | // @BindView(R.id.img_view) 71 | ImageView imgView; 72 | 73 | ViewHolder(ImageView itemView) { 74 | super(itemView); 75 | this.imgView = itemView; 76 | // ButterKnife.bind(this, itemView); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/page/poster/ShowMoviePosterActivity.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.page.poster; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.support.v7.widget.StaggeredGridLayoutManager; 7 | 8 | import com.zhangke.shizhong.R; 9 | import com.zhangke.shizhong.contract.poster.IShowMoviePosterContract; 10 | import com.zhangke.shizhong.model.poster.GlideLoadBitmap; 11 | import com.zhangke.shizhong.model.poster.ILoadBitmap; 12 | import com.zhangke.shizhong.model.poster.MoviePosterBean; 13 | import com.zhangke.shizhong.model.poster.ShowMoviePosterModel; 14 | import com.zhangke.shizhong.page.base.BaseActivity; 15 | import com.zhangke.shizhong.model.poster.UserBean; 16 | import com.zhangke.shizhong.util.ISaveFileEngine; 17 | import com.zhangke.shizhong.util.SaveFileEngine; 18 | import com.zhangke.shizhong.widget.SpacesItemDecoration; 19 | 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | 23 | import butterknife.BindView; 24 | import butterknife.ButterKnife; 25 | 26 | /** 27 | * 用于显示豆瓣电影海报 28 | * Created by ZhangKe on 2018/4/22. 29 | */ 30 | 31 | public class ShowMoviePosterActivity extends BaseActivity implements IShowMoviePosterContract.View { 32 | 33 | @BindView(R.id.recycler_view) 34 | RecyclerView recyclerView; 35 | 36 | private List posterList = new ArrayList<>(); 37 | private MoviePosterAdapter adapter; 38 | 39 | private IShowMoviePosterContract.Model showMoviePosterModel; 40 | 41 | private ISaveFileEngine saveFileEngine; 42 | 43 | @Override 44 | protected int getLayoutResId() { 45 | return R.layout.activity_show_music_poster; 46 | } 47 | 48 | @Override 49 | protected void initView(@Nullable Bundle savedInstanceState) { 50 | ButterKnife.bind(this); 51 | fullScreen(); 52 | 53 | saveFileEngine = new SaveFileEngine(); 54 | ILoadBitmap loadBitmap = new GlideLoadBitmap(this, saveFileEngine); 55 | 56 | adapter = new MoviePosterAdapter(this, posterList, loadBitmap); 57 | recyclerView.setLayoutManager(new StaggeredGridLayoutManager(5, StaggeredGridLayoutManager.VERTICAL)); 58 | recyclerView.addItemDecoration(new SpacesItemDecoration()); 59 | recyclerView.setAdapter(adapter); 60 | 61 | UserBean userBean = (UserBean) getIntent().getSerializableExtra(INTENT_ARG_01); 62 | showMoviePosterModel = new ShowMoviePosterModel(this, this, userBean.getUserId()); 63 | showMoviePosterModel.getMoviePoster(); 64 | } 65 | 66 | @Override 67 | public void notifyDataChanged(List list) { 68 | posterList.clear(); 69 | posterList.addAll(list); 70 | adapter.notifyDataSetChanged(); 71 | } 72 | 73 | @Override 74 | protected void onDestroy() { 75 | saveFileEngine.exit(); 76 | super.onDestroy(); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/page/poster/UserAdapter.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.page.poster; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.NonNull; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.ImageView; 8 | import android.widget.TextView; 9 | 10 | import com.bumptech.glide.Glide; 11 | import com.zhangke.shizhong.R; 12 | import com.zhangke.shizhong.model.poster.UserBean; 13 | import com.zhangke.shizhong.page.base.BaseRecyclerAdapter; 14 | import com.zhangke.shizhong.util.GlideCircleTransform; 15 | 16 | import java.util.List; 17 | 18 | import butterknife.BindView; 19 | import butterknife.ButterKnife; 20 | 21 | /** 22 | * 用户列表 23 | *

24 | * Created by ZhangKe on 2018/4/18. 25 | */ 26 | 27 | public class UserAdapter extends BaseRecyclerAdapter{ 28 | 29 | public UserAdapter(Context context, List listData) { 30 | super(context, listData); 31 | } 32 | 33 | @NonNull 34 | @Override 35 | public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { 36 | return new ViewHolder(inflater.inflate(R.layout.adapter_search_result, parent,false)); 37 | } 38 | 39 | @Override 40 | public void onBindViewHolder(@NonNull ViewHolder holder, int position) { 41 | UserBean itemBean = listData.get(position); 42 | holder.tv_name.setText(itemBean.getNickName()); 43 | holder.tv_desc.setText(itemBean.getDescription()); 44 | 45 | Glide.with(context) 46 | .load(itemBean.getUserIcon()) 47 | .transform(new GlideCircleTransform(context)) 48 | .crossFade() 49 | .into(holder.img_icon); 50 | } 51 | 52 | class ViewHolder extends BaseRecyclerAdapter.ViewHolder{ 53 | 54 | @BindView(R.id.img_icon) 55 | ImageView img_icon; 56 | @BindView(R.id.tv_name) 57 | TextView tv_name; 58 | @BindView(R.id.tv_desc) 59 | TextView tv_desc; 60 | 61 | ViewHolder(View itemView) { 62 | super(itemView); 63 | ButterKnife.bind(this, itemView); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/presenter/plan/RationPlanDetailPresenterImpl.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.presenter.plan; 2 | 3 | import android.app.Activity; 4 | import android.os.Handler; 5 | import android.os.Looper; 6 | 7 | import com.zhangke.shizhong.contract.plan.IRationPlanDetailContract; 8 | import com.zhangke.shizhong.db.DBManager; 9 | import com.zhangke.shizhong.db.RationPlan; 10 | import com.zhangke.shizhong.db.RationPlanDao; 11 | import com.zhangke.shizhong.db.RationRecord; 12 | import com.zhangke.shizhong.db.RationRecordDao; 13 | 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | 17 | import io.reactivex.Observable; 18 | import io.reactivex.ObservableEmitter; 19 | import io.reactivex.android.schedulers.AndroidSchedulers; 20 | import io.reactivex.schedulers.Schedulers; 21 | 22 | /** 23 | * 定量计划详情 24 | *

25 | * Created by ZhangKe on 2018/7/26. 26 | */ 27 | public class RationPlanDetailPresenterImpl implements IRationPlanDetailContract.Presenter { 28 | 29 | private IRationPlanDetailContract.View view; 30 | private long planId; 31 | 32 | private Handler mHandler = new Handler(Looper.getMainLooper()); 33 | 34 | private RationPlanDao mRationPlanDao; 35 | private RationRecordDao mRationRecordDao; 36 | 37 | private List listData = new ArrayList<>(); 38 | 39 | private RationPlan rationPlan; 40 | 41 | public RationPlanDetailPresenterImpl(IRationPlanDetailContract.View view, long planId) { 42 | this.view = view; 43 | this.planId = planId; 44 | 45 | mRationPlanDao = DBManager.getInstance().getRationPlanDao(); 46 | mRationRecordDao = DBManager.getInstance().getRationRecordDao(); 47 | } 48 | 49 | @Override 50 | public void update() { 51 | Observable.create((ObservableEmitter e) -> { 52 | listData.clear(); 53 | listData.addAll(mRationRecordDao.queryBuilder() 54 | .where(RationRecordDao.Properties.ParentPlanId.eq(planId)) 55 | .list()); 56 | List rationPlanList = mRationPlanDao.queryBuilder() 57 | .where(RationPlanDao.Properties.Id.eq(planId)) 58 | .list(); 59 | if (rationPlanList.isEmpty()) { 60 | e.onNext(0); 61 | } else { 62 | rationPlan = rationPlanList.get(0); 63 | e.onNext(1); 64 | } 65 | e.onComplete(); 66 | }).subscribeOn(Schedulers.io()) 67 | .observeOn(AndroidSchedulers.mainThread()) 68 | .subscribe(value -> { 69 | view.notifyDataChanged(listData); 70 | if (value == 0) { 71 | view.showNoActionSnackbar("计划不存在,刚刚被你删了吧?"); 72 | mHandler.postDelayed(() -> ((Activity) view).finish(), 700); 73 | } else { 74 | mHandler.postDelayed(() -> view.fillRationPlanData(rationPlan), 500); 75 | } 76 | }); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/presenter/todo/CompletedTodoPresenterImpl.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.presenter.todo; 2 | 3 | import com.zhangke.shizhong.contract.todo.ICompletedTodoContract; 4 | import com.zhangke.shizhong.db.DBManager; 5 | import com.zhangke.shizhong.db.Todo; 6 | import com.zhangke.shizhong.db.TodoDao; 7 | import com.zhangke.shizhong.model.todo.ShowTodoEntity; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | import io.reactivex.Observable; 13 | import io.reactivex.android.schedulers.AndroidSchedulers; 14 | import io.reactivex.schedulers.Schedulers; 15 | 16 | /** 17 | * 已完成的待办事项 18 | * 19 | * Created by ZhangKe on 2018/7/28. 20 | */ 21 | public class CompletedTodoPresenterImpl implements ICompletedTodoContract.Presenter { 22 | 23 | private ICompletedTodoContract.View view; 24 | 25 | 26 | private TodoDao mTodoDao; 27 | private Observable updateTodoObservable; 28 | 29 | private List listData = new ArrayList<>(); 30 | 31 | public CompletedTodoPresenterImpl(ICompletedTodoContract.View view) { 32 | this.view = view; 33 | 34 | mTodoDao = DBManager.getInstance().getTodoDao(); 35 | 36 | updateTodoObservable = Observable.create(e -> { 37 | listData.clear(); 38 | List todoList = mTodoDao.queryBuilder() 39 | .where(TodoDao.Properties.Completed.eq(true)) 40 | .orderAsc(TodoDao.Properties.Date) 41 | .list(); 42 | if (!todoList.isEmpty()) { 43 | listData.addAll(Observable.fromIterable(todoList) 44 | .map(todo -> { 45 | ShowTodoEntity showTodo = new ShowTodoEntity(); 46 | showTodo.setType(0); 47 | showTodo.setTodo(todo); 48 | return showTodo; 49 | }) 50 | .toList() 51 | .blockingGet()); 52 | } 53 | e.onNext(0); 54 | e.onComplete(); 55 | }); 56 | } 57 | 58 | @Override 59 | public void update() { 60 | updateTodoObservable.subscribeOn(Schedulers.io()) 61 | .observeOn(AndroidSchedulers.mainThread()) 62 | .subscribe(integer -> view.notifyTodoChanged(listData)); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/presenter/todo/ShowTodoPresenterImpl.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.presenter.todo; 2 | 3 | import android.content.Context; 4 | 5 | import com.zhangke.shizhong.contract.todo.IShowTodoContract; 6 | import com.zhangke.shizhong.db.DBManager; 7 | import com.zhangke.shizhong.db.Todo; 8 | import com.zhangke.shizhong.db.TodoDao; 9 | import com.zhangke.shizhong.model.todo.ShowTodoEntity; 10 | import com.zhangke.shizhong.util.DateUtils; 11 | 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | import io.reactivex.Observable; 16 | import io.reactivex.android.schedulers.AndroidSchedulers; 17 | import io.reactivex.schedulers.Schedulers; 18 | 19 | /** 20 | * 待办事项展示 21 | *

22 | * Created by ZhangKe on 2018/7/24. 23 | */ 24 | public class ShowTodoPresenterImpl implements IShowTodoContract.Presenter { 25 | 26 | private Context context; 27 | private IShowTodoContract.View view; 28 | 29 | private TodoDao mTodoDao; 30 | private Observable updateTodoObservable; 31 | 32 | private String dateFormat = "yyyy-MM-dd HH:mm"; 33 | private String currentDate = DateUtils.getCurrentDate(dateFormat); 34 | 35 | private List listData = new ArrayList<>(); 36 | 37 | public ShowTodoPresenterImpl(Context context, IShowTodoContract.View view) { 38 | this.context = context; 39 | this.view = view; 40 | 41 | mTodoDao = DBManager.getInstance().getTodoDao(); 42 | 43 | updateTodoObservable = Observable.create(e -> { 44 | listData.clear(); 45 | List todoList = mTodoDao.queryBuilder() 46 | .where(TodoDao.Properties.Completed.eq(false)) 47 | .orderAsc(TodoDao.Properties.Date) 48 | .list(); 49 | if (!todoList.isEmpty()) { 50 | listData.addAll(Observable.fromIterable(todoList) 51 | .map(todo -> { 52 | ShowTodoEntity showTodo = new ShowTodoEntity(); 53 | showTodo.setType(0); 54 | showTodo.setTodo(todo); 55 | showTodo.setLevel(getLevel(todo)); 56 | return showTodo; 57 | }) 58 | .toList() 59 | .blockingGet()); 60 | } 61 | ShowTodoEntity addTodoEntity = new ShowTodoEntity(); 62 | addTodoEntity.setType(1); 63 | listData.add(addTodoEntity); 64 | e.onNext(0); 65 | e.onComplete(); 66 | }); 67 | } 68 | 69 | /** 70 | * 获取待办事项紧急等级 71 | */ 72 | private int getLevel(Todo todo) { 73 | int level = 1; 74 | int hourSpace = DateUtils.getHourSpace(dateFormat, currentDate, todo.getDate()); 75 | if (hourSpace <= 1) { 76 | level = 6; 77 | } else if (hourSpace <= 5) { 78 | level = 5; 79 | } else if (hourSpace <= 12) { 80 | level = 4; 81 | } else if (hourSpace <= 24) { 82 | level = 3; 83 | } else if (hourSpace <= 48) { 84 | level = 2; 85 | } 86 | return level; 87 | } 88 | 89 | @Override 90 | public void update() { 91 | updateTodoObservable.subscribeOn(Schedulers.io()) 92 | .observeOn(AndroidSchedulers.mainThread()) 93 | .subscribe(integer -> view.notifyTodoChanged(listData)); 94 | 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/service/ProcessPlanService.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.service; 2 | 3 | import android.app.IntentService; 4 | import android.content.Intent; 5 | import android.support.annotation.Nullable; 6 | import android.text.TextUtils; 7 | 8 | import com.zhangke.shizhong.db.DBManager; 9 | import com.zhangke.shizhong.db.RationPlan; 10 | import com.zhangke.shizhong.db.RationPlanDao; 11 | import com.zhangke.shizhong.event.PlanChangedEvent; 12 | import com.zhangke.shizhong.presenter.plan.PlanHelper; 13 | import com.zhangke.shizhong.util.DateUtils; 14 | 15 | import org.greenrobot.eventbus.EventBus; 16 | 17 | import java.text.DecimalFormat; 18 | import java.util.List; 19 | 20 | /** 21 | * 计算计划数据 22 | *

23 | * Created by ZhangKe on 2018/8/10. 24 | */ 25 | public class ProcessPlanService extends IntentService { 26 | 27 | private RationPlanDao rationPlanDao; 28 | private String curDate = DateUtils.getCurrentDate("yyyy-MM-dd"); 29 | private DecimalFormat decimalFormat = new DecimalFormat("0.00"); 30 | 31 | public ProcessPlanService() { 32 | super("ProcessPlanService"); 33 | rationPlanDao = DBManager.getInstance().getRationPlanDao(); 34 | } 35 | 36 | @Override 37 | protected void onHandleIntent(@Nullable Intent intent) { 38 | List rationPlanList = rationPlanDao.loadAll(); 39 | if (rationPlanList != null && !rationPlanList.isEmpty()) { 40 | for (RationPlan plan : rationPlanList) { 41 | processRationPlan(plan); 42 | } 43 | } 44 | DBManager.getInstance().clear(); 45 | EventBus.getDefault().post(new PlanChangedEvent()); 46 | } 47 | 48 | private void processRationPlan(RationPlan plan) { 49 | if (plan.getPeriodIsOpen() && 50 | (TextUtils.isEmpty(plan.getLastUpdatePeriodDate()) || 51 | !PlanHelper.isCurPeriod(plan.getPeriodPlanType(), plan.getLastUpdatePeriodDate(), "yyyy-MM-dd"))) { 52 | //短期计划存在且短期计划上次更新时间为空或者上次更新时间不在当前周期 53 | plan.setPeriodPlanTarget(Double.valueOf(decimalFormat.format(PlanHelper.getPeriodTarget(plan, plan.getPeriodPlanType())))); 54 | plan.setLastUpdatePeriodDate(curDate); 55 | rationPlanDao.update(plan); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/util/CrashHandler.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.util; 2 | 3 | import android.content.Context; 4 | import android.os.Process; 5 | import android.util.Log; 6 | 7 | import com.zhangke.zlog.ZLog; 8 | 9 | import java.lang.Thread.UncaughtExceptionHandler; 10 | 11 | /** 12 | * 异常捕获 13 | *

14 | * Created by ZhangKe on 2017/12/5. 15 | */ 16 | 17 | public class CrashHandler implements UncaughtExceptionHandler { 18 | 19 | private static final String TAG = "CrashHandler"; 20 | 21 | private static CrashHandler sInstance = new CrashHandler(); 22 | private Context mContext; 23 | //系统默认的异常处理(默认情况下,系统会终止当前的异常程序) 24 | private UncaughtExceptionHandler mDefaultCrashHandler; 25 | 26 | public static CrashHandler getInstance() { 27 | return sInstance; 28 | } 29 | 30 | public void init(Context context) { 31 | mContext = context.getApplicationContext(); 32 | 33 | mDefaultCrashHandler = Thread.getDefaultUncaughtExceptionHandler(); 34 | Thread.setDefaultUncaughtExceptionHandler(this); 35 | } 36 | 37 | @Override 38 | public void uncaughtException(Thread thread, Throwable ex) { 39 | dumpException(ex); 40 | ex.printStackTrace(); 41 | if (mDefaultCrashHandler != null) { 42 | mDefaultCrashHandler.uncaughtException(thread, ex); 43 | } else { 44 | Process.killProcess(Process.myPid()); 45 | } 46 | } 47 | 48 | private void dumpException(Throwable ex) { 49 | try { 50 | StringBuilder sbMessage = new StringBuilder(); 51 | sbMessage.append(ex.getMessage()); 52 | sbMessage.append("\n"); 53 | StackTraceElement[] stackTrace = ex.getStackTrace(); 54 | for (StackTraceElement s : stackTrace) { 55 | sbMessage.append(s.toString()); 56 | sbMessage.append("\n"); 57 | } 58 | 59 | ZLog.openSaveToFile(); 60 | ZLog.crash(TAG, sbMessage.toString()); 61 | } catch (Exception e) { 62 | Log.e(TAG, "dump crash i failed"); 63 | e.printStackTrace(); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/util/GlideCircleTransform.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.util; 2 | 3 | import com.bumptech.glide.load.resource.bitmap.BitmapTransformation; 4 | 5 | import android.content.Context; 6 | import android.graphics.Bitmap; 7 | import android.graphics.BitmapShader; 8 | import android.graphics.Canvas; 9 | import android.graphics.Paint; 10 | 11 | import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; 12 | /** 13 | * Glide 加载圆形图片 14 | * 15 | * Created by ZhangKe on 2018/4/18. 16 | */ 17 | 18 | public class GlideCircleTransform extends BitmapTransformation { 19 | public GlideCircleTransform(Context context) { 20 | super(context); 21 | } 22 | 23 | @Override protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) { 24 | return circleCrop(pool, toTransform); 25 | } 26 | 27 | private static Bitmap circleCrop(BitmapPool pool, Bitmap source) { 28 | if (source == null) return null; 29 | 30 | int size = Math.min(source.getWidth(), source.getHeight()); 31 | int x = (source.getWidth() - size) / 2; 32 | int y = (source.getHeight() - size) / 2; 33 | 34 | Bitmap squared = Bitmap.createBitmap(source, x, y, size, size); 35 | 36 | Bitmap result = pool.get(size, size, Bitmap.Config.ARGB_8888); 37 | if (result == null) { 38 | result = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); 39 | } 40 | 41 | Canvas canvas = new Canvas(result); 42 | Paint paint = new Paint(); 43 | paint.setShader(new BitmapShader(squared, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP)); 44 | paint.setAntiAlias(true); 45 | float r = size / 2f; 46 | canvas.drawCircle(r, r, r, paint); 47 | return result; 48 | } 49 | 50 | @Override public String getId() { 51 | return getClass().getName(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/util/HttpUtils.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.util; 2 | 3 | import android.util.Log; 4 | 5 | import java.io.UnsupportedEncodingException; 6 | import java.net.URLEncoder; 7 | 8 | /** 9 | * HTTP 工具类 10 | * 11 | * Created by ZhangKe on 2018/4/18. 12 | */ 13 | 14 | public class HttpUtils { 15 | 16 | private static final String TAG = "HttpUtils"; 17 | 18 | public static String encode(String text){ 19 | try{ 20 | text = URLEncoder.encode(text, "utf-8"); 21 | } catch(UnsupportedEncodingException e){ 22 | Log.e(TAG, e.toString()); 23 | } 24 | return text; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/util/ISaveFileEngine.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.util; 2 | 3 | import android.graphics.Bitmap; 4 | 5 | import java.io.File; 6 | 7 | /** 8 | * 负责将一个 Bitmap 保存到文件中 9 | * Created by ZhangKe on 2018/4/23. 10 | */ 11 | public interface ISaveFileEngine { 12 | 13 | /** 14 | * 添加一个需要保存的图片 15 | */ 16 | void addFile(File file, Bitmap bitmap); 17 | 18 | /** 19 | * 结束 20 | */ 21 | void exit(); 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/util/NumberFormatUtil.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.util; 2 | 3 | import java.text.DecimalFormat; 4 | 5 | /** 6 | * 数字格式化 7 | *

8 | * Created by ZhangKe on 2019/2/18. 9 | */ 10 | public class NumberFormatUtil { 11 | 12 | private static DecimalFormat oneDecimalFormat = new DecimalFormat("0.0"); 13 | private static DecimalFormat twoDecimalFormat = new DecimalFormat("0.00"); 14 | 15 | /** 16 | * 如果小数点后面有值则保留一位小数,否则不显示小数点及之后数字 17 | */ 18 | public static String formatOnePoint(double src) { 19 | if (NumberUtil.equals(src, 0.0)) { 20 | return "0"; 21 | } 22 | if (src % 1.0 >= 0.01) { 23 | //小数点后面有数据 24 | return oneDecimalFormat.format(src); 25 | } else { 26 | return String.valueOf(Double.valueOf(src).intValue()); 27 | } 28 | } 29 | 30 | /** 31 | * 如果小数点后面有值则保留两位小数,否则不显示小数点及之后数字 32 | */ 33 | public static String formatPoint(double src) { 34 | if (NumberUtil.equals(src, 0.0)) { 35 | return "0"; 36 | } 37 | if (src % 1.0 >= 0.01) { 38 | //小数点后面有数据 39 | return twoDecimalFormat.format(src); 40 | } else { 41 | return String.valueOf(Double.valueOf(src).intValue()); 42 | } 43 | } 44 | 45 | /** 46 | * 将输入的数字格式化为保留两位小数点 47 | */ 48 | public static String formatTwoDecimal(double src) { 49 | return twoDecimalFormat.format(src); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/util/NumberUtil.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.util; 2 | 3 | /** 4 | * Created by ZhangKe on 2018/12/29. 5 | */ 6 | public class NumberUtil { 7 | 8 | private static double epsilon = 0.00000001; 9 | 10 | public static boolean equals(float a, float b){ 11 | return Math.abs(a - b) < epsilon; 12 | } 13 | 14 | public static boolean equals(double a, double b){ 15 | return Math.abs(a - b) < epsilon; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/util/PermissionUtil.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.util; 2 | 3 | import android.content.Context; 4 | import android.content.pm.PackageManager; 5 | import android.os.Build; 6 | import android.support.v4.content.ContextCompat; 7 | 8 | /** 9 | * 用户权限相关工具 10 | *

11 | * Created by ZhangKe on 2017/11/15. 12 | */ 13 | 14 | public class PermissionUtil { 15 | 16 | /** 17 | * 判断是否缺乏该权限 18 | * 19 | * @return true-缺乏 20 | */ 21 | public static boolean isLacksOfPermission(Context context, String permission) { 22 | return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) && ContextCompat.checkSelfPermission( 23 | context, permission) == PackageManager.PERMISSION_DENIED; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/util/PosterUtils.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.util; 2 | 3 | import android.text.TextUtils; 4 | 5 | import com.zhangke.shizhong.common.APPConfig; 6 | 7 | import java.io.File; 8 | 9 | /** 10 | * 海报操作相关方法 11 | *

12 | * Created by ZhangKe on 2018/4/22. 13 | */ 14 | 15 | public class PosterUtils { 16 | 17 | /** 18 | * 通过电影名获取海报存储地址 19 | */ 20 | public static File getMoviePosterFileWithName(File rootPath, String movieName) { 21 | movieName = movieName.replaceAll("\\\\", "-"); 22 | movieName = movieName.replaceAll(" ", "-"); 23 | return new File(rootPath, String.format("%s.jpg", movieName)); 24 | } 25 | 26 | /** 27 | * 通过电影名获取海报存储地址 28 | */ 29 | public static File getMoviePosterFileWithName(String movieName) { 30 | return getMoviePosterFileWithName(APPConfig.getMoviePosterRootFile(), movieName); 31 | } 32 | 33 | /** 34 | * 通过歌名及歌手名获取文件名 35 | */ 36 | public static File getMusicFileWithName(String albumName, String musicName, String userName) { 37 | if (!TextUtils.isEmpty(albumName)) { 38 | albumName = albumName.replaceAll("\\\\", "-"); 39 | albumName = albumName.replaceAll(" ", "-"); 40 | } else { 41 | albumName = "其他"; 42 | } 43 | if (!TextUtils.isEmpty(musicName)) { 44 | musicName = musicName.replaceAll("\\\\", "-"); 45 | musicName = musicName.replaceAll(" ", "-"); 46 | } 47 | if (!TextUtils.isEmpty(userName)) { 48 | userName = userName.replaceAll("\\\\", "-"); 49 | userName = userName.replaceAll(" ", "-"); 50 | } 51 | File parentFile = new File(String.format("%s/%s", APPConfig.getMusicPosterRootFile(), albumName)); 52 | if (!parentFile.exists()) { 53 | if (parentFile.mkdirs()) { 54 | return new File(parentFile, String.format("%s-%s.jpg", musicName, userName)); 55 | } else { 56 | return new File(APPConfig.getMusicPosterRootFile(), String.format("%s-%s.jpg", musicName, userName)); 57 | } 58 | } else { 59 | return new File(parentFile, String.format("%s-%s.jpg", musicName, userName)); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/util/SaveFileEngine.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.util; 2 | 3 | import android.graphics.Bitmap; 4 | import android.os.Process; 5 | import android.util.Log; 6 | 7 | import com.zhangke.zlog.ZLog; 8 | 9 | import java.io.File; 10 | import java.util.concurrent.LinkedBlockingQueue; 11 | 12 | /** 13 | * 负责将图片保存到文件中,适用于高并发场景。 14 | *

15 | * Created by ZhangKe on 2018/4/23. 16 | */ 17 | public class SaveFileEngine implements ISaveFileEngine { 18 | 19 | private static final String TAG = "SaveFileEngine"; 20 | 21 | private LinkedBlockingQueue mBitmapQueue = new LinkedBlockingQueue<>(); 22 | private boolean exited = false; 23 | private SaveFileThread saveFileThread; 24 | 25 | private class SaveFileThread extends Thread { 26 | 27 | @Override 28 | public void run() { 29 | super.run(); 30 | Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 31 | while (!exited) { 32 | try { 33 | FileBitmapBean item = mBitmapQueue.take(); 34 | FileUtils.saveBitmapToDisk(item.file, item.bitmap); 35 | } catch (InterruptedException e) { 36 | if (exited) { 37 | return; 38 | } 39 | } 40 | } 41 | } 42 | } 43 | 44 | public SaveFileEngine() { 45 | exited = false; 46 | saveFileThread = new SaveFileThread(); 47 | saveFileThread.start(); 48 | } 49 | 50 | @Override 51 | public void addFile(File file, Bitmap bitmap) { 52 | if (!mBitmapQueue.offer(new FileBitmapBean(file, bitmap))) { 53 | ThreadPool.getInstance().getThreadPool().execute(() -> { 54 | try { 55 | mBitmapQueue.put(new FileBitmapBean(file, bitmap)); 56 | } catch (InterruptedException e) { 57 | ZLog.e(TAG, "run: ", e); 58 | } 59 | }); 60 | } 61 | } 62 | 63 | @Override 64 | public void exit() { 65 | exited = true; 66 | saveFileThread.interrupt(); 67 | } 68 | 69 | private class FileBitmapBean { 70 | File file; 71 | Bitmap bitmap; 72 | 73 | FileBitmapBean(File file, Bitmap bitmap) { 74 | this.file = file; 75 | this.bitmap = bitmap; 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/util/SimpleTextWatcher.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.util; 2 | 3 | import android.text.Editable; 4 | import android.text.TextWatcher; 5 | 6 | /** 7 | * Created by ZhangKe on 2019/2/28. 8 | */ 9 | public class SimpleTextWatcher implements TextWatcher { 10 | 11 | @Override 12 | public void beforeTextChanged(CharSequence s, int start, int count, int after) { 13 | 14 | } 15 | 16 | @Override 17 | public void onTextChanged(CharSequence s, int start, int before, int count) { 18 | 19 | } 20 | 21 | @Override 22 | public void afterTextChanged(Editable s) { 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/util/TaxHelper.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.util; 2 | 3 | import java.text.DecimalFormat; 4 | 5 | /** 6 | * Created by ZhangKe on 2019/3/15. 7 | */ 8 | public class TaxHelper { 9 | 10 | /** 11 | * 获取扣税总和 12 | * 13 | * @param salaryArray 每月工资 14 | * @param insurance 五险一金 15 | * @param special 专项附加扣除 16 | */ 17 | public static String getTaxDescription(double[] salaryArray, double insurance, double[] special) { 18 | if (salaryArray == null || salaryArray.length == 0) return ""; 19 | StringBuilder taxBuilder = new StringBuilder(); 20 | DecimalFormat decimalFormat = new DecimalFormat("0.00"); 21 | double taxTotal = 0;//累计扣税 22 | double salaryTotal = 0;//工资累计金额 23 | for (int i = 0; i < salaryArray.length; i++) { 24 | salaryTotal += salaryArray[i]; 25 | double specialTotal = 0; 26 | if (special != null && special.length > 0) { 27 | for (double item : special) { 28 | specialTotal += item * (i + 1); 29 | } 30 | } 31 | //应纳税所得额度 32 | double needTax = salaryTotal - 5000 * (i + 1) - specialTotal - insurance * (i + 1); 33 | double thisMonthTax; 34 | if (needTax >= 960000) { 35 | thisMonthTax = needTax * 0.45 - 181920 - taxTotal; 36 | } else if (needTax >= 660000) { 37 | thisMonthTax = needTax * 0.35 - 85920 - taxTotal; 38 | } else if (needTax >= 420000) { 39 | thisMonthTax = needTax * 0.30 - 52920 - taxTotal; 40 | } else if (needTax >= 300000) { 41 | thisMonthTax = needTax * 0.25 - 31920 - taxTotal; 42 | } else if (needTax >= 144000) { 43 | thisMonthTax = needTax * 0.20 - 16920 - taxTotal; 44 | } else if (needTax >= 36000) { 45 | thisMonthTax = needTax * 0.1 - 2520 - taxTotal; 46 | } else if (needTax > 0) { 47 | thisMonthTax = needTax * 0.03 - taxTotal; 48 | } else { 49 | thisMonthTax = 0; 50 | } 51 | taxTotal += thisMonthTax; 52 | taxBuilder.append(String.format( 53 | "第%s月份工资:%s,应纳税额:%s元,到手工资:%s,当前纳税总额:%s元\n\n", 54 | i + 1, 55 | salaryArray[i], 56 | decimalFormat.format(thisMonthTax), 57 | salaryArray[i] - thisMonthTax - insurance, 58 | decimalFormat.format(taxTotal))); 59 | } 60 | taxBuilder.append("累计扣税:"); 61 | taxBuilder.append(taxTotal); 62 | return taxBuilder.toString(); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/util/ThreadPool.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.util; 2 | 3 | import java.util.concurrent.ExecutorService; 4 | import java.util.concurrent.Executors; 5 | 6 | /** 7 | * 获取线程池对象,单例类 8 | * Created by ZhangKe on 2018/4/23. 9 | */ 10 | public class ThreadPool { 11 | 12 | private static ThreadPool threadPool = null; 13 | 14 | public static ThreadPool getInstance() { 15 | if(threadPool == null){ 16 | synchronized (ThreadPool.class){ 17 | if(threadPool == null){ 18 | threadPool = new ThreadPool(); 19 | } 20 | } 21 | } 22 | return threadPool; 23 | } 24 | 25 | private ExecutorService executorService = Executors.newCachedThreadPool(); 26 | 27 | private ThreadPool() { 28 | } 29 | 30 | public ExecutorService getThreadPool() { 31 | return executorService; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/widget/CustomAutoCompleteTextView.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.widget; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.AppCompatAutoCompleteTextView; 5 | import android.util.AttributeSet; 6 | import android.widget.AutoCompleteTextView; 7 | 8 | /** 9 | * Created by ZhangKe on 2018/7/19. 10 | */ 11 | public class CustomAutoCompleteTextView extends AppCompatAutoCompleteTextView { 12 | 13 | public CustomAutoCompleteTextView(Context context) { 14 | super(context); 15 | } 16 | 17 | public CustomAutoCompleteTextView(Context context, AttributeSet attrs) { 18 | super(context, attrs); 19 | init(); 20 | } 21 | 22 | public CustomAutoCompleteTextView(Context context, AttributeSet attrs, int defStyleAttr) { 23 | super(context, attrs, defStyleAttr); 24 | init(); 25 | } 26 | 27 | private void init() { 28 | post(this::showDropDown); 29 | } 30 | 31 | @Override 32 | public boolean enoughToFilter() { 33 | return true; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/widget/NoScrollViewPager.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.widget; 2 | 3 | import android.content.Context; 4 | import android.support.v4.view.ViewPager; 5 | import android.util.AttributeSet; 6 | import android.view.MotionEvent; 7 | 8 | /** 9 | * Created by ZhangKe on 2018/7/31. 10 | */ 11 | public class NoScrollViewPager extends ViewPager{ 12 | 13 | public NoScrollViewPager(Context context, AttributeSet attrs) { 14 | super(context, attrs); 15 | } 16 | 17 | public NoScrollViewPager(Context context) { 18 | super(context); 19 | } 20 | 21 | @Override 22 | public void scrollTo(int x, int y) { 23 | super.scrollTo(x, y); 24 | } 25 | 26 | @Override 27 | public boolean onTouchEvent(MotionEvent arg0) { 28 | return false; 29 | } 30 | 31 | @Override 32 | public boolean onInterceptTouchEvent(MotionEvent arg0) { 33 | return false; 34 | } 35 | 36 | @Override 37 | public void setCurrentItem(int item, boolean smoothScroll) { 38 | super.setCurrentItem(item, smoothScroll); 39 | } 40 | 41 | @Override 42 | public void setCurrentItem(int item) { 43 | super.setCurrentItem(item); 44 | } 45 | 46 | 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/widget/RoundProgressDialog.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.widget; 2 | 3 | import android.app.ProgressDialog; 4 | import android.content.Context; 5 | 6 | /** 7 | * 加载进度条 8 | * Created by ZhangKe on 2018/4/15. 9 | */ 10 | 11 | public class RoundProgressDialog { 12 | private ProgressDialog progressDialog; 13 | private Context context; 14 | 15 | private RoundProgressDialog() { 16 | } 17 | 18 | public RoundProgressDialog(Context context) { 19 | this.context = context; 20 | } 21 | 22 | /** 23 | * 显示进度条 24 | */ 25 | public void showProgressDialog() { 26 | if (progressDialog == null) { 27 | progressDialog = new ProgressDialog(context); 28 | progressDialog.setMessage("请稍等..."); 29 | progressDialog.setCanceledOnTouchOutside(false); 30 | } 31 | progressDialog.show(); 32 | } 33 | 34 | public boolean isShowing() { 35 | return null != progressDialog && progressDialog.isShowing(); 36 | } 37 | 38 | /** 39 | * 显示进度条 40 | */ 41 | public void showProgressDialog(String msg) { 42 | if (progressDialog == null) { 43 | progressDialog = new ProgressDialog(context); 44 | progressDialog.setMessage(msg); 45 | progressDialog.setCanceledOnTouchOutside(false); 46 | } 47 | progressDialog.show(); 48 | } 49 | 50 | /** 51 | * 关闭进度条 52 | */ 53 | public void closeProgressDialog() { 54 | if (progressDialog != null) { 55 | progressDialog.dismiss(); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhangke/shizhong/widget/SpacesItemDecoration.java: -------------------------------------------------------------------------------- 1 | package com.zhangke.shizhong.widget; 2 | 3 | import android.graphics.Rect; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.View; 6 | 7 | /** 8 | * 上下左右完全没有边距的 ItemDecoration 9 | *

10 | * Created by ZhangKe on 2018/4/22. 11 | */ 12 | 13 | public class SpacesItemDecoration extends RecyclerView.ItemDecoration { 14 | public SpacesItemDecoration() { 15 | } 16 | 17 | @Override 18 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { 19 | outRect.left = 0; 20 | outRect.right = 0; 21 | outRect.bottom = 0; 22 | if (parent.getChildAdapterPosition(view) == 0) { 23 | outRect.top = 0; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/res/anim/dialog_show_scale.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 15 | 16 | 28 | 29 | -------------------------------------------------------------------------------- /app/src/main/res/anim/dismiss.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/anim/item_anim_right_to_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/anim/layout_anim_right_to_left.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/anim/right_to_left_in.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/anim/show.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slogan_01.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slogan_02.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/arrow_down.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/common_btn_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/custom_progress_color.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/svg_add.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/svg_add_light.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/svg_completed.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/svg_delete.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/svg_edit.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/svg_edit_light.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/svg_extend.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/svg_home.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/svg_search.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/svg_todo.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/tab_top_line.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/toolbar_bottom_line.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_add_plan.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | 14 | 15 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_application_statistics.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 16 | 17 | 24 | 25 | 30 | 31 | 39 | 40 | 49 | 50 | 51 | 52 | 57 | 58 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_clock_plan_detail.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 14 | 15 | 16 | 17 | 22 | 23 | 27 | 28 | 49 | 50 | 59 | 60 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_complete_todo.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | 15 | 16 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_input_name.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 13 | 14 | 17 | 18 | 25 | 26 | 32 | 33 | 39 | 40 | 41 |