diff --git a/DateTimePickerLibrary/build.gradle b/DateTimePickerLibrary/build.gradle
index 5b6150a..778e23d 100644
--- a/DateTimePickerLibrary/build.gradle
+++ b/DateTimePickerLibrary/build.gradle
@@ -1,12 +1,12 @@
apply plugin: 'com.android.library'
android {
- compileSdkVersion 23
- buildToolsVersion "23.0.3"
+ compileSdkVersion 24
+ buildToolsVersion "24.0.0"
defaultConfig {
minSdkVersion 16
- targetSdkVersion 23
+ targetSdkVersion 24
}
compileOptions {
@@ -16,6 +16,7 @@ android {
}
dependencies {
- compile 'com.android.support:support-v4:23.3.0'
- compile 'com.android.support:appcompat-v7:23.3.0'
+ compile 'com.android.support:support-v4:24.0.0@aar'
+ compile 'com.android.support:appcompat-v7:24.0.0@aar'
+ compile 'com.android.support:support-annotations:24.0.0'
}
diff --git a/DateTimePickerLibrary/src/main/java/io/doist/datetimepicker/time/RadialTimePickerView.java b/DateTimePickerLibrary/src/main/java/io/doist/datetimepicker/time/RadialTimePickerView.java
index de715ba..b554adb 100644
--- a/DateTimePickerLibrary/src/main/java/io/doist/datetimepicker/time/RadialTimePickerView.java
+++ b/DateTimePickerLibrary/src/main/java/io/doist/datetimepicker/time/RadialTimePickerView.java
@@ -44,6 +44,7 @@
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.TextView;
+import java.text.DateFormatSymbols;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
@@ -181,6 +182,32 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
private boolean mInputEnabled = true;
+ // NOT a real index for the purpose of what's showing.
+ // See TimePickerClockDelegate.AMPM_INDEX.
+ private static final int AMPM_INDEX = 2;
+ // Also NOT a real index, just used for keyboard mode.
+ // See TimePickerClockDelegate.ENABLE_PICKER_INDEX.
+ private static final int ENABLE_PICKER_INDEX = 3;
+
+ private float mAmPmCircleRadiusMultiplier;
+
+ private final Paint mAmPmPaint = new Paint();
+ private int mSelectedAlpha;
+ private int mSelectedColor;
+ private int mUnselectedColor;
+ private int mAmPmTextColor;
+ private int mTouchedColor;
+
+ private String mAmText;
+ private String mPmText;
+
+ private boolean mDrawValuesReady = false;
+ private int mAmPmCircleRadius;
+ private int mAmXCenter;
+ private int mPmXCenter;
+ private int mAmPmYCenter;
+ private int mAmOrPmPressed = -1;
+
public interface OnValueSelectedListener {
void onValueSelected(int pickerIndex, int newValue, boolean autoAdvance);
}
@@ -338,46 +365,39 @@ public RadialTimePickerView(Context context, AttributeSet attrs, int defStyleAtt
mPaintCenter.setAntiAlias(true);
mPaintCenter.setTextAlign(Paint.Align.CENTER);
+ int selectorColor = a.getColor(R.styleable.TimePicker_numbersSelectorColor,
+ res.getColor(R.color.timepicker_default_selector_color_material));
+
mPaintSelector[HOURS][SELECTOR_CIRCLE] = new Paint();
mPaintSelector[HOURS][SELECTOR_CIRCLE].setAntiAlias(true);
- mColorSelector[HOURS][SELECTOR_CIRCLE] = a.getColor(
- R.styleable.TimePicker_numbersSelectorColor,
- R.color.timepicker_default_selector_color_material);
+ mColorSelector[HOURS][SELECTOR_CIRCLE] = selectorColor;
mPaintSelector[HOURS][SELECTOR_DOT] = new Paint();
mPaintSelector[HOURS][SELECTOR_DOT].setAntiAlias(true);
- mColorSelector[HOURS][SELECTOR_DOT] = a.getColor(
- R.styleable.TimePicker_numbersSelectorColor,
- R.color.timepicker_default_selector_color_material);
+ mColorSelector[HOURS][SELECTOR_DOT] = selectorColor;
mPaintSelector[HOURS][SELECTOR_LINE] = new Paint();
mPaintSelector[HOURS][SELECTOR_LINE].setAntiAlias(true);
mPaintSelector[HOURS][SELECTOR_LINE].setStrokeWidth(2);
- mColorSelector[HOURS][SELECTOR_LINE] = a.getColor(
- R.styleable.TimePicker_numbersSelectorColor,
- R.color.timepicker_default_selector_color_material);
+ mColorSelector[HOURS][SELECTOR_LINE] = selectorColor;
mPaintSelector[MINUTES][SELECTOR_CIRCLE] = new Paint();
mPaintSelector[MINUTES][SELECTOR_CIRCLE].setAntiAlias(true);
- mColorSelector[MINUTES][SELECTOR_CIRCLE] = a.getColor(
- R.styleable.TimePicker_numbersSelectorColor,
- R.color.timepicker_default_selector_color_material);
+ mColorSelector[MINUTES][SELECTOR_CIRCLE] = selectorColor;
mPaintSelector[MINUTES][SELECTOR_DOT] = new Paint();
mPaintSelector[MINUTES][SELECTOR_DOT].setAntiAlias(true);
- mColorSelector[MINUTES][SELECTOR_DOT] = a.getColor(
- R.styleable.TimePicker_numbersSelectorColor,
- R.color.timepicker_default_selector_color_material);
+ mColorSelector[MINUTES][SELECTOR_DOT] = selectorColor;
mPaintSelector[MINUTES][SELECTOR_LINE] = new Paint();
mPaintSelector[MINUTES][SELECTOR_LINE].setAntiAlias(true);
mPaintSelector[MINUTES][SELECTOR_LINE].setStrokeWidth(2);
- mColorSelector[MINUTES][SELECTOR_LINE] = a.getColor(
- R.styleable.TimePicker_numbersSelectorColor,
- R.color.timepicker_default_selector_color_material);
+ mColorSelector[MINUTES][SELECTOR_LINE] = selectorColor;
- mPaintBackground.setColor(a.getColor(R.styleable.TimePicker_numbersBackgroundColor,
- res.getColor(R.color.timepicker_default_numbers_background_color_material)));
+ int bgColor = a.getColor(R.styleable.TimePicker_numbersBackgroundColor,
+ res.getColor(R.color.timepicker_default_numbers_background_color_material));
+
+ mPaintBackground.setColor(bgColor);
mPaintBackground.setAntiAlias(true);
if (DEBUG) {
@@ -414,6 +434,22 @@ public RadialTimePickerView(Context context, AttributeSet attrs, int defStyleAtt
mSelectionRadiusMultiplier = Float.parseFloat(
res.getString(R.string.timepicker_selection_radius_multiplier));
+ mAmPmCircleRadiusMultiplier = Float.parseFloat(
+ res.getString(R.string.timepicker_ampm_circle_radius_multiplier));
+
+ mAmPmPaint.setTypeface(mTypeface);
+ mAmPmPaint.setAntiAlias(true);
+ mAmPmPaint.setTextAlign(Paint.Align.CENTER);
+
+ mSelectedColor = a.getColor(R.styleable.TimePicker_amPmSelectedBackgroundColor, selectorColor);
+ mTouchedColor = a.getColor(R.styleable.TimePicker_amPmSelectedBackgroundColor, selectorColor);
+ mUnselectedColor = a.getColor(R.styleable.TimePicker_amPmBackgroundColor, bgColor);
+ mAmPmTextColor = a.getColor(R.styleable.TimePicker_amPmTextColor, numbersTextColor);
+
+ String[] amPmTexts = new DateFormatSymbols().getAmPmStrings();
+ mAmText = amPmTexts[0];
+ mPmText = amPmTexts[1];
+
a.recycle();
setOnTouchListener(this);
@@ -689,6 +725,8 @@ private void initData() {
mShowHours ? ALPHA_TRANSPARENT : ALPHA_OPAQUE);
mAlphaSelector[MINUTES][SELECTOR_LINE].setValue(
mShowHours ? ALPHA_TRANSPARENT : ALPHA_SELECTOR);
+
+ mSelectedAlpha = ALPHA_SELECTOR;
}
@Override
@@ -760,6 +798,10 @@ public void onDraw(Canvas canvas) {
drawCenter(canvas);
+ if (!mIs24HourMode) {
+ drawAmPmCircle(canvas);
+ }
+
if (DEBUG) {
drawDebug(canvas);
}
@@ -767,6 +809,68 @@ public void onDraw(Canvas canvas) {
canvas.restore();
}
+ private void drawAmPmCircle(Canvas canvas) {
+ int viewWidth = getWidth();
+ if (viewWidth == 0) {
+ return;
+ }
+
+ if (!mDrawValuesReady) {
+ int layoutXCenter = getWidth() / 2;
+ int layoutYCenter = getHeight() / 2;
+ int circleRadius =
+ (int) (Math.min(layoutXCenter, layoutYCenter) * mCircleRadiusMultiplier[HOURS]);
+ mAmPmCircleRadius = (int) (circleRadius * mAmPmCircleRadiusMultiplier);
+ layoutYCenter += mAmPmCircleRadius * 0.75;
+ int textSize = mAmPmCircleRadius * 3 / 4;
+ mAmPmPaint.setTextSize(textSize);
+
+ // Line up the vertical center of the AM/PM circles with the bottom of the main circle.
+ mAmPmYCenter = layoutYCenter - mAmPmCircleRadius + circleRadius;
+ // Line up the horizontal edges of the AM/PM circles with the horizontal edges
+ // of the main circle.
+ mAmXCenter = layoutXCenter - circleRadius + mAmPmCircleRadius / 2;
+ mPmXCenter = layoutXCenter + circleRadius - mAmPmCircleRadius / 2;
+
+ mDrawValuesReady = true;
+ }
+
+ // We'll need to draw either a lighter blue (for selection), a darker blue (for touching)
+ // or white (for not selected).
+ int amColor = mUnselectedColor;
+ int amAlpha = Color.alpha(mUnselectedColor);
+ int pmColor = mUnselectedColor;
+ int pmAlpha = Color.alpha(mUnselectedColor);
+ if (mAmOrPm == AM) {
+ amColor = mSelectedColor;
+ amAlpha = mSelectedAlpha;
+ } else if (mAmOrPm == PM) {
+ pmColor = mSelectedColor;
+ pmAlpha = mSelectedAlpha;
+ }
+ if (mAmOrPmPressed == AM) {
+ amColor = mTouchedColor;
+ amAlpha = Color.alpha(mTouchedColor);
+ } else if (mAmOrPmPressed == PM) {
+ pmColor = mTouchedColor;
+ pmAlpha = Color.alpha(mTouchedColor);
+ }
+
+ // Draw the two circles.
+ mAmPmPaint.setColor(amColor);
+ mAmPmPaint.setAlpha(amAlpha);
+ canvas.drawCircle(mAmXCenter, mAmPmYCenter, mAmPmCircleRadius, mAmPmPaint);
+ mAmPmPaint.setColor(pmColor);
+ mAmPmPaint.setAlpha(pmAlpha);
+ canvas.drawCircle(mPmXCenter, mAmPmYCenter, mAmPmCircleRadius, mAmPmPaint);
+
+ // Draw the AM/PM texts on top.
+ mAmPmPaint.setColor(mAmPmTextColor);
+ int textYCenter = mAmPmYCenter - (int) (mAmPmPaint.descent() + mAmPmPaint.ascent()) / 2;
+ canvas.drawText(mAmText, mAmXCenter, textYCenter, mAmPmPaint);
+ canvas.drawText(mPmText, mPmXCenter, textYCenter, mAmPmPaint);
+ }
+
private void drawCircleBackground(Canvas canvas) {
canvas.drawCircle(mXCenter, mYCenter, mCircleRadius[HOURS], mPaintBackground);
}
@@ -1198,32 +1302,75 @@ private int getDegreesFromXY(float x, float y) {
@Override
public boolean onTouch(View v, MotionEvent event) {
- if (!mInputEnabled) {
- return true;
- }
final int action = event.getActionMasked();
- if (action == MotionEvent.ACTION_MOVE
- || action == MotionEvent.ACTION_UP
- || action == MotionEvent.ACTION_DOWN) {
- boolean forceSelection = false;
- boolean autoAdvance = false;
+ boolean forceSelection = false;
+ boolean autoAdvance = false;
- if (action == MotionEvent.ACTION_DOWN) {
+ float eventX = event.getX();
+ float eventY = event.getY();
+
+ int isTouchingAmOrPm = !mIs24HourMode ? getIsTouchingAmOrPm(eventX, eventY) : -1;
+
+ switch (action) {
+ case MotionEvent.ACTION_DOWN: {
+ if (!mInputEnabled) {
+ return true;
+ }
// This is a new event stream, reset whether the value changed.
mChangedDuringTouch = false;
- } else if (action == MotionEvent.ACTION_UP) {
- autoAdvance = true;
- // If we saw a down/up pair without the value changing, assume
- // this is a single-tap selection and force a change.
- if (!mChangedDuringTouch) {
- forceSelection = true;
+ if (isTouchingAmOrPm == AM || isTouchingAmOrPm == PM) {
+ mAmOrPmPressed = isTouchingAmOrPm;
+ invalidate();
+ } else {
+ mChangedDuringTouch |= handleTouchInput(
+ event.getX(), event.getY(), forceSelection, autoAdvance);
}
+ break;
}
+ case MotionEvent.ACTION_MOVE: {
+ if (!mInputEnabled) {
+ return true;
+ }
+ if (isTouchingAmOrPm == AM || isTouchingAmOrPm == PM) {
+ mAmOrPmPressed = isTouchingAmOrPm;
+ invalidate();
+ } else {
+ mAmOrPmPressed = -1;
+ invalidate();
+ mChangedDuringTouch |= handleTouchInput(
+ event.getX(), event.getY(), forceSelection, autoAdvance);
+ }
+ break;
+ }
+ case MotionEvent.ACTION_UP: {
+ if (!mInputEnabled) {
+ mListener.onValueSelected(ENABLE_PICKER_INDEX, 1, false);
+ return true;
+ }
+ if (isTouchingAmOrPm == AM || isTouchingAmOrPm == PM) {
+ mAmOrPmPressed = -1;
+ invalidate();
- mChangedDuringTouch |= handleTouchInput(
- event.getX(), event.getY(), forceSelection, autoAdvance);
+ if (isTouchingAmOrPm != mAmOrPm) {
+ setAmOrPm(isTouchingAmOrPm);
+ mListener.onValueSelected(AMPM_INDEX, isTouchingAmOrPm, false);
+ }
+ } else {
+ autoAdvance = true;
+
+ // If we saw a down/up pair without the value changing, assume
+ // this is a single-tap selection and force a change.
+ if (!mChangedDuringTouch) {
+ forceSelection = true;
+ }
+ mChangedDuringTouch |= handleTouchInput(
+ event.getX(), event.getY(), forceSelection, autoAdvance);
+ }
+ break;
+ }
+ default:
}
return true;
@@ -1293,6 +1440,29 @@ public void setInputEnabled(boolean inputEnabled) {
invalidate();
}
+ private int getIsTouchingAmOrPm(float xCoord, float yCoord) {
+ if (!mDrawValuesReady) {
+ return -1;
+ }
+
+ int squaredYDistance = (int) ((yCoord - mAmPmYCenter) * (yCoord - mAmPmYCenter));
+
+ int distanceToAmCenter =
+ (int) Math.sqrt((xCoord - mAmXCenter) * (xCoord - mAmXCenter) + squaredYDistance);
+ if (distanceToAmCenter <= mAmPmCircleRadius) {
+ return AM;
+ }
+
+ int distanceToPmCenter =
+ (int) Math.sqrt((xCoord - mPmXCenter) * (xCoord - mPmXCenter) + squaredYDistance);
+ if (distanceToPmCenter <= mAmPmCircleRadius) {
+ return PM;
+ }
+
+ // Neither was close enough.
+ return -1;
+ }
+
private class RadialPickerTouchHelper extends ExploreByTouchHelper {
private final Rect mTempRect = new Rect();
diff --git a/DateTimePickerLibrary/src/main/res/values/strings.xml b/DateTimePickerLibrary/src/main/res/values/strings.xml
index 9fcc135..1ee637c 100644
--- a/DateTimePickerLibrary/src/main/res/values/strings.xml
+++ b/DateTimePickerLibrary/src/main/res/values/strings.xml
@@ -52,4 +52,7 @@
sans-serif
+
+
+ 0.22
diff --git a/DateTimePickerSamples/build.gradle b/DateTimePickerSamples/build.gradle
index 69e137c..5fa50ac 100644
--- a/DateTimePickerSamples/build.gradle
+++ b/DateTimePickerSamples/build.gradle
@@ -1,15 +1,16 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 23
- buildToolsVersion "22.0.3"
+ compileSdkVersion 24
+ buildToolsVersion "24.0.0"
defaultConfig {
applicationId "io.doist.datetimepicker.sample"
minSdkVersion 16
- targetSdkVersion 23
+ targetSdkVersion 24
versionCode 1
versionName "1.0"
+ vectorDrawables.useSupportLibrary = true
}
buildTypes {
release {
@@ -23,5 +24,7 @@ dependencies {
compile project(':DateTimePickerLibrary')
compile fileTree(dir: 'libs', include: ['*.jar'])
- compile 'com.android.support:appcompat-v7:22.0.0'
+ compile 'com.android.support:appcompat-v7:24.0.0@aar'
+ compile 'com.android.support:support-vector-drawable:24.0.0@aar'
+ compile 'com.android.support:animated-vector-drawable:24.0.0@aar'
}
diff --git a/build.gradle b/build.gradle
index d3ff69d..e220f0b 100644
--- a/build.gradle
+++ b/build.gradle
@@ -5,7 +5,7 @@ buildscript {
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:1.1.0'
+ classpath 'com.android.tools.build:gradle:2.1.2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 0c71e76..4c74aab 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.14-all.zip