├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── picker │ │ └── ugurtekbas │ │ └── com │ │ └── DialTimePicker │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── picker │ │ └── ugurtekbas │ │ └── com │ │ └── DialTimePicker │ │ ├── ActivityAdapter.kt │ │ ├── Main.kt │ │ └── MainFragment.kt │ └── res │ ├── layout │ ├── ampm_picker.xml │ ├── main.xml │ └── normal_picker.xml │ ├── menu │ └── menu_main.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── images ├── 1.png └── 2.png ├── library ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── picker │ │ └── ugurtekbas │ │ └── com │ │ └── Picker │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── picker │ │ └── ugurtekbas │ │ └── com │ │ └── Picker │ │ └── Picker.kt │ └── res │ └── values │ └── attrs.xml └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.aar 4 | *.ap_ 5 | *.aab 6 | 7 | # Files for the ART/Dalvik VM 8 | *.dex 9 | 10 | # Java class files 11 | *.class 12 | 13 | # Generated files 14 | bin/ 15 | gen/ 16 | out/ 17 | # Uncomment the following line in case you need and you don't have the release build type files in your app 18 | # release/ 19 | 20 | # Gradle files 21 | .gradle/ 22 | build/ 23 | 24 | # Local configuration file (sdk path, etc) 25 | local.properties 26 | 27 | # Proguard folder generated by Eclipse 28 | proguard/ 29 | 30 | # Log Files 31 | *.log 32 | 33 | # Android Studio Navigation editor temp files 34 | .navigation/ 35 | 36 | # Android Studio captures folder 37 | captures/ 38 | 39 | # IntelliJ 40 | *.iml 41 | .idea/workspace.xml 42 | .idea/tasks.xml 43 | .idea/gradle.xml 44 | .idea/assetWizardSettings.xml 45 | .idea/dictionaries 46 | .idea/libraries 47 | # Android Studio 3 in .gitignore file. 48 | .idea/caches 49 | .idea/modules.xml 50 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you 51 | .idea/navEditor.xml 52 | 53 | # Keystore files 54 | # Uncomment the following lines if you do not want to check your keystore files in. 55 | #*.jks 56 | #*.keystore 57 | 58 | # External native build folder generated in Android Studio 2.2 and later 59 | .externalNativeBuild 60 | .cxx/ 61 | 62 | # Google Services (e.g. APIs or Firebase) 63 | # google-services.json 64 | 65 | # Freeline 66 | freeline.py 67 | freeline/ 68 | freeline_project_description.json 69 | 70 | # fastlane 71 | fastlane/report.xml 72 | fastlane/Preview.html 73 | fastlane/screenshots 74 | fastlane/test_output 75 | fastlane/readme.md 76 | 77 | # Version control 78 | vcs.xml 79 | 80 | # lint 81 | lint/intermediates/ 82 | lint/generated/ 83 | lint/outputs/ 84 | lint/tmp/ 85 | # lint/reports/ 86 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dialTimePicker 2 | A custom time picker library for Android. 3 |
4 | As a result of needing a fixed time picker for pre-lollipop devices, for my 5 | [alarm app](https://play.google.com/store/apps/details?id=com.ugurtekbas.alarmshuffle) i developed a dial time picker view. 6 | Calculations in the main class mostly based on [erz05's view.](https://github.com/erz05/TimePicker) 7 | 8 | [![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-dialTimePicker-green.svg?style=true)](https://android-arsenal.com/details/1/3244) 9 | 10 |

Images

11 | 12 | 13 |
14 | 15 |

Usage

16 | Gradle Import: 17 | 18 | Add the specific repository to your build file: 19 | ```groovy 20 | repositories { 21 | maven { 22 | url "https://jitpack.io" 23 | } 24 | } 25 | ``` 26 | Add the dependency in your build file (do not forget to specify the correct qualifier, usually 'aar'): 27 | ```groovy 28 | dependencies { 29 | compile 'com.github.ugurtekbas:dialTimePicker:8d263fc3a1' 30 | } 31 | ``` 32 | 33 | ```xml 34 | 35 | 40 | 41 | 42 | 54 | ``` 55 | 56 | ```java 57 | Picker picker = (Picker) findViewById(R.id.picker); 58 | //or 59 | Picker picker = new Picker(context); 60 | 61 | //Set background color 62 | picker.setCanvasColor(Color.WHITE); 63 | //Set dial color 64 | picker.setDialColor(Color.ORANGE); 65 | //Set clock color 66 | picker.setClockColor(Color.CYAN); 67 | //Set text color 68 | picker.setTextColor(Color.BLACK); 69 | //Enable 24 or 12 hour clock 70 | picker.setHourFormat(true); 71 | //Get current hour 72 | picker.getCurrentHour(); 73 | //Get current minutes 74 | picker.getCurrentMin(); 75 | //Diasble/enable the picker 76 | picker.setEnabled(false); 77 | //Set dial's size 78 | picker.setTrackSize(20); 79 | //Set adjuster's size 80 | picker.setDialRadiusDP(60); 81 | //Initialize picker's time 82 | picker.setTime(9,0); 83 | //Set picker's time with calendar object 84 | picker.setTime(Calendar.getInstance()); 85 | //Set dialAdjust to adjust time by touching on clock's dial 86 | picker.setDialAdjust(true); 87 | //Set TimeChangedListener 88 | picker.setTimeChangedListener(this); 89 | 90 | //TimeChangeListener method 91 | public void timeChanged(Date date){ 92 | } 93 | 94 | ``` 95 |

License

96 | Copyright 2018 Ugur Tekbas 97 | 98 | Licensed under the Apache License, Version 2.0 (the "License"); 99 | you may not use this file except in compliance with the License. 100 | You may obtain a copy of the License at 101 | 102 | http://www.apache.org/licenses/LICENSE-2.0 103 | 104 | Unless required by applicable law or agreed to in writing, software 105 | distributed under the License is distributed on an "AS IS" BASIS, 106 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 107 | See the License for the specific language governing permissions and 108 | limitations under the License. 109 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'kotlin-android' 3 | 4 | android { 5 | compileSdkVersion 30 6 | defaultConfig { 7 | applicationId 'ugurtekbas.com.dialtimepicker' 8 | minSdkVersion 21 9 | targetSdkVersion 30 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | productFlavors { 20 | } 21 | } 22 | 23 | dependencies { 24 | implementation fileTree(include: ['*.jar'], dir: 'libs') 25 | implementation "androidx.appcompat:appcompat:1.2.0" 26 | implementation project(':library') 27 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 28 | } 29 | repositories { 30 | mavenCentral() 31 | } 32 | -------------------------------------------------------------------------------- /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 C:\Program Files (x86)\Android/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/androidTest/java/picker/ugurtekbas/com/DialTimePicker/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package picker.ugurtekbas.com.DialTimePicker; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/java/picker/ugurtekbas/com/DialTimePicker/ActivityAdapter.kt: -------------------------------------------------------------------------------- 1 | package picker.ugurtekbas.com.DialTimePicker 2 | 3 | import androidx.fragment.app.Fragment 4 | import androidx.fragment.app.FragmentManager 5 | import androidx.fragment.app.FragmentStatePagerAdapter 6 | 7 | class ActivityAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) { 8 | 9 | var layoutIDs = intArrayOf(R.layout.normal_picker, R.layout.ampm_picker) 10 | 11 | override fun getItem(position: Int): Fragment { 12 | return MainFragment.newInstance(layoutIDs[position]) 13 | } 14 | 15 | override fun getCount(): Int { 16 | return layoutIDs.size 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/picker/ugurtekbas/com/DialTimePicker/Main.kt: -------------------------------------------------------------------------------- 1 | package picker.ugurtekbas.com.DialTimePicker 2 | 3 | import android.os.Bundle 4 | import android.view.Menu 5 | import android.view.MenuItem 6 | import android.view.View 7 | import androidx.appcompat.app.AppCompatActivity 8 | import androidx.viewpager.widget.ViewPager 9 | 10 | class Main : AppCompatActivity() { 11 | 12 | private var viewPager: ViewPager? = null 13 | 14 | override fun onCreate(savedInstanceState: Bundle?) { 15 | super.onCreate(savedInstanceState) 16 | setContentView(R.layout.main) 17 | 18 | title = resources.getString(R.string.appTitle) 19 | (findViewById(R.id.viewPager) as ViewPager).apply { 20 | adapter = ActivityAdapter(supportFragmentManager) 21 | } 22 | } 23 | 24 | override fun onCreateOptionsMenu(menu: Menu): Boolean { 25 | menuInflater.inflate(R.menu.menu_main, menu) 26 | return true 27 | } 28 | 29 | override fun onOptionsItemSelected(item: MenuItem): Boolean { 30 | val id = item.itemId 31 | return super.onOptionsItemSelected(item) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/picker/ugurtekbas/com/DialTimePicker/MainFragment.kt: -------------------------------------------------------------------------------- 1 | package picker.ugurtekbas.com.DialTimePicker 2 | 3 | import android.os.Bundle 4 | import android.util.Log 5 | import android.view.LayoutInflater 6 | import android.view.View 7 | import android.view.ViewGroup 8 | import android.widget.Button 9 | import android.widget.CheckBox 10 | import android.widget.TextView 11 | import androidx.fragment.app.Fragment 12 | import picker.ugurtekbas.com.Picker.Picker 13 | import picker.ugurtekbas.com.Picker.TimeChangedListener 14 | import java.util.* 15 | 16 | class MainFragment : Fragment(), TimeChangedListener { 17 | 18 | companion object { 19 | const val idKey = "layoutID" 20 | fun newInstance(layoutID: Int): MainFragment { 21 | val fragment = MainFragment() 22 | fragment.layoutID = layoutID 23 | return fragment 24 | } 25 | } 26 | 27 | private var layoutID = 0 28 | 29 | override fun onSaveInstanceState(bundle: Bundle) { 30 | super.onSaveInstanceState(bundle) 31 | bundle.putInt(idKey, layoutID) 32 | } 33 | 34 | override fun onCreate(bundle: Bundle?) { 35 | super.onCreate(bundle) 36 | if (bundle?.getInt(idKey) != null) { 37 | layoutID = bundle.getInt(idKey) 38 | } 39 | } 40 | 41 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { 42 | val v = inflater.inflate(layoutID, container, false) 43 | if (layoutID == R.layout.ampm_picker) { 44 | with(v.findViewById(R.id.amPicker) as Picker) { 45 | setClockColor(resources.getColor(R.color.clockColor)) 46 | setDialColor(resources.getColor(R.color.dialColor)) 47 | setTime(12, 45, Picker.AM) 48 | setTrackSize(20) 49 | setDialRadiusDP(60) 50 | val checkBox = v.findViewById(R.id.checkbox) as CheckBox 51 | this.isEnabled = checkBox.isChecked 52 | checkBox.setOnCheckedChangeListener { buttonView, isChecked -> this.isEnabled = isChecked } 53 | } 54 | } else { 55 | val picker = v.findViewById(R.id.picker) as Picker 56 | picker.isDialAdjust = false 57 | picker.timeListener = this 58 | val et = v.findViewById(R.id.et) as TextView 59 | val btn = v.findViewById(R.id.btn) as Button 60 | btn.setOnClickListener { 61 | var minute = picker.currentMin.toString() 62 | if (picker.currentMin < 10) { 63 | minute = "0$minute" 64 | } 65 | et.text = "It's " + picker.currentHour + ":" + minute 66 | } 67 | } 68 | return v 69 | } 70 | 71 | override fun timeChanged(date: Date?) { 72 | Log.i("Time changed: ", date.toString()) 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /app/src/main/res/layout/ampm_picker.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 17 | 18 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /app/src/main/res/layout/main.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/layout/normal_picker.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 17 | 18 | 26 |