├── .gitignore
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── io
│ │ └── github
│ │ └── deweyreed
│ │ └── digitalwatchview
│ │ └── app
│ │ ├── MainActivity.kt
│ │ └── SecondActivity.kt
│ └── res
│ ├── drawable-v24
│ └── ic_launcher_foreground.xml
│ ├── drawable
│ └── ic_launcher_background.xml
│ ├── layout
│ ├── activity_main.xml
│ └── activity_second.xml
│ ├── mipmap-anydpi-v26
│ ├── ic_launcher.xml
│ └── ic_launcher_round.xml
│ ├── mipmap-hdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-mdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ └── values
│ ├── colors.xml
│ ├── strings.xml
│ └── styles.xml
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── image
└── preview.gif
├── library
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── io
│ │ └── github
│ │ └── deweyreed
│ │ └── digitalwatchview
│ │ ├── DigitalWatchView.kt
│ │ └── Utility.kt
│ └── res
│ ├── font
│ ├── digital_7_colon.ttf
│ └── digital_7_mono_nums.ttf
│ └── values
│ ├── attrs.xml
│ ├── ids.xml
│ └── public.xml
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.gitignore.io/api/java,linux,macos,gradle,kotlin,windows,android,jetbrains,jetbrains+iml,jetbrains+all,androidstudio
3 | # Edit at https://www.gitignore.io/?templates=java,linux,macos,gradle,kotlin,windows,android,jetbrains,jetbrains+iml,jetbrains+all,androidstudio
4 |
5 | ### Android ###
6 | # Built application files
7 | *.apk
8 | *.ap_
9 | *.aab
10 |
11 | # Files for the ART/Dalvik VM
12 | *.dex
13 |
14 | # Java class files
15 | *.class
16 |
17 | # Generated files
18 | bin/
19 | gen/
20 | out/
21 |
22 | # Gradle files
23 | .gradle/
24 | build/
25 |
26 | # Local configuration file (sdk path, etc)
27 | local.properties
28 |
29 | # Proguard folder generated by Eclipse
30 | proguard/
31 |
32 | # Log Files
33 | *.log
34 |
35 | # Android Studio Navigation editor temp files
36 | .navigation/
37 |
38 | # Android Studio captures folder
39 | captures/
40 |
41 | # IntelliJ
42 | *.iml
43 | .idea/workspace.xml
44 | .idea/tasks.xml
45 | .idea/gradle.xml
46 | .idea/assetWizardSettings.xml
47 | .idea/dictionaries
48 | .idea/libraries
49 | .idea/caches
50 |
51 | # Keystore files
52 | # Uncomment the following lines if you do not want to check your keystore files in.
53 | #*.jks
54 | #*.keystore
55 |
56 | # External native build folder generated in Android Studio 2.2 and later
57 | .externalNativeBuild
58 |
59 | # Google Services (e.g. APIs or Firebase)
60 | google-services.json
61 |
62 | # Freeline
63 | freeline.py
64 | freeline/
65 | freeline_project_description.json
66 |
67 | # fastlane
68 | fastlane/report.xml
69 | fastlane/Preview.html
70 | fastlane/screenshots
71 | fastlane/test_output
72 | fastlane/readme.md
73 |
74 | ### Android Patch ###
75 | gen-external-apklibs
76 |
77 | ### AndroidStudio ###
78 | # Covers files to be ignored for android development using Android Studio.
79 |
80 | # Built application files
81 |
82 | # Files for the ART/Dalvik VM
83 |
84 | # Java class files
85 |
86 | # Generated files
87 |
88 | # Gradle files
89 | .gradle
90 |
91 | # Signing files
92 | .signing/
93 |
94 | # Local configuration file (sdk path, etc)
95 |
96 | # Proguard folder generated by Eclipse
97 |
98 | # Log Files
99 |
100 | # Android Studio
101 | /*/build/
102 | /*/local.properties
103 | /*/out
104 | /*/*/build
105 | /*/*/production
106 | *.ipr
107 | *~
108 | *.swp
109 |
110 | # Android Patch
111 |
112 | # External native build folder generated in Android Studio 2.2 and later
113 |
114 | # NDK
115 | obj/
116 |
117 | # IntelliJ IDEA
118 | *.iws
119 | /out/
120 |
121 | # User-specific configurations
122 | .idea/caches/
123 | .idea/libraries/
124 | .idea/shelf/
125 | .idea/.name
126 | .idea/compiler.xml
127 | .idea/copyright/profiles_settings.xml
128 | .idea/encodings.xml
129 | .idea/misc.xml
130 | .idea/modules.xml
131 | .idea/scopes/scope_settings.xml
132 | .idea/vcs.xml
133 | .idea/jsLibraryMappings.xml
134 | .idea/datasources.xml
135 | .idea/dataSources.ids
136 | .idea/sqlDataSources.xml
137 | .idea/dynamic.xml
138 | .idea/uiDesigner.xml
139 |
140 | # OS-specific files
141 | .DS_Store
142 | .DS_Store?
143 | ._*
144 | .Spotlight-V100
145 | .Trashes
146 | ehthumbs.db
147 | Thumbs.db
148 |
149 | # Legacy Eclipse project files
150 | .classpath
151 | .project
152 | .cproject
153 | .settings/
154 |
155 | # Mobile Tools for Java (J2ME)
156 | .mtj.tmp/
157 |
158 | # Package Files #
159 | *.war
160 | *.ear
161 |
162 | # virtual machine crash logs (Reference: http://www.java.com/en/download/help/error_hotspot.xml)
163 | hs_err_pid*
164 |
165 | ## Plugin-specific files:
166 |
167 | # mpeltonen/sbt-idea plugin
168 | .idea_modules/
169 |
170 | # JIRA plugin
171 | atlassian-ide-plugin.xml
172 |
173 | # Mongo Explorer plugin
174 | .idea/mongoSettings.xml
175 |
176 | # Crashlytics plugin (for Android Studio and IntelliJ)
177 | com_crashlytics_export_strings.xml
178 | crashlytics.properties
179 | crashlytics-build.properties
180 | fabric.properties
181 |
182 | ### AndroidStudio Patch ###
183 |
184 | !/gradle/wrapper/gradle-wrapper.jar
185 |
186 | ### Java ###
187 | # Compiled class file
188 |
189 | # Log file
190 |
191 | # BlueJ files
192 | *.ctxt
193 |
194 | # Mobile Tools for Java (J2ME)
195 |
196 | # Package Files #
197 | *.jar
198 | *.nar
199 | *.zip
200 | *.tar.gz
201 | *.rar
202 |
203 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
204 |
205 | ### JetBrains ###
206 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
207 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
208 |
209 | # User-specific stuff
210 | .idea/**/workspace.xml
211 | .idea/**/tasks.xml
212 | .idea/**/usage.statistics.xml
213 | .idea/**/dictionaries
214 | .idea/**/shelf
215 |
216 | # Generated files
217 | .idea/**/contentModel.xml
218 |
219 | # Sensitive or high-churn files
220 | .idea/**/dataSources/
221 | .idea/**/dataSources.ids
222 | .idea/**/dataSources.local.xml
223 | .idea/**/sqlDataSources.xml
224 | .idea/**/dynamic.xml
225 | .idea/**/uiDesigner.xml
226 | .idea/**/dbnavigator.xml
227 |
228 | # Gradle
229 | .idea/**/gradle.xml
230 | .idea/**/libraries
231 |
232 | # Gradle and Maven with auto-import
233 | # When using Gradle or Maven with auto-import, you should exclude module files,
234 | # since they will be recreated, and may cause churn. Uncomment if using
235 | # auto-import.
236 | # .idea/modules.xml
237 | # .idea/*.iml
238 | # .idea/modules
239 |
240 | # CMake
241 | cmake-build-*/
242 |
243 | # Mongo Explorer plugin
244 | .idea/**/mongoSettings.xml
245 |
246 | # File-based project format
247 |
248 | # IntelliJ
249 |
250 | # mpeltonen/sbt-idea plugin
251 |
252 | # JIRA plugin
253 |
254 | # Cursive Clojure plugin
255 | .idea/replstate.xml
256 |
257 | # Crashlytics plugin (for Android Studio and IntelliJ)
258 |
259 | # Editor-based Rest Client
260 | .idea/httpRequests
261 |
262 | # Android studio 3.1+ serialized cache file
263 | .idea/caches/build_file_checksums.ser
264 |
265 | ### JetBrains Patch ###
266 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
267 |
268 | # *.iml
269 | # modules.xml
270 | # .idea/misc.xml
271 | # *.ipr
272 |
273 | # Sonarlint plugin
274 | .idea/sonarlint
275 |
276 | ### JetBrains+all ###
277 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
278 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
279 |
280 | # User-specific stuff
281 |
282 | # Generated files
283 |
284 | # Sensitive or high-churn files
285 |
286 | # Gradle
287 |
288 | # Gradle and Maven with auto-import
289 | # When using Gradle or Maven with auto-import, you should exclude module files,
290 | # since they will be recreated, and may cause churn. Uncomment if using
291 | # auto-import.
292 | # .idea/modules.xml
293 | # .idea/*.iml
294 | # .idea/modules
295 |
296 | # CMake
297 |
298 | # Mongo Explorer plugin
299 |
300 | # File-based project format
301 |
302 | # IntelliJ
303 |
304 | # mpeltonen/sbt-idea plugin
305 |
306 | # JIRA plugin
307 |
308 | # Cursive Clojure plugin
309 |
310 | # Crashlytics plugin (for Android Studio and IntelliJ)
311 |
312 | # Editor-based Rest Client
313 |
314 | # Android studio 3.1+ serialized cache file
315 |
316 | ### JetBrains+all Patch ###
317 | # Ignores the whole .idea folder and all .iml files
318 | # See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360
319 |
320 | .idea/
321 |
322 | # Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
323 |
324 | modules.xml
325 |
326 | ### JetBrains+iml ###
327 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
328 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
329 |
330 | # User-specific stuff
331 |
332 | # Generated files
333 |
334 | # Sensitive or high-churn files
335 |
336 | # Gradle
337 |
338 | # Gradle and Maven with auto-import
339 | # When using Gradle or Maven with auto-import, you should exclude module files,
340 | # since they will be recreated, and may cause churn. Uncomment if using
341 | # auto-import.
342 | # .idea/modules.xml
343 | # .idea/*.iml
344 | # .idea/modules
345 |
346 | # CMake
347 |
348 | # Mongo Explorer plugin
349 |
350 | # File-based project format
351 |
352 | # IntelliJ
353 |
354 | # mpeltonen/sbt-idea plugin
355 |
356 | # JIRA plugin
357 |
358 | # Cursive Clojure plugin
359 |
360 | # Crashlytics plugin (for Android Studio and IntelliJ)
361 |
362 | # Editor-based Rest Client
363 |
364 | # Android studio 3.1+ serialized cache file
365 |
366 | ### JetBrains+iml Patch ###
367 | # Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
368 |
369 |
370 | ### Kotlin ###
371 | # Compiled class file
372 |
373 | # Log file
374 |
375 | # BlueJ files
376 |
377 | # Mobile Tools for Java (J2ME)
378 |
379 | # Package Files #
380 |
381 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
382 |
383 | ### Linux ###
384 |
385 | # temporary files which can be created if a process still has a handle open of a deleted file
386 | .fuse_hidden*
387 |
388 | # KDE directory preferences
389 | .directory
390 |
391 | # Linux trash folder which might appear on any partition or disk
392 | .Trash-*
393 |
394 | # .nfs files are created when an open file is removed but is still being accessed
395 | .nfs*
396 |
397 | ### macOS ###
398 | # General
399 | .AppleDouble
400 | .LSOverride
401 |
402 | # Icon must end with two \r
403 | Icon
404 |
405 | # Thumbnails
406 |
407 | # Files that might appear in the root of a volume
408 | .DocumentRevisions-V100
409 | .fseventsd
410 | .TemporaryItems
411 | .VolumeIcon.icns
412 | .com.apple.timemachine.donotpresent
413 |
414 | # Directories potentially created on remote AFP share
415 | .AppleDB
416 | .AppleDesktop
417 | Network Trash Folder
418 | Temporary Items
419 | .apdisk
420 |
421 | ### Windows ###
422 | # Windows thumbnail cache files
423 | ehthumbs_vista.db
424 |
425 | # Dump file
426 | *.stackdump
427 |
428 | # Folder config file
429 | [Dd]esktop.ini
430 |
431 | # Recycle Bin used on file shares
432 | $RECYCLE.BIN/
433 |
434 | # Windows Installer files
435 | *.cab
436 | *.msi
437 | *.msix
438 | *.msm
439 | *.msp
440 |
441 | # Windows shortcuts
442 | *.lnk
443 |
444 | ### Gradle ###
445 | /build/
446 |
447 | # Ignore Gradle GUI config
448 | gradle-app.setting
449 |
450 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
451 | !gradle-wrapper.jar
452 |
453 | # Cache of project
454 | .gradletasknamecache
455 |
456 | # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
457 | # gradle/wrapper/gradle-wrapper.properties
458 |
459 | ### Gradle Patch ###
460 | **/build/
461 |
462 | # End of https://www.gitignore.io/api/java,linux,macos,gradle,kotlin,windows,android,jetbrains,jetbrains+iml,jetbrains+all,androidstudio
463 |
464 | *.aar
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 DeweyReed
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | []( https://android-arsenal.com/details/1/6847)
2 | [](https://jitpack.io/#DeweyReed/DigitalWatchView)
3 |
4 | ## Deprecated
5 |
6 | Since [a TextView with a custom font works perfectly](https://github.com/DeweyReed/DigitalWatchView/issues/2), this library is of little use.
7 |
8 | # DigitalWatchView
9 |
10 | Just looks like your digital watch.
11 |
12 | 
13 |
14 | ## Install
15 |
16 | Step 1. Add the JitPack repository to your build file
17 |
18 | Add it in your root build.gradle at the end of repositories:
19 |
20 | ```Groovy
21 | allprojects {
22 | repositories {
23 | ...
24 | maven { url 'https://jitpack.io' }
25 | }
26 | }
27 | ```
28 |
29 | Step 2. Add the dependency => [](https://jitpack.io/#DeweyReed/DigitalWatchView)
30 |
31 | ```Groovy
32 | dependencies {
33 | implementation 'com.github.DeweyReed:DigitalWatchView:$version'
34 | }
35 | ```
36 |
37 | **1.0.2 is the last version using the support library.**
38 |
39 | ## Try
40 |
41 | Download a sample APK [here](https://github.com/DeweyReed/DigitalWatchView/releases/download/1.0/sample.apk)
42 |
43 | ## Usage
44 |
45 | ```Kotlin
46 |
64 | ```
65 |
66 | ## Attributes
67 |
68 | |xml|method|type|default|meaning|
69 | |:-:|:-:|:-:|:-:|:-|
70 | |dwv_show_background|setShowBackground|boolean|false|Show a shadow background|
71 | |dwv_background_color|setBackgroundViewColorInt|(ColorInt) int|darker_gray|Background text color|
72 | |dwv_background_alpha|setBackgroundViewAlpha|float([0.0, 1.0])|1.0|Set background text alpha|
73 | |dwv_foreground_color|setForegroundViewColorInt|(ColorInt) int|holo_green_dark|Digital text color|
74 | |dwv_normal_text_size|setNormalTextSize|float|18sp|Set hours and minutes text size|
75 | |dwv_show_seconds|setShowSeconds|boolean|true|Show seconds digits|
76 | |dwv_seconds_text_size|setSecondsTextSize|float|18sp|Set seconds text size|
77 | |dwv_show_hours|setShowHours|boolean|true|Show hours digits|
78 | |dwv_show_two_digits|setShowTwoDigits|boolean|true|Use %02d format for hours digits(minutes if hours are hidden)|
79 | |dwv_hours|setHours|int|0|Set hours|
80 | |dwv_minutes|setMinutes|int|0|Set minutes|
81 | |dwv_seconds|setSeconds|int|0|Set seconds|
82 | |dwv_blink_colons|setBlinkColons|boolean|false|Blink colons like a digital watch|
83 | ||setTime|(int, int, int)||Set hours, minutes and seconds using one method|
84 | ||getHours|||Return current hours|
85 | ||getMinutes|||Return current minutes|
86 | ||getSeconds|||Return current seconds|
87 | ||Other Getters|||Every setter has its corresponding getter|
88 |
89 | ## =-=
90 |
91 | `digital_7_colon.ttf` the two colons use is a subset font of `digital_7.ttf`. It simply includes one glyph(the colon) but takes 2.89KB space. So does `digital_7_mono_nums.ttf`, ten numbers glyphs take 5.44KB space.
92 |
93 | I do care about APK size but I don't know if there is a way to reduce these two fonts size. I need help!!
94 |
95 | ## License
96 |
97 | [MIT License](https://github.com/DeweyReed/DigitalWatchView/blob/master/LICENSE)
98 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | apply plugin: 'kotlin-android'
4 |
5 | apply plugin: 'kotlin-android-extensions'
6 |
7 | android {
8 | compileSdkVersion versions.compileSdk
9 | defaultConfig {
10 | applicationId "io.github.deweyreed.digitalwatchview.app"
11 | minSdkVersion versions.minSdk
12 | targetSdkVersion versions.targetSdk
13 | versionCode 1
14 | versionName "1.0"
15 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
16 | }
17 | buildTypes {
18 | release {
19 | minifyEnabled false
20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
21 | }
22 | }
23 | }
24 |
25 | dependencies {
26 | implementation fileTree(dir: 'libs', include: ['*.jar'])
27 |
28 | implementation project(':library')
29 | implementation libs.kotlin_stdlib_jdk7
30 | implementation libs.appcompat
31 |
32 | implementation 'org.adw.library:discrete-seekbar:1.0.1'
33 | //noinspection GradleDependency
34 | implementation 'com.jaredrummler:colorpicker:1.1.0'
35 | debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.2'
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/app/src/main/java/io/github/deweyreed/digitalwatchview/app/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package io.github.deweyreed.digitalwatchview.app
2 |
3 | import android.content.Context
4 | import android.content.Intent
5 | import android.os.Bundle
6 | import androidx.appcompat.app.AppCompatActivity
7 | import com.jaredrummler.android.colorpicker.ColorPickerDialog
8 | import com.jaredrummler.android.colorpicker.ColorPickerDialogListener
9 | import kotlinx.android.synthetic.main.activity_main.*
10 | import org.adw.library.widgets.discreteseekbar.DiscreteSeekBar
11 |
12 | class MainActivity : AppCompatActivity(),
13 | ColorPickerDialogListener, DiscreteSeekBar.OnProgressChangeListener {
14 |
15 | override fun onCreate(savedInstanceState: Bundle?) {
16 | super.onCreate(savedInstanceState)
17 | setContentView(R.layout.activity_main)
18 |
19 | setupListeners()
20 | }
21 |
22 | override fun onDialogDismissed(dialogId: Int) = Unit
23 |
24 | override fun onColorSelected(dialogId: Int, color: Int) {
25 | when (dialogId) {
26 | R.id.imageBackgroundColor -> {
27 | imageBackgroundColor.setBackgroundColor(color)
28 | digitalWatchView.setBackgroundViewColorInt(color)
29 | }
30 | R.id.imageForegroundColor -> {
31 | imageForegroundColor.setBackgroundColor(color)
32 | digitalWatchView.setForegroundViewColorInt(color)
33 | }
34 | }
35 | }
36 |
37 | override fun onProgressChanged(seekBar: DiscreteSeekBar?, value: Int, fromUser: Boolean) {
38 | if (fromUser) {
39 | when (seekBar?.id) {
40 | R.id.seekBackgroundAlpha -> digitalWatchView.setBackgroundViewAlpha(value / 100f)
41 | R.id.seekNormalTextSize -> digitalWatchView.setNormalTextSize(sp(value))
42 | R.id.seekSecondsTextSize -> digitalWatchView.setSecondsTextSize(sp(value))
43 | R.id.seekHours -> digitalWatchView.setHours(value)
44 | R.id.seekMinutes -> digitalWatchView.setMinutes(value)
45 | R.id.seekSeconds -> digitalWatchView.setSeconds(value)
46 | }
47 | }
48 | }
49 |
50 | override fun onStartTrackingTouch(seekBar: DiscreteSeekBar?) = Unit
51 |
52 | override fun onStopTrackingTouch(seekBar: DiscreteSeekBar?) = Unit
53 |
54 | private fun setupListeners() {
55 | checkShowBackground.setOnCheckedChangeListener { _, isChecked ->
56 | digitalWatchView.setShowBackground(isChecked)
57 | imageBackgroundColor.isEnabled = isChecked
58 | seekBackgroundAlpha.isEnabled = isChecked
59 | }
60 | checkShowHours.setOnCheckedChangeListener { _, isChecked ->
61 | digitalWatchView.setShowHours(isChecked)
62 | }
63 | checkShowTwoDigits.setOnCheckedChangeListener { _, isChecked ->
64 | digitalWatchView.setShowTwoDigits(isChecked)
65 | }
66 | checkShowSeconds.setOnCheckedChangeListener { _, isChecked ->
67 | digitalWatchView.setShowSeconds(isChecked)
68 | seekSecondsTextSize.isEnabled = isChecked
69 | }
70 | checkBlinkColons.setOnCheckedChangeListener { _, isChecked ->
71 | digitalWatchView.setBlinkColons(isChecked)
72 | }
73 |
74 | arrayOf(imageBackgroundColor, imageForegroundColor).forEach { view ->
75 | view.setOnClickListener {
76 | ColorPickerDialog.newBuilder().setDialogId(it.id).show(this@MainActivity)
77 | }
78 | }
79 |
80 | arrayOf(
81 | seekBackgroundAlpha, seekNormalTextSize, seekSecondsTextSize,
82 | seekHours, seekMinutes, seekSeconds
83 | ).forEach {
84 | it.setOnProgressChangeListener(this@MainActivity)
85 | }
86 |
87 | btnExample.setOnClickListener {
88 | startActivity(Intent(this, SecondActivity::class.java))
89 | }
90 | }
91 | }
92 |
93 | val Context.scaledDensity: Float get() = resources.displayMetrics.scaledDensity
94 |
95 | fun Context.sp(value: Int): Float = value * scaledDensity
96 |
--------------------------------------------------------------------------------
/app/src/main/java/io/github/deweyreed/digitalwatchview/app/SecondActivity.kt:
--------------------------------------------------------------------------------
1 | package io.github.deweyreed.digitalwatchview.app
2 |
3 | import android.os.Bundle
4 | import androidx.appcompat.app.AppCompatActivity
5 |
6 | class SecondActivity : AppCompatActivity() {
7 |
8 | override fun onCreate(savedInstanceState: Bundle?) {
9 | super.onCreate(savedInstanceState)
10 | setContentView(R.layout.activity_second)
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
17 |
18 |
28 |
29 |
34 |
35 |
39 |
40 |
45 |
46 |
50 |
51 |
56 |
57 |
62 |
63 |
64 |
69 |
70 |
75 |
76 |
83 |
84 |
85 |
91 |
92 |
97 |
98 |
105 |
106 |
107 |
113 |
114 |
119 |
120 |
125 |
126 |
133 |
134 |
135 |
141 |
142 |
147 |
148 |
155 |
156 |
157 |
163 |
164 |
168 |
169 |
174 |
175 |
180 |
181 |
182 |
188 |
189 |
194 |
195 |
202 |
203 |
204 |
210 |
211 |
215 |
216 |
221 |
222 |
227 |
228 |
229 |
233 |
234 |
239 |
240 |
245 |
246 |
247 |
253 |
254 |
259 |
260 |
266 |
267 |
268 |
274 |
275 |
280 |
281 |
287 |
288 |
289 |
295 |
296 |
301 |
302 |
308 |
309 |
310 |
314 |
315 |
320 |
321 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_second.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
15 |
16 |
33 |
34 |
45 |
46 |
57 |
58 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeweyReed/DigitalWatchView/3187f1cb385171fa6fb8351f68b71fe77e00b98f/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeweyReed/DigitalWatchView/3187f1cb385171fa6fb8351f68b71fe77e00b98f/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeweyReed/DigitalWatchView/3187f1cb385171fa6fb8351f68b71fe77e00b98f/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeweyReed/DigitalWatchView/3187f1cb385171fa6fb8351f68b71fe77e00b98f/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeweyReed/DigitalWatchView/3187f1cb385171fa6fb8351f68b71fe77e00b98f/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeweyReed/DigitalWatchView/3187f1cb385171fa6fb8351f68b71fe77e00b98f/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeweyReed/DigitalWatchView/3187f1cb385171fa6fb8351f68b71fe77e00b98f/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeweyReed/DigitalWatchView/3187f1cb385171fa6fb8351f68b71fe77e00b98f/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeweyReed/DigitalWatchView/3187f1cb385171fa6fb8351f68b71fe77e00b98f/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeweyReed/DigitalWatchView/3187f1cb385171fa6fb8351f68b71fe77e00b98f/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | DigitalWatchView
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext.kotlin_version = '1.3.71'
5 | repositories {
6 | google()
7 | jcenter()
8 | }
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:3.6.2'
11 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
12 | classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
13 | // NOTE: Do not place your application dependencies here; they belong
14 | // in the individual module build.gradle files
15 | }
16 | }
17 |
18 | ext {
19 | versions = [
20 | compileSdk: 29,
21 | minSdk : 16,
22 | targetSdk : 29
23 | ]
24 | libs = [
25 | appcompat : "androidx.appcompat:appcompat:1.1.0",
26 | kotlin_stdlib_jdk7 : "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version",
27 | androidx_constraintlayout: 'androidx.constraintlayout:constraintlayout:1.1.3',
28 |
29 | ]
30 | }
31 |
32 | allprojects {
33 | repositories {
34 | google()
35 | jcenter()
36 | }
37 | }
38 |
39 | task clean(type: Delete) {
40 | delete rootProject.buildDir
41 | }
42 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | ## Project-wide Gradle settings.
2 | #
3 | # For more details on how to configure your build environment visit
4 | # http://www.gradle.org/docs/current/userguide/build_environment.html
5 | #
6 | # Specifies the JVM arguments used for the daemon process.
7 | # The setting is particularly useful for tweaking memory settings.
8 | # Default value: -Xmx1024m -XX:MaxPermSize=256m
9 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
10 | #
11 | # When configured, Gradle will run in incubating parallel mode.
12 | # This option should only be used with decoupled projects. More details, visit
13 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
14 | # org.gradle.parallel=true
15 | #Mon Feb 26 20:31:23 CST 2018
16 | android.enableJetifier=true
17 | android.useAndroidX=true
18 | org.gradle.jvmargs=-Xmx1536m
19 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeweyReed/DigitalWatchView/3187f1cb385171fa6fb8351f68b71fe77e00b98f/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sun Apr 12 11:45:40 CST 2020
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.2.2-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/image/preview.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeweyReed/DigitalWatchView/3187f1cb385171fa6fb8351f68b71fe77e00b98f/image/preview.gif
--------------------------------------------------------------------------------
/library/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/library/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'kotlin-android'
3 |
4 | apply plugin: 'com.github.dcendents.android-maven'
5 |
6 | group = 'com.github.DeweyReed'
7 |
8 | android {
9 | compileSdkVersion versions.compileSdk
10 |
11 | defaultConfig {
12 | minSdkVersion versions.minSdk
13 | targetSdkVersion versions.targetSdk
14 | versionCode 1
15 | versionName "1.0"
16 | }
17 | }
18 |
19 | dependencies {
20 | implementation libs.kotlin_stdlib_jdk7
21 | implementation libs.appcompat
22 | implementation libs.androidx_constraintlayout
23 | }
24 |
--------------------------------------------------------------------------------
/library/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 |
--------------------------------------------------------------------------------
/library/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/library/src/main/java/io/github/deweyreed/digitalwatchview/DigitalWatchView.kt:
--------------------------------------------------------------------------------
1 | package io.github.deweyreed.digitalwatchview
2 |
3 | import android.content.Context
4 | import android.graphics.Color
5 | import android.os.SystemClock
6 | import android.util.AttributeSet
7 | import android.view.View
8 | import android.widget.FrameLayout
9 | import android.widget.TextView
10 | import androidx.annotation.ColorInt
11 | import androidx.annotation.FloatRange
12 | import androidx.annotation.FontRes
13 | import androidx.appcompat.widget.AppCompatTextView
14 | import androidx.constraintlayout.widget.ConstraintLayout
15 | import kotlin.math.max
16 |
17 | @Suppress("unused", "MemberVisibilityCanBePrivate")
18 | /**
19 | * Created on 2018/2/26.
20 | */
21 |
22 | class DigitalWatchView @JvmOverloads constructor(
23 | context: Context,
24 | attrs: AttributeSet? = null
25 | ) : FrameLayout(context, attrs) {
26 |
27 | private val backgroundView: DigitalView
28 | private val foregroundView: DigitalView
29 |
30 | private var showBackground = false
31 |
32 | @ColorInt
33 | private var backgroundColorInt = -1
34 | private var backgroundAlpha = 1f
35 |
36 | @ColorInt
37 | private var foregroundColorInt = -1
38 | private var normalTextSize = 1f
39 | private var showSeconds = true
40 | private var secondsTextSize = 1f
41 | private var showHours = true
42 | private var showTwoDigits = true
43 | private var hours = 0
44 | private var minutes = 0
45 | private var seconds = 0
46 |
47 | private var blinkColons: Boolean
48 | private var blinkRunnable: BlinkRunnable? = null
49 |
50 | init {
51 | val ta = context.obtainStyledAttributes(attrs, R.styleable.DigitalWatchView, 0, 0)
52 | showBackground = ta.getBoolean(
53 | R.styleable.DigitalWatchView_dwv_show_background,
54 | false
55 | )
56 | backgroundColorInt = ta.getColor(
57 | R.styleable.DigitalWatchView_dwv_background_color,
58 | color(android.R.color.darker_gray)
59 | )
60 | backgroundAlpha = ta.getFloat(
61 | R.styleable.DigitalWatchView_dwv_background_alpha,
62 | 1f
63 | )
64 | foregroundColorInt = ta.getColor(
65 | R.styleable.DigitalWatchView_dwv_foreground_color,
66 | Color.BLACK
67 | )
68 | normalTextSize = ta.getDimension(
69 | R.styleable.DigitalWatchView_dwv_normal_text_size,
70 | sp(18).toFloat()
71 | )
72 | showSeconds = ta.getBoolean(
73 | R.styleable.DigitalWatchView_dwv_show_seconds,
74 | true
75 | )
76 | secondsTextSize = ta.getDimension(
77 | R.styleable.DigitalWatchView_dwv_seconds_text_size,
78 | sp(18).toFloat()
79 | )
80 | showHours = ta.getBoolean(
81 | R.styleable.DigitalWatchView_dwv_show_hours,
82 | true
83 | )
84 | showTwoDigits = ta.getBoolean(
85 | R.styleable.DigitalWatchView_dwv_show_two_digits,
86 | true
87 | )
88 | hours = ta.getInteger(R.styleable.DigitalWatchView_dwv_hours, 0)
89 | minutes = ta.getInteger(R.styleable.DigitalWatchView_dwv_minutes, 0)
90 | seconds = ta.getInteger(R.styleable.DigitalWatchView_dwv_seconds, 0)
91 | blinkColons = ta.getBoolean(R.styleable.DigitalWatchView_dwv_blink_colons, false)
92 | ta.recycle()
93 |
94 | backgroundView = DigitalView(
95 | context, backgroundColorInt, normalTextSize,
96 | showSeconds, secondsTextSize, showHours, showTwoDigits,
97 | 88, 88, 88
98 | ).apply {
99 | if (!showBackground) gone()
100 | alpha = backgroundAlpha.clamp(0f, 1f)
101 | }
102 | foregroundView = DigitalView(
103 | context, foregroundColorInt, normalTextSize,
104 | showSeconds, secondsTextSize, showHours, showTwoDigits,
105 | hours, minutes, seconds
106 | )
107 |
108 | addView(backgroundView)
109 | addView(foregroundView)
110 |
111 | if (blinkColons) setBlinkColons(true)
112 | }
113 |
114 | override fun onDetachedFromWindow() {
115 | stopBlinking()
116 | super.onDetachedFromWindow()
117 | }
118 |
119 | fun getShowBackground() = showBackground
120 | fun setShowBackground(show: Boolean) {
121 | showBackground = show
122 | if (show) backgroundView.show() else backgroundView.gone()
123 | }
124 |
125 | @ColorInt
126 | fun getBackgroundViewColorInt() = backgroundColorInt
127 |
128 | fun setBackgroundViewColorInt(@ColorInt color: Int) {
129 | backgroundColorInt = color
130 | backgroundView.setColorInt(color)
131 | }
132 |
133 | fun getBackgroundViewAlpha() = backgroundAlpha
134 | fun setBackgroundViewAlpha(@FloatRange(from = 0.0, to = 1.0) alpha: Float) {
135 | backgroundAlpha = alpha
136 | backgroundView.alpha = alpha.clamp(0f, 1f)
137 | }
138 |
139 | @ColorInt
140 | fun getForegroundViewColorInt() = foregroundColorInt
141 |
142 | fun setForegroundViewColorInt(@ColorInt color: Int) {
143 | foregroundColorInt = color
144 | foregroundView.setColorInt(color)
145 | }
146 |
147 | fun getNormalTextSize() = normalTextSize
148 | fun setNormalTextSize(textSize: Float) {
149 | normalTextSize = textSize
150 | backgroundView.setNormalTextSize(textSize)
151 | foregroundView.setNormalTextSize(textSize)
152 | }
153 |
154 | fun getShowSeconds() = showSeconds
155 | fun setShowSeconds(show: Boolean) {
156 | showSeconds = show
157 | backgroundView.setShowSeconds(show)
158 | foregroundView.setShowSeconds(show)
159 | }
160 |
161 | fun getSecondsTextSize() = secondsTextSize
162 | fun setSecondsTextSize(textSize: Float) {
163 | secondsTextSize = textSize
164 | backgroundView.setSecondsTextSize(textSize)
165 | foregroundView.setSecondsTextSize(textSize)
166 | }
167 |
168 | fun getShowHours() = showHours
169 | fun setShowHours(show: Boolean) {
170 | showHours = show
171 | backgroundView.setShowHours(show)
172 | foregroundView.setShowHours(show)
173 | }
174 |
175 | fun getShowTwoDigits() = showTwoDigits
176 | fun setShowTwoDigits(show: Boolean) {
177 | showTwoDigits = show
178 | foregroundView.setShowTwoDigits(show)
179 | setTime(hours, minutes, seconds)
180 | }
181 |
182 | fun setTime(h: Int, m: Int, s: Int) {
183 | foregroundView.setTime(h, m, s)
184 | }
185 |
186 | fun getHours(): Int = hours
187 | fun setHours(h: Int) {
188 | hours = h
189 | foregroundView.setHoursOnly(h)
190 | }
191 |
192 | fun getMinutes(): Int = minutes
193 | fun setMinutes(m: Int) {
194 | minutes = m
195 | foregroundView.setMinutesOnly(m)
196 | }
197 |
198 | fun getSeconds(): Int = seconds
199 | fun setSeconds(s: Int) {
200 | seconds = s
201 | foregroundView.setSecondsOnly(s)
202 | }
203 |
204 | fun setBlinkColons(blink: Boolean) {
205 | blinkColons = blink
206 | stopBlinking()
207 | if (blinkColons) {
208 | blinkRunnable = BlinkRunnable()
209 | post(blinkRunnable)
210 | }
211 | }
212 |
213 | private fun stopBlinking() {
214 | removeCallbacks(blinkRunnable)
215 | backgroundView.showColons()
216 | foregroundView.showColons()
217 | blinkRunnable = null
218 | }
219 |
220 | private inner class BlinkRunnable : Runnable {
221 | override fun run() {
222 | val startTime = SystemClock.elapsedRealtime()
223 | if (blinkColons) {
224 | if (SystemClock.elapsedRealtime() % 1000 < 500) {
225 | backgroundView.hideColons()
226 | foregroundView.hideColons()
227 | } else {
228 | backgroundView.showColons()
229 | foregroundView.showColons()
230 | }
231 | }
232 | val endTime = SystemClock.elapsedRealtime()
233 | // Try to maintain a consistent period of time between redraws.
234 | val delay = max(0, startTime + 100 - endTime)
235 | this@DigitalWatchView.postDelayed(this, delay)
236 | }
237 | }
238 |
239 | private class DigitalView(
240 | context: Context,
241 | @ColorInt private val textColor: Int,
242 | normalTextSize: Float,
243 | showSeconds: Boolean,
244 | secondsTextSize: Float,
245 | private var showHours: Boolean,
246 | private var showTwoDigits: Boolean,
247 | hours: Int,
248 | minutes: Int,
249 | seconds: Int
250 | ) : ConstraintLayout(context) {
251 |
252 | companion object {
253 | private const val TWO_DIGITS_FORMAT = "%02d"
254 | }
255 |
256 | private val hoursView: TextView
257 | private val colonHmView: TextView
258 | private val minutesView: TextView
259 | private val colonMsView: TextView
260 | private val secondsView: TextView
261 |
262 | private val allViews: Array
263 |
264 | init {
265 |
266 | fun View.add(f: LayoutParams.() -> Unit) {
267 | addView(
268 | this,
269 | LayoutParams(
270 | LayoutParams.MATCH_CONSTRAINT,
271 | LayoutParams.WRAP_CONTENT
272 | ).apply {
273 | matchConstraintDefaultWidth = LayoutParams.MATCH_CONSTRAINT_WRAP
274 | constrainedWidth = true
275 | topToTop = LayoutParams.PARENT_ID
276 | bottomToBottom = LayoutParams.PARENT_ID
277 | f.invoke(this)
278 | }
279 | )
280 | }
281 |
282 | hoursView = createTextView(
283 | context = context,
284 | font = R.font.digital_7_mono_nums,
285 | textSize = normalTextSize,
286 | show = showHours
287 | ).apply {
288 | id = R.id.dwv_id_hours
289 | add {
290 | startToStart = LayoutParams.PARENT_ID
291 | endToStart = R.id.dwv_id_colon_hours_minutes
292 | horizontalChainStyle = LayoutParams.CHAIN_PACKED
293 | }
294 | }
295 | colonHmView = createTextView(
296 | context = context,
297 | font = R.font.digital_7_colon,
298 | textSize = normalTextSize,
299 | show = showHours
300 | ).apply {
301 | id = R.id.dwv_id_colon_hours_minutes
302 | text = ":"
303 | add {
304 | startToEnd = R.id.dwv_id_hours
305 | endToStart = R.id.dwv_id_minutes
306 | }
307 | }
308 | minutesView = createTextView(
309 | context = context,
310 | font = R.font.digital_7_mono_nums,
311 | textSize = normalTextSize
312 | ).apply {
313 | id = R.id.dwv_id_minutes
314 | add {
315 | startToEnd = R.id.dwv_id_colon_hours_minutes
316 | endToStart = R.id.dwv_id_colon_minutes_seconds
317 | }
318 | }
319 | colonMsView = createTextView(
320 | context = context,
321 | font = R.font.digital_7_colon,
322 | textSize = secondsTextSize,
323 | show = showSeconds
324 | ).apply {
325 | id = R.id.dwv_id_colon_minutes_seconds
326 | text = ":"
327 | add {
328 | startToEnd = R.id.dwv_id_minutes
329 | endToStart = R.id.dwv_id_seconds
330 | topToTop = LayoutParams.UNSET
331 | bottomToBottom = LayoutParams.UNSET
332 | baselineToBaseline = R.id.dwv_id_minutes
333 | }
334 | }
335 | secondsView = createTextView(
336 | context = context,
337 | font = R.font.digital_7_mono_nums,
338 | textSize = secondsTextSize,
339 | show = showSeconds
340 | ).apply {
341 | id = R.id.dwv_id_seconds
342 | add {
343 | startToEnd = R.id.dwv_id_colon_minutes_seconds
344 | endToEnd = LayoutParams.PARENT_ID
345 | topToTop = LayoutParams.UNSET
346 | bottomToBottom = LayoutParams.UNSET
347 | baselineToBaseline = R.id.dwv_id_minutes
348 | }
349 | }
350 |
351 | allViews = arrayOf(hoursView, colonHmView, minutesView, colonMsView, secondsView)
352 |
353 | setTime(hours, minutes, seconds)
354 | }
355 |
356 | fun setColorInt(@ColorInt color: Int) {
357 | allViews.forEach {
358 | it.setTextColor(color)
359 | }
360 | }
361 |
362 | fun setNormalTextSize(textSize: Float) {
363 | arrayOf(hoursView, colonHmView, minutesView).forEach { it.textSize = textSize }
364 | }
365 |
366 | fun setShowSeconds(show: Boolean) {
367 | arrayOf(colonMsView, secondsView).run {
368 | if (show) forEach { it.show() } else forEach { it.gone() }
369 | }
370 | }
371 |
372 | fun setSecondsTextSize(textSize: Float) {
373 | arrayOf(colonMsView, secondsView).forEach { it.textSize = textSize }
374 | }
375 |
376 | fun setShowHours(show: Boolean) {
377 | showHours = show
378 | arrayOf(hoursView, colonHmView).run {
379 | if (show) forEach { it.show() } else forEach { it.gone() }
380 | }
381 | }
382 |
383 | fun setShowTwoDigits(show: Boolean) {
384 | showTwoDigits = show
385 | }
386 |
387 | fun setTime(h: Int, m: Int, s: Int) {
388 | setHoursOnly(h)
389 | setMinutesOnly(m)
390 | setSecondsOnly(s)
391 | }
392 |
393 | fun setHoursOnly(h: Int) {
394 | if (showTwoDigits) {
395 | hoursView.text = TWO_DIGITS_FORMAT.format(h)
396 | } else {
397 | hoursView.text = if (h < 10) " $h" else h.toString()
398 | }
399 | }
400 |
401 | fun setMinutesOnly(m: Int) {
402 | if (!showTwoDigits && !showHours) {
403 | minutesView.text = m.toString()
404 | } else {
405 | minutesView.text = TWO_DIGITS_FORMAT.format(m)
406 | }
407 | }
408 |
409 | fun setSecondsOnly(s: Int) {
410 | secondsView.text = TWO_DIGITS_FORMAT.format(s)
411 | }
412 |
413 | fun showColons() {
414 | arrayOf(colonHmView, colonMsView).forEach { it.alpha = 1f }
415 | }
416 |
417 | fun hideColons() {
418 | arrayOf(colonHmView, colonMsView).forEach { it.alpha = 0f }
419 | }
420 |
421 | private fun createTextView(
422 | context: Context,
423 | @FontRes font: Int,
424 | textSize: Float,
425 | show: Boolean = true
426 | ): TextView = AppCompatTextView(context).apply {
427 | typeface = context.getFontCompat(font)
428 | setTextColor(textColor)
429 | setTextSize(textSize)
430 | maxLines = 1
431 | // TextViewCompat.setAutoSizeTextTypeWithDefaults(
432 | // this,
433 | // TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM
434 | // )
435 | if (!show) gone()
436 | }
437 | }
438 | }
--------------------------------------------------------------------------------
/library/src/main/java/io/github/deweyreed/digitalwatchview/Utility.kt:
--------------------------------------------------------------------------------
1 | package io.github.deweyreed.digitalwatchview
2 |
3 | import android.content.Context
4 | import android.graphics.Typeface
5 | import android.os.Build
6 | import androidx.annotation.ColorInt
7 | import androidx.annotation.ColorRes
8 | import androidx.annotation.FontRes
9 | import androidx.core.content.ContextCompat
10 | import androidx.core.content.res.ResourcesCompat
11 | import android.view.View
12 |
13 | /**
14 | * Created on 2018/2/27.
15 | */
16 |
17 | internal fun Float.clamp(min: Float, max: Float) = Math.max(min, Math.min(max, this))
18 |
19 | @ColorInt
20 | internal fun View.color(@ColorRes color: Int): Int = ContextCompat.getColor(context, color)
21 |
22 | internal fun View.sp(value: Int): Int = (value * resources.displayMetrics.scaledDensity).toInt()
23 |
24 | internal fun View.gone() {
25 | visibility = View.GONE
26 | }
27 |
28 | internal fun View.show() {
29 | visibility = View.VISIBLE
30 | }
31 |
32 | /**
33 | * [ResourcesCompat.getFont] doesn't check API version, resulting in accessing hidden API.
34 | */
35 | internal fun Context.getFontCompat(@FontRes fontRes: Int): Typeface? {
36 | return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
37 | resources.getFont(fontRes)
38 | } else {
39 | ResourcesCompat.getFont(this, fontRes)
40 | }
41 | }
--------------------------------------------------------------------------------
/library/src/main/res/font/digital_7_colon.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeweyReed/DigitalWatchView/3187f1cb385171fa6fb8351f68b71fe77e00b98f/library/src/main/res/font/digital_7_colon.ttf
--------------------------------------------------------------------------------
/library/src/main/res/font/digital_7_mono_nums.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DeweyReed/DigitalWatchView/3187f1cb385171fa6fb8351f68b71fe77e00b98f/library/src/main/res/font/digital_7_mono_nums.ttf
--------------------------------------------------------------------------------
/library/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/library/src/main/res/values/ids.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/library/src/main/res/values/public.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':library'
2 |
--------------------------------------------------------------------------------