-
Notifications
You must be signed in to change notification settings - Fork 10
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
Add AM/PM circles #2
base: master
Are you sure you want to change the base?
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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,28 @@ public class RadialTimePickerView extends View implements View.OnTouchListener { | |
|
||
private boolean mInputEnabled = true; | ||
|
||
private static final int AMPM_INDEX = 2; | ||
private static final int ENABLE_PICKER_INDEX =3; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you comment on both of these with their original declarations, ie. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Those variables are from |
||
|
||
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 +361,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 +430,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 +721,8 @@ private void initData() { | |
mShowHours ? ALPHA_TRANSPARENT : ALPHA_OPAQUE); | ||
mAlphaSelector[MINUTES][SELECTOR_LINE].setValue( | ||
mShowHours ? ALPHA_TRANSPARENT : ALPHA_SELECTOR); | ||
|
||
mSelectedAlpha = ALPHA_SELECTOR; | ||
} | ||
|
||
@Override | ||
|
@@ -760,13 +794,79 @@ public void onDraw(Canvas canvas) { | |
|
||
drawCenter(canvas); | ||
|
||
if (!mIs24HourMode) { | ||
drawAmPmCircle(canvas); | ||
} | ||
|
||
if (DEBUG) { | ||
drawDebug(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 +1298,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 +1436,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(); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why
@aar
on both of these? Shouldn't be needed?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For lean dependencies.
You can run gradle task - [androidDependencies] and see the results. For use there is no different.
No
@aar
With
@aar