Appearance changes to NumberGridTimePickerDialog

This commit is contained in:
Phillip Hsu 2016-08-20 04:05:09 -07:00
parent abd1551bc3
commit a473f3fd2c
24 changed files with 964 additions and 446 deletions

View File

@ -260,8 +260,11 @@ public class MainActivity extends BaseActivity {
// has no reference to the AlarmsFragment, but it does have a reference to a // has no reference to the AlarmsFragment, but it does have a reference to a
// Context (which we can cast to Activity). Thus, ExpandedAlarmViewHolder // Context (which we can cast to Activity). Thus, ExpandedAlarmViewHolder
// uses Activity#startActivityForResult(). // uses Activity#startActivityForResult().
mSectionsPagerAdapter.getFragment(mViewPager.getCurrentItem())
.onActivityResult(requestCode, resultCode, data); // THIS WAS ACTUALLY A BAD IDEA, ESPECIALLY FOR TIMERSFRAGMENT. THIS ENDS UP ADDING
// DUPLICATE TIMERS.
// mSectionsPagerAdapter.getFragment(mViewPager.getCurrentItem())
// .onActivityResult(requestCode, resultCode, data);
} }
@Override @Override

View File

@ -22,10 +22,8 @@ import android.animation.PropertyValuesHolder;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.graphics.Color;
import android.os.Build; import android.os.Build;
import android.support.annotation.AttrRes; import android.support.annotation.AttrRes;
import android.support.v4.content.ContextCompat;
import android.text.format.Time; import android.text.format.Time;
import android.util.TypedValue; import android.util.TypedValue;
import android.view.View; import android.view.View;
@ -151,37 +149,45 @@ public class Utils {
* @param context The context to use as reference for the color * @param context The context to use as reference for the color
* @return the accent color of the current context * @return the accent color of the current context
*/ */
public static int getThemeAccentColor(Context context) {
// Source from MDTP // Source from MDTP
public static int getAccentColorFromThemeIfAvailable(Context context) { // TypedValue typedValue = new TypedValue();
TypedValue typedValue = new TypedValue(); // // First, try the android:colorAccent
// First, try the android:colorAccent // if (Build.VERSION.SDK_INT >= 21) {
if (Build.VERSION.SDK_INT >= 21) { // context.getTheme().resolveAttribute(android.R.attr.colorAccent, typedValue, true);
context.getTheme().resolveAttribute(android.R.attr.colorAccent, typedValue, true); // return typedValue.data;
return typedValue.data; // }
} // // Next, try colorAccent from support lib
// Next, try colorAccent from support lib // int colorAccentResId = context.getResources().getIdentifier("colorAccent", "attr", context.getPackageName());
int colorAccentResId = context.getResources().getIdentifier("colorAccent", "attr", context.getPackageName()); // if (colorAccentResId != 0 && context.getTheme().resolveAttribute(colorAccentResId, typedValue, true)) {
if (colorAccentResId != 0 && context.getTheme().resolveAttribute(colorAccentResId, typedValue, true)) { // return typedValue.data;
return typedValue.data; // }
//
// return ContextCompat.getColor(context, R.color.accent_color);
return getColorFromThemeAttr(context, R.attr.colorAccent);
} }
return ContextCompat.getColor(context, R.color.accent_color); public static int getTextColorPrimary(Context context) {
// http://stackoverflow.com/a/33839580/5055032
final TypedValue value = new TypedValue();
context.getTheme().resolveAttribute(android.R.attr.textColorPrimary, value, true);
TypedArray a = context.obtainStyledAttributes(value.data,
new int[] {android.R.attr.textColorPrimary});
final int color = a.getColor(0/*index*/, 0/*defValue*/);
a.recycle();
return color;
// Didn't work! Gave me white!
// return getColorFromThemeAttr(context, android.R.attr.textColorPrimary);
} }
// See http://stackoverflow.com/a/4928826/5055032 /**
public static int darkenColor(int color) { * @param resId The resource identifier of the desired theme attribute.
float[] hsv = new float[3]; */
Color.colorToHSV(color, hsv); public static int getColorFromThemeAttr(Context context, int resId) {
hsv[2] *= 0.8f; // value component // http://stackoverflow.com/a/28777489/5055032
return Color.HSVToColor(hsv); final TypedValue value = new TypedValue();
} context.getTheme().resolveAttribute(resId, value, true);
return value.data;
// See http://stackoverflow.com/a/4928826/5055032
public static int lightenColor(int color) {
float[] hsv = new float[3];
Color.colorToHSV(color, hsv);
hsv[2] = 1.0f - 0.8f * (1.0f - hsv[2]);
return Color.HSVToColor(hsv);
} }
/** /**

View File

@ -0,0 +1,275 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.philliphsu.clock2.editalarm;
import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.FrameLayout;
/**
* Created by Phillip Hsu on 8/17/2016.
*
* A derivative of the AOSP datetimepicker RadialPickerLayout class.
*/
public class GridSelectorLayout extends FrameLayout implements NumbersGrid.OnNumberSelectedListener {
private static final String TAG = "GridSelectorLayout";
// Delay before auto-advancing the page, in ms.
// TODO: If we animate the page change, then we don't need this delay. This was
// my own logic, not ported from AOSP timepicker.
public static final int ADVANCE_PAGE_DELAY = 150;
private static final int HOUR_INDEX = NumberGridTimePickerDialog.HOUR_INDEX;
private static final int MINUTE_INDEX = NumberGridTimePickerDialog.MINUTE_INDEX;
// TODO: Rename to HALF_DAY_INDEX?
private static final int AMPM_INDEX = NumberGridTimePickerDialog.AMPM_INDEX;
private static final int HALF_DAY_1 = NumberGridTimePickerDialog.HALF_DAY_1;
private static final int HALF_DAY_2 = NumberGridTimePickerDialog.HALF_DAY_2;
private OnValueSelectedListener mListener;
private boolean mTimeInitialized;
private int mCurrentHoursOfDay;
private int mCurrentMinutes;
private boolean mIs24HourMode;
private int mCurrentItemShowing;
private HoursGrid mHoursGrid = null;
private TwentyFourHoursGrid m24HoursGrid = null;
private MinutesGrid mMinutesGrid;
private final Handler mHandler = new Handler();
public interface OnValueSelectedListener {
void onValueSelected(int pickerIndex, int newValue, boolean autoAdvance);
}
public GridSelectorLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
// TODO: Why do we need a Context param? RadialPickerLayout does it too.
public void initialize(Context context, int initialHoursOfDay, int initialMinutes, boolean is24HourMode) {
if (mTimeInitialized) {
Log.e(TAG, "Time has already been initialized.");
return;
}
mIs24HourMode = is24HourMode;
if (is24HourMode) {
m24HoursGrid = new TwentyFourHoursGrid(context);
m24HoursGrid.initialize(this/*OnNumberSelectedListener*/);
addView(m24HoursGrid);
} else {
mHoursGrid = new HoursGrid(context);
mHoursGrid.initialize(this/*OnNumberSelectedListener*/);
addView(mHoursGrid);
}
mMinutesGrid = new MinutesGrid(context);
mMinutesGrid.initialize(this/*OnNumberSelectedListener*/);
// Initialize the currently-selected hour and minute.
setValueForItem(HOUR_INDEX, initialHoursOfDay);
setValueForItem(MINUTE_INDEX, initialMinutes);
// Record the selected values in the number grids.
if (!is24HourMode) {
initialHoursOfDay = initialHoursOfDay % 12;
if (initialHoursOfDay == 0) {
initialHoursOfDay = 12;
}
mHoursGrid.setSelection(initialHoursOfDay);
} else {
m24HoursGrid.setSelection(initialHoursOfDay);
}
mMinutesGrid.setSelection(initialMinutes);
mTimeInitialized = true;
}
void setTheme(Context context, boolean themeDark) {
// TODO: This logic needs to be in the Dialog class, since the am/pm view is contained there.
// mAmPmView.setTheme(context, themeDark);
// TODO: These aren't doing much currently, if at all.
if (m24HoursGrid != null) {
m24HoursGrid.setTheme(context, themeDark);
} else if (mHoursGrid != null) {
mHoursGrid.setTheme(context, themeDark);
}
mMinutesGrid.setTheme(context, themeDark);
}
public void setTime(int hours, int minutes) {
setItem(HOUR_INDEX, hours);
setItem(MINUTE_INDEX, minutes);
}
/**
* Set either the hour or the minute. Will set the internal value, and set the selection.
*/
private void setItem(int index, int value) {
if (index == HOUR_INDEX) {
setValueForItem(HOUR_INDEX, value);
if (mIs24HourMode) {
m24HoursGrid.setSelection(value);
} else {
mHoursGrid.setSelection(value);
}
} else if (index == MINUTE_INDEX) {
setValueForItem(MINUTE_INDEX, value);
mMinutesGrid.setSelection(value);
}
}
public void setOnValueSelectedListener(OnValueSelectedListener listener) {
mListener = listener;
}
/**
* Get the item (hours or minutes) that is currently showing.
*/
public int getCurrentItemShowing() {
if (mCurrentItemShowing != HOUR_INDEX && mCurrentItemShowing != MINUTE_INDEX) {
Log.e(TAG, "Current item showing was unfortunately set to "+mCurrentItemShowing);
return -1;
}
return mCurrentItemShowing;
}
/**
* Set either minutes or hours as showing.
* @param animate True to animate the transition, false to show with no animation.
*/
public void setCurrentItemShowing(int index, boolean animate) {
if (index != HOUR_INDEX && index != MINUTE_INDEX) {
Log.e(TAG, "TimePicker does not support view at index "+index);
return;
}
int lastIndex = getCurrentItemShowing();
mCurrentItemShowing = index;
if (index != lastIndex) {
removeViewAt(0); // We could also call removeAllViews(), since we only have one child.
// We already verified that the index is either HOUR_INDEX or MINUTE_INDEX
addView(index == HOUR_INDEX ?
(mIs24HourMode ? m24HoursGrid : mHoursGrid)
: mMinutesGrid);
}
}
// TODO: The Dialog should be telling us that AM/PM was selected, via setAmOrPm().
// @Override
// public void onAmPmSelected(int amOrPm) {
// setValueForItem(AMPM_INDEX, amOrPm);
// mListener.onValueSelected(AMPM_INDEX, amOrPm, false);
// }
@Override
public void onNumberSelected(int number) {
if (getCurrentItemShowing() == HOUR_INDEX && !mIs24HourMode) {
// Change the value before passing it through the callback
int amOrPm = getIsCurrentlyAmOrPm();
if (amOrPm == HALF_DAY_1 && number == 12) {
number = 0;
} else if (amOrPm == HALF_DAY_2 && number != 12) {
number += 12;
}
}
// final int value = number;
// mHandler.postDelayed(new Runnable() {
// @Override
// public void run() {
// mListener.onValueSelected(HOUR_INDEX, value, true);
// }
// }, ADVANCE_PAGE_DELAY);
// mListener.onValueSelected(HOUR_INDEX, value, true);
// } else {
// mListener.onValueSelected(getCurrentItemShowing(), number, false);
// }
setValueForItem(getCurrentItemShowing(), number);
mListener.onValueSelected(getCurrentItemShowing(), number,
true/*autoAdvance, not considered for MINUTE_INDEX*/);
}
public int getHours() {
return mCurrentHoursOfDay;
}
public int getMinutes() {
return mCurrentMinutes;
}
/**
* If the hours are showing, return the current hour. If the minutes are showing, return the
* current minute.
*/
private int getCurrentlyShowingValue() {
int currentIndex = getCurrentItemShowing();
if (currentIndex == HOUR_INDEX) {
return mCurrentHoursOfDay;
} else if (currentIndex == MINUTE_INDEX) {
return mCurrentMinutes;
} else {
return -1;
}
}
public int getIsCurrentlyAmOrPm() {
if (mCurrentHoursOfDay < 12) {
return HALF_DAY_1;
} else if (mCurrentHoursOfDay < 24) {
return HALF_DAY_2;
}
return -1;
}
/**
* Set the internal as either AM or PM.
*/
// TODO: Rename to setHalfDay
public void setAmOrPm(int amOrPm) {
final int initialHalfDay = getIsCurrentlyAmOrPm();
setValueForItem(AMPM_INDEX, amOrPm);
if (amOrPm != initialHalfDay
&& mIs24HourMode
// && getCurrentItemShowing() == HOUR_INDEX
&& m24HoursGrid != null) {
m24HoursGrid.swapTexts();
mListener.onValueSelected(HOUR_INDEX, mCurrentHoursOfDay, false);
}
}
/**
* Set the internal value for the hour, minute, or AM/PM.
*/
private void setValueForItem(int index, int value) {
if (index == HOUR_INDEX) {
mCurrentHoursOfDay = value;
} else if (index == MINUTE_INDEX){
mCurrentMinutes = value;
} else if (index == AMPM_INDEX) {
if (value == HALF_DAY_1) {
mCurrentHoursOfDay = mCurrentHoursOfDay % 12;
} else if (value == HALF_DAY_2) {
mCurrentHoursOfDay = (mCurrentHoursOfDay % 12) + 12;
}
}
}
}

View File

@ -0,0 +1,26 @@
package com.philliphsu.clock2.editalarm;
import android.content.Context;
import com.philliphsu.clock2.R;
/**
* Created by Phillip Hsu on 8/17/2016.
*/
public class HoursGrid extends NumbersGrid {
public HoursGrid(Context context) {
super(context);
}
@Override
protected int contentLayout() {
return R.layout.content_hours_grid;
}
@Override
protected int indexOfDefaultValue() {
// This is the index of number 12.
return getChildCount() - 1;
}
}

View File

@ -0,0 +1,71 @@
package com.philliphsu.clock2.editalarm;
import android.content.Context;
import android.view.View;
import android.widget.ImageButton;
import com.philliphsu.clock2.R;
/**
* Created by Phillip Hsu on 8/17/2016.
*/
public class MinutesGrid extends NumbersGrid {
private static final String TAG = "MinutesGrid";
private final ImageButton mMinusButton;
private final ImageButton mPlusButton;
public MinutesGrid(Context context) {
super(context);
mMinusButton = (ImageButton) getChildAt(getChildCount() - 2);
mPlusButton = (ImageButton) getChildAt(getChildCount() - 1);
// We're not doing method binding because we don't have IDs set on these buttons.
mMinusButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
int value = getSelection() - 1;
if (value < 0)
value = 59;
setIndicator(value);
setSelection(value);
mSelectionListener.onNumberSelected(value);
}
});
mPlusButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
int value = getSelection() + 1;
if (value == 60)
value = 0;
setIndicator(value);
setSelection(value);
mSelectionListener.onNumberSelected(value);
}
});
}
@Override
protected int contentLayout() {
return R.layout.content_minutes_grid;
}
@Override
void setTheme(Context context, boolean themeDark) {
super.setTheme(context, themeDark);
mMinusButton.setImageResource(themeDark? R.drawable.ic_minus_circle_dark_24dp : R.drawable.ic_minus_circle_24dp);
mPlusButton.setImageResource(themeDark? R.drawable.ic_add_circle_dark_24dp : R.drawable.ic_add_circle_24dp);
}
/**
* Helper method for minute tuners to set the indicator.
* @param value the new value set by the minute tuners
*/
private void setIndicator(int value) {
clearIndicator();
if (value % 5 == 0) {
// The new value is one of the predetermined minute values
int positionOfValue = value / 5;
setIndicator(getChildAt(positionOfValue));
}
}
}

View File

@ -18,11 +18,10 @@ package com.philliphsu.clock2.editalarm;
import android.animation.ObjectAnimator; import android.animation.ObjectAnimator;
import android.app.ActionBar.LayoutParams; import android.app.ActionBar.LayoutParams;
import android.content.res.ColorStateList;
import android.content.res.Resources; import android.content.res.Resources;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.support.design.widget.FloatingActionButton; import android.support.design.widget.FloatingActionButton;
import android.support.v7.widget.GridLayout;
import android.util.Log; import android.util.Log;
import android.view.KeyCharacterMap; import android.view.KeyCharacterMap;
import android.view.KeyEvent; import android.view.KeyEvent;
@ -36,6 +35,7 @@ import android.widget.TextView;
import com.philliphsu.clock2.R; import com.philliphsu.clock2.R;
import com.philliphsu.clock2.aospdatetimepicker.Utils; import com.philliphsu.clock2.aospdatetimepicker.Utils;
import com.philliphsu.clock2.editalarm.GridSelectorLayout.OnValueSelectedListener;
import java.text.DateFormatSymbols; import java.text.DateFormatSymbols;
import java.util.ArrayList; import java.util.ArrayList;
@ -53,8 +53,12 @@ import static com.philliphsu.clock2.util.ConversionUtils.dpToPx;
/** /**
* Dialog to set a time. * Dialog to set a time.
*
* A derivative of the AOSP datetimepicker TimePickerDialog class.
*
* TODO: Rename to GridSelectorTimePickerDialog
*/ */
public class NumberGridTimePickerDialog extends BaseTimePickerDialog /*DialogFragment implements OnValueSelectedListener*/{ public class NumberGridTimePickerDialog extends BaseTimePickerDialog implements OnValueSelectedListener {
private static final String TAG = "TimePickerDialog"; private static final String TAG = "TimePickerDialog";
private static final String KEY_HOUR_OF_DAY = "hour_of_day"; private static final String KEY_HOUR_OF_DAY = "hour_of_day";
@ -68,15 +72,16 @@ public class NumberGridTimePickerDialog extends BaseTimePickerDialog /*DialogFra
public static final int HOUR_INDEX = 0; public static final int HOUR_INDEX = 0;
public static final int MINUTE_INDEX = 1; public static final int MINUTE_INDEX = 1;
// NOT a real index for the purpose of what's showing. // NOT a real index for the purpose of what's showing.
// TODO: Rename to HALF_DAY_INDEX?
public static final int AMPM_INDEX = 2; public static final int AMPM_INDEX = 2;
// Also NOT a real index, just used for keyboard mode. // Also NOT a real index, just used for keyboard mode.
public static final int ENABLE_PICKER_INDEX = 3; public static final int ENABLE_PICKER_INDEX = 3;
/** /**
* TODO: (Me) Use HALF_DAY_1 instead * TODO: Use HALF_DAY_1 instead
*/ */
public static final int AM = 0; public static final int AM = 0;
/** /**
* TODO: (Me) Use HALF_DAY_2 instead * TODO: Use HALF_DAY_2 instead
*/ */
public static final int PM = 1; public static final int PM = 1;
@ -93,7 +98,7 @@ public class NumberGridTimePickerDialog extends BaseTimePickerDialog /*DialogFra
private TextView mMinuteSpaceView; private TextView mMinuteSpaceView;
private TextView mAmPmTextView; private TextView mAmPmTextView;
private View mAmPmHitspace; private View mAmPmHitspace;
// private RadialPickerLayout mTimePicker; private GridSelectorLayout mTimePicker;
private int mSelectedColor; private int mSelectedColor;
private int mUnselectedColor; private int mUnselectedColor;
@ -123,27 +128,18 @@ public class NumberGridTimePickerDialog extends BaseTimePickerDialog /*DialogFra
private String mSelectMinutes; private String mSelectMinutes;
// ====================================== MY STUFF ============================================= // ====================================== MY STUFF =============================================
private static final int[] HOURS_12 = {1,2,3,4,5,6,7,8,9,10,11,12};
private static final int[] HOURS_24_HALF_DAY_1 = {0,1,2,3,4,5,6,7,8,9,10,11};
private static final int[] HOURS_24_HALF_DAY_2 = {12,13,14,15,16,17,18,19,20,21,22,23};
private static final int[] MINUTES = {0,5,10,15,20,25,30,35,40,45,50,55};
// The delay in ms before a OnLongClick on a TwentyFourHourGridItem defers to OnClick
private static final int LONG_CLICK_RESULT_LEEWAY = 150;
// The padding in dp for the half day icon compound drawable // The padding in dp for the half day icon compound drawable
public static final int HALF_DAY_ICON_PADDING = 8; public static final int HALF_DAY_ICON_PADDING = 8;
// TODO: Private?
// Describes both AM/PM in the 12-hour clock and the half-days of the 24-hour clock. // Describes both AM/PM in the 12-hour clock and the half-days of the 24-hour clock.
// TODO: Use the *values* of AM and PM instead.
public static final int HALF_DAY_1 = AM; public static final int HALF_DAY_1 = AM;
public static final int HALF_DAY_2 = PM; public static final int HALF_DAY_2 = PM;
private int mCurrentIndex = HOUR_INDEX; // TODO: Consider moving these to GridSelectorLayout?
private int mSelectedHalfDay = HALF_DAY_1; // TODO: Consider using findViewById() instead. This could be useful if you plan on
private int mSelectedHourOfDay; // releasing a library with this timepicker, because then we have no dependence on
private int mSelectedMinute; // other third party libraries.
private Handler mHandler;
@Bind(R.id.grid_layout) GridLayout mGridLayout;
@Bind(R.id.fab) FloatingActionButton mDoneButton; @Bind(R.id.fab) FloatingActionButton mDoneButton;
// These are currently defined as Buttons in the dialog's layout, // These are currently defined as Buttons in the dialog's layout,
// but we refer to them as TextViews to save an extra refactoring // but we refer to them as TextViews to save an extra refactoring
@ -156,213 +152,70 @@ public class NumberGridTimePickerDialog extends BaseTimePickerDialog /*DialogFra
return R.layout.dialog_time_picker_number_grid; return R.layout.dialog_time_picker_number_grid;
} }
private void setNumberTexts() {
if (mCurrentIndex != HOUR_INDEX && mCurrentIndex != MINUTE_INDEX) {
Log.e(TAG, "TimePicker does not support view at index "+mCurrentIndex);
return;
}
// Set the appropriate texts on each view
for (int i = 0; i < mGridLayout.getChildCount(); i++) {
View v = mGridLayout.getChildAt(i);
if (mCurrentIndex == MINUTE_INDEX || mCurrentIndex == HOUR_INDEX && !mIs24HourMode) {
if (!(v instanceof TextView))
return; // Reached the ImageButtons
TextView tv = (TextView) v;
tv.setText(mCurrentIndex == MINUTE_INDEX
? String.format("%02d", MINUTES[i])
: String.valueOf(HOURS_12[i]));
} else if (mCurrentIndex == HOUR_INDEX && mIs24HourMode) {
TwentyFourHourGridItem item = (TwentyFourHourGridItem) v;
String s1 = String.format("%02d", HOURS_24_HALF_DAY_1[i]);
String s2 = String.valueOf(HOURS_24_HALF_DAY_2[i]);
if (mSelectedHalfDay == HALF_DAY_1) {
item.setPrimaryText(s1);
item.setSecondaryText(s2);
} else if (mSelectedHalfDay == HALF_DAY_2) {
item.setPrimaryText(s2);
item.setSecondaryText(s1);
} else {
Log.e(TAG, "mSelectedHalfDay = " + mSelectedHalfDay + "?");
}
}
}
}
// TODO: boolean animate param???
private void setCurrentItemShowing(int index) {
if (index != HOUR_INDEX && index != MINUTE_INDEX) {
Log.e(TAG, "TimePicker does not support view at index "+index);
return;
}
int lastIndex = mCurrentIndex;
mCurrentIndex = index;
if (index != lastIndex) {
if (mIs24HourMode) {
// Hours layout and normal layout use different Views for their grid items,
// so we have to start fresh.
mGridLayout.removeAllViews();
int layout = index == HOUR_INDEX ? R.layout.content_24h_number_grid : R.layout.content_number_grid;
View.inflate(getActivity(), layout, mGridLayout);
// TOneverDO: call after inflating minute tuner buttons
setNumberTexts();
setClickListenersOnButtons();
//end TOneverDO
} else {
if (index == HOUR_INDEX) {
// Remove the minute tuners
mGridLayout.removeViews(mGridLayout.getChildCount() - 2, 2);
}
// We can reuse the existing child Views, just change the texts.
// They already have the click listener set.
setNumberTexts();
}
if (index == MINUTE_INDEX) {
createMinuteTuners();
}
}
}
private void setClickListenersOnButtons() {
for (int i = 0; i < mGridLayout.getChildCount(); i++) {
// TODO: Consider leaving out the minute tuner buttons
View v = mGridLayout.getChildAt(i);
v.setOnClickListener(mOnNumberClickListener);
if (v instanceof TwentyFourHourGridItem) {
v.setOnLongClickListener(mOn24HourItemLongClickListener);
}
}
}
@OnClick({ R.id.half_day_toggle_1, R.id.half_day_toggle_2 }) @OnClick({ R.id.half_day_toggle_1, R.id.half_day_toggle_2 })
void onHalfDayToggleClick(View v) { void onHalfDayToggleClick(View v) {
int halfDay = v == mLeftHalfDayToggle ? HALF_DAY_1 : HALF_DAY_2; final int halfDay = v == mLeftHalfDayToggle ? HALF_DAY_1 : HALF_DAY_2;
if (halfDay != mSelectedHalfDay) { if (halfDay != mTimePicker.getIsCurrentlyAmOrPm()) {
toggleHalfDay(); // if (currentHalfDay == HALF_DAY_1) {
// currentHalfDay = HALF_DAY_2;
// } else if (currentHalfDay == HALF_DAY_2) {
// currentHalfDay = HALF_DAY_1;
// }
updateAmPmDisplay(halfDay);
mTimePicker.setAmOrPm(halfDay);
} }
} }
private void toggleHalfDay() { // private void toggleHalfDay() {
// int amOrPm = mTimePicker.getIsCurrentlyAmOrPm(); // int amOrPm = mTimePicker.getIsCurrentlyAmOrPm();
int amOrPm = mSelectedHalfDay; // // TODO: Use HALF_DAY_1 and 2 instead
// TODO: Use HALF_DAY_1 and 2 instead // if (amOrPm == AM) {
if (amOrPm == AM) { // amOrPm = PM;
amOrPm = PM; // } else if (amOrPm == PM){
} else if (amOrPm == PM){ // amOrPm = AM;
amOrPm = AM; // }
} // updateAmPmDisplay(amOrPm);
updateAmPmDisplay(amOrPm);
// mTimePicker.setAmOrPm(amOrPm); // mTimePicker.setAmOrPm(amOrPm);
mSelectedHalfDay = amOrPm; // // TODO: Pretty sure we don't need this
//// mSelectedHalfDay = amOrPm;
//
// // TODO: Verify the corresponding TwentyFourHourGridItem retains its indicator
// // TODO: Don't use mSelectedHourOfDay anymore. Use mTimePicker.getHours()?
// if (amOrPm == HALF_DAY_1) {
// mSelectedHourOfDay %= 12;
// } else if (amOrPm == HALF_DAY_2) {
// mSelectedHourOfDay = (mSelectedHourOfDay % 12) + 12;
// }
// // Updates the header display
// onValueSelected(HOUR_INDEX, mSelectedHourOfDay, false);
// }
if (mIs24HourMode) { // private final OnClickListener mOnNumberClickListener = new OnClickListener() {
if (mCurrentIndex == HOUR_INDEX) { // @Override
for (int i = 0; i < mGridLayout.getChildCount(); i++) { // public void onClick(View v) {
View v = mGridLayout.getChildAt(i); // String number;
((TwentyFourHourGridItem) v).swapTexts(); // if (v instanceof TextView) {
} // number = ((TextView) v).getText().toString();
} // } else if (v instanceof TwentyFourHourGridItem) {
} // number = ((TwentyFourHourGridItem) v).getPrimaryText().toString();
// } else {
// TODO: Verify the corresponding TwentyFourHourGridItem retains its indicator // Log.e(TAG, "TimePicker does not support button type " + v.getClass().getName());
if (amOrPm == HALF_DAY_1) { // return;
mSelectedHourOfDay %= 12; // }
} else if (amOrPm == HALF_DAY_2) { // int value = Integer.parseInt(number);
mSelectedHourOfDay = (mSelectedHourOfDay % 12) + 12; // if (mCurrentIndex == HOUR_INDEX && !mIs24HourMode) {
} // if (value == 12 && mSelectedHalfDay == HALF_DAY_1) {
onValueSelected(HOUR_INDEX, mSelectedHourOfDay, false); // value = 0;
} // } else if (value != 12 && mSelectedHalfDay == HALF_DAY_2) {
// value += 12;
private void createMinuteTuners() { // }
// https://android-developers.blogspot.com/2009/03/android-layout-tricks-3-optimize-by.html // }
// "When inflating a layout starting with a <merge />, you *must* specify a parent ViewGroup // onValueSelected(mCurrentIndex, value, true);
// and you must set attachToRoot to true (see the documentation of the LayoutInflater#inflate() method)" // }
// Note that by passing in a non-null parent, this will pass in true for attachToRoot. // };
View.inflate(getActivity(), R.layout.content_number_grid_minute_tuners, mGridLayout);
int childCount = mGridLayout.getChildCount();
// The tuner buttons are always the last two children in the grid
mGridLayout.getChildAt(childCount - 2).setOnClickListener(mOnDecrementMinuteListener);
mGridLayout.getChildAt(childCount - 1).setOnClickListener(mOnIncrementMinuteListener);
}
// TODO: Break this into two OnClickListeners instead--one for normal TextViews and
// the other for TwentyFourHourGridItem.
// TODO: Set the indicator
private final OnClickListener mOnNumberClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
String number;
if (v instanceof TextView) {
number = ((TextView) v).getText().toString();
} else if (v instanceof TwentyFourHourGridItem) {
number = ((TwentyFourHourGridItem) v).getPrimaryText().toString();
} else {
Log.e(TAG, "TimePicker does not support button type " + v.getClass().getName());
return;
}
int value = Integer.parseInt(number);
if (mCurrentIndex == HOUR_INDEX && !mIs24HourMode) {
if (value == 12 && mSelectedHalfDay == HALF_DAY_1) {
value = 0;
} else if (value != 12 && mSelectedHalfDay == HALF_DAY_2) {
value += 12;
}
}
onValueSelected(mCurrentIndex, value, true);
}
};
private final View.OnLongClickListener mOn24HourItemLongClickListener = new View.OnLongClickListener() {
@Override
public boolean onLongClick(final View v) {
// TODO: Do we need this if we already check this before setting the listener on the view?
if (!(v instanceof TwentyFourHourGridItem))
return false;
toggleHalfDay();
mOnNumberClickListener.onClick(v);
return true;
}
};
private final OnClickListener mOnIncrementMinuteListener = new OnClickListener() {
@Override
public void onClick(View v) {
// Don't need to check for minute overflow, because setMinute()
// sets minute to 0 if we pass in 60
onValueSelected(MINUTE_INDEX, mSelectedMinute + 1, false);
}
};
private final OnClickListener mOnDecrementMinuteListener = new OnClickListener() {
@Override
public void onClick(View v) {
int value = mSelectedMinute - 1;
if (value < 0)
value = 59;
onValueSelected(MINUTE_INDEX, value, false);
}
};
// ============================================================================================= // =============================================================================================
// /**
// * The callback interface used to indicate the user is done filling in
// * the time (they clicked on the 'Set' button).
// */
// public interface OnTimeSetListener {
//
// /**
// * @param view The view associated with this listener.
// * @param hourOfDay The hour that was set.
// * @param minute The minute that was set.
// */
// void onTimeSet(RadialPickerLayout view, int hourOfDay, int minute);
// }
public NumberGridTimePickerDialog() { public NumberGridTimePickerDialog() {
// Empty constructor required for dialog fragment. // Empty constructor required for dialog fragment.
} }
@ -379,23 +232,6 @@ public class NumberGridTimePickerDialog extends BaseTimePickerDialog /*DialogFra
return ret; return ret;
} }
/**
* @param timeFieldIndex The index representing the time field whose values, ranging from its natural
* lower and upper limits, will be presented as choices in the GridLayout
* contained in this dialog's layout. Must be one of {@link #HOUR_INDEX}
* or {@link #MINUTE_INDEX}. TODO: Why do we need this?
* @param initialHalfDay The half-day, a.k.a. AM/PM for 12-hour time, that this picker should be
* initialized to. Must be one of {@link #HALF_DAY_1} or {@link #HALF_DAY_2}.
* TODO: Why do we need this?
*/
@Deprecated
public static NumberGridTimePickerDialog newInstance(int timeFieldIndex, int initialHalfDay) {
NumberGridTimePickerDialog dialog = new NumberGridTimePickerDialog();
dialog.mCurrentIndex = timeFieldIndex;
dialog.mSelectedHalfDay = initialHalfDay;
return dialog;
}
public void initialize(OnTimeSetListener callback, public void initialize(OnTimeSetListener callback,
int hourOfDay, int minute, boolean is24HourMode) { int hourOfDay, int minute, boolean is24HourMode) {
mCallback = callback; // TODO: Use setOnTimeSetListener() instead? mCallback = callback; // TODO: Use setOnTimeSetListener() instead?
@ -405,8 +241,6 @@ public class NumberGridTimePickerDialog extends BaseTimePickerDialog /*DialogFra
mIs24HourMode = is24HourMode; mIs24HourMode = is24HourMode;
mInKbMode = false; mInKbMode = false;
mThemeDark = false; mThemeDark = false;
mSelectedHalfDay = hourOfDay < 12 ? HALF_DAY_1 : HALF_DAY_2;
} }
/** /**
@ -420,6 +254,7 @@ public class NumberGridTimePickerDialog extends BaseTimePickerDialog /*DialogFra
return mThemeDark; return mThemeDark;
} }
// Defined as final in our base class.
// public void setOnTimeSetListener(OnTimeSetListener callback) { // public void setOnTimeSetListener(OnTimeSetListener callback) {
// mCallback = callback; // mCallback = callback;
// } // }
@ -433,16 +268,13 @@ public class NumberGridTimePickerDialog extends BaseTimePickerDialog /*DialogFra
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
// The Activity is created at this point
// mIs24HourMode = DateFormat.is24HourFormat(getActivity());
mHandler = new Handler();
if (savedInstanceState != null && savedInstanceState.containsKey(KEY_HOUR_OF_DAY) if (savedInstanceState != null && savedInstanceState.containsKey(KEY_HOUR_OF_DAY)
&& savedInstanceState.containsKey(KEY_MINUTE) && savedInstanceState.containsKey(KEY_MINUTE)
&& savedInstanceState.containsKey(KEY_IS_24_HOUR_VIEW)) { && savedInstanceState.containsKey(KEY_IS_24_HOUR_VIEW)) {
mInitialHourOfDay = savedInstanceState.getInt(KEY_HOUR_OF_DAY); mInitialHourOfDay = savedInstanceState.getInt(KEY_HOUR_OF_DAY);
mInitialMinute = savedInstanceState.getInt(KEY_MINUTE); mInitialMinute = savedInstanceState.getInt(KEY_MINUTE);
mIs24HourMode = savedInstanceState.getBoolean(KEY_IS_24_HOUR_VIEW); mIs24HourMode = savedInstanceState.getBoolean(KEY_IS_24_HOUR_VIEW);
// mInKbMode = savedInstanceState.getBoolean(KEY_IN_KB_MODE); mInKbMode = savedInstanceState.getBoolean(KEY_IN_KB_MODE);
mThemeDark = savedInstanceState.getBoolean(KEY_DARK_THEME); mThemeDark = savedInstanceState.getBoolean(KEY_DARK_THEME);
} }
} }
@ -458,23 +290,16 @@ public class NumberGridTimePickerDialog extends BaseTimePickerDialog /*DialogFra
View view = super.onCreateView(inflater, container, savedInstanceState); View view = super.onCreateView(inflater, container, savedInstanceState);
// Inflate the buttons into the grid
int layout = mIs24HourMode ? R.layout.content_24h_number_grid : R.layout.content_number_grid;
View.inflate(getActivity(), layout, mGridLayout);
setNumberTexts();
setClickListenersOnButtons();
if (mCurrentIndex == MINUTE_INDEX) {
createMinuteTuners();
}
Resources res = getResources(); Resources res = getResources();
mHourPickerDescription = res.getString(R.string.hour_picker_description); mHourPickerDescription = res.getString(R.string.hour_picker_description);
mSelectHours = res.getString(R.string.select_hours); mSelectHours = res.getString(R.string.select_hours);
mMinutePickerDescription = res.getString(R.string.minute_picker_description); mMinutePickerDescription = res.getString(R.string.minute_picker_description);
mSelectMinutes = res.getString(R.string.select_minutes); mSelectMinutes = res.getString(R.string.select_minutes);
mSelectedColor = res.getColor(mThemeDark? R.color.red : R.color.blue); // mSelectedColor = res.getColor(mThemeDark? R.color.red : R.color.blue);
mUnselectedColor = // mUnselectedColor =
res.getColor(mThemeDark? android.R.color.white : R.color.numbers_text_color); // res.getColor(mThemeDark? android.R.color.white : R.color.numbers_text_color);
mSelectedColor = res.getColor(android.R.color.white);
mUnselectedColor = res.getColor(R.color.unselected_color);
mHourView = (TextView) view.findViewById(R.id.hours); mHourView = (TextView) view.findViewById(R.id.hours);
// mHourView.setOnKeyListener(keyboardListener); // mHourView.setOnKeyListener(keyboardListener);
@ -506,12 +331,11 @@ public class NumberGridTimePickerDialog extends BaseTimePickerDialog /*DialogFra
} }
// mHapticFeedbackController = new HapticFeedbackController(getActivity()); // mHapticFeedbackController = new HapticFeedbackController(getActivity());
mTimePicker = (GridSelectorLayout) view.findViewById(R.id.time_picker);
// mTimePicker = (RadialPickerLayout) view.findViewById(R.id.time_picker); mTimePicker.setOnValueSelectedListener(this);
// mTimePicker.setOnValueSelectedListener(this);
// mTimePicker.setOnKeyListener(keyboardListener); // mTimePicker.setOnKeyListener(keyboardListener);
// mTimePicker.initialize(getActivity(), mHapticFeedbackController, mInitialHourOfDay, mTimePicker.initialize(getActivity(), /*mHapticFeedbackController,*/ mInitialHourOfDay,
// mInitialMinute, mIs24HourMode); mInitialMinute, mIs24HourMode);
int currentItemShowing = HOUR_INDEX; int currentItemShowing = HOUR_INDEX;
if (savedInstanceState != null && if (savedInstanceState != null &&
@ -519,7 +343,7 @@ public class NumberGridTimePickerDialog extends BaseTimePickerDialog /*DialogFra
currentItemShowing = savedInstanceState.getInt(KEY_CURRENT_ITEM_SHOWING); currentItemShowing = savedInstanceState.getInt(KEY_CURRENT_ITEM_SHOWING);
} }
setCurrentItemShowing(currentItemShowing, false, true, true); setCurrentItemShowing(currentItemShowing, false, true, true);
// mTimePicker.invalidate(); mTimePicker.invalidate();
mHourView.setOnClickListener(new OnClickListener() { mHourView.setOnClickListener(new OnClickListener() {
@Override @Override
@ -537,6 +361,7 @@ public class NumberGridTimePickerDialog extends BaseTimePickerDialog /*DialogFra
}); });
// mDoneButton = (TextView) view.findViewById(R.id.done_button); // mDoneButton = (TextView) view.findViewById(R.id.done_button);
// This is our FAB.
mDoneButton.setOnClickListener(new OnClickListener() { mDoneButton.setOnClickListener(new OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
@ -545,12 +370,8 @@ public class NumberGridTimePickerDialog extends BaseTimePickerDialog /*DialogFra
} else { } else {
tryVibrate(); tryVibrate();
} }
Log.i(TAG, String.format("Selected time is %02d:%02d", mSelectedHourOfDay, mSelectedMinute));
if (mCallback != null) { if (mCallback != null) {
// mCallback.onTimeSet(mTimePicker, mTimePicker.getHours(), mTimePicker.getMinutes()); mCallback.onTimeSet(mTimePicker, mTimePicker.getHours(), mTimePicker.getMinutes());
// I don't think the listener actually uses the first param passed back,
// so passing null is fine.
mCallback.onTimeSet(null, mSelectedHourOfDay, mSelectedMinute);
} }
dismiss(); dismiss();
} }
@ -574,15 +395,14 @@ public class NumberGridTimePickerDialog extends BaseTimePickerDialog /*DialogFra
@Override @Override
public void onClick(View v) { public void onClick(View v) {
tryVibrate(); tryVibrate();
// int amOrPm = mTimePicker.getIsCurrentlyAmOrPm(); int amOrPm = mTimePicker.getIsCurrentlyAmOrPm();
// if (amOrPm == AM) { if (amOrPm == AM) {
// amOrPm = PM; amOrPm = PM;
// } else if (amOrPm == PM){ } else if (amOrPm == PM){
// amOrPm = AM; amOrPm = AM;
// } }
// updateAmPmDisplay(amOrPm); updateAmPmDisplay(amOrPm);
// mTimePicker.setAmOrPm(amOrPm); mTimePicker.setAmOrPm(amOrPm);
toggleHalfDay();
} }
}); });
} }
@ -606,30 +426,44 @@ public class NumberGridTimePickerDialog extends BaseTimePickerDialog /*DialogFra
} }
// Set the theme at the end so that the initialize()s above don't counteract the theme. // Set the theme at the end so that the initialize()s above don't counteract the theme.
// mTimePicker.setTheme(getActivity().getApplicationContext(), mThemeDark); mTimePicker.setTheme(getActivity().getApplicationContext(), mThemeDark);
// Prepare some colors to use. // Prepare some colors to use.
int white = res.getColor(android.R.color.white); int white = res.getColor(android.R.color.white);
// int circleBackground = res.getColor(R.color.circle_background); int circleBackground = res.getColor(R.color.circle_background);
// int line = res.getColor(R.color.line_background); int line = res.getColor(R.color.line_background);
int timeDisplay = res.getColor(R.color.numbers_text_color); int timeDisplay = res.getColor(R.color.numbers_text_color);
// TODO: Port the AOSP timepicker files that contain these resources.
// ColorStateList doneTextColor = res.getColorStateList(R.color.done_text_color); // ColorStateList doneTextColor = res.getColorStateList(R.color.done_text_color);
// int doneBackground = R.drawable.done_background_color; // int doneBackground = R.drawable.done_background_color;
int darkGray = res.getColor(R.color.dark_gray); int darkGray = res.getColor(R.color.dark_gray);
// int lightGray = res.getColor(R.color.light_gray); int lightGray = res.getColor(R.color.light_gray);
// int darkLine = res.getColor(R.color.line_dark); int darkLine = res.getColor(R.color.line_dark);
// TODO: Port the AOSP timepicker files that contain these resources.
// ColorStateList darkDoneTextColor = res.getColorStateList(R.color.done_text_color_dark); // ColorStateList darkDoneTextColor = res.getColorStateList(R.color.done_text_color_dark);
// int darkDoneBackground = R.drawable.done_background_color_dark; // int darkDoneBackground = R.drawable.done_background_color_dark;
// My colors
int accentColor = Utils.getThemeAccentColor(getContext());
// Set the colors for each view based on the theme. // Set the colors for each view based on the theme.
view.findViewById(R.id.time_display_background).setBackgroundColor(mThemeDark? darkGray : white); view.findViewById(R.id.time_display_background).setBackgroundColor(mThemeDark? lightGray : accentColor);
view.findViewById(R.id.time_display).setBackgroundColor(mThemeDark? darkGray : white); view.findViewById(R.id.time_display).setBackgroundColor(mThemeDark? lightGray : accentColor);
((TextView) view.findViewById(R.id.separator)).setTextColor(mThemeDark? white : timeDisplay); ((TextView) view.findViewById(R.id.separator)).setTextColor(/*mThemeDark? white : timeDisplay*/mUnselectedColor);
((TextView) view.findViewById(R.id.ampm_label)).setTextColor(mThemeDark? white : timeDisplay); ((TextView) view.findViewById(R.id.ampm_label)).setTextColor(/*mThemeDark? white : timeDisplay*/mUnselectedColor);
// view.findViewById(R.id.line).setBackgroundColor(mThemeDark? darkLine : line); // view.findViewById(R.id.line).setBackgroundColor(mThemeDark? darkLine : line);
// mDoneButton.setTextColor(mThemeDark? darkDoneTextColor : doneTextColor); // mDoneButton.setTextColor(mThemeDark? darkDoneTextColor : doneTextColor);
// mTimePicker.setBackgroundColor(mThemeDark? lightGray : circleBackground); // The AOSP timepicker originally uses these colors for the CircleView
mTimePicker.setBackgroundColor(mThemeDark? /*lightGray : circleBackground*/ darkGray : white);
// mDoneButton.setBackgroundResource(mThemeDark? darkDoneBackground : doneBackground); // mDoneButton.setBackgroundResource(mThemeDark? darkDoneBackground : doneBackground);
// http://stackoverflow.com/a/32031019/5055032
// Color in normal state
mDoneButton.setBackgroundTintList(ColorStateList.valueOf(accentColor));
// Color in pressed state. A ripple expands outwards from the point of contact throughout
// the fab when it is long pressed.
// mDoneButton.setRippleColor(/*your color here*/);
view.findViewById(R.id.half_day_toggles).setBackgroundColor(mThemeDark? /*lightGray : circleBackground*/ darkGray : white);
return view; return view;
} }
@ -652,11 +486,11 @@ public class NumberGridTimePickerDialog extends BaseTimePickerDialog /*DialogFra
private void updateAmPmDisplay(int amOrPm) { private void updateAmPmDisplay(int amOrPm) {
if (amOrPm == AM) { if (amOrPm == AM) {
mAmPmTextView.setText(mAmText); mAmPmTextView.setText(mAmText);
// Utils.tryAccessibilityAnnounce(mTimePicker, mAmText); Utils.tryAccessibilityAnnounce(mTimePicker, mAmText);
mAmPmHitspace.setContentDescription(mAmText); mAmPmHitspace.setContentDescription(mAmText);
} else if (amOrPm == PM){ } else if (amOrPm == PM){
mAmPmTextView.setText(mPmText); mAmPmTextView.setText(mPmText);
// Utils.tryAccessibilityAnnounce(mTimePicker, mPmText); Utils.tryAccessibilityAnnounce(mTimePicker, mPmText);
mAmPmHitspace.setContentDescription(mPmText); mAmPmHitspace.setContentDescription(mPmText);
} else { } else {
mAmPmTextView.setText(mDoublePlaceholderText); mAmPmTextView.setText(mDoublePlaceholderText);
@ -665,28 +499,23 @@ public class NumberGridTimePickerDialog extends BaseTimePickerDialog /*DialogFra
@Override @Override
public void onSaveInstanceState(Bundle outState) { public void onSaveInstanceState(Bundle outState) {
// if (mTimePicker != null) { if (mTimePicker != null) {
// outState.putInt(KEY_HOUR_OF_DAY, mTimePicker.getHours()); outState.putInt(KEY_HOUR_OF_DAY, mTimePicker.getHours());
// outState.putInt(KEY_MINUTE, mTimePicker.getMinutes()); outState.putInt(KEY_MINUTE, mTimePicker.getMinutes());
// outState.putBoolean(KEY_IS_24_HOUR_VIEW, mIs24HourMode);
// outState.putInt(KEY_CURRENT_ITEM_SHOWING, mTimePicker.getCurrentItemShowing());
// outState.putBoolean(KEY_IN_KB_MODE, mInKbMode);
// if (mInKbMode) {
// outState.putIntegerArrayList(KEY_TYPED_TIMES, mTypedTimes);
// }
// outState.putBoolean(KEY_DARK_THEME, mThemeDark);
// }
outState.putInt(KEY_HOUR_OF_DAY, mSelectedHourOfDay);
outState.putInt(KEY_MINUTE, mSelectedMinute);
outState.putBoolean(KEY_IS_24_HOUR_VIEW, mIs24HourMode); outState.putBoolean(KEY_IS_24_HOUR_VIEW, mIs24HourMode);
outState.putInt(KEY_CURRENT_ITEM_SHOWING, mCurrentIndex); outState.putInt(KEY_CURRENT_ITEM_SHOWING, mTimePicker.getCurrentItemShowing());
outState.putBoolean(KEY_IN_KB_MODE, mInKbMode);
if (mInKbMode) {
outState.putIntegerArrayList(KEY_TYPED_TIMES, mTypedTimes);
}
outState.putBoolean(KEY_DARK_THEME, mThemeDark); outState.putBoolean(KEY_DARK_THEME, mThemeDark);
} }
}
// /** /**
// * Called by the picker for updating the header display. * Called by the picker for updating the header display.
// */ */
// @Override @Override
public void onValueSelected(int pickerIndex, int newValue, boolean autoAdvance) { public void onValueSelected(int pickerIndex, int newValue, boolean autoAdvance) {
if (pickerIndex == HOUR_INDEX) { if (pickerIndex == HOUR_INDEX) {
setHour(newValue, false); setHour(newValue, false);
@ -695,13 +524,13 @@ public class NumberGridTimePickerDialog extends BaseTimePickerDialog /*DialogFra
setCurrentItemShowing(MINUTE_INDEX, true, true, false); setCurrentItemShowing(MINUTE_INDEX, true, true, false);
announcement += ". " + mSelectMinutes; announcement += ". " + mSelectMinutes;
} else { } else {
// mTimePicker.setContentDescription(mHourPickerDescription + ": " + newValue); mTimePicker.setContentDescription(mHourPickerDescription + ": " + newValue);
} }
// Utils.tryAccessibilityAnnounce(mTimePicker, announcement); Utils.tryAccessibilityAnnounce(mTimePicker, announcement);
} else if (pickerIndex == MINUTE_INDEX){ } else if (pickerIndex == MINUTE_INDEX){
setMinute(newValue); setMinute(newValue);
// mTimePicker.setContentDescription(mMinutePickerDescription + ": " + newValue); mTimePicker.setContentDescription(mMinutePickerDescription + ": " + newValue);
} else if (pickerIndex == AMPM_INDEX) { } else if (pickerIndex == AMPM_INDEX) {
updateAmPmDisplay(newValue); updateAmPmDisplay(newValue);
} else if (pickerIndex == ENABLE_PICKER_INDEX) { } else if (pickerIndex == ENABLE_PICKER_INDEX) {
@ -713,9 +542,6 @@ public class NumberGridTimePickerDialog extends BaseTimePickerDialog /*DialogFra
} }
private void setHour(int value, boolean announce) { private void setHour(int value, boolean announce) {
// TOneverDO: Set after if-else block (modulo operation changes value!)
mSelectedHourOfDay = value;
String format; String format;
if (mIs24HourMode) { if (mIs24HourMode) {
format = "%02d"; format = "%02d";
@ -731,7 +557,7 @@ public class NumberGridTimePickerDialog extends BaseTimePickerDialog /*DialogFra
mHourView.setText(text); mHourView.setText(text);
mHourSpaceView.setText(text); mHourSpaceView.setText(text);
if (announce) { if (announce) {
// Utils.tryAccessibilityAnnounce(mTimePicker, text); Utils.tryAccessibilityAnnounce(mTimePicker, text);
} }
} }
@ -740,37 +566,33 @@ public class NumberGridTimePickerDialog extends BaseTimePickerDialog /*DialogFra
value = 0; value = 0;
} }
CharSequence text = String.format(Locale.getDefault(), "%02d", value); CharSequence text = String.format(Locale.getDefault(), "%02d", value);
// Utils.tryAccessibilityAnnounce(mTimePicker, text); Utils.tryAccessibilityAnnounce(mTimePicker, text);
mMinuteView.setText(text); mMinuteView.setText(text);
mMinuteSpaceView.setText(text); mMinuteSpaceView.setText(text);
// Setting this here is fine.
mSelectedMinute = value;
} }
// Show either Hours or Minutes. // Show either Hours or Minutes.
private void setCurrentItemShowing(int index, boolean animateCircle, boolean delayLabelAnimate, private void setCurrentItemShowing(int index, boolean animateCircle, boolean delayLabelAnimate,
boolean announce) { boolean announce) {
// mTimePicker.setCurrentItemShowing(index, animateCircle); mTimePicker.setCurrentItemShowing(index, animateCircle);
setCurrentItemShowing(index);
TextView labelToAnimate; TextView labelToAnimate;
if (index == HOUR_INDEX) { if (index == HOUR_INDEX) {
// int hours = mTimePicker.getHours(); int hours = mTimePicker.getHours();
// if (!mIs24HourMode) { if (!mIs24HourMode) {
// hours = hours % 12; hours = hours % 12;
// } }
// mTimePicker.setContentDescription(mHourPickerDescription + ": " + hours); mTimePicker.setContentDescription(mHourPickerDescription + ": " + hours);
// if (announce) { if (announce) {
// Utils.tryAccessibilityAnnounce(mTimePicker, mSelectHours); Utils.tryAccessibilityAnnounce(mTimePicker, mSelectHours);
// } }
labelToAnimate = mHourView; labelToAnimate = mHourView;
} else { } else {
// int minutes = mTimePicker.getMinutes(); int minutes = mTimePicker.getMinutes();
// mTimePicker.setContentDescription(mMinutePickerDescription + ": " + minutes); mTimePicker.setContentDescription(mMinutePickerDescription + ": " + minutes);
// if (announce) { if (announce) {
// Utils.tryAccessibilityAnnounce(mTimePicker, mSelectMinutes); Utils.tryAccessibilityAnnounce(mTimePicker, mSelectMinutes);
// } }
labelToAnimate = mMinuteView; labelToAnimate = mMinuteView;
} }

View File

@ -0,0 +1,143 @@
package com.philliphsu.clock2.editalarm;
import android.content.Context;
import android.support.annotation.LayoutRes;
import android.support.v7.widget.GridLayout;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import com.philliphsu.clock2.aospdatetimepicker.Utils;
/**
* Created by Phillip Hsu on 8/17/2016.
*/
public abstract class NumbersGrid extends GridLayout implements View.OnClickListener {
private static final String TAG = "NumbersGrid";
private static final int COLUMN_COUNT = 3;
// Package visible so our concrete subclasses (in the same package) can access this.
OnNumberSelectedListener mSelectionListener;
View mLastSelectedView;
private final int mDefaultTextColor;
private final int mSelectedTextColor;
private boolean mIsInitialized;
private int mSelection; // The number selected from this grid
public interface OnNumberSelectedListener {
void onNumberSelected(int number);
}
@LayoutRes
protected abstract int contentLayout();
public NumbersGrid(Context context) {
super(context);
setColumnCount(COLUMN_COUNT);
inflate(context, contentLayout(), this);
// We don't do method binding because we don't know the IDs of
// our subclasses' buttons, if any.
registerClickListeners();
mIsInitialized = false;
mDefaultTextColor = Utils.getTextColorPrimary(context);
mSelectedTextColor = Utils.getThemeAccentColor(context);
// Show the first button as default selected
setIndicator(getChildAt(indexOfDefaultValue()));
}
public void initialize(OnNumberSelectedListener listener) {
if (mIsInitialized) {
Log.e(TAG, "This NumbersGrid may only be initialized once.");
return;
}
mSelectionListener = listener;
mIsInitialized = true;
}
public int getSelection() {
return mSelection;
}
public void setSelection(int value) {
mSelection = value;
}
/**
* The default implementation assumes the clicked view is of type TextView,
* casts the view accordingly, and parses the number from the text it contains.
* @param v the View that was clicked
*/
@Override
public void onClick(View v) {
TextView tv = (TextView) v;
clearIndicator(); // Does nothing if there was no indicator last selected
setIndicator(v);
mSelection = Integer.parseInt(tv.getText().toString());
mSelectionListener.onNumberSelected(mSelection);
}
/**
* Returns whether the specified View from our hierarchy can have an
* OnClickListener registered on it. The default implementation
* checks if this view is of type TextView. Subclasses can override
* this to fit their own criteria of what types of Views in their
* hierarchy can have a click listener registered on.
*
* @param view a child view from our hierarchy
*/
protected boolean canRegisterClickListener(View view) {
return view instanceof TextView;
}
/**
* Sets a selection indicator on the clicked number button. The indicator
* is the accent color applied to the button's text.
*
* @param view the clicked number button
*/
protected void setIndicator(View view) {
TextView tv = (TextView) view;
tv.setTextColor(mSelectedTextColor);
mLastSelectedView = view;
}
/**
* Clear the selection indicator on the last selected view. Clearing the indicator
* reverts the text color back to its default.
*/
protected void clearIndicator() {
if (mLastSelectedView != null) {
TextView tv = (TextView) mLastSelectedView;
tv.setTextColor(mDefaultTextColor);
mLastSelectedView = null;
}
}
/**
* @return the index for the number button that should have the indicator set on by default.
* The base implementation returns 0, for the first child.
*/
protected int indexOfDefaultValue() {
return 0;
}
void setTheme(Context context, boolean themeDark) {
// TODO: Change background color and text color
}
/**
* Iterates through our hierarchy and sets the subclass's implementation of OnClickListener
* on each number button encountered. By default, the number buttons are assumed to be of
* type TextView.
*/
private void registerClickListeners() {
int i = 0;
View v;
while (i < getChildCount() && canRegisterClickListener(v = getChildAt(i))) {
v.setOnClickListener(this);
i++;
}
}
}

View File

@ -111,7 +111,7 @@ public class NumbersGridView extends GridLayout {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
setNumbers(new int[] {0,5,10,15,20,25,30,35,40,45,50,55}, true); setNumbers(new int[] {0,5,10,15,20,25,30,35,40,45,50,55}, true);
inflate(getContext(), R.layout.content_number_grid_minute_tuners, NumbersGridView.this); inflate(getContext(), R.layout.content_minutes_grid, NumbersGridView.this);
} }
}); });
i++; i++;
@ -145,7 +145,7 @@ public class NumbersGridView extends GridLayout {
boolean is24HourMode = DateFormat.is24HourFormat(getContext()); boolean is24HourMode = DateFormat.is24HourFormat(getContext());
int layout = is24HourMode int layout = is24HourMode
? R.layout.content_24h_number_grid ? R.layout.content_24h_number_grid
: R.layout.content_number_grid; : R.layout.content_hours_grid;
inflate(getContext(), layout, this); inflate(getContext(), layout, this);
if (!is24HourMode) { if (!is24HourMode) {
setNumbers(new int[] {1,2,3,4,5,6,7,8,9,10,11,12}); setNumbers(new int[] {1,2,3,4,5,6,7,8,9,10,11,12});

View File

@ -0,0 +1,69 @@
package com.philliphsu.clock2.editalarm;
import android.content.Context;
import android.view.View;
import com.philliphsu.clock2.R;
/**
* Created by Phillip Hsu on 8/17/2016.
*/
public class TwentyFourHoursGrid extends NumbersGrid implements View.OnLongClickListener {
private static final String TAG = "TwentyFourHoursGrid";
public TwentyFourHoursGrid(Context context) {
super(context);
for (int i = 0; i < getChildCount(); i++) {
getChildAt(i).setOnLongClickListener(this);
}
}
@Override
protected int contentLayout() {
return R.layout.content_24h_number_grid;
}
@Override
protected boolean canRegisterClickListener(View view) {
return view instanceof TwentyFourHourGridItem;
}
@Override
public void onClick(View v) {
// We already verified that this view can have a click listener registered on.
// See canRegisterClickListener().
TwentyFourHourGridItem item = (TwentyFourHourGridItem) v;
clearIndicator();
setIndicator(v);
int newVal = Integer.parseInt(item.getPrimaryText().toString());
setSelection(newVal);
mSelectionListener.onNumberSelected(newVal);
}
@Override
public boolean onLongClick(View v) {
TwentyFourHourGridItem item = (TwentyFourHourGridItem) v;
int newVal = Integer.parseInt(item.getSecondaryText().toString());
setSelection(newVal);
mSelectionListener.onNumberSelected(newVal);
clearIndicator();
swapTexts();
// TOneverDO: Call before swapping texts, because setIndicator() uses the primary TextView.
setIndicator(v);
return true; // Consume the long click
}
@Override
protected void setIndicator(View view) {
TwentyFourHourGridItem item = (TwentyFourHourGridItem) view;
// Set indicator on the primary TextView
super.setIndicator(item.getChildAt(0));
}
public void swapTexts() {
for (int i = 0; i < getChildCount(); i++) {
View v = getChildAt(i);
((TwentyFourHourGridItem) v).swapTexts();
}
}
}

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<!-- TODO: Define styles -->
<TextView
android:id="@+id/primary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-condensed-light"
android:textSize="@dimen/number_grid_24_hour_item_primary_text_size"
android:includeFontPadding="false"
style="@style/TextAppearance.AppCompat"/>
<TextView
android:id="@+id/secondary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:includeFontPadding="false"/>
</merge>

View File

@ -7,12 +7,15 @@
android:id="@+id/primary" android:id="@+id/primary"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textColor="@color/colorPrimary" android:fontFamily="sans-serif-light"
android:textSize="@dimen/grid_element_text_size"/> android:textSize="@dimen/number_grid_24_hour_item_primary_text_size"
android:includeFontPadding="false"
style="@style/TextAppearance.AppCompat"/>
<TextView <TextView
android:id="@+id/secondary" android:id="@+id/secondary"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"/> android:layout_height="wrap_content"
android:includeFontPadding="false"/>
</merge> </merge>

View File

@ -1,15 +1,53 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<merge> <merge xmlns:app="http://schemas.android.com/apk/res-auto">
<include layout="@layout/item_24h_number_grid"/> <!-- Although the style defines a textSize attribute, it will not be
<include layout="@layout/item_24h_number_grid"/> applied because this is just a LinearLayout. -->
<include layout="@layout/item_24h_number_grid"/> <com.philliphsu.clock2.editalarm.TwentyFourHourGridItem
<include layout="@layout/item_24h_number_grid"/> style="@style/NumberGridButton.Hour"
<include layout="@layout/item_24h_number_grid"/> app:primaryText="00"
<include layout="@layout/item_24h_number_grid"/> app:secondaryText="12"/>
<include layout="@layout/item_24h_number_grid"/> <com.philliphsu.clock2.editalarm.TwentyFourHourGridItem
<include layout="@layout/item_24h_number_grid"/> style="@style/NumberGridButton.Hour"
<include layout="@layout/item_24h_number_grid"/> app:primaryText="01"
<include layout="@layout/item_24h_number_grid"/> app:secondaryText="13"/>
<include layout="@layout/item_24h_number_grid"/> <com.philliphsu.clock2.editalarm.TwentyFourHourGridItem
<include layout="@layout/item_24h_number_grid"/> style="@style/NumberGridButton.Hour"
app:primaryText="02"
app:secondaryText="14"/>
<com.philliphsu.clock2.editalarm.TwentyFourHourGridItem
style="@style/NumberGridButton.Hour"
app:primaryText="03"
app:secondaryText="15"/>
<com.philliphsu.clock2.editalarm.TwentyFourHourGridItem
style="@style/NumberGridButton.Hour"
app:primaryText="04"
app:secondaryText="16"/>
<com.philliphsu.clock2.editalarm.TwentyFourHourGridItem
style="@style/NumberGridButton.Hour"
app:primaryText="05"
app:secondaryText="17"/>
<com.philliphsu.clock2.editalarm.TwentyFourHourGridItem
style="@style/NumberGridButton.Hour"
app:primaryText="06"
app:secondaryText="18"/>
<com.philliphsu.clock2.editalarm.TwentyFourHourGridItem
style="@style/NumberGridButton.Hour"
app:primaryText="07"
app:secondaryText="19"/>
<com.philliphsu.clock2.editalarm.TwentyFourHourGridItem
style="@style/NumberGridButton.Hour"
app:primaryText="08"
app:secondaryText="20"/>
<com.philliphsu.clock2.editalarm.TwentyFourHourGridItem
style="@style/NumberGridButton.Hour"
app:primaryText="09"
app:secondaryText="21"/>
<com.philliphsu.clock2.editalarm.TwentyFourHourGridItem
style="@style/NumberGridButton.Hour"
app:primaryText="10"
app:secondaryText="22"/>
<com.philliphsu.clock2.editalarm.TwentyFourHourGridItem
style="@style/NumberGridButton.Hour"
app:primaryText="11"
app:secondaryText="23"/>
</merge> </merge>

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<TextView style="@style/NumberGridButton.Hour"
android:text="1"/>
<TextView style="@style/NumberGridButton.Hour"
android:text="2"/>
<TextView style="@style/NumberGridButton.Hour"
android:text="3"/>
<TextView style="@style/NumberGridButton.Hour"
android:text="4"/>
<TextView style="@style/NumberGridButton.Hour"
android:text="5"/>
<TextView style="@style/NumberGridButton.Hour"
android:text="6"/>
<TextView style="@style/NumberGridButton.Hour"
android:text="7"/>
<TextView style="@style/NumberGridButton.Hour"
android:text="8"/>
<TextView style="@style/NumberGridButton.Hour"
android:text="9"/>
<TextView style="@style/NumberGridButton.Hour"
android:text="10"/>
<TextView style="@style/NumberGridButton.Hour"
android:text="11"/>
<TextView style="@style/NumberGridButton.Hour"
android:text="12"/>
</merge>

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<TextView style="@style/NumberGridButton.Minute"
android:text="00"/>
<TextView style="@style/NumberGridButton.Minute"
android:text="05"/>
<TextView style="@style/NumberGridButton.Minute"
android:text="10"/>
<TextView style="@style/NumberGridButton.Minute"
android:text="15"/>
<TextView style="@style/NumberGridButton.Minute"
android:text="20"/>
<TextView style="@style/NumberGridButton.Minute"
android:text="25"/>
<TextView style="@style/NumberGridButton.Minute"
android:text="30"/>
<TextView style="@style/NumberGridButton.Minute"
android:text="35"/>
<TextView style="@style/NumberGridButton.Minute"
android:text="40"/>
<TextView style="@style/NumberGridButton.Minute"
android:text="45"/>
<TextView style="@style/NumberGridButton.Minute"
android:text="50"/>
<TextView style="@style/NumberGridButton.Minute"
android:text="55"/>
<ImageButton
style="@style/NumberGridButton.Minute"
android:src="@drawable/ic_minus_circle_24dp"
app:layout_column="0"/>
<ImageButton
style="@style/NumberGridButton.Minute"
android:src="@drawable/ic_add_circle_24dp"
app:layout_column="2"/>
</merge>

View File

@ -1,15 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<merge>
<include layout="@layout/item_number_grid"/>
<include layout="@layout/item_number_grid"/>
<include layout="@layout/item_number_grid"/>
<include layout="@layout/item_number_grid"/>
<include layout="@layout/item_number_grid"/>
<include layout="@layout/item_number_grid"/>
<include layout="@layout/item_number_grid"/>
<include layout="@layout/item_number_grid"/>
<include layout="@layout/item_number_grid"/>
<include layout="@layout/item_number_grid"/>
<include layout="@layout/item_number_grid"/>
<include layout="@layout/item_number_grid"/>
</merge>

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<!-- TODO: Use fixed width and height -->
<ImageButton
style="@style/GridLayoutNumpadElement"
android:src="@drawable/ic_minus_circle_24dp"
app:layout_column="0"/>
<ImageButton
style="@style/GridLayoutNumpadElement"
android:src="@drawable/ic_add_circle_24dp"
app:layout_column="2"/>
</merge>

View File

@ -23,24 +23,24 @@
android:layout_gravity="center" /> android:layout_gravity="center" />
</FrameLayout> </FrameLayout>
<android.support.v7.widget.GridLayout <com.philliphsu.clock2.editalarm.GridSelectorLayout
android:id="@+id/grid_layout" android:id="@+id/time_picker"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/numpad_height" android:layout_height="@dimen/number_grid_height"
android:layout_below="@id/time_display_background" android:layout_below="@id/time_display_background"
app:columnCount="3" android:paddingStart="@dimen/bottom_sheet_edge_margin"
android:layout_marginStart="@dimen/bottom_sheet_edge_margin" android:paddingEnd="@dimen/bottom_sheet_edge_margin"
android:layout_marginEnd="@dimen/bottom_sheet_edge_margin"
android:paddingBottom="@dimen/anchored_fab_vertical_space"/> android:paddingBottom="@dimen/anchored_fab_vertical_space"/>
<View <View
android:id="@+id/divider" android:id="@+id/divider"
style="@style/Divider.Horizontal" style="@style/Divider.Horizontal"
android:layout_below="@id/grid_layout"/> android:layout_below="@id/time_picker"/>
<LinearLayout <LinearLayout
android:id="@+id/half_day_toggles"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="48dp" android:layout_height="@dimen/half_day_button_bar_height"
android:layout_below="@id/divider" android:layout_below="@id/divider"
android:orientation="horizontal"> android:orientation="horizontal">
@ -56,8 +56,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:gravity="center"
android:layout_gravity="center" android:layout_gravity="center"
style="@style/TextAppearance.AppCompat.Button" style="@style/TextAppearance.AppCompat.Button"/>
android:textSize="@dimen/half_day_text_size"/>
</FrameLayout> </FrameLayout>
@ -73,8 +72,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:gravity="center"
android:layout_gravity="center" android:layout_gravity="center"
style="@style/TextAppearance.AppCompat.Button" style="@style/TextAppearance.AppCompat.Button"/>
android:textSize="@dimen/half_day_text_size"/>
</FrameLayout> </FrameLayout>
@ -82,6 +80,8 @@
</RelativeLayout> </RelativeLayout>
<!-- app:borderWidth="0dp"
Remove the stroke that is otherwise visible when long pressed -->
<android.support.design.widget.FloatingActionButton <android.support.design.widget.FloatingActionButton
android:id="@+id/fab" android:id="@+id/fab"
android:layout_width="wrap_content" android:layout_width="wrap_content"

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<!-- TODO: Define a grid item style with the first 3 attrs-->
<com.philliphsu.clock2.editalarm.TwentyFourHourGridItem
style="@style/GridLayoutNumpadElement"/>
</merge>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<!-- TODO: Use a fixed height so the circular indicator doesn't stretch into an oval. -->
<!-- Or measure the text dimensions and use the larger of its width and height, plus some
small integer extra, and use that as the diameter of the circle indicator. -->
<TextView style="@style/GridLayoutNumpadButton"/>
</merge>

View File

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<!-- 4 x (numeric_keypad_cell_height) + 56dp FAB height + 16dp FAB bottom margin --> <!-- 4 * (numeric_keypad_cell_height) + 56dp FAB height + 16dp FAB bottom margin -->
<dimen name="numeric_keypad_height">328dp</dimen> <dimen name="numeric_keypad_height">328dp</dimen>
<dimen name="numeric_keypad_backspace_height">56dp</dimen> <!-- Same as FAB height --> <dimen name="numeric_keypad_backspace_height">56dp</dimen> <!-- Same as FAB height -->
<dimen name="numeric_keypad_fab_bottom_margin">16dp</dimen> <dimen name="numeric_keypad_fab_bottom_margin">16dp</dimen>
</resources> </resources>

View File

@ -38,15 +38,13 @@
<!-- Colors for red theme --> <!-- Colors for red theme -->
<color name="red">#ff3333</color> <color name="red">#ff3333</color>
<color name="red_focused">#853333</color> <color name="red_focused">#853333</color>
<color name="light_gray">#404040</color> <color name="light_gray">#424242</color> <!--Grey 800. Originally #404040-->
<color name="dark_gray">#363636</color> <color name="dark_gray">#212121</color> <!--Grey 900. Originally #363636-->
<color name="line_dark">#808080</color> <color name="line_dark">#808080</color>
<color name="done_text_color_dark_normal">#ffffff</color> <color name="done_text_color_dark_normal">#ffffff</color>
<color name="done_text_color_dark_disabled">#888888</color> <color name="done_text_color_dark_disabled">#888888</color>
<color name="done_disabled_dark">#bfbfbf</color> <color name="done_disabled_dark">#bfbfbf</color>
<!-- My stuff --> <!--My stuff-->
<color name="accent_color">#009688</color> <color name="unselected_color">#a2ffffff</color><!--63%-64% white-->
<color name="accent_color_focused">#76ffffff</color>
<color name="accent_color_dark">#00796b</color>
</resources> </resources>

View File

@ -2,7 +2,7 @@
<resources> <resources>
<color name="colorPrimary">#3F51B5</color> <color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color> <color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color> <color name="colorAccent">#FF4081</color> <!--Alternatives: Red 700 #D32F2F-->
<color name="black_overlay">#66000000</color> <color name="black_overlay">#66000000</color>
</resources> </resources>

View File

@ -20,10 +20,18 @@
<dimen name="numpad_height">300dp</dimen> <!-- TODO: Deprecated --> <dimen name="numpad_height">300dp</dimen> <!-- TODO: Deprecated -->
<dimen name="numeric_keypad_cell_height">64dp</dimen> <dimen name="numeric_keypad_cell_height">64dp</dimen>
<dimen name="numeric_keypad_output_box_height">80dp</dimen> <dimen name="numeric_keypad_output_box_height">80dp</dimen>
<dimen name="numeric_keypad_height">344dp</dimen> <!-- 4 x (numeric_keypad_cell_height) + 88dp pre-21 FAB height --> <dimen name="numeric_keypad_height">344dp</dimen> <!-- 4 * (numeric_keypad_cell_height) + 88dp pre-21 FAB height -->
<dimen name="numeric_keypad_backspace_height">88dp</dimen> <!-- Same as pre-21 FAB height --> <dimen name="numeric_keypad_backspace_height">88dp</dimen> <!-- Same as pre-21 FAB height -->
<dimen name="numeric_keypad_fab_bottom_margin">0dp</dimen> <!-- 88dp height already big enough --> <dimen name="numeric_keypad_fab_bottom_margin">0dp</dimen> <!-- 88dp height already big enough -->
<!-- NumberGridTimePickerDialog -->
<dimen name="number_grid_height">308dp</dimen> <!-- 5 * (number_grid_minute_cell_height) + half-FAB height bottom padding -->
<dimen name="number_grid_hour_cell_height">70dp</dimen> <!-- 4 * 70 + 28 = 308 -->
<dimen name="number_grid_minute_cell_height">56dp</dimen>
<dimen name="half_day_button_bar_height">48dp</dimen>
<dimen name="number_grid_24_hour_item_primary_text_size">30sp</dimen>
<dimen name="number_grid_minute_text_size">28sp</dimen>
<!-- Bottom sheet specs --> <!-- Bottom sheet specs -->
<dimen name="bottom_sheet_edge_margin">24dp</dimen> <dimen name="bottom_sheet_edge_margin">24dp</dimen>
<dimen name="bottom_sheet_vertical_space">16dp</dimen> <dimen name="bottom_sheet_vertical_space">16dp</dimen>

View File

@ -47,6 +47,24 @@
<item name="android:fontFamily">sans-serif-light</item> <item name="android:fontFamily">sans-serif-light</item>
</style> </style>
<style name="NumberGridButton" parent="GridLayoutNumpadButton">
<!-- This should give us 87% black. By default, TextView has a grayish text color.
The reason GridLayoutNumpadButton style used in the NumpadTimerPickerDialog is 87% black
already is because the numpad's buttons are actually of type Button. For whatever reason,
I decided to make the buttons for the NumbersGrid of type TextView... -->
<item name="android:textColor">?android:attr/textColorPrimary</item>
</style>
<style name="NumberGridButton.Hour">
<item name="android:layout_height">@dimen/number_grid_hour_cell_height</item>
</style>
<style name="NumberGridButton.Minute">
<!-- Lowered text size, otherwise it looks weird that the minute grid, with 5 rows
of buttons, has the same text size as the hours grid, with 4 rows of buttons; they look
too big, and the space between them is smaller. -->
<item name="android:textSize">@dimen/number_grid_minute_text_size</item>
<item name="android:layout_height">@dimen/number_grid_minute_cell_height</item>
</style>
<!-- TODO: Replace and Delete --> <!-- TODO: Replace and Delete -->
<style name="hybrid_time_picker_grid_element"> <style name="hybrid_time_picker_grid_element">
<item name="android:layout_width">@dimen/grid_element_touch_target</item> <item name="android:layout_width">@dimen/grid_element_touch_target</item>