Numpad looking good
This commit is contained in:
@@ -52,6 +52,11 @@ public class MainActivity extends BaseActivity {
|
||||
@Bind(R.id.fab)
|
||||
FloatingActionButton mFab;
|
||||
|
||||
// // https://medium.com/@chrisbanes/appcompat-v23-2-age-of-the-vectors-91cbafa87c88#.141274xy8
|
||||
// // This is needed to load vector drawables from 23.4.0
|
||||
// static {
|
||||
// AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
|
||||
// }
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
||||
@@ -14,6 +14,7 @@ import butterknife.ButterKnife;
|
||||
* Created by Phillip Hsu on 7/16/2016.
|
||||
*/
|
||||
public abstract class BaseTimePickerDialog extends BottomSheetDialogFragment {
|
||||
private static final String TAG = "BaseTimePickerDialog";
|
||||
|
||||
// TODO: Consider private access, and then writing package/protected API that subclasses
|
||||
// can use to interface with this field.
|
||||
@@ -53,9 +54,59 @@ public abstract class BaseTimePickerDialog extends BottomSheetDialogFragment {
|
||||
// getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
|
||||
final View view = inflater.inflate(contentLayout(), container, false);
|
||||
ButterKnife.bind(this, view);
|
||||
|
||||
// TODO: We could move this to onCreateDialog() if we cared.
|
||||
//
|
||||
// onShow() is called immediately as this DialogFragment is showing, so the
|
||||
// FAB's animation will barely be noticeable.
|
||||
// getDialog().setOnShowListener(new DialogInterface.OnShowListener() {
|
||||
// @Override
|
||||
// public void onShow(DialogInterface dialog) {
|
||||
// Log.i(TAG, "onShow()");
|
||||
// // Animate the FAB into view
|
||||
// View v = view.findViewById(R.id.fab);
|
||||
// if (v != null) {
|
||||
// FloatingActionButton fab = (FloatingActionButton) v;
|
||||
// fab.show();
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void onResume() {
|
||||
// super.onResume();
|
||||
// final View view = getView();
|
||||
// final BottomSheetBehavior behavior = BottomSheetBehavior.from((View) view.getParent());
|
||||
// // Copy over the internal callback logic, and also implement our own
|
||||
// //
|
||||
// // This callback is set AFTER this Fragment has become visible, so is useless for what
|
||||
// // you wanted to do (show the FAB during the settling phase).
|
||||
// behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
|
||||
// @Override
|
||||
// public void onStateChanged(@NonNull View bottomSheet, int newState) {
|
||||
// Log.i(TAG, "onStateChanged(): " + newState);
|
||||
// if (newState == BottomSheetBehavior.STATE_HIDDEN) {
|
||||
// dismiss();
|
||||
// }
|
||||
// // My logic below
|
||||
// else if (newState == BottomSheetBehavior.STATE_SETTLING) {
|
||||
// View fab = view.findViewById(R.id.fab);
|
||||
// if (fab != null) {
|
||||
// ((FloatingActionButton) fab).show();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onSlide(@NonNull View bottomSheet, float slideOffset) {
|
||||
//
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package com.philliphsu.clock2.editalarm;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.support.annotation.CallSuper;
|
||||
import android.support.annotation.LayoutRes;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.widget.GridLayout;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
@@ -23,6 +25,10 @@ import butterknife.OnClick;
|
||||
* Unlike Numpad, this class only manages the logic for number button clicks
|
||||
* and not the backspace button. However, we do provide an API for removing
|
||||
* digits from the input.
|
||||
*
|
||||
* TODO: Is NumpadTimePicker the only subclass? If so, why do we need this
|
||||
* superclass? If we move the contents of this class to NumpadTimePicker,
|
||||
* the implementation of setTheme() would make more sense.
|
||||
*/
|
||||
public abstract class GridLayoutNumpad extends GridLayout {
|
||||
// TODO: change to private?
|
||||
@@ -33,6 +39,8 @@ public abstract class GridLayoutNumpad extends GridLayout {
|
||||
private int mCount = 0;
|
||||
private OnInputChangeListener mOnInputChangeListener;
|
||||
|
||||
ColorStateList mColors;
|
||||
|
||||
@Bind({ R.id.zero, R.id.one, R.id.two, R.id.three, R.id.four,
|
||||
R.id.five, R.id.six, R.id.seven, R.id.eight, R.id.nine })
|
||||
TextView[] mButtons;
|
||||
@@ -64,6 +72,24 @@ public abstract class GridLayoutNumpad extends GridLayout {
|
||||
init();
|
||||
}
|
||||
|
||||
void setTheme(Context context, boolean themeDark) {
|
||||
// Since the Dialog class already set the background color of its entire view tree,
|
||||
// our background is already colored. Why did we set it in the Dialog class? Because
|
||||
// we use margins around the numpad, and if we had instead set the background on
|
||||
// this numpad here, the margins will not be colored. Why not use padding instead
|
||||
// of margins? It turns out we tried that--replacing each margin attribute
|
||||
// with the padding counterpart--but we lost the pre-21 FAB inherent bottom margin.
|
||||
|
||||
// The buttons are actually of type Button, but we kept references
|
||||
// to them as TextViews... which is fine since TextView is the superclass
|
||||
// of Button.
|
||||
mColors = ContextCompat.getColorStateList(context,
|
||||
themeDark? R.color.numeric_keypad_button_text_dark : R.color.numeric_keypad_button_text);
|
||||
for (TextView b : mButtons) {
|
||||
b.setTextColor(mColors);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of digits we can input
|
||||
*/
|
||||
|
||||
@@ -470,6 +470,13 @@ public class NumberGridTimePickerDialog extends BaseTimePickerDialog implements
|
||||
|
||||
// Set the color on the FAB
|
||||
// http://stackoverflow.com/a/32031019/5055032
|
||||
// *****************************************************************************************
|
||||
// NOTE: IF YOU DECIDE TO MOVE THE FAB AND THE HALF DAY TOGGLES TO THE GRIDSELECTORLAYOUT
|
||||
// CLASS, YOU SHOULD CHANGE THE CONTEXT PASSED TO GridSelectorLayout#setTheme() FROM THE
|
||||
// APPLICATION CONTEXT TO THE LOCAL CONTEXT. OTHERWISE, IT WOULD NOT BE ABLE TO RETRIEVE
|
||||
// THE CORRECT ACCENT COLOR. WE ALREADY FACED THIS ISSUE WITH THE NUMPADTIMEPICKERDIALOG.
|
||||
// DO A CTRL+F FOR mTimePicker.setTheme FOR THE CODE IN DISCUSSION.
|
||||
// *****************************************************************************************
|
||||
// Color in normal state
|
||||
mDoneButton.setBackgroundTintList(ColorStateList.valueOf(accentColor));
|
||||
// Color in pressed state. A ripple expands outwards from the point of contact throughout
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
package com.philliphsu.clock2.editalarm;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.annotation.IntDef;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v4.graphics.drawable.DrawableCompat;
|
||||
import android.text.format.DateFormat;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.Button;
|
||||
@@ -10,6 +14,8 @@ import android.widget.ImageButton;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.philliphsu.clock2.R;
|
||||
import com.philliphsu.clock2.aospdatetimepicker.Utils;
|
||||
import com.philliphsu.clock2.util.ConversionUtils;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@@ -55,6 +61,11 @@ public class NumpadTimePicker extends GridLayoutNumpad {
|
||||
@Bind(R.id.fab) FloatingActionButton mFab;
|
||||
@Bind(R.id.backspace) ImageButton mBackspace;
|
||||
|
||||
private boolean mThemeDark;
|
||||
private int mAccentColor;
|
||||
private int mFabDisabledColorDark;
|
||||
private int mFabDisabledColorLight;
|
||||
|
||||
/**
|
||||
* Provides additional APIs to configure clients' display output.
|
||||
*/
|
||||
@@ -75,7 +86,53 @@ public class NumpadTimePicker extends GridLayoutNumpad {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
void setTheme(Context context, boolean themeDark) {
|
||||
super.setTheme(context, themeDark);
|
||||
mThemeDark = themeDark;
|
||||
|
||||
// So, we kept the 0-9 buttons as TextViews, but here we kept
|
||||
// the alt buttons as actual Buttons...
|
||||
for (Button b : mAltButtons) {
|
||||
b.setTextColor(mColors);
|
||||
}
|
||||
|
||||
// Get a mutable instance of the drawable, so we only affect this instance.
|
||||
// This is especially useful when you need to modify properties of drawables loaded from
|
||||
// resources. By default, all drawables instances loaded from the same resource share a
|
||||
// common state; if you modify the state of one instance, all the other instances will
|
||||
// receive the same modification.
|
||||
// TODO: What is the VectorDrawable counterpart for this process?
|
||||
Drawable backspaceDrawable = mBackspace.getDrawable().mutate();
|
||||
// Wrap drawable so that it may be used for tinting across the different
|
||||
// API levels, via the tinting methods in this class.
|
||||
backspaceDrawable = DrawableCompat.wrap(backspaceDrawable);
|
||||
// Prepare the tints
|
||||
ColorStateList colorBackspace = ContextCompat.getColorStateList(context,
|
||||
themeDark? R.color.icon_color_dark : R.color.icon_color);
|
||||
DrawableCompat.setTintList(backspaceDrawable, colorBackspace);
|
||||
mBackspace.setImageDrawable(backspaceDrawable);
|
||||
|
||||
// TODO: What is the VectorDrawable counterpart for this process?
|
||||
Drawable iconDrawable = mFab.getDrawable().mutate();
|
||||
iconDrawable = DrawableCompat.wrap(iconDrawable);
|
||||
ColorStateList colorIcon = ContextCompat.getColorStateList(context,
|
||||
themeDark? R.color.icon_color_dark : R.color.fab_icon_color);
|
||||
DrawableCompat.setTintList(iconDrawable, colorIcon);
|
||||
mFab.setImageDrawable(iconDrawable);
|
||||
|
||||
// this.getContext() ==> default teal accent color
|
||||
// application context ==> white
|
||||
// The Context that was passed in is NumpadTimePickerDialog.getContext() which
|
||||
// is probably the host Activity. I have no idea what this.getContext() returns,
|
||||
// but its probably some internal type that isn't tied to any of our application
|
||||
// components.
|
||||
mAccentColor = Utils.getThemeAccentColor(context);
|
||||
// Make sure the dark theme disabled color shows up initially
|
||||
updateFabState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int capacity() {
|
||||
return MAX_DIGITS;
|
||||
@@ -255,6 +312,9 @@ public class NumpadTimePicker extends GridLayoutNumpad {
|
||||
}
|
||||
|
||||
private void init() {
|
||||
mFabDisabledColorDark = ContextCompat.getColor(getContext(), R.color.fab_disabled_dark);
|
||||
mFabDisabledColorLight = ContextCompat.getColor(getContext(), R.color.fab_disabled_light);
|
||||
// TODO: We should have the user pass in is24HourMode when they create an instance of the dialog.
|
||||
if (DateFormat.is24HourFormat(getContext())) {
|
||||
mAltButtons[0].setText(R.string.left_alt_24hr);
|
||||
mAltButtons[1].setText(R.string.right_alt_24hr);
|
||||
@@ -383,6 +443,19 @@ public class NumpadTimePicker extends GridLayoutNumpad {
|
||||
|
||||
private void updateFabState() {
|
||||
mFab.setEnabled(checkTimeValid());
|
||||
// Workaround for mFab.setBackgroundTintList() because I don't know how to reference the
|
||||
// correct accent color in XML. Also because I don't want to programmatically create a
|
||||
// ColorStateList.
|
||||
int color;
|
||||
// TODO: Animate elevation property "compatElevation"
|
||||
if (mFab.isEnabled()) {
|
||||
color = mAccentColor;
|
||||
mFab.setCompatElevation(ConversionUtils.dpToPx(getContext(), 6));
|
||||
} else {
|
||||
color = mThemeDark? mFabDisabledColorDark : mFabDisabledColorLight;
|
||||
mFab.setCompatElevation(0);
|
||||
}
|
||||
mFab.setBackgroundTintList(ColorStateList.valueOf(color));
|
||||
}
|
||||
|
||||
private void updateBackspaceState() {
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package com.philliphsu.clock2.editalarm;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.philliphsu.clock2.R;
|
||||
import com.philliphsu.clock2.aospdatetimepicker.Utils;
|
||||
|
||||
import butterknife.Bind;
|
||||
import butterknife.OnClick;
|
||||
@@ -36,6 +38,7 @@ public class NumpadTimePickerDialog extends BaseTimePickerDialog
|
||||
* depends on the dialog to save its state.
|
||||
*/
|
||||
private int[] mInputtedDigits;
|
||||
private boolean mThemeDark;
|
||||
|
||||
// Don't need to keep a reference to the dismiss ImageButton
|
||||
@Bind(R.id.input_time) TextView mInputField;
|
||||
@@ -54,7 +57,9 @@ public class NumpadTimePickerDialog extends BaseTimePickerDialog
|
||||
// TODO: is24HourMode param
|
||||
public static NumpadTimePickerDialog newInstance(OnTimeSetListener callback) {
|
||||
NumpadTimePickerDialog ret = new NumpadTimePickerDialog();
|
||||
// TODO: Do these in initialize()
|
||||
ret.setOnTimeSetListener(callback);
|
||||
ret.mThemeDark = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -67,6 +72,17 @@ public class NumpadTimePickerDialog extends BaseTimePickerDialog
|
||||
mIs24HourMode = is24HourMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a dark or light theme. NOTE: this will only take effect for the next onCreateView.
|
||||
*/
|
||||
public void setThemeDark(boolean dark) {
|
||||
mThemeDark = dark;
|
||||
}
|
||||
|
||||
public boolean isThemeDark() {
|
||||
return mThemeDark;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@@ -84,8 +100,24 @@ public class NumpadTimePickerDialog extends BaseTimePickerDialog
|
||||
mNumpad.insertDigits(mInputtedDigits); // TOneverDO: before mNumpad.setOnInputChangeListener(this);
|
||||
// Show the cursor immediately
|
||||
// mInputField.requestFocus();
|
||||
// TODO: Disabled color
|
||||
//updateInputText(""); // Primarily to disable 'OK'
|
||||
|
||||
// Prepare colors
|
||||
int accentColor = Utils.getThemeAccentColor(getContext());
|
||||
int lightGray = ContextCompat.getColor(getContext(), R.color.light_gray);
|
||||
int darkGray = ContextCompat.getColor(getContext(), R.color.dark_gray);
|
||||
int white = ContextCompat.getColor(getContext(), android.R.color.white);
|
||||
|
||||
// Set background color of entire view
|
||||
view.setBackgroundColor(mThemeDark? darkGray : white);
|
||||
|
||||
TextView inputTime = (TextView) view.findViewById(R.id.input_time);
|
||||
inputTime.setBackgroundColor(mThemeDark? lightGray : accentColor);
|
||||
inputTime.setTextColor(ContextCompat.getColor(getContext(), android.R.color.white));
|
||||
|
||||
mNumpad.setTheme(getContext()/*DO NOT GIVE THE APPLICATION CONTEXT, OR ELSE THE NUMPAD
|
||||
CAN'T GET THE CORRECT ACCENT COLOR*/, mThemeDark);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user