├── ic_launcher-web.png
├── TimePickerWithSeconds.apk
├── libs
└── android-support-v4.jar
├── res
├── drawable-hdpi
│ └── ic_launcher.png
├── drawable-mdpi
│ └── ic_launcher.png
├── drawable-xhdpi
│ └── ic_launcher.png
├── drawable-xxhdpi
│ └── ic_launcher.png
├── values-sw600dp
│ └── dimens.xml
├── values
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
├── menu
│ └── main.xml
├── values-sw720dp-land
│ └── dimens.xml
├── values-nl
│ └── strings.xml
├── values-v11
│ └── styles.xml
├── values-v14
│ └── styles.xml
└── layout
│ ├── time_picker_dialog.xml
│ ├── activity_main.xml
│ └── time_picker_widget.xml
├── Screenshot_2014-03-03-19-55-49.png
├── .settings
└── org.eclipse.jdt.core.prefs
├── .classpath
├── project.properties
├── .gitignore
├── proguard-project.txt
├── .project
├── AndroidManifest.xml
├── README.md
└── src
└── com
└── ikovac
└── timepickerwithseconds
├── MainActivity.java
└── view
├── MyTimePickerDialog.java
└── TimePicker.java
/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IvanKovac/TimePickerWithSeconds/HEAD/ic_launcher-web.png
--------------------------------------------------------------------------------
/TimePickerWithSeconds.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IvanKovac/TimePickerWithSeconds/HEAD/TimePickerWithSeconds.apk
--------------------------------------------------------------------------------
/libs/android-support-v4.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IvanKovac/TimePickerWithSeconds/HEAD/libs/android-support-v4.jar
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IvanKovac/TimePickerWithSeconds/HEAD/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IvanKovac/TimePickerWithSeconds/HEAD/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/Screenshot_2014-03-03-19-55-49.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IvanKovac/TimePickerWithSeconds/HEAD/Screenshot_2014-03-03-19-55-49.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IvanKovac/TimePickerWithSeconds/HEAD/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IvanKovac/TimePickerWithSeconds/HEAD/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
3 | org.eclipse.jdt.core.compiler.compliance=1.6
4 | org.eclipse.jdt.core.compiler.source=1.6
5 |
--------------------------------------------------------------------------------
/res/values-sw600dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 16dp
5 | 16dp
6 |
7 |
8 |
--------------------------------------------------------------------------------
/res/menu/main.xml:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/res/values-sw720dp-land/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 | 128dp
8 |
9 |
10 |
--------------------------------------------------------------------------------
/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | TimePickerWithSeconds
5 | Settings
6 | Set time
7 | Cancel
8 | Time :
9 |
10 |
11 |
--------------------------------------------------------------------------------
/res/values-nl/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | TimePickerWithSeconds
5 | Instellingen
6 | Tijd instellen
7 | Annuleren
8 | Tijd :
9 |
10 |
11 |
--------------------------------------------------------------------------------
/res/values-v11/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/res/values-v14/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-18
15 | android.library=true
16 |
--------------------------------------------------------------------------------
/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
14 |
15 |
16 |
17 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #Android specific
2 | # built application files
3 | *.ap_
4 |
5 | obj
6 |
7 | # files for the dex VM
8 | *.dex
9 |
10 | # Java class files
11 | *.class
12 |
13 | # generated files
14 | bin/
15 | gen/
16 | .apt_generated/
17 | gen-db/
18 |
19 | target/
20 | # Local configuration file (sdk path, etc)
21 | local.properties
22 |
23 | #Eclipse specific
24 | *.pydevproject
25 | .project
26 | .metadata
27 | bin/**
28 | tmp/**
29 | tmp/**/*
30 | *.tmp
31 | *.bak
32 | *.swp
33 | *~.nib
34 | local.properties
35 | .classpath
36 | .settings/
37 | .loadpath
38 |
39 | # External tool builders
40 | .externalToolBuilders/
41 |
42 | # Locally stored "Eclipse launch configurations"
43 | *.launch
44 |
45 | # CDT-specific
46 | .cproject
47 |
48 | # PDT-specific
49 | .buildpath
50 |
51 | # IDEA specific
52 | .idea
53 | *.iml
54 |
--------------------------------------------------------------------------------
/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | TimePickerWithSeconds
4 |
5 |
6 |
7 |
8 |
9 | com.android.ide.eclipse.adt.ResourceManagerBuilder
10 |
11 |
12 |
13 |
14 | com.android.ide.eclipse.adt.PreCompilerBuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.jdt.core.javabuilder
20 |
21 |
22 |
23 |
24 | com.android.ide.eclipse.adt.ApkBuilder
25 |
26 |
27 |
28 |
29 |
30 | com.android.ide.eclipse.adt.AndroidNature
31 | org.eclipse.jdt.core.javanature
32 |
33 |
34 |
--------------------------------------------------------------------------------
/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
16 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/res/layout/time_picker_dialog.xml:
--------------------------------------------------------------------------------
1 |
2 |
20 |
24 |
30 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | TimePickerWithSeconds
2 | =====================
3 |
4 | Android TimePicker widget with seconds field as well. This widget is an extension of native TimePicker which provides only minute and hour fields.
5 |
6 | 
7 |
8 |
9 |
10 | Aplication
11 | ------
12 | The demo application (.apk) is under the root dir : TimePickerWithSeconds.apk
13 |
14 | Quick Setup - Gradle
15 | ------
16 |
17 | ``` java
18 | dependencies {
19 | ...
20 | compile 'com.kovachcode:timePickerWithSeconds:1.0.1'
21 | }
22 | ```
23 |
24 | Quick Setup - Eclipse
25 | ------
26 |
27 | This is Android library project. To use it within your application follow these steps:
28 |
29 | 1. Download the project to your workspace
30 | 2. Import project into Eclipse
31 | 3. Right click on YOUR project - > Properties -> Android
32 | Under the library choose "Add" and add TimePickerWithSeconds project
33 |
34 | Usage
35 | ------
36 |
37 | Show the Picker with:
38 |
39 | ``` java
40 | MyTimePickerDialog mTimePicker = new MyTimePickerDialog(this, new MyTimePickerDialog.OnTimeSetListener() {
41 |
42 | @Override
43 | public void onTimeSet(TimePicker view, int hourOfDay, int minute, int seconds) {
44 | // TODO Auto-generated method stub
45 | /*time.setText(getString(R.string.time) + String.format("%02d", hourOfDay)+
46 | ":" + String.format("%02d", minute) +
47 | ":" + String.format("%02d", seconds)); */
48 | }
49 | }, now.get(Calendar.HOUR_OF_DAY), now.get(Calendar.MINUTE), now.get(Calendar.SECOND), true);
50 | mTimePicker.show();
51 | ```
52 |
53 |
54 | Enjoy!
55 |
56 | Licence
57 | ------
58 | Feel free to use and change this code and include it in any of the projects you wish. There is no guarantee of any kind.
59 |
--------------------------------------------------------------------------------
/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
32 |
33 |
40 |
41 |
46 |
47 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/src/com/ikovac/timepickerwithseconds/MainActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 Ivan Kovac navratnanos@gmail.com
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.ikovac.timepickerwithseconds;
18 |
19 | import java.util.Calendar;
20 |
21 | import android.app.Activity;
22 | import android.os.Bundle;
23 | import android.view.Menu;
24 | import android.view.View;
25 | import android.widget.TextView;
26 |
27 | import com.ikovac.timepickerwithseconds.view.MyTimePickerDialog;
28 | import com.ikovac.timepickerwithseconds.view.TimePicker;
29 |
30 | public class MainActivity extends Activity {
31 | private TextView time;
32 |
33 | @Override
34 | protected void onCreate(Bundle savedInstanceState) {
35 | super.onCreate(savedInstanceState);
36 | setContentView(R.layout.activity_main);
37 | updateViews();
38 | }
39 |
40 | private void updateViews(){
41 | time = (TextView) findViewById(R.id.time);
42 | }
43 |
44 | public void showPicker(View v){
45 | Calendar now = Calendar.getInstance();
46 | MyTimePickerDialog mTimePicker = new MyTimePickerDialog(this, new MyTimePickerDialog.OnTimeSetListener() {
47 |
48 | @Override
49 | public void onTimeSet(TimePicker view, int hourOfDay, int minute, int seconds) {
50 | // TODO Auto-generated method stub
51 | time.setText(getString(R.string.time) + String.format("%02d", hourOfDay)+
52 | ":" + String.format("%02d", minute) +
53 | ":" + String.format("%02d", seconds));
54 | }
55 | }, now.get(Calendar.HOUR_OF_DAY), now.get(Calendar.MINUTE), now.get(Calendar.SECOND), true);
56 | mTimePicker.show();
57 | }
58 |
59 | @Override
60 | public boolean onCreateOptionsMenu(Menu menu) {
61 | // Inflate the menu; this adds items to the action bar if it is present.
62 | getMenuInflater().inflate(R.menu.main, menu);
63 | return true;
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/res/layout/time_picker_widget.xml:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
22 |
23 |
28 |
29 |
33 |
34 |
35 |
42 |
43 |
44 |
52 |
53 |
54 |
62 |
63 |
64 |
65 |
66 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/src/com/ikovac/timepickerwithseconds/view/MyTimePickerDialog.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2007 The Android Open Source Project
3 | * Copyright (C) 2013 Ivan Kovac navratnanos@gmail.com
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.ikovac.timepickerwithseconds.view;
18 |
19 | import java.util.Calendar;
20 |
21 | import android.app.AlertDialog;
22 | import android.content.Context;
23 | import android.content.DialogInterface;
24 | import android.content.DialogInterface.OnClickListener;
25 | import android.os.Bundle;
26 | import android.text.format.DateFormat;
27 | import android.view.LayoutInflater;
28 | import android.view.View;
29 | import android.view.Window;
30 |
31 | import com.ikovac.timepickerwithseconds.R;
32 | import com.ikovac.timepickerwithseconds.view.TimePicker.OnTimeChangedListener;
33 |
34 | /**
35 | * A dialog that prompts the user for the time of day using a {@link TimePicker}.
36 | */
37 | public class MyTimePickerDialog extends AlertDialog implements OnClickListener,
38 | OnTimeChangedListener {
39 |
40 | /**
41 | * The callback interface used to indicate the user is done filling in
42 | * the time (they clicked on the 'Set' button).
43 | */
44 | public interface OnTimeSetListener {
45 |
46 | /**
47 | * @param view The view associated with this listener.
48 | * @param hourOfDay The hour that was set.
49 | * @param minute The minute that was set.
50 | */
51 | void onTimeSet(TimePicker view, int hourOfDay, int minute, int seconds);
52 | }
53 |
54 | private static final String HOUR = "hour";
55 | private static final String MINUTE = "minute";
56 | private static final String SECONDS = "seconds";
57 | private static final String IS_24_HOUR = "is24hour";
58 |
59 | private final TimePicker mTimePicker;
60 | private final OnTimeSetListener mCallback;
61 | private final Calendar mCalendar;
62 | private final java.text.DateFormat mDateFormat;
63 |
64 | int mInitialHourOfDay;
65 | int mInitialMinute;
66 | int mInitialSeconds;
67 | boolean mIs24HourView;
68 |
69 | /**
70 | * @param context Parent.
71 | * @param callBack How parent is notified.
72 | * @param hourOfDay The initial hour.
73 | * @param minute The initial minute.
74 | * @param is24HourView Whether this is a 24 hour view, or AM/PM.
75 | */
76 | public MyTimePickerDialog(Context context,
77 | OnTimeSetListener callBack,
78 | int hourOfDay, int minute, int seconds, boolean is24HourView) {
79 |
80 | this(context, 0,
81 | callBack, hourOfDay, minute, seconds, is24HourView);
82 | }
83 |
84 | /**
85 | * @param context Parent.
86 | * @param theme the theme to apply to this dialog
87 | * @param callBack How parent is notified.
88 | * @param hourOfDay The initial hour.
89 | * @param minute The initial minute.
90 | * @param is24HourView Whether this is a 24 hour view, or AM/PM.
91 | */
92 | public MyTimePickerDialog(Context context,
93 | int theme,
94 | OnTimeSetListener callBack,
95 | int hourOfDay, int minute, int seconds, boolean is24HourView) {
96 | super(context, theme);
97 | requestWindowFeature(Window.FEATURE_NO_TITLE);
98 | mCallback = callBack;
99 | mInitialHourOfDay = hourOfDay;
100 | mInitialMinute = minute;
101 | mInitialSeconds = seconds;
102 | mIs24HourView = is24HourView;
103 |
104 | mDateFormat = DateFormat.getTimeFormat(context);
105 | mCalendar = Calendar.getInstance();
106 | updateTitle(mInitialHourOfDay, mInitialMinute, mInitialSeconds);
107 |
108 | setButton(context.getText(R.string.time_set), this);
109 | setButton2(context.getText(R.string.cancel), (OnClickListener) null);
110 | //setIcon(android.R.drawable.ic_dialog_time);
111 |
112 | LayoutInflater inflater =
113 | (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
114 | View view = inflater.inflate(R.layout.time_picker_dialog, null);
115 | setView(view);
116 | mTimePicker = (TimePicker) view.findViewById(R.id.timePicker);
117 |
118 | // initialize state
119 | mTimePicker.setCurrentHour(mInitialHourOfDay);
120 | mTimePicker.setCurrentMinute(mInitialMinute);
121 | mTimePicker.setCurrentSecond(mInitialSeconds);
122 | mTimePicker.setIs24HourView(mIs24HourView);
123 | mTimePicker.setOnTimeChangedListener(this);
124 | }
125 |
126 | public void onClick(DialogInterface dialog, int which) {
127 | if (mCallback != null) {
128 | mTimePicker.clearFocus();
129 | mCallback.onTimeSet(mTimePicker, mTimePicker.getCurrentHour(),
130 | mTimePicker.getCurrentMinute(), mTimePicker.getCurrentSeconds());
131 | }
132 | }
133 |
134 | public void onTimeChanged(TimePicker view, int hourOfDay, int minute, int seconds) {
135 | updateTitle(hourOfDay, minute, seconds);
136 | }
137 |
138 | public void updateTime(int hourOfDay, int minutOfHour, int seconds) {
139 | mTimePicker.setCurrentHour(hourOfDay);
140 | mTimePicker.setCurrentMinute(minutOfHour);
141 | mTimePicker.setCurrentSecond(seconds);
142 | }
143 |
144 | private void updateTitle(int hour, int minute, int seconds) {
145 | String sHour = String.format("%02d", hour);
146 | String sMin = String.format("%02d", minute);
147 | String sSec = String.format("%02d", seconds);
148 | setTitle(sHour + ":" + sMin + ":" + sSec);
149 | }
150 |
151 | @Override
152 | public Bundle onSaveInstanceState() {
153 | Bundle state = super.onSaveInstanceState();
154 | state.putInt(HOUR, mTimePicker.getCurrentHour());
155 | state.putInt(MINUTE, mTimePicker.getCurrentMinute());
156 | state.putInt(SECONDS, mTimePicker.getCurrentSeconds());
157 | state.putBoolean(IS_24_HOUR, mTimePicker.is24HourView());
158 | return state;
159 | }
160 |
161 | @Override
162 | public void onRestoreInstanceState(Bundle savedInstanceState) {
163 | super.onRestoreInstanceState(savedInstanceState);
164 | int hour = savedInstanceState.getInt(HOUR);
165 | int minute = savedInstanceState.getInt(MINUTE);
166 | int seconds = savedInstanceState.getInt(SECONDS);
167 | mTimePicker.setCurrentHour(hour);
168 | mTimePicker.setCurrentMinute(minute);
169 | mTimePicker.setCurrentSecond(seconds);
170 | mTimePicker.setIs24HourView(savedInstanceState.getBoolean(IS_24_HOUR));
171 | mTimePicker.setOnTimeChangedListener(this);
172 | updateTitle(hour, minute, seconds);
173 | }
174 |
175 |
176 | }
177 |
--------------------------------------------------------------------------------
/src/com/ikovac/timepickerwithseconds/view/TimePicker.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2007 The Android Open Source Project
3 | * Copyright (C) 2013 Ivan Kovac navratnanos@gmail.com
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package com.ikovac.timepickerwithseconds.view;
19 |
20 | import java.text.DateFormatSymbols;
21 | import java.util.Calendar;
22 |
23 | import android.content.Context;
24 | import android.os.Parcel;
25 | import android.os.Parcelable;
26 | import android.util.AttributeSet;
27 | import android.view.LayoutInflater;
28 | import android.view.View;
29 | import android.widget.Button;
30 | import android.widget.FrameLayout;
31 | import android.widget.NumberPicker;
32 | import android.widget.NumberPicker.Formatter;
33 |
34 | import com.ikovac.timepickerwithseconds.R;
35 |
36 | /**
37 | * A view for selecting the time of day, in either 24 hour or AM/PM mode.
38 | *
39 | * The hour, each minute digit, each seconds digit, and AM/PM (if applicable) can be conrolled by
40 | * vertical spinners.
41 | *
42 | * The hour can be entered by keyboard input. Entering in two digit hours
43 | * can be accomplished by hitting two digits within a timeout of about a
44 | * second (e.g. '1' then '2' to select 12).
45 | *
46 | * The minutes can be entered by entering single digits.
47 | * The seconds can be entered by entering single digits.
48 | *
49 | * Under AM/PM mode, the user can hit 'a', 'A", 'p' or 'P' to pick.
50 | *
51 | * For a dialog using this view, see {@link android.app.TimePickerDialog}.
52 | */
53 | public class TimePicker extends FrameLayout {
54 |
55 | /**
56 | * A no-op callback used in the constructor to avoid null checks
57 | * later in the code.
58 | */
59 | private static final OnTimeChangedListener NO_OP_CHANGE_LISTENER = new OnTimeChangedListener() {
60 | public void onTimeChanged(TimePicker view, int hourOfDay, int minute, int seconds) {
61 | }
62 | };
63 |
64 | public static final NumberPicker.Formatter TWO_DIGIT_FORMATTER =
65 | new Formatter() {
66 |
67 | @Override
68 | public String format(int value) {
69 | // TODO Auto-generated method stub
70 | return String.format("%02d", value);
71 | }
72 | };
73 |
74 | // state
75 | private int mCurrentHour = 0; // 0-23
76 | private int mCurrentMinute = 0; // 0-59
77 | private int mCurrentSeconds = 0; // 0-59
78 | private Boolean mIs24HourView = false;
79 | private boolean mIsAm;
80 |
81 | // ui components
82 | private final NumberPicker mHourPicker;
83 | private final NumberPicker mMinutePicker;
84 | private final NumberPicker mSecondPicker;
85 | private final Button mAmPmButton;
86 | private final String mAmText;
87 | private final String mPmText;
88 |
89 | // callbacks
90 | private OnTimeChangedListener mOnTimeChangedListener;
91 |
92 | /**
93 | * The callback interface used to indicate the time has been adjusted.
94 | */
95 | public interface OnTimeChangedListener {
96 |
97 | /**
98 | * @param view The view associated with this listener.
99 | * @param hourOfDay The current hour.
100 | * @param minute The current minute.
101 | * @param seconds The current second.
102 | */
103 | void onTimeChanged(TimePicker view, int hourOfDay, int minute, int seconds);
104 | }
105 |
106 | public TimePicker(Context context) {
107 | this(context, null);
108 | }
109 |
110 | public TimePicker(Context context, AttributeSet attrs) {
111 | this(context, attrs, 0);
112 | }
113 |
114 | public TimePicker(Context context, AttributeSet attrs, int defStyle) {
115 | super(context, attrs, defStyle);
116 |
117 | LayoutInflater inflater =
118 | (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
119 | inflater.inflate(R.layout.time_picker_widget,
120 | this, // we are the parent
121 | true);
122 |
123 | // hour
124 | mHourPicker = (NumberPicker) findViewById(R.id.hour);
125 | mHourPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
126 |
127 | @Override
128 | public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
129 | // TODO Auto-generated method stub
130 | mCurrentHour = newVal;
131 | if (!mIs24HourView) {
132 | // adjust from [1-12] to [0-11] internally, with the times
133 | // written "12:xx" being the start of the half-day
134 | if (mCurrentHour == 12) {
135 | mCurrentHour = 0;
136 | }
137 | if (!mIsAm) {
138 | // PM means 12 hours later than nominal
139 | mCurrentHour += 12;
140 | }
141 | }
142 | onTimeChanged();
143 | }
144 | });
145 |
146 | // digits of minute
147 | mMinutePicker = (NumberPicker) findViewById(R.id.minute);
148 | mMinutePicker.setMinValue(0);
149 | mMinutePicker.setMaxValue(59);
150 | mMinutePicker.setFormatter(TWO_DIGIT_FORMATTER);
151 | mMinutePicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
152 | @Override
153 | public void onValueChange(NumberPicker spinner, int oldVal, int newVal) {
154 | mCurrentMinute = newVal;
155 | onTimeChanged();
156 | }
157 | });
158 |
159 | // digits of seconds
160 | mSecondPicker = (NumberPicker) findViewById(R.id.seconds);
161 | mSecondPicker.setMinValue(0);
162 | mSecondPicker.setMaxValue(59);
163 | mSecondPicker.setFormatter( TWO_DIGIT_FORMATTER);
164 | mSecondPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
165 |
166 | @Override
167 | public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
168 | mCurrentSeconds = newVal;
169 | onTimeChanged();
170 |
171 | }
172 | });
173 |
174 | // am/pm
175 | mAmPmButton = (Button) findViewById(R.id.amPm);
176 |
177 | // now that the hour/minute picker objects have been initialized, set
178 | // the hour range properly based on the 12/24 hour display mode.
179 | configurePickerRanges();
180 |
181 | // initialize to current time
182 | Calendar cal = Calendar.getInstance();
183 | setOnTimeChangedListener(NO_OP_CHANGE_LISTENER);
184 |
185 | // by default we're not in 24 hour mode
186 | setCurrentHour(cal.get(Calendar.HOUR_OF_DAY));
187 | setCurrentMinute(cal.get(Calendar.MINUTE));
188 | setCurrentSecond(cal.get(Calendar.SECOND));
189 |
190 | mIsAm = (mCurrentHour < 12);
191 |
192 | /* Get the localized am/pm strings and use them in the spinner */
193 | DateFormatSymbols dfs = new DateFormatSymbols();
194 | String[] dfsAmPm = dfs.getAmPmStrings();
195 | mAmText = dfsAmPm[Calendar.AM];
196 | mPmText = dfsAmPm[Calendar.PM];
197 | mAmPmButton.setText(mIsAm ? mAmText : mPmText);
198 | mAmPmButton.setOnClickListener(new OnClickListener() {
199 | public void onClick(View v) {
200 | requestFocus();
201 | if (mIsAm) {
202 |
203 | // Currently AM switching to PM
204 | if (mCurrentHour < 12) {
205 | mCurrentHour += 12;
206 | }
207 | } else {
208 |
209 | // Currently PM switching to AM
210 | if (mCurrentHour >= 12) {
211 | mCurrentHour -= 12;
212 | }
213 | }
214 | mIsAm = !mIsAm;
215 | mAmPmButton.setText(mIsAm ? mAmText : mPmText);
216 | onTimeChanged();
217 | }
218 | });
219 |
220 | if (!isEnabled()) {
221 | setEnabled(false);
222 | }
223 | }
224 |
225 | @Override
226 | public void setEnabled(boolean enabled) {
227 | super.setEnabled(enabled);
228 | mMinutePicker.setEnabled(enabled);
229 | mHourPicker.setEnabled(enabled);
230 | mAmPmButton.setEnabled(enabled);
231 | }
232 |
233 | /**
234 | * Used to save / restore state of time picker
235 | */
236 | private static class SavedState extends BaseSavedState {
237 |
238 | private final int mHour;
239 | private final int mMinute;
240 |
241 | private SavedState(Parcelable superState, int hour, int minute) {
242 | super(superState);
243 | mHour = hour;
244 | mMinute = minute;
245 | }
246 |
247 | private SavedState(Parcel in) {
248 | super(in);
249 | mHour = in.readInt();
250 | mMinute = in.readInt();
251 | }
252 |
253 | public int getHour() {
254 | return mHour;
255 | }
256 |
257 | public int getMinute() {
258 | return mMinute;
259 | }
260 |
261 | @Override
262 | public void writeToParcel(Parcel dest, int flags) {
263 | super.writeToParcel(dest, flags);
264 | dest.writeInt(mHour);
265 | dest.writeInt(mMinute);
266 | }
267 |
268 | public static final Parcelable.Creator CREATOR
269 | = new Creator() {
270 | public SavedState createFromParcel(Parcel in) {
271 | return new SavedState(in);
272 | }
273 |
274 | public SavedState[] newArray(int size) {
275 | return new SavedState[size];
276 | }
277 | };
278 | }
279 |
280 | @Override
281 | protected Parcelable onSaveInstanceState() {
282 | Parcelable superState = super.onSaveInstanceState();
283 | return new SavedState(superState, mCurrentHour, mCurrentMinute);
284 | }
285 |
286 | @Override
287 | protected void onRestoreInstanceState(Parcelable state) {
288 | SavedState ss = (SavedState) state;
289 | super.onRestoreInstanceState(ss.getSuperState());
290 | setCurrentHour(ss.getHour());
291 | setCurrentMinute(ss.getMinute());
292 | }
293 |
294 | /**
295 | * Set the callback that indicates the time has been adjusted by the user.
296 | * @param onTimeChangedListener the callback, should not be null.
297 | */
298 | public void setOnTimeChangedListener(OnTimeChangedListener onTimeChangedListener) {
299 | mOnTimeChangedListener = onTimeChangedListener;
300 | }
301 |
302 | /**
303 | * @return The current hour (0-23).
304 | */
305 | public Integer getCurrentHour() {
306 | return mCurrentHour;
307 | }
308 |
309 | /**
310 | * Set the current hour.
311 | */
312 | public void setCurrentHour(Integer currentHour) {
313 | this.mCurrentHour = currentHour;
314 | updateHourDisplay();
315 | }
316 |
317 | /**
318 | * Set whether in 24 hour or AM/PM mode.
319 | * @param is24HourView True = 24 hour mode. False = AM/PM.
320 | */
321 | public void setIs24HourView(Boolean is24HourView) {
322 | if (mIs24HourView != is24HourView) {
323 | mIs24HourView = is24HourView;
324 | configurePickerRanges();
325 | updateHourDisplay();
326 | }
327 | }
328 |
329 | /**
330 | * @return true if this is in 24 hour view else false.
331 | */
332 | public boolean is24HourView() {
333 | return mIs24HourView;
334 | }
335 |
336 | /**
337 | * @return The current minute.
338 | */
339 | public Integer getCurrentMinute() {
340 | return mCurrentMinute;
341 | }
342 |
343 | /**
344 | * Set the current minute (0-59).
345 | */
346 | public void setCurrentMinute(Integer currentMinute) {
347 | this.mCurrentMinute = currentMinute;
348 | updateMinuteDisplay();
349 | }
350 |
351 | /**
352 | * @return The current minute.
353 | */
354 | public Integer getCurrentSeconds() {
355 | return mCurrentSeconds;
356 | }
357 |
358 | /**
359 | * Set the current second (0-59).
360 | */
361 | public void setCurrentSecond(Integer currentSecond) {
362 | this.mCurrentSeconds = currentSecond;
363 | updateSecondsDisplay();
364 | }
365 |
366 | @Override
367 | public int getBaseline() {
368 | return mHourPicker.getBaseline();
369 | }
370 |
371 | /**
372 | * Set the state of the spinners appropriate to the current hour.
373 | */
374 | private void updateHourDisplay() {
375 | int currentHour = mCurrentHour;
376 | if (!mIs24HourView) {
377 | // convert [0,23] ordinal to wall clock display
378 | if (currentHour > 12) currentHour -= 12;
379 | else if (currentHour == 0) currentHour = 12;
380 | }
381 | mHourPicker.setValue(currentHour);
382 | mIsAm = mCurrentHour < 12;
383 | mAmPmButton.setText(mIsAm ? mAmText : mPmText);
384 | onTimeChanged();
385 | }
386 |
387 | private void configurePickerRanges() {
388 | if (mIs24HourView) {
389 | mHourPicker.setMinValue(0);
390 | mHourPicker.setMaxValue(23);
391 | mHourPicker.setFormatter(TWO_DIGIT_FORMATTER);
392 | mAmPmButton.setVisibility(View.GONE);
393 | } else {
394 | mHourPicker.setMinValue(1);
395 | mHourPicker.setMaxValue(12);
396 | mHourPicker.setFormatter(null);
397 | mAmPmButton.setVisibility(View.VISIBLE);
398 | }
399 | }
400 |
401 | private void onTimeChanged() {
402 | mOnTimeChangedListener.onTimeChanged(this, getCurrentHour(), getCurrentMinute(), getCurrentSeconds());
403 | }
404 |
405 | /**
406 | * Set the state of the spinners appropriate to the current minute.
407 | */
408 | private void updateMinuteDisplay() {
409 | mMinutePicker.setValue(mCurrentMinute);
410 | mOnTimeChangedListener.onTimeChanged(this, getCurrentHour(), getCurrentMinute(), getCurrentSeconds());
411 | }
412 |
413 | /**
414 | * Set the state of the spinners appropriate to the current second.
415 | */
416 | private void updateSecondsDisplay() {
417 | mSecondPicker.setValue(mCurrentSeconds);
418 | mOnTimeChangedListener.onTimeChanged(this, getCurrentHour(), getCurrentMinute(), getCurrentSeconds());
419 | }
420 | }
421 |
422 |
--------------------------------------------------------------------------------