├── .gitignore ├── CHANGELOG.txt ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── libs │ ├── aboutmsgrender-1.0.0.aar │ ├── globaltoast-1.1.0.aar │ └── sp-1.0.2.aar ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── by_syk │ │ └── mdcolor │ │ ├── BaseActivity.java │ │ ├── DetailsActivity.java │ │ ├── MainActivity.java │ │ ├── fragment │ │ ├── AboutDialog.java │ │ └── HelpDialog.java │ │ └── util │ │ ├── C.java │ │ ├── ExtraUtil.java │ │ ├── Palette.java │ │ ├── TransitionHelper.java │ │ └── adapter │ │ ├── GradesAdapter.java │ │ └── MainAdapter.java │ └── res │ ├── anim │ ├── fab_bottom_in.xml │ ├── fade_in.xml │ └── translate.xml │ ├── animator │ └── fab_elevation.xml │ ├── drawable-anydpi │ ├── ic_action_help_dark.xml │ ├── ic_action_help_light.xml │ ├── ic_action_notification_dark.xml │ ├── ic_action_notification_light.xml │ ├── ic_fab_touch.xml │ ├── ic_head.xml │ ├── ic_head_checked.xml │ ├── ic_notify_pantone.xml │ └── ic_star.xml │ ├── drawable │ ├── fab_oval_ripple.xml │ └── list_item_divider.xml │ ├── layout-land │ ├── activity_main.xml │ ├── view_control_bar.xml │ └── view_ui_board.xml │ ├── layout-sw600dp-land │ └── view_ui_board.xml │ ├── layout-sw600dp │ └── view_ui_board.xml │ ├── layout │ ├── activity_details.xml │ ├── activity_main.xml │ ├── list_item.xml │ ├── list_item_card.xml │ ├── view_control_bar.xml │ └── view_ui_board.xml │ ├── menu │ ├── menu_details.xml │ └── menu_main.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ ├── raw-zh │ └── palette.txt │ ├── raw │ └── palette.txt │ ├── values-land │ └── config.xml │ ├── values-sw600dp │ └── dimens.xml │ ├── values-w820dp │ └── dimens.xml │ ├── values-zh │ └── strings.xml │ └── values │ ├── attrs.xml │ ├── colors.xml │ ├── config.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── art ├── icon.png └── screenshot.png ├── build.gradle ├── out └── com.by_syk.mdcolor.apk └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | /reserve -------------------------------------------------------------------------------- /CHANGELOG.txt: -------------------------------------------------------------------------------- 1 | v1.1.4 2 | - Add notification test. 3 | - Adjust 3 default accent colors. 4 | - Fix: Reset issue. 5 | - Fix: The item color of list is wrong. 6 | 7 | v1.1.1 8 | - No screen flicker while switching colors. 9 | - Support for tablets more better. 10 | 11 | v1.1.0 12 | - Fix: failed to tint buttons on Lollipop. 13 | 14 | v1.0.9 15 | - New launcher icon. (Thank @ToddThink) 16 | - Add UI BOARD for seeing how color affects widgets. 17 | 18 | v1.0.3 19 | - Add Chinese translation partly. 20 | - Fix: star color error. 21 | 22 | v1.0.1 23 | - New launcher icon. 24 | 25 | v1.0.0 26 | - First release. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![icon.png](art/icon.png) 2 | 3 | # Color Reference - Material color palette 4 | 5 | 6 | ### Description 7 | 8 | `"A little rusty on your color theory? Material design makes color easy."` 9 | — Google says. 10 | 11 | **Color Reference** helps you choose a nice primary color for your new Android app. 12 | 13 | ![screenshot.png](art/screenshot.png) 14 | 15 | * To learn more, please visit Google's 16 | [https://www.google.com/design/spec/style/color.html](https://www.google.com/design/spec/style/color.html "Material design - Color") 17 | 18 | * To do it online, please visit MaterialUp's 19 | [http://www.materialpalette.com](http://www.materialpalette.com "Material Design Color Palette Generator - Material Palette") 20 | 21 | 22 | ### Download APK 23 | 24 | * Get it 25 | * on [Google Play](https://play.google.com/store/apps/details?id=com.by_syk.mdcolor "Color Reference") 26 | * on [Cool Market](http://www.coolapk.com/apk/com.by_syk.mdcolor "Color Reference") 27 | * [here](art/com.by_syk.mdcolor.apk "Color Reference") 28 | 29 | 30 | ### Changelog 31 | 32 | * View it [here](CHANGELOG.txt "Changelog"). 33 | 34 | 35 | ### Contact author 36 | 37 | * E-mail: [By_syk@163.com](mailto:By_syk@163.com "By_syk") 38 | 39 | 40 | ### License 41 | 42 | Copyright 2016-2017 By_syk 43 | 44 | Licensed under the Apache License, Version 2.0 (the "License"); 45 | you may not use this file except in compliance with the License. 46 | You may obtain a copy of the License at 47 | 48 | http://www.apache.org/licenses/LICENSE-2.0 49 | 50 | Unless required by applicable law or agreed to in writing, software 51 | distributed under the License is distributed on an "AS IS" BASIS, 52 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 53 | See the License for the specific language governing permissions and 54 | limitations under the License. 55 | 56 | 57 | *Copyright © 2016-2017 By_syk. All rights reserved.* -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "25.0.2" 6 | 7 | defaultConfig { 8 | applicationId "com.by_syk.mdcolor" 9 | minSdkVersion 21 10 | targetSdkVersion 25 11 | versionCode 17011600 12 | versionName "1.1.5.nightly" 13 | } 14 | 15 | buildTypes { 16 | release { 17 | shrinkResources true 18 | minifyEnabled true 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | } 22 | } 23 | 24 | repositories { 25 | flatDir { 26 | dirs 'libs' 27 | } 28 | } 29 | 30 | dependencies { 31 | compile fileTree(dir: 'libs', include: ['*.jar']) 32 | 33 | testCompile 'junit:junit:4.12' 34 | 35 | compile (name:'sp-1.0.2', ext:'aar') 36 | compile (name:'globaltoast-1.1.0', ext:'aar') 37 | compile(name:'aboutmsgrender-1.0.0', ext:'aar') 38 | 39 | compile 'com.android.support:cardview-v7:25.1.0' 40 | //compile 'com.android.support:appcompat-v7:23.2.1' 41 | 42 | //compile 'me.imid.swipebacklayout.lib:library:1.0.0' 43 | } 44 | -------------------------------------------------------------------------------- /app/libs/aboutmsgrender-1.0.0.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/by-syk/ColorReference/3811fd5948d33a4230d5abc57280dfb476d9c2ed/app/libs/aboutmsgrender-1.0.0.aar -------------------------------------------------------------------------------- /app/libs/globaltoast-1.1.0.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/by-syk/ColorReference/3811fd5948d33a4230d5abc57280dfb476d9c2ed/app/libs/globaltoast-1.1.0.aar -------------------------------------------------------------------------------- /app/libs/sp-1.0.2.aar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/by-syk/ColorReference/3811fd5948d33a4230d5abc57280dfb476d9c2ed/app/libs/sp-1.0.2.aar -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\Android\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 20 | 21 | 27 | 28 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/by_syk/mdcolor/BaseActivity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016-2017 By_syk 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.by_syk.mdcolor; 18 | 19 | import android.app.Activity; 20 | import android.os.Bundle; 21 | 22 | import com.by_syk.lib.storage.SP; 23 | import com.by_syk.mdcolor.util.C; 24 | 25 | /** 26 | * Created by By_syk on 2016-03-31. 27 | */ 28 | public class BaseActivity extends Activity { 29 | protected SP sp = null; 30 | 31 | public static final int[] DEFAULT_THEME_ID = {R.style.AppThemeDark, 32 | R.style.AppThemeLight, R.style.AppThemeLightD}; 33 | public static final int[][] THEMES_ID = { 34 | {R.style.AppThemeDark_Red, R.style.AppThemeLight_Red, R.style.AppThemeLightD_Red}, 35 | {R.style.AppThemeDark_Pink, R.style.AppThemeLight_Pink, R.style.AppThemeLightD_Pink}, 36 | {R.style.AppThemeDark_Purple, R.style.AppThemeLight_Purple, R.style.AppThemeLightD_Purple}, 37 | {R.style.AppThemeDark_DeepPurple, R.style.AppThemeLight_DeepPurple, R.style.AppThemeLightD_DeepPurple}, 38 | {R.style.AppThemeDark_Indigo, R.style.AppThemeLight_Indigo, R.style.AppThemeLightD_Indigo}, 39 | {R.style.AppThemeDark_Blue, R.style.AppThemeLight_Blue, R.style.AppThemeLightD_Blue}, 40 | {R.style.AppThemeDark_LightBlue, R.style.AppThemeLight_LightBlue, R.style.AppThemeLightD_LightBlue}, 41 | {R.style.AppThemeDark_Cyan, R.style.AppThemeLight_Cyan, R.style.AppThemeLightD_Cyan}, 42 | {R.style.AppThemeDark_Teal, R.style.AppThemeLight_Teal, R.style.AppThemeLightD_Teal}, 43 | {R.style.AppThemeDark_Green, R.style.AppThemeLight_Green, R.style.AppThemeLightD_Green}, 44 | {R.style.AppThemeDark_LightGreen, R.style.AppThemeLight_LightGreen, R.style.AppThemeLightD_LightGreen}, 45 | {R.style.AppThemeDark_Lime, R.style.AppThemeLight_Lime, R.style.AppThemeLightD_Lime}, 46 | {R.style.AppThemeDark_Yellow, R.style.AppThemeLight_Yellow, R.style.AppThemeLightD_Yellow}, 47 | {R.style.AppThemeDark_Amber, R.style.AppThemeLight_Amber, R.style.AppThemeLightD_Amber}, 48 | {R.style.AppThemeDark_Orange, R.style.AppThemeLight_Orange, R.style.AppThemeLightD_Orange}, 49 | {R.style.AppThemeDark_DeepOrange, R.style.AppThemeLight_DeepOrange, R.style.AppThemeLightD_DeepOrange}, 50 | {R.style.AppThemeDark_Brown, R.style.AppThemeLight_Brown, R.style.AppThemeLightD_Brown}, 51 | {R.style.AppThemeDark_Grey, R.style.AppThemeLight_Grey, R.style.AppThemeLightD_Grey}, 52 | {R.style.AppThemeDark_BlueGrey, R.style.AppThemeLight_BlueGrey, R.style.AppThemeLightD_BlueGrey}, 53 | }; 54 | public static final int[] DIALOG_THEME_ID = {R.style.DialogThemeDark, 55 | R.style.DialogThemeLight, R.style.DialogThemeLight}; 56 | 57 | @Override 58 | protected void onCreate(Bundle savedInstanceState) { 59 | sp = new SP(this, false); 60 | 61 | int themeColor = sp.getInt(C.SP_THEME_COLOR, -1); 62 | int themeStyle = sp.getInt(C.SP_THEME_STYLE); 63 | boolean withDarkAb = sp.getBoolean(C.SP_WITH_DARK_AB); 64 | 65 | if (themeColor >= 0 && themeColor < THEMES_ID.length) { 66 | if (themeStyle == 0) { 67 | setTheme(THEMES_ID[themeColor][0]); 68 | } else { 69 | setTheme(THEMES_ID[themeColor][withDarkAb ? 2 : 1]); 70 | } 71 | } else { 72 | setTheme(DEFAULT_THEME_ID[themeStyle]); 73 | } 74 | 75 | super.onCreate(savedInstanceState); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /app/src/main/java/com/by_syk/mdcolor/DetailsActivity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016-2017 By_syk 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.by_syk.mdcolor; 18 | 19 | import android.app.ActionBar; 20 | import android.content.ClipData; 21 | import android.content.ClipboardManager; 22 | import android.content.Intent; 23 | import android.os.Bundle; 24 | import android.view.Menu; 25 | import android.view.MenuItem; 26 | import android.view.View; 27 | import android.widget.AdapterView; 28 | import android.widget.ListView; 29 | 30 | import com.by_syk.lib.toast.GlobalToast; 31 | import com.by_syk.mdcolor.fragment.HelpDialog; 32 | import com.by_syk.mdcolor.util.C; 33 | import com.by_syk.mdcolor.util.adapter.GradesAdapter; 34 | import com.by_syk.mdcolor.util.Palette; 35 | 36 | /** 37 | * Created by By_syk on 2016-04-01. 38 | */ 39 | public class DetailsActivity extends BaseActivity { 40 | private ListView lvGrades; 41 | 42 | private GradesAdapter gradesAdapter = null; 43 | private Palette palette = null; 44 | 45 | @Override 46 | protected void onCreate(Bundle savedInstanceState) { 47 | super.onCreate(savedInstanceState); 48 | 49 | /*// Translucent navigation bar 50 | // android:fitsSystemWindows="true" 51 | if (!getResources().getBoolean(R.bool.is_land)) { 52 | getWindow().setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, 53 | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); 54 | }*/ 55 | 56 | setContentView(R.layout.activity_details); 57 | 58 | init(); 59 | 60 | // Tell users how to copy color values. 61 | // Just once. 62 | copyToast(); 63 | } 64 | 65 | private void init() { 66 | Intent intent = getIntent(); 67 | palette = (Palette) intent.getSerializableExtra("palette"); 68 | 69 | ActionBar actionBar = getActionBar(); 70 | if (actionBar != null) { 71 | actionBar.setDisplayHomeAsUpEnabled(true); 72 | actionBar.setTitle(palette.getName()); 73 | } 74 | 75 | lvGrades = (ListView) findViewById(R.id.lv_grades); 76 | 77 | gradesAdapter = new GradesAdapter(this, palette); 78 | lvGrades.setAdapter(gradesAdapter); 79 | 80 | lvGrades.setOnItemClickListener(new AdapterView.OnItemClickListener() { 81 | @Override 82 | public void onItemClick(AdapterView parent, View view, int position, long id) { 83 | copy2Clipboard(palette.getColorStr(position)); 84 | 85 | // Do not show again. 86 | sp.save(C.SP_TOAST_COPY, false); 87 | } 88 | }); 89 | } 90 | 91 | private void copyToast() { 92 | if (sp.getBoolean(C.SP_TOAST_COPY, true)) { 93 | GlobalToast.showToast(this, R.string.toast_tap_card_to_copy); 94 | 95 | //sp.save(C.SP_TOAST_COPY, false); 96 | } 97 | } 98 | 99 | private void copy2Clipboard(String text) { 100 | if (text == null) { 101 | return; 102 | } 103 | 104 | ClipboardManager clipboardManager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE); 105 | clipboardManager.setPrimaryClip(ClipData.newPlainText(null, text)); 106 | 107 | GlobalToast.showToast(DetailsActivity.this, getString(R.string.toast_copied, text)); 108 | } 109 | 110 | @Override 111 | public boolean onCreateOptionsMenu(Menu menu) { 112 | getMenuInflater().inflate(R.menu.menu_details, menu); 113 | 114 | return true; 115 | } 116 | 117 | @Override 118 | public boolean onOptionsItemSelected(MenuItem item) { 119 | switch (item.getItemId()) { 120 | case android.R.id.home: 121 | finish(); 122 | return true; 123 | case R.id.menu_help: 124 | (new HelpDialog()).show(getFragmentManager(), "helpDialog"); 125 | return true; 126 | default: 127 | return super.onOptionsItemSelected(item); 128 | } 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /app/src/main/java/com/by_syk/mdcolor/MainActivity.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016-2017 By_syk 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.by_syk.mdcolor; 18 | 19 | import android.app.Notification; 20 | import android.app.NotificationManager; 21 | import android.app.PendingIntent; 22 | import android.content.Intent; 23 | import android.os.AsyncTask; 24 | import android.os.Bundle; 25 | import android.os.Handler; 26 | import android.util.Log; 27 | import android.util.TypedValue; 28 | import android.view.Menu; 29 | import android.view.MenuItem; 30 | import android.view.View; 31 | import android.view.ViewStub; 32 | import android.view.animation.AnimationUtils; 33 | import android.widget.AdapterView; 34 | import android.widget.CompoundButton; 35 | import android.widget.ImageButton; 36 | import android.widget.ListView; 37 | import android.widget.RadioGroup; 38 | import android.widget.Switch; 39 | 40 | import com.by_syk.lib.toast.GlobalToast; 41 | import com.by_syk.mdcolor.fragment.AboutDialog; 42 | import com.by_syk.mdcolor.util.C; 43 | import com.by_syk.mdcolor.util.Palette; 44 | import com.by_syk.mdcolor.util.TransitionHelper; 45 | import com.by_syk.mdcolor.util.adapter.MainAdapter; 46 | 47 | import java.io.BufferedReader; 48 | import java.io.IOException; 49 | import java.io.InputStreamReader; 50 | import java.util.ArrayList; 51 | import java.util.List; 52 | import java.util.Random; 53 | 54 | public class MainActivity extends BaseActivity { 55 | private ListView lvColors; 56 | private Switch switchBoard; 57 | private View viewControlBar; 58 | private View viewUIBoard; 59 | private ImageButton fabLucky; 60 | 61 | private MainAdapter mainAdapter = null; 62 | 63 | private NotificationManager notificationManager; 64 | 65 | private static Handler handler = new Handler(); 66 | 67 | @Override 68 | protected void onCreate(Bundle savedInstanceState) { 69 | super.onCreate(savedInstanceState); 70 | setContentView(R.layout.activity_main); 71 | 72 | init(); 73 | 74 | (new LoadColorsTask()).execute(); 75 | 76 | TransitionHelper.getInstance().onActivityCreate(this); 77 | } 78 | 79 | @Override 80 | protected void onPostCreate(Bundle savedInstanceState) { 81 | Log.d(C.LOG_TAG, "onPostCreate"); 82 | 83 | super.onPostCreate(savedInstanceState); 84 | 85 | handler.postDelayed(new Runnable() { 86 | @Override 87 | public void run() { 88 | fabLucky.setVisibility(View.VISIBLE); 89 | fabLucky.setAnimation(AnimationUtils 90 | .loadAnimation(MainActivity.this, R.anim.fab_bottom_in)); 91 | } 92 | }, 134); 93 | } 94 | 95 | @Override 96 | protected void onDestroy() { 97 | super.onDestroy(); 98 | 99 | cancelNotification(); 100 | } 101 | 102 | private void init() { 103 | viewControlBar = findViewById(R.id.view_control_bar); 104 | switchBoard = (Switch) findViewById(R.id.switch_board); 105 | fabLucky = (ImageButton) findViewById(R.id.fab_lucky); 106 | 107 | // Sets the data behind the ListView. 108 | mainAdapter = new MainAdapter(this, sp.getInt(C.SP_THEME_COLOR, -1)); 109 | lvColors = (ListView) findViewById(R.id.lv_colors); 110 | lvColors.setAdapter(mainAdapter); 111 | 112 | //lvColors.setChoiceMode(ListView.CHOICE_MODE_SINGLE); 113 | 114 | lvColors.setOnItemClickListener(new AdapterView.OnItemClickListener() { 115 | @Override 116 | public void onItemClick(AdapterView parent, View view, int position, long id) { 117 | if (position == sp.getInt(C.SP_THEME_COLOR, -1)) { 118 | gotoDetails(position); 119 | return; 120 | } 121 | 122 | // Tell users how to view details. 123 | // Just once. 124 | viewDetailsToast(); 125 | 126 | sp.put(C.SP_THEME_COLOR, position).put(C.SP_WITH_DARK_AB, 127 | mainAdapter.getItem(position).isLightThemeWithDarkABSuggested()) 128 | .save(); 129 | 130 | changeTheme(); 131 | } 132 | }); 133 | 134 | RadioGroup radioGroup = (RadioGroup) findViewById(R.id.rg_themes); 135 | radioGroup.check(switchRadioButtonOrderAndId(sp.getInt(C.SP_THEME_STYLE))); 136 | radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { 137 | @Override 138 | public void onCheckedChanged(RadioGroup group, int checkedId) { 139 | int theme_style = switchRadioButtonOrderAndId(checkedId); 140 | if (theme_style == -1) { 141 | return; 142 | } 143 | 144 | sp.save(C.SP_THEME_STYLE, theme_style); 145 | 146 | changeTheme(); 147 | } 148 | }); 149 | 150 | initControlAndUIBoard(); 151 | 152 | initFab(); 153 | } 154 | 155 | private void initControlAndUIBoard() { 156 | // As default, off if in portrait, and on if in landscape. 157 | if (sp.getBoolean(C.SP_UI_BOARD, getResources().getBoolean(R.bool.is_land))) { 158 | viewUIBoard = ((ViewStub) findViewById(R.id.vs_ui_board)).inflate(); 159 | switchBoard.setChecked(true); 160 | } 161 | 162 | switchBoard.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 163 | @Override 164 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 165 | sp.save(C.SP_UI_BOARD, isChecked); 166 | 167 | if (isChecked) { // Show the UI board. 168 | if (viewUIBoard == null) { 169 | viewUIBoard = ((ViewStub) findViewById(R.id.vs_ui_board)).inflate(); 170 | } else { 171 | viewUIBoard.setVisibility(View.VISIBLE); 172 | } 173 | 174 | if (!getResources().getBoolean(R.bool.is_land)) { 175 | viewControlBar.startAnimation(AnimationUtils.loadAnimation(MainActivity.this, 176 | R.anim.translate)); 177 | } 178 | viewUIBoard.startAnimation(AnimationUtils.loadAnimation(MainActivity.this, 179 | R.anim.fade_in)); 180 | } else { // Hide the UI board. 181 | viewUIBoard.setVisibility(View.GONE); 182 | } 183 | } 184 | }); 185 | 186 | viewControlBar.setOnClickListener(new View.OnClickListener() { 187 | @Override 188 | public void onClick(View v) { 189 | //switchBoard.clearFocus(); 190 | 191 | switchBoard.performClick(); 192 | } 193 | }); 194 | /*viewControlBar.setOnTouchListener(new View.OnTouchListener() { 195 | @Override 196 | public boolean onTouch(View v, MotionEvent event) { 197 | switchBoard.requestFocusFromTouch(); 198 | return false; 199 | } 200 | });*/ 201 | } 202 | 203 | private void initFab() { 204 | /*fabLucky.setImageResource(System.currentTimeMillis() % 2 == 0 205 | ? R.drawable.ic_fab_random : R.drawable.ic_fab_random2); 206 | fabLucky.setImageResource(sharedPreferences.getInt(C.SP_THEME_STYLE, 0) == 0 207 | ? R.drawable.ic_fab_random : R.drawable.ic_fab_random2);*/ 208 | 209 | fabLucky.setOnClickListener(new View.OnClickListener() { 210 | @Override 211 | public void onClick(View v) { 212 | // Choose a random number except for current one. 213 | Random random = new Random(); 214 | int lucky_one; 215 | do { 216 | lucky_one = random.nextInt(mainAdapter.getCount()); 217 | } while (lucky_one == mainAdapter.getChecked()); 218 | 219 | sp.put(C.SP_THEME_COLOR, lucky_one) 220 | .put(C.SP_WITH_DARK_AB, mainAdapter.getItem(lucky_one) 221 | .isLightThemeWithDarkABSuggested()) 222 | .save(); 223 | 224 | GlobalToast.showToast(MainActivity.this, getString(R.string.toast_lucky_color, 225 | mainAdapter.getItem(lucky_one).getName())); 226 | 227 | changeTheme(); 228 | } 229 | }); 230 | fabLucky.setOnLongClickListener(new View.OnLongClickListener() { 231 | @Override 232 | public boolean onLongClick(View v) { 233 | GlobalToast.showToast(MainActivity.this, R.string.menu_lucky); 234 | 235 | return true; 236 | } 237 | }); 238 | 239 | //fabLucky.setVisibility(View.VISIBLE); 240 | //fabLucky.setAnimation(AnimationUtils.loadAnimation(this, R.anim.fab_bottom_in)); 241 | } 242 | 243 | /*private void showTips() { 244 | if (sp.getBoolean(C.SP_BOARD, true) && sp.getInt(C.SP_THEME_COLOR, -1) >= 0) { 245 | viewTip = ((ViewStub) findViewById(R.id.vs_tip)).inflate(); 246 | 247 | viewTip.findViewById(R.id.bt_hide_tip).setOnClickListener(new View.OnClickListener() { 248 | @Override 249 | public void onClick(View v) { 250 | viewTip.setVisibility(View.GONE); 251 | 252 | sp.save(C.SP_BOARD, false); 253 | } 254 | }); 255 | 256 | viewTip.startAnimation(AnimationUtils.loadAnimation(this, R.anim.alpha_in)); 257 | } 258 | }*/ 259 | 260 | private void gotoDetails(int which) { 261 | // Do not show toast again. 262 | sp.save(C.SP_TOAST_DETAILS, false); 263 | 264 | Intent intent = new Intent(this, DetailsActivity.class); 265 | intent.putExtra("palette", mainAdapter.getItem(which)); 266 | 267 | startActivity(intent); 268 | } 269 | 270 | private void viewDetailsToast() { 271 | if (sp.getBoolean(C.SP_TOAST_DETAILS, true)) { 272 | GlobalToast.showToast(this, R.string.toast_tap_again_details); 273 | 274 | //sp.save(C.SP_TOAST_DETAILS, false); 275 | } 276 | } 277 | 278 | private int switchRadioButtonOrderAndId(int i) { 279 | switch (i) { 280 | case 0: 281 | return R.id.rb_dark_theme; 282 | case 1: 283 | return R.id.rb_light_theme; 284 | case R.id.rb_dark_theme: 285 | return 0; 286 | case R.id.rb_light_theme: 287 | return 1; 288 | //case R.id.rb_light_with_dark_theme: 289 | // return 2; 290 | default: 291 | return -1; 292 | } 293 | } 294 | 295 | private class LoadColorsTask extends AsyncTask> { 296 | @Override 297 | protected List doInBackground(String... params) { 298 | return loadColors(); 299 | } 300 | 301 | @Override 302 | protected void onPostExecute(List dataList) { 303 | super.onPostExecute(dataList); 304 | 305 | mainAdapter.notifyRefresh(dataList); 306 | //mainAdapter.notifyDataSetChanged(); 307 | 308 | //lvColors.smoothScrollToPosition(sharedPreferences.getInt(C.SP_THEME_COLOR, 0)); 309 | lvColors.setSelection(sp.getInt(C.SP_THEME_COLOR)); 310 | } 311 | } 312 | 313 | private List loadColors() { 314 | List dataList = new ArrayList<>(); 315 | 316 | BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(getResources() 317 | .openRawResource(R.raw.palette))); 318 | 319 | Palette palette; 320 | String tempStr; 321 | try { 322 | while ((tempStr = bufferedReader.readLine()) != null) { 323 | if (tempStr.startsWith("# ")) { 324 | continue; 325 | } 326 | 327 | palette = new Palette(); 328 | boolean is_ok = palette.setAll(tempStr); 329 | if (!is_ok) { 330 | continue; 331 | } 332 | 333 | dataList.add(palette); 334 | } 335 | } catch (IOException e) { 336 | e.printStackTrace(); 337 | } 338 | 339 | return dataList; 340 | } 341 | 342 | private void changeTheme() { 343 | // Shine!!! 344 | //recreate(); 345 | 346 | TransitionHelper.getInstance().onRestartActivity(this); 347 | startActivity(new Intent(this, MainActivity.class)); 348 | finish(); 349 | overridePendingTransition(0, 0); 350 | } 351 | 352 | private void showNotification() { 353 | TypedValue typedValue = new TypedValue(); 354 | getTheme().resolveAttribute(R.attr.colorPrimary, typedValue, true); 355 | int primaryColor = typedValue.data; 356 | 357 | Notification.Builder builder = new Notification.Builder(this) 358 | .setSmallIcon(R.drawable.ic_notify_pantone) 359 | //.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)) 360 | .setColor(primaryColor) 361 | .setPriority(Notification.PRIORITY_LOW) 362 | .setAutoCancel(true) 363 | .setFullScreenIntent(PendingIntent.getActivity(this, 0, new Intent(), 0), false); 364 | if (C.SDK >= 24) { 365 | builder.setContentTitle(getString(R.string.notify_content)); 366 | } else { 367 | builder.setContentTitle(getString(R.string.notify_title)); 368 | builder.setContentText(getString(R.string.notify_content)); 369 | } 370 | 371 | if (notificationManager == null) { 372 | notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); 373 | } 374 | notificationManager.notify(1, builder.build()); 375 | } 376 | 377 | private void cancelNotification() { 378 | if (notificationManager != null) { 379 | notificationManager.cancel(1); 380 | } 381 | } 382 | 383 | @Override 384 | public boolean onCreateOptionsMenu(Menu menu) { 385 | getMenuInflater().inflate(R.menu.menu_main, menu); 386 | return true; 387 | } 388 | 389 | @Override 390 | public boolean onOptionsItemSelected(MenuItem item) { 391 | switch (item.getItemId()) { 392 | case R.id.menu_notification: 393 | showNotification(); 394 | return true; 395 | case R.id.menu_reset: { 396 | sp.delete(C.SP_THEME_COLOR); 397 | sp.delete(C.SP_THEME_STYLE); 398 | 399 | GlobalToast.showToast(this, R.string.toast_reset); 400 | 401 | handler.postDelayed(new Runnable() { 402 | @Override 403 | public void run() { 404 | /*// Instead of this: 405 | // ((RadioGroup) findViewById(R.id.rg_themes)).check(R.id.rb_dark_theme); 406 | 407 | ((RadioGroup) findViewById(R.id.rg_themes)).clearCheck(); 408 | ((RadioButton) findViewById(R.id.rb_dark_theme)).setChecked(true);*/ 409 | 410 | changeTheme(); 411 | } 412 | }, 400); 413 | 414 | return true; 415 | } 416 | case R.id.menu_about: 417 | (new AboutDialog()).show(getFragmentManager(), "aboutDialog"); 418 | return true; 419 | default: 420 | return super.onOptionsItemSelected(item); 421 | } 422 | } 423 | } 424 | -------------------------------------------------------------------------------- /app/src/main/java/com/by_syk/mdcolor/fragment/AboutDialog.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016-2017 By_syk 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.by_syk.mdcolor.fragment; 18 | 19 | import android.app.AlertDialog; 20 | import android.app.Dialog; 21 | import android.app.DialogFragment; 22 | import android.content.DialogInterface; 23 | import android.os.Bundle; 24 | import android.text.SpannableString; 25 | import android.text.method.LinkMovementMethod; 26 | import android.widget.TextView; 27 | 28 | import com.by_syk.lib.storage.SP; 29 | import com.by_syk.lib.text.AboutMsgRender; 30 | import com.by_syk.mdcolor.BaseActivity; 31 | import com.by_syk.mdcolor.R; 32 | import com.by_syk.mdcolor.util.C; 33 | import com.by_syk.mdcolor.util.ExtraUtil; 34 | 35 | /** 36 | * Created by By_syk on 2017-01-14. 37 | */ 38 | 39 | public class AboutDialog extends DialogFragment { 40 | private boolean isExecuted = false; 41 | 42 | @Override 43 | public Dialog onCreateDialog(Bundle savedInstanceState) { 44 | SpannableString message = AboutMsgRender.render(getActivity(), getString(R.string.about_desc)); 45 | 46 | return getDialogBuilder() 47 | .setTitle(R.string.dlg_title_about) 48 | .setMessage(message) 49 | .setPositiveButton(R.string.dlg_bt_ok, null) 50 | .setNegativeButton(R.string.dlg_bt_rate_me, new DialogInterface.OnClickListener() { 51 | @Override 52 | public void onClick(DialogInterface dialogInterface, int i) { 53 | ExtraUtil.gotoMarket(getActivity(), false); 54 | } 55 | }) 56 | .create(); 57 | } 58 | 59 | @Override 60 | public void onStart() { 61 | super.onStart(); 62 | 63 | if (!isExecuted) { 64 | isExecuted = true; 65 | 66 | // Make the url text clickable. 67 | TextView tvMessage = (TextView) getDialog().findViewById(android.R.id.message); 68 | if (tvMessage != null) { 69 | tvMessage.setMovementMethod(LinkMovementMethod.getInstance()); 70 | } 71 | } 72 | } 73 | 74 | private AlertDialog.Builder getDialogBuilder() { 75 | if (/*C.SDK >= 21 && */C.SDK < 23) { 76 | SP sp = new SP(getActivity(), false); 77 | if (sp.getInt(C.SP_THEME_COLOR, -1) >= 0) { 78 | return new AlertDialog.Builder(getActivity(), 79 | BaseActivity.DIALOG_THEME_ID[sp.getInt(C.SP_THEME_STYLE)]); 80 | } 81 | } 82 | 83 | return new AlertDialog.Builder(getActivity()); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /app/src/main/java/com/by_syk/mdcolor/fragment/HelpDialog.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016-2017 By_syk 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.by_syk.mdcolor.fragment; 18 | 19 | import android.app.AlertDialog; 20 | import android.app.Dialog; 21 | import android.app.DialogFragment; 22 | import android.os.Bundle; 23 | import android.text.Spannable; 24 | import android.text.SpannableString; 25 | import android.text.style.UnderlineSpan; 26 | 27 | import com.by_syk.lib.storage.SP; 28 | import com.by_syk.mdcolor.BaseActivity; 29 | import com.by_syk.mdcolor.R; 30 | import com.by_syk.mdcolor.util.C; 31 | 32 | /** 33 | * Created by By_syk on 2017-01-14. 34 | */ 35 | 36 | public class HelpDialog extends DialogFragment { 37 | @Override 38 | public Dialog onCreateDialog(Bundle savedInstanceState) { 39 | // String message = getString(R.string.help_desc); 40 | // 41 | // // Add underlines for words: 500, 700, A200, A400. 42 | // SpannableString spannableString = new SpannableString(message); 43 | // int index = message.indexOf("500"); 44 | // //new ForegroundColorSpan(palette.getColor(500)) 45 | // spannableString.setSpan(new UnderlineSpan(), index, index + 3, 46 | // Spannable.SPAN_INCLUSIVE_EXCLUSIVE); 47 | // index = message.indexOf("700"); 48 | // spannableString.setSpan(new UnderlineSpan(), index, index + 3, 49 | // Spannable.SPAN_INCLUSIVE_EXCLUSIVE); 50 | // index = message.indexOf("A200"); 51 | // spannableString.setSpan(new UnderlineSpan(), index, index + 4, 52 | // Spannable.SPAN_INCLUSIVE_EXCLUSIVE); 53 | // index = message.indexOf("A400"); 54 | // spannableString.setSpan(new UnderlineSpan(), index, index + 4, 55 | // Spannable.SPAN_INCLUSIVE_EXCLUSIVE); 56 | 57 | return getDialogBuilder() 58 | .setTitle(R.string.dlg_title_help) 59 | .setMessage(R.string.help_desc) 60 | .setPositiveButton(R.string.dlg_bt_got_it, null) 61 | .create(); 62 | } 63 | 64 | private AlertDialog.Builder getDialogBuilder() { 65 | if (/*C.SDK >= 21 && */C.SDK < 23) { 66 | SP sp = new SP(getActivity(), false); 67 | if (sp.getInt(C.SP_THEME_COLOR, -1) >= 0) { 68 | return new AlertDialog.Builder(getActivity(), 69 | BaseActivity.DIALOG_THEME_ID[sp.getInt(C.SP_THEME_STYLE)]); 70 | } 71 | } 72 | 73 | return new AlertDialog.Builder(getActivity()); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /app/src/main/java/com/by_syk/mdcolor/util/C.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016-2017 By_syk 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.by_syk.mdcolor.util; 18 | 19 | import android.os.Build; 20 | 21 | /** 22 | * Created by By_syk on 2016-03-31. 23 | */ 24 | public class C { 25 | public final static int SDK = Build.VERSION.SDK_INT; 26 | 27 | public final static String LOG_TAG = "COLOR_REFERENCE"; 28 | 29 | public final static String SP_THEME_COLOR = "theme_color"; 30 | public final static String SP_THEME_STYLE = "theme_style"; 31 | public final static String SP_WITH_DARK_AB = "theme_style_light_with_dark"; 32 | public final static String SP_UI_BOARD = "show_ui_board"; 33 | public final static String SP_TOAST_DETAILS = "toast_view_details"; 34 | public final static String SP_TOAST_COPY = "toast_copy_color"; 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/by_syk/mdcolor/util/ExtraUtil.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016-2017 By_syk 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.by_syk.mdcolor.util; 18 | 19 | import android.content.ActivityNotFoundException; 20 | import android.content.Context; 21 | import android.content.Intent; 22 | import android.net.Uri; 23 | 24 | /** 25 | * Created by By_syk on 2016-03-31. 26 | */ 27 | public class ExtraUtil { 28 | /** 29 | * Go to app market to view details of this app. 30 | * 31 | * @param viaBrowser Whether view via browser or client app. 32 | */ 33 | public static void gotoMarket(Context context, boolean viaBrowser) { 34 | String packageName = context.getPackageName(); 35 | 36 | final String LINK = String.format((viaBrowser 37 | ? "https://play.google.com/store/apps/details?id=%s" 38 | : "market://details?id=%s"), packageName); 39 | 40 | Intent intent = new Intent(Intent.ACTION_VIEW); 41 | intent.setData(Uri.parse(LINK)); 42 | 43 | try { 44 | context.startActivity(intent); 45 | } catch (ActivityNotFoundException e) { 46 | e.printStackTrace(); 47 | 48 | if (!viaBrowser) { 49 | gotoMarket(context, true); 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/by_syk/mdcolor/util/Palette.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016-2017 By_syk 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.by_syk.mdcolor.util; 18 | 19 | import android.graphics.Color; 20 | import android.text.TextUtils; 21 | 22 | import java.io.Serializable; 23 | 24 | /** 25 | * Created by By_syk on 2016-03-31. 26 | */ 27 | public class Palette implements Serializable { 28 | private final int NUM = 14; 29 | 30 | // Color name 31 | private String name = ""; 32 | 33 | /* 34 | * 共11个或14个:50、100、200、300、400、500、600、700、800、900、(A100、A200、A400、A700) 35 | * 默认值为0,即透明 36 | */ 37 | private int[] colors = new int[NUM]; 38 | /* 39 | * 共11个或14个 40 | * 背景之上的建议文字颜色 41 | */ 42 | private int[] colorsFloatingText = new int[NUM]; 43 | // The name of color versions 44 | private String[] gradeNames = {"50", "100", "200", "300", "400", "500", "600", "700", "800", "900", 45 | "A100", "A200", "A400", "A700" 46 | }; 47 | 48 | private int primaryColorOrder = 5; 49 | private int darkPrimaryColorOrder = 7; 50 | private int accentColorOrder = 11; 51 | 52 | private int size = NUM; 53 | 54 | public Palette() {} 55 | 56 | public Palette(String csvData) { 57 | setAll(csvData); 58 | } 59 | 60 | public Palette(String name, int[] colors) { 61 | setName(name); 62 | 63 | setColors(colors); 64 | } 65 | 66 | private int getArrOrder(int i) { 67 | if (i >= 0 && i < size) { 68 | return i; 69 | } 70 | 71 | switch (i) { 72 | case 50: 73 | return 0; 74 | case 100: 75 | return 1; 76 | case 200: 77 | return 2; 78 | case 300: 79 | return 3; 80 | case 400: 81 | return 4; 82 | case 500: 83 | return 5; 84 | case 600: 85 | return 6; 86 | case 700: 87 | return 7; 88 | case 800: 89 | return 8; 90 | case 900: 91 | return 9; 92 | case 1100: 93 | return 10; 94 | case 1200: 95 | return 11; 96 | case 1400: 97 | return 12; 98 | case 1700: 99 | return 13; 100 | default: 101 | return -1; 102 | } 103 | } 104 | 105 | /** 106 | * @param csvData Like: 107 | * Red, 108 | * 6,8,12, 109 | * #FFEBEE,#000000, 110 | * #FFCDD2,#000000, 111 | * #EF9A9A,#000000, 112 | * #E57373,#000000, 113 | * #EF5350,#FFFFFF, 114 | * #F44336,#FFFFFF, 115 | * #E53935,#FFFFFF, 116 | * #D32F2F,#FFFFFF, 117 | * #C62828,#FFFFFF, 118 | * #B71C1C,#FFFFFF, 119 | * #FF8A80,#000000, 120 | * #FF5252,#FFFFFF, 121 | * #FF1744,#FFFFFF, 122 | * #D50000,#FFFFFF 123 | */ 124 | public boolean setAll(String csvData) { 125 | if (TextUtils.isEmpty(csvData)) { 126 | return false; 127 | } 128 | 129 | String[] data = csvData.split(","); 130 | 131 | setName(data[0]); 132 | 133 | try { 134 | primaryColorOrder = Integer.parseInt(data[1]) - 1; 135 | darkPrimaryColorOrder = Integer.parseInt(data[2]) - 1; 136 | accentColorOrder = Integer.parseInt(data[3]) - 1; 137 | 138 | for (int i = 4, len = data.length; i < len; i += 2) { 139 | colors[(i - 4) / 2] = Color.parseColor(data[i]); 140 | colorsFloatingText[(i - 4) / 2] = Color.parseColor(data[i + 1]); 141 | } 142 | 143 | size = (data.length - 4) / 2; 144 | 145 | return true; 146 | } catch (IllegalArgumentException e) { 147 | e.printStackTrace(); 148 | } 149 | 150 | return false; 151 | } 152 | 153 | public boolean setName(String name) { 154 | if (name == null) { 155 | return false; 156 | } 157 | 158 | this.name = name; 159 | 160 | return true; 161 | } 162 | 163 | public String getName() { 164 | return name; 165 | } 166 | 167 | public boolean setColors(int[] colors) { 168 | if (colors == null) { 169 | return false; 170 | } 171 | 172 | for (int i = 0, len = colors.length; i < len; ++i) { 173 | this.colors[i] = colors[i]; 174 | } 175 | 176 | size = colors.length; 177 | 178 | for (int i = 0; i < size; ++i) { 179 | colorsFloatingText[i] = Color.WHITE; 180 | } 181 | 182 | return true; 183 | } 184 | 185 | public int[] getColors() { 186 | return colors; 187 | } 188 | 189 | public int getColor(int i) { 190 | int order = getArrOrder(i); 191 | 192 | if (i < 0) { 193 | return Color.TRANSPARENT; 194 | } 195 | 196 | return colors[order]; 197 | } 198 | 199 | public String getColorStr(int i) { 200 | int color = getColor(i); 201 | if ((color & 0xff000000) == 0x00000000) { 202 | return ""; 203 | } 204 | 205 | String hex = "00000000" + Integer.toHexString(color); 206 | 207 | return String.format("#%1$s", hex.substring(hex.length() - 6).toUpperCase()); 208 | } 209 | 210 | public int getFloatingTextColor(int i) { 211 | int order = getArrOrder(i); 212 | 213 | if (i < 0) { 214 | return Color.WHITE; 215 | } 216 | 217 | return colorsFloatingText[order]; 218 | } 219 | 220 | public String getGradeName(int i) { 221 | int order = getArrOrder(i); 222 | 223 | if (i < 0) { 224 | return ""; 225 | } 226 | 227 | return gradeNames[order]; 228 | } 229 | 230 | public int getPrimaryColor() { 231 | return getColor(primaryColorOrder); 232 | } 233 | 234 | public String getPrimaryColorStr() { 235 | return getColorStr(primaryColorOrder); 236 | } 237 | 238 | public int getDarkPrimaryColor() { 239 | return getColor(darkPrimaryColorOrder); 240 | } 241 | 242 | public String getDarkPrimaryColorStr() { 243 | return getColorStr(darkPrimaryColorOrder); 244 | } 245 | 246 | public int getAccentColor() { 247 | return getColor(accentColorOrder); 248 | } 249 | 250 | public String getAccentColorStr() { 251 | return getColorStr(accentColorOrder); 252 | } 253 | 254 | public int getSize() { 255 | return size; 256 | } 257 | 258 | /** 259 | * 以色调500为准 260 | * 避免背景与文字对比度不高,若主题为 Theme.Material 则忽略此建议 261 | * @return false - Theme.Material.Light 262 | * true - Theme.Material.Light.DarkActionBar 263 | */ 264 | public boolean isLightThemeWithDarkABSuggested() { 265 | return getFloatingTextColor(500) == Color.WHITE; 266 | } 267 | 268 | /** 269 | * 500、700、A200(A400) 270 | */ 271 | public boolean isSuggestedHue(int i) { 272 | int order = getArrOrder(i); 273 | 274 | if (i < 0) { 275 | return false; 276 | } 277 | 278 | return order == primaryColorOrder || order == darkPrimaryColorOrder 279 | || order == accentColorOrder; 280 | } 281 | } -------------------------------------------------------------------------------- /app/src/main/java/com/by_syk/mdcolor/util/TransitionHelper.java: -------------------------------------------------------------------------------- 1 | package com.by_syk.mdcolor.util; 2 | 3 | import android.animation.Animator; 4 | import android.animation.AnimatorListenerAdapter; 5 | import android.animation.ArgbEvaluator; 6 | import android.animation.ValueAnimator; 7 | import android.graphics.Bitmap; 8 | import android.graphics.drawable.BitmapDrawable; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | 12 | import com.by_syk.mdcolor.MainActivity; 13 | 14 | import java.lang.ref.WeakReference; 15 | 16 | /** 17 | * Created by liubaoyua on 2017/1/19. 18 | */ 19 | 20 | public class TransitionHelper { 21 | 22 | private static TransitionHelper sHelper = new TransitionHelper(); 23 | private WeakReference screenShot; 24 | private int statusBarColor; 25 | 26 | public static TransitionHelper getInstance() { 27 | return sHelper; 28 | } 29 | 30 | public void onRestartActivity(MainActivity activity) { 31 | final ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView(); 32 | statusBarColor = activity.getWindow().getStatusBarColor(); 33 | screenShot = new WeakReference<>(takeSnapshot(decorView)); 34 | } 35 | 36 | public void onActivityCreate(final MainActivity activity) { 37 | if (screenShot != null && screenShot.get() != null) { 38 | final ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView(); 39 | final View view = new View(activity); 40 | final int endStatusBarColor = activity.getWindow().getStatusBarColor(); 41 | 42 | view.setBackground(new BitmapDrawable(activity.getResources(), screenShot.get())); 43 | view.setClickable(true); 44 | decorView.addView(view, new ViewGroup.LayoutParams( 45 | ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); 46 | 47 | view.animate().alpha(0.0f).setDuration(400) 48 | .setListener(new AnimatorListenerAdapter() { 49 | public void onAnimationEnd(Animator animator) { 50 | decorView.removeView(view); 51 | screenShot = null; 52 | } 53 | }) 54 | .setUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 55 | 56 | ArgbEvaluator evaluator = new ArgbEvaluator(); 57 | 58 | @Override 59 | public void onAnimationUpdate(ValueAnimator animation) { 60 | int color = (int) evaluator.evaluate(animation.getAnimatedFraction(), statusBarColor, endStatusBarColor); 61 | activity.getWindow().setStatusBarColor(color); 62 | } 63 | }) 64 | .start(); 65 | } 66 | } 67 | 68 | private static Bitmap takeSnapshot(View view) { 69 | view.setDrawingCacheEnabled(true); 70 | view.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_AUTO); 71 | 72 | Bitmap snapshot = null; 73 | Bitmap cacheBitmap = view.getDrawingCache(); 74 | if (cacheBitmap != null) { 75 | snapshot = Bitmap.createBitmap(cacheBitmap); 76 | view.setDrawingCacheEnabled(false); 77 | view.destroyDrawingCache(); 78 | } 79 | return snapshot; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /app/src/main/java/com/by_syk/mdcolor/util/adapter/GradesAdapter.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016-2017 By_syk 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.by_syk.mdcolor.util.adapter; 18 | 19 | import android.content.Context; 20 | import android.graphics.drawable.Drawable; 21 | import android.support.v7.widget.CardView; 22 | import android.view.LayoutInflater; 23 | import android.view.View; 24 | import android.view.ViewGroup; 25 | import android.widget.BaseAdapter; 26 | import android.widget.ImageView; 27 | import android.widget.TextView; 28 | 29 | import com.by_syk.mdcolor.R; 30 | import com.by_syk.mdcolor.util.Palette; 31 | 32 | /** 33 | * Created by By_syk on 2016-04-01. 34 | */ 35 | public class GradesAdapter extends BaseAdapter { 36 | private Context context = null; 37 | 38 | private LayoutInflater layoutInflater = null; 39 | 40 | private Palette palette = null; 41 | 42 | private static class ViewHolder { 43 | CardView cardView; 44 | TextView tvGrade; 45 | TextView tvHex; 46 | ImageView ivStar; 47 | } 48 | 49 | public GradesAdapter(Context context, Palette palette) { 50 | this.context = context; 51 | this.palette = palette; 52 | 53 | layoutInflater = LayoutInflater.from(context); 54 | } 55 | 56 | @Override 57 | public int getCount() { 58 | return palette.getSize(); 59 | } 60 | 61 | @Override 62 | public Integer getItem(int position) { 63 | return palette.getColor(position); 64 | } 65 | 66 | @Override 67 | public long getItemId(int position) { 68 | return position; 69 | } 70 | 71 | @Override 72 | public View getView(int position, View convertView, ViewGroup parent) { 73 | /* 74 | * 使用ViewHolder模式来避免没有必要的调用findViewById():因为太多的findViewById也会影响性能 75 | * ViewHolder模式通过getView()方法返回的视图的标签(Tag)中存储一个数据结构, 76 | * 这个数据结构包含了指向我们要绑定数据的视图的引用,从而避免每次调用getView()的时候调用findViewById() 77 | */ 78 | ViewHolder viewHolder; 79 | 80 | // 重用缓存convertView传递给getView()方法来避免填充不必要的视图 81 | if (convertView == null) { 82 | /* 避免这样使用: 83 | * layoutInflater.inflate(R.layout.list_item, null); 84 | * 查看 85 | * https://possiblemobile.com/2013/05/layout-inflation-as-intended/ 86 | */ 87 | convertView = layoutInflater.inflate(R.layout.list_item_card, parent, false); 88 | 89 | viewHolder = new ViewHolder(); 90 | viewHolder.cardView = (CardView) convertView.findViewById(R.id.card_view); 91 | viewHolder.tvGrade = (TextView) convertView.findViewById(R.id.tv_grade); 92 | viewHolder.tvHex = (TextView) convertView.findViewById(R.id.tv_hex); 93 | viewHolder.ivStar = (ImageView) convertView.findViewById(R.id.iv_star); 94 | 95 | convertView.setTag(viewHolder); 96 | } else { 97 | viewHolder = (ViewHolder) convertView.getTag(); 98 | } 99 | 100 | viewHolder.cardView.setCardBackgroundColor(palette.getColor(position)); 101 | 102 | viewHolder.tvGrade.setText(palette.getGradeName(position)); 103 | viewHolder.tvHex.setText(palette.getColorStr(position)); 104 | 105 | int floating_text_color = palette.getFloatingTextColor(position); 106 | viewHolder.tvGrade.setTextColor(floating_text_color); 107 | viewHolder.tvHex.setTextColor(floating_text_color); 108 | 109 | if (palette.isSuggestedHue(position)) { 110 | viewHolder.ivStar.setVisibility(View.VISIBLE); 111 | 112 | // Create new Drawable to avoid star color error. 113 | Drawable drawable = context.getDrawable(R.drawable.ic_star); 114 | viewHolder.ivStar.setImageDrawable(drawable); 115 | viewHolder.ivStar.getDrawable().setTint(floating_text_color); 116 | } else { 117 | viewHolder.ivStar.setVisibility(View.GONE); 118 | } 119 | 120 | return convertView; 121 | } 122 | } -------------------------------------------------------------------------------- /app/src/main/java/com/by_syk/mdcolor/util/adapter/MainAdapter.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2016-2017 By_syk 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.by_syk.mdcolor.util.adapter; 18 | 19 | import android.content.Context; 20 | import android.graphics.drawable.Drawable; 21 | import android.view.LayoutInflater; 22 | import android.view.View; 23 | import android.view.ViewGroup; 24 | import android.widget.BaseAdapter; 25 | import android.widget.ImageView; 26 | import android.widget.TextView; 27 | 28 | import com.by_syk.mdcolor.R; 29 | import com.by_syk.mdcolor.util.Palette; 30 | 31 | import java.util.ArrayList; 32 | import java.util.List; 33 | 34 | /** 35 | * Created by By_syk on 2016-03-31. 36 | */ 37 | public class MainAdapter extends BaseAdapter { 38 | private Context context = null; 39 | private LayoutInflater layoutInflater = null; 40 | 41 | private List dataList = null; 42 | 43 | private int checked = -1; 44 | 45 | private static class ViewHolder { 46 | TextView tvName; 47 | TextView tvHex; 48 | ImageView ivHead; 49 | } 50 | 51 | public MainAdapter(Context context, int checked) { 52 | this.context = context; 53 | this.checked = checked; 54 | 55 | layoutInflater = LayoutInflater.from(context); 56 | 57 | /* 58 | * 不直接引用传入的List对象: 59 | * this.dataList = dataList; 60 | * 避免不可控的数据变更导致崩溃: 61 | * java.lang.IllegalStateException: 62 | * The content of the adapter has changed but ListView did not receive a notification. 63 | * 因此采用复制一份数据的方案,完全由该Adapter对象维护。 64 | */ 65 | dataList = new ArrayList<>(); 66 | } 67 | 68 | @Override 69 | public int getCount() { 70 | return dataList.size(); 71 | } 72 | 73 | @Override 74 | public Palette getItem(int position) { 75 | return dataList.get(position); 76 | } 77 | 78 | @Override 79 | public long getItemId(int position) { 80 | return position; 81 | } 82 | 83 | @Override 84 | public View getView(int position, View convertView, ViewGroup parent) { 85 | /* 86 | * 使用ViewHolder模式来避免没有必要的调用findViewById():因为太多的findViewById也会影响性能 87 | * ViewHolder模式通过getView()方法返回的视图的标签(Tag)中存储一个数据结构, 88 | * 这个数据结构包含了指向我们要绑定数据的视图的引用,从而避免每次调用getView()的时候调用findViewById() 89 | */ 90 | ViewHolder viewHolder; 91 | 92 | // 重用缓存convertView传递给getView()方法来避免填充不必要的视图 93 | if (convertView == null) { 94 | /* 避免这样使用: 95 | * layoutInflater.inflate(R.layout.list_item, null); 96 | * 查看 97 | * https://possiblemobile.com/2013/05/layout-inflation-as-intended/ 98 | */ 99 | convertView = layoutInflater.inflate(R.layout.list_item, parent, false); 100 | 101 | viewHolder = new ViewHolder(); 102 | viewHolder.tvName = (TextView) convertView.findViewById(R.id.tv_name); 103 | viewHolder.tvHex = (TextView) convertView.findViewById(R.id.tv_hex); 104 | viewHolder.ivHead = (ImageView) convertView.findViewById(R.id.iv_head); 105 | 106 | convertView.setTag(viewHolder); 107 | } else { 108 | viewHolder = (ViewHolder) convertView.getTag(); 109 | } 110 | 111 | Palette palette = dataList.get(position); 112 | 113 | viewHolder.tvName.setText(palette.getName()); 114 | viewHolder.tvHex.setText(palette.getPrimaryColorStr()); 115 | 116 | Drawable drawable = context.getDrawable(position == checked 117 | ? R.drawable.ic_head_checked : R.drawable.ic_head); 118 | viewHolder.ivHead.setImageDrawable(drawable); 119 | // BUG:由于用了缓存,这样变色会导致颜色错乱 120 | //viewHolder.ivHead.getDrawable().setTint(palette.getPrimaryColor()); 121 | viewHolder.ivHead.setColorFilter(palette.getPrimaryColor()); 122 | 123 | return convertView; 124 | } 125 | 126 | /*public Palette getCheckedItem() { 127 | if (checked < 0 || checked >= dataList.size()) { 128 | return null; 129 | } 130 | 131 | return dataList.get(checked); 132 | }*/ 133 | 134 | public int getChecked() { 135 | return checked; 136 | } 137 | 138 | /*public List getDataList() { 139 | return dataList; 140 | }*/ 141 | 142 | public void notifyRefresh(List dataList) { 143 | if (dataList == null) { 144 | return; 145 | } 146 | 147 | this.dataList.clear(); 148 | this.dataList.addAll(dataList); 149 | 150 | notifyDataSetChanged(); 151 | } 152 | 153 | /*public void notifyRefreshChecked(int checked) { 154 | this.checked = checked; 155 | 156 | notifyDataSetChanged(); 157 | }*/ 158 | } -------------------------------------------------------------------------------- /app/src/main/res/anim/fab_bottom_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | 22 | 25 | 26 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/anim/fade_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | 22 | 25 | 26 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/anim/translate.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | 22 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/animator/fab_elevation.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 27 | 28 | 29 | 30 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_action_help_dark.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 23 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_action_help_light.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 23 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_action_notification_dark.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 22 | 23 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_action_notification_light.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 22 | 23 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_fab_touch.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 22 | 23 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_head.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 23 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_head_checked.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 23 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_notify_pantone.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 22 | 23 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-anydpi/ic_star.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 22 | 23 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/fab_oval_ripple.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/list_item_divider.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/layout-land/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 24 | 25 | 34 | 35 | 39 | 43 | 44 | 48 | 49 | 80 | 81 | 85 | 86 | 87 | 88 | 94 | 95 | 96 | 97 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /app/src/main/res/layout-land/view_control_bar.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 24 | 25 | 32 | 33 | 41 | 42 | 47 | 48 | 54 | 55 | 56 | 57 | 65 | 66 | -------------------------------------------------------------------------------- /app/src/main/res/layout-land/view_ui_board.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 21 | 22 | 26 | 27 | 34 | 35 | 39 | 40 | 45 | 46 | 51 | 52 | 60 | 61 | 67 | 68 | 69 | 70 | 71 | 72 | 80 | 81 |