Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementing Date and Time pickers #789

Merged
merged 29 commits into from
Apr 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
e73dec9
TimeWidget: added new button and TextView
grzesiek2010 Mar 27, 2017
21b28d1
TimeWidget: added setTime() method
grzesiek2010 Mar 27, 2017
7a3ac30
TimeWidget: added TimePickerDialog
grzesiek2010 Mar 27, 2017
8ba95ee
TimeWidget: removed unnecessary code
grzesiek2010 Mar 27, 2017
4282264
DateWidget: added new button and TextView
grzesiek2010 Mar 27, 2017
b865221
DateWidget: Added DatePickerDialog
grzesiek2010 Mar 27, 2017
d235a66
DateWidget: refactored hideDayFieldIfNotInFormat() method
grzesiek2010 Mar 27, 2017
6002e2d
DateWidget: Removed unnecessary code
grzesiek2010 Mar 27, 2017
4173b73
DateWidget: Code refactoring
grzesiek2010 Mar 27, 2017
5cdbce0
DateWidget: Implemented setDate() method
grzesiek2010 Mar 27, 2017
665e85a
DateWidget: Fixed some bugs
grzesiek2010 Mar 27, 2017
dc7d3b7
Added new DateTimeWidget
grzesiek2010 Mar 27, 2017
471d839
Merge branch 'master' into COLLECT-427_2
grzesiek2010 Mar 29, 2017
63c051e
Fixed bugs and lints
grzesiek2010 Mar 29, 2017
0950934
Removed calendar appearance
grzesiek2010 Mar 31, 2017
96ef6b0
Hide dialog title
grzesiek2010 Mar 31, 2017
f5657b3
Merge branch 'master' into COLLECT-427_2
grzesiek2010 Apr 7, 2017
8b9ad9d
Update strings.xml
grzesiek2010 Apr 7, 2017
af35cbe
Merge branch 'master' into COLLECT-427_2
grzesiek2010 Apr 9, 2017
2b37745
Update strings.xml
grzesiek2010 Apr 9, 2017
314646a
Fixed test
grzesiek2010 Apr 10, 2017
64589aa
Added calendar back
grzesiek2010 Apr 12, 2017
82399be
Fixed displayed text
grzesiek2010 Apr 12, 2017
c8333d7
Fixed bug
grzesiek2010 Apr 12, 2017
6a8b9a7
Added custom dialogs
grzesiek2010 Apr 12, 2017
afc34e9
Fixed bugs and test
grzesiek2010 Apr 12, 2017
91ef23f
Merge branch 'master' into COLLECT-427_2
grzesiek2010 Apr 14, 2017
609f29d
Update strings.xml
grzesiek2010 Apr 14, 2017
d623d86
Changes for calendar appearance
grzesiek2010 Apr 14, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,10 @@ public void setTextcolor(int color) {
mView_Text.setTextColor(color);
}

public TextView getView_Text() {
return mView_Text;
}

/**
* This is what gets called when the AudioButton gets clicked
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,17 @@

package org.odk.collect.android.widgets;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.os.Build;
import android.view.Gravity;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.CalendarView;
import android.widget.DatePicker;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import android.widget.TimePicker;

import org.javarosa.core.model.data.DateTimeData;
import org.javarosa.core.model.data.IAnswerData;
import org.javarosa.form.api.FormEntryPrompt;
import org.joda.time.DateTime;

import org.joda.time.DateTimeZone;
import org.joda.time.LocalDateTime;
import org.odk.collect.android.application.Collect;
import org.odk.collect.android.utilities.DateWidgetUtils;

import java.util.Calendar;
import java.util.Date;

/**
* Displays a DatePicker widget. DateWidget handles leap years and does not allow dates that do not
* exist.
Expand All @@ -48,214 +34,60 @@
*/
public class DateTimeWidget extends QuestionWidget {

private DatePicker mDatePicker;
private TimePicker mTimePicker;
private DatePicker.OnDateChangedListener mDateListener;
private boolean hideDay = false;
private boolean hideMonth = false;
private boolean showCalendar = false;
private HorizontalScrollView scrollView = null;
private DateWidget mDateWidget;
private TimeWidget mTimeWidget;

public DateTimeWidget(Context context, FormEntryPrompt prompt) {
super(context, prompt);

mDatePicker = new DatePicker(getContext());
mDatePicker.setId(QuestionWidget.newUniqueId());
mDatePicker.setFocusable(!prompt.isReadOnly());
mDatePicker.setEnabled(!prompt.isReadOnly());

if (Build.VERSION.SDK_INT == Build.VERSION_CODES.JELLY_BEAN) {
DateWidgetUtils.fixCalendarViewIfJellyBean(mDatePicker.getCalendarView());
}

mTimePicker = new TimePicker(getContext());
mTimePicker.setId(QuestionWidget.newUniqueId());
mTimePicker.setFocusable(!prompt.isReadOnly());
mTimePicker.setEnabled(!prompt.isReadOnly());
mTimePicker.setPadding(0, 20, 0, 0);

String clockType =
android.provider.Settings.System.getString(context.getContentResolver(),
android.provider.Settings.System.TIME_12_24);
if (clockType == null || clockType.equalsIgnoreCase("24")) {
mTimePicker.setIs24HourView(true);
}

hideDayFieldIfNotInFormat(prompt);

mDateListener = new DatePicker.OnDateChangedListener() {
@Override
public void onDateChanged(DatePicker view, int year, int month, int day) {
if (mPrompt.isReadOnly()) {
setAnswer();
} else {
// handle leap years and number of days in month
// TODO
// http://code.google.com/p/android/issues/detail?id=2081
// in older versions of android (1.6ish) the datepicker lets you pick bad dates
// in newer versions, calling updateDate() calls onDatechangedListener(),
// causing an
// endless loop.
Calendar c = Calendar.getInstance();
c.set(year, month, 1);
int max = c.getActualMaximum(Calendar.DAY_OF_MONTH);
if (day > max) {
if (!(mDatePicker.getDayOfMonth() == day && mDatePicker.getMonth() == month
&& mDatePicker.getYear() == year)) {
Collect.getInstance().getActivityLogger().logInstanceAction(
DateTimeWidget.this, "onDateChanged",
String.format("%1$04d-%2$02d-%3$02d", year, month, max),
mPrompt.getIndex());
mDatePicker.updateDate(year, month, max);
}
} else {
if (!(mDatePicker.getDayOfMonth() == day && mDatePicker.getMonth() == month
&& mDatePicker.getYear() == year)) {
Collect.getInstance().getActivityLogger().logInstanceAction(
DateTimeWidget.this, "onDateChanged",
String.format("%1$04d-%2$02d-%3$02d", year, month, day),
mPrompt.getIndex());
mDatePicker.updateDate(year, month, day);
}
}
}
}
};

mTimePicker.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {
@Override
public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
Collect.getInstance().getActivityLogger().logInstanceAction(DateTimeWidget.this,
"onTimeChanged",
String.format("%1$02d:%2$02d", hourOfDay, minute), mPrompt.getIndex());
}
});

setGravity(Gravity.START);
LinearLayout answerLayout = new LinearLayout(getContext());
answerLayout.setOrientation(LinearLayout.VERTICAL);
if (showCalendar) {
scrollView = new HorizontalScrollView(context);
LinearLayout ll = new LinearLayout(context);
ll.addView(mDatePicker);
ll.setPadding(10, 10, 10, 10);
scrollView.addView(ll);
answerLayout.addView(scrollView);
} else {
answerLayout.addView(mDatePicker);
}
answerLayout.addView(mTimePicker);
addAnswerView(answerLayout);

// If there's an answer, use it.
setAnswer();
}
mDateWidget = new DateWidget(context, prompt);
mTimeWidget= new TimeWidget(context, prompt);

mDateWidget.mQuestionMediaLayout.getView_Text().setVisibility(GONE);
mTimeWidget.mQuestionMediaLayout.getView_Text().setVisibility(GONE);

/**
* Shared between DateWidget and DateTimeWidget.
* There are extra appearance settings that do not apply for dateTime...
* TODO: move this into utilities or base class?
*/
@SuppressLint("NewApi")
private void hideDayFieldIfNotInFormat(FormEntryPrompt prompt) {
String appearance = prompt.getQuestion().getAppearanceAttr();
if (appearance == null) {
showCalendar = true;
this.mDatePicker.setCalendarViewShown(true);
CalendarView cv = this.mDatePicker.getCalendarView();
cv.setShowWeekNumber(false);
this.mDatePicker.setSpinnersShown(true);
hideDay = true;
hideMonth = false;
} else if ("month-year".equals(appearance)) {
hideDay = true;
this.mDatePicker.setCalendarViewShown(false);
this.mDatePicker.setSpinnersShown(true);
mTimePicker.setVisibility(GONE);
} else if ("year".equals(appearance)) {
hideMonth = true;
this.mDatePicker.setCalendarViewShown(false);
this.mDatePicker.setSpinnersShown(true);
mTimePicker.setVisibility(GONE);
} else if ("no-calendar".equals(appearance)) {
this.mDatePicker.setCalendarViewShown(false);
this.mDatePicker.setSpinnersShown(true);
} else {
showCalendar = true;
this.mDatePicker.setCalendarViewShown(true);
CalendarView cv = this.mDatePicker.getCalendarView();
cv.setShowWeekNumber(false);
this.mDatePicker.setSpinnersShown(true);
hideDay = true;
hideMonth = false;
}

if (hideMonth || hideDay) {
mDatePicker.findViewById(
Resources.getSystem().getIdentifier("day", "id", "android"))
.setVisibility(View.GONE);
if (hideMonth) {
mDatePicker
.findViewById(
Resources.getSystem().getIdentifier("month", "id", "android"))
.setVisibility(View.GONE);
}
LinearLayout linearLayout = new LinearLayout(getContext());
linearLayout.setOrientation(LinearLayout.VERTICAL);
linearLayout.addView(mDateWidget);
if (mDateWidget.isCalendarShown() || !mDateWidget.isDayHidden()) {
linearLayout.addView(mTimeWidget);
}
addAnswerView(linearLayout);
}

private void setAnswer() {

if (mPrompt.getAnswerValue() != null) {

DateTime ldt =
new DateTime(
((Date) mPrompt.getAnswerValue().getValue()).getTime
());
mDatePicker.init(ldt.getYear(), ldt.getMonthOfYear() - 1, ldt.getDayOfMonth(),
mDateListener);
mTimePicker.setCurrentHour(ldt.getHourOfDay());
mTimePicker.setCurrentMinute(ldt.getMinuteOfHour());

} else {
// create time widget with current time as of right now
clearAnswer();
}
}


/**
* Resets date to today.
*/
@Override
public void clearAnswer() {
DateTime ldt = new DateTime();
mDatePicker.init(ldt.getYear(), ldt.getMonthOfYear() - 1, ldt.getDayOfMonth(),
mDateListener);
mTimePicker.setCurrentHour(ldt.getHourOfDay());
mTimePicker.setCurrentMinute(ldt.getMinuteOfHour());
}


@Override
public IAnswerData getAnswer() {
if (showCalendar) {
scrollView.clearChildFocus(mDatePicker);
}
clearFocus();

boolean hideDay = mDateWidget.isDayHidden();
boolean hideMonth = mDateWidget.isMonthHidden();
boolean showCalendar = mDateWidget.isCalendarShown();

int year = mDateWidget.getYear();
int month = mDateWidget.getMonth();
int day = mDateWidget.getDay();
int hour = mTimeWidget.getHour();
int minute = mTimeWidget.getMinute();

LocalDateTime ldt = new LocalDateTime()
.withYear(mDatePicker.getYear())
.withMonthOfYear((!showCalendar && hideMonth) ? 1 : mDatePicker.getMonth() + 1)
.withDayOfMonth((!showCalendar && (hideMonth || hideDay)) ? 1 : mDatePicker.getDayOfMonth())
.withHourOfDay((!showCalendar && (hideMonth || hideDay)) ? 0 : mTimePicker.getCurrentHour())
.withMinuteOfHour((!showCalendar && (hideMonth || hideDay)) ? 0 : mTimePicker.getCurrentMinute())
.withYear(year)
.withMonthOfYear((!showCalendar && hideMonth) ? 1 : month)
.withDayOfMonth((!showCalendar && (hideMonth || hideDay)) ? 1 : day)
.withHourOfDay((!showCalendar && (hideMonth || hideDay)) ? 0 : hour)
.withMinuteOfHour((!showCalendar && (hideMonth || hideDay)) ? 0 : minute)
.withSecondOfMinute(0);

ldt = skipDaylightSavingGapIfExists(ldt);
return new DateTimeData(ldt.toDate());
}

@Override
public void clearAnswer() {
mDateWidget.clearAnswer();
mTimeWidget.clearAnswer();
}

@Override
public void setFocus(Context context) {
Expand All @@ -265,22 +97,19 @@ public void setFocus(Context context) {
inputManager.hideSoftInputFromWindow(this.getWindowToken(), 0);
}


@Override
public void setOnLongClickListener(OnLongClickListener l) {
mDatePicker.setOnLongClickListener(l);
mTimePicker.setOnLongClickListener(l);
mDateWidget.setOnLongClickListener(l);
mTimeWidget.setOnLongClickListener(l);
}


@Override
public void cancelLongPress() {
super.cancelLongPress();
mDatePicker.cancelLongPress();
mTimePicker.cancelLongPress();
mDateWidget.cancelLongPress();
mTimeWidget.cancelLongPress();
}


// Skip over a "daylight savings gap". This is needed on the day and time of a daylight savings
// transition because that date/time doesn't exist.
// Today clocks are almost always set one hour back or ahead.
Expand Down
Loading