New numpad time picker layout

This commit is contained in:
Phillip Hsu 2016-07-15 23:43:55 -07:00
parent 69d8812c4a
commit 231aa9a280
6 changed files with 110 additions and 100 deletions

View File

@ -141,7 +141,7 @@ public abstract class GridLayoutNumpad extends GridLayout implements View.OnClic
} }
} }
public final boolean clear() { public boolean clear() {
Arrays.fill(mInput, UNMODIFIED); Arrays.fill(mInput, UNMODIFIED);
mCount = 0; mCount = 0;
onDigitsCleared(); onDigitsCleared();

View File

@ -2,9 +2,11 @@ package com.philliphsu.clock2.editalarm;
import android.content.Context; import android.content.Context;
import android.support.annotation.IntDef; import android.support.annotation.IntDef;
import android.support.design.widget.FloatingActionButton;
import android.text.format.DateFormat; import android.text.format.DateFormat;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.widget.Button; import android.widget.Button;
import android.widget.ImageButton;
import com.philliphsu.clock2.R; import com.philliphsu.clock2.R;
@ -15,6 +17,7 @@ import java.util.Calendar;
import butterknife.Bind; import butterknife.Bind;
import butterknife.OnClick; import butterknife.OnClick;
import butterknife.OnLongClick;
/** /**
* Created by Phillip Hsu on 7/12/2016. * Created by Phillip Hsu on 7/12/2016.
@ -48,6 +51,8 @@ public class NumpadTimePicker extends GridLayoutNumpad implements TimePicker {
@Bind({ R.id.leftAlt, R.id.rightAlt }) @Bind({ R.id.leftAlt, R.id.rightAlt })
Button[] mAltButtons; Button[] mAltButtons;
@Bind(R.id.fab) FloatingActionButton mFab;
@Bind(R.id.backspace) ImageButton mBackspace;
public NumpadTimePicker(Context context) { public NumpadTimePicker(Context context) {
super(context); super(context);
@ -93,6 +98,7 @@ public class NumpadTimePicker extends GridLayoutNumpad implements TimePicker {
} }
@Override @Override
@OnClick(R.id.backspace)
public void delete() { public void delete() {
int len = mFormattedInput.length(); int len = mFormattedInput.length();
if (!is24HourFormat() && mAmPmState != UNSPECIFIED) { if (!is24HourFormat() && mAmPmState != UNSPECIFIED) {
@ -108,6 +114,12 @@ public class NumpadTimePicker extends GridLayoutNumpad implements TimePicker {
} }
} }
@Override
@OnLongClick(R.id.backspace)
public boolean clear() {
return super.clear();
}
/** Returns the hour of day (0-23) regardless of clock system */ /** Returns the hour of day (0-23) regardless of clock system */
@Override @Override
public int hourOfDay() { public int hourOfDay() {
@ -213,6 +225,10 @@ public class NumpadTimePicker extends GridLayoutNumpad implements TimePicker {
return mFormattedInput.toString(); return mFormattedInput.toString();
} }
public void setFabClickListener(OnClickListener fabClickListener) {
mFab.setOnClickListener(fabClickListener);
}
private void init() { private void init() {
if (is24HourFormat()) { if (is24HourFormat()) {
mAltButtons[0].setText(R.string.left_alt_24hr); mAltButtons[0].setText(R.string.left_alt_24hr);
@ -332,8 +348,17 @@ public class NumpadTimePicker extends GridLayoutNumpad implements TimePicker {
private void updateNumpadStates() { private void updateNumpadStates() {
updateAltButtonStates(); updateAltButtonStates();
//updateBackspaceState(); // Backspace is not part of the numpad updateBackspaceState();
updateNumberKeysStates(); updateNumberKeysStates();
updateFabState();
}
private void updateFabState() {
mFab.setEnabled(checkTimeValid());
}
private void updateBackspaceState() {
mBackspace.setEnabled(count() > 0);
} }
private void updateAltButtonStates() { private void updateAltButtonStates() {

View File

@ -6,24 +6,20 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.Window; import android.view.Window;
import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageButton;
import com.philliphsu.clock2.R; import com.philliphsu.clock2.R;
import butterknife.Bind; import butterknife.Bind;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import butterknife.OnClick; import butterknife.OnClick;
import butterknife.OnLongClick;
import butterknife.OnTouch; import butterknife.OnTouch;
/** /**
* Created by Phillip Hsu on 7/12/2016. * Created by Phillip Hsu on 7/12/2016.
* *
*/ */
public class NumpadTimePickerDialog extends DialogFragment public class NumpadTimePickerDialog extends DialogFragment implements NumpadTimePicker.OnInputChangeListener {
implements NumpadTimePicker.OnInputChangeListener {
private static final String KEY_HOUR_OF_DAY = "hour_of_day"; private static final String KEY_HOUR_OF_DAY = "hour_of_day";
private static final String KEY_MINUTE = "minute"; private static final String KEY_MINUTE = "minute";
@ -45,10 +41,7 @@ public class NumpadTimePickerDialog extends DialogFragment
*/ */
private int[] mInputtedDigits; private int[] mInputtedDigits;
@Bind(R.id.backspace) ImageButton mBackspace; @Bind(R.id.input_time) EditText mInputField;
@Bind(R.id.input) EditText mInputField;
@Bind(R.id.cancel) Button mCancelButton;
@Bind(R.id.ok) Button mOkButton;
@Bind(R.id.number_grid) NumpadTimePicker mNumpad; @Bind(R.id.number_grid) NumpadTimePicker mNumpad;
public NumpadTimePickerDialog() { public NumpadTimePickerDialog() {
@ -101,12 +94,24 @@ public class NumpadTimePickerDialog extends DialogFragment
View view = inflater.inflate(R.layout.dialog_time_picker_numpad, container, false); View view = inflater.inflate(R.layout.dialog_time_picker_numpad, container, false);
ButterKnife.bind(this, view); ButterKnife.bind(this, view);
// Can't do a method bind because the FAB is not part of this dialog's layout
// Also can't do the bind in the Numpad's class, because it doesn't have access to
// the OnTimeSetListener callback contained here or the dialog's dismiss()
mNumpad.setFabClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!mNumpad.checkTimeValid())
return;
mCallback.onTimeSet(mNumpad, mNumpad.hourOfDay(), mNumpad.minute());
dismiss();
}
});
mNumpad.setOnInputChangeListener(this); mNumpad.setOnInputChangeListener(this);
mNumpad.insertDigits(mInputtedDigits); // TOneverDO: before mNumpad.setOnInputChangeListener(this); mNumpad.insertDigits(mInputtedDigits); // TOneverDO: before mNumpad.setOnInputChangeListener(this);
// Show the cursor immediately // Show the cursor immediately
mInputField.requestFocus(); // TODO: If changed to TextView, then don't need this. mInputField.requestFocus();
// TODO: Disabled color // TODO: Disabled color
updateInputText(""); // Primarily to disable 'OK' //updateInputText(""); // Primarily to disable 'OK'
return view; return view;
} }
@ -135,41 +140,20 @@ public class NumpadTimePickerDialog extends DialogFragment
updateInputText(""); updateInputText("");
} }
// TODO: If you change the input field to a TextView, then you don't need this. @OnTouch(R.id.input_time)
@OnTouch(R.id.input)
boolean captureTouchOnEditText() { boolean captureTouchOnEditText() {
// Capture touch events on the EditText field, because we want it to do nothing. // Capture touch events on the EditText field, because we want it to do nothing.
return true; return true;
} }
@OnClick(R.id.cancel) @OnClick(R.id.cancel_icon)
void myCancel() { void myCancel() {
dismiss(); dismiss();
} }
@OnClick(R.id.ok)
void ok() {
if (!mNumpad.checkTimeValid())
return;
mCallback.onTimeSet(mNumpad, mNumpad.hourOfDay(), mNumpad.minute());
dismiss();
}
@OnClick(R.id.backspace)
void backspace() {
mNumpad.delete();
}
@OnLongClick(R.id.backspace)
boolean longBackspace() {
mNumpad.clear();
return true;
}
private void updateInputText(String inputText) { private void updateInputText(String inputText) {
mInputField.setText(inputText); mInputField.setText(inputText);
// Move the cursor // Move the cursor
//mInputField.setSelection(mInputField.length()); // TODO: If changed to TextView, don't need this mInputField.setSelection(mInputField.length());
mOkButton.setEnabled(mNumpad.checkTimeValid());
} }
} }

View File

@ -17,4 +17,31 @@
grid:layout_rowWeight="1" grid:layout_rowWeight="1"
grid:layout_columnWeight="1" grid:layout_columnWeight="1"
grid:layout_column="2"/> grid:layout_column="2"/>
<!-- Used to properly position the FAB -->
<FrameLayout
android:layout_width="0dp"
android:layout_height="0dp"
grid:layout_rowWeight="1"
grid:layout_columnWeight="1"
grid:layout_column="1">
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_done_24dp"
android:layout_gravity="center"/>
</FrameLayout>
<ImageButton
android:id="@+id/backspace"
android:layout_width="0dp"
android:layout_height="0dp"
android:src="@drawable/ic_backspace_24dp"
android:background="?selectableItemBackground"
grid:layout_rowWeight="1"
grid:layout_columnWeight="1"
grid:layout_column="2"/>
</merge> </merge>

View File

@ -1,70 +1,43 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="@dimen/header_height"
android:background="@color/colorPrimary">
<ImageButton <ImageButton
android:id="@+id/backspace" android:id="@+id/cancel_icon"
android:layout_width="@dimen/header_height" android:layout_width="@dimen/cancel_icon_size"
android:layout_height="@dimen/header_height" android:layout_height="match_parent"
android:src="@drawable/ic_backspace_24dp" android:src="@android:drawable/ic_menu_close_clear_cancel"
android:background="?selectableItemBackground" android:background="?selectableItemBackground"
android:layout_alignParentEnd="true" android:layout_alignParentStart="true"/>
android:layout_alignParentTop="true"/>
<!-- TODO: Consider changing to TextView if you don't <!-- We want this to be an EditText because the cursor indicates
want the cursor after all. A reason you may want to do where the user's input will go. Otherwise, when the dialog first
so is the cursor is getting cut off, most likely because opens, the user sees the header view as just an appbar that has
of the text size being larger than the view bounds. You can a single navigation icon, with no indication that the dialog
probably solve this by adding some padding. Another reason is actually displays input. -->
the cursor looks ugly with it blinking. -->
<EditText <EditText
android:id="@+id/input" android:id="@+id/input_time"
android:layout_width="wrap_content"
android:layout_height="@dimen/header_height"
android:layout_centerHorizontal="true"
android:layout_alignParentTop="true"
android:background="@android:color/transparent"
android:textSize="@dimen/time_input_text_size"
android:focusable="false"
android:focusableInTouchMode="false"/>
<View
android:id="@+id/divider"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="1dp" android:layout_height="wrap_content"
android:background="?android:listDivider" android:layout_toEndOf="@id/cancel_icon"
android:layout_below="@id/input"/> android:layout_centerInParent="true"
android:textSize="@dimen/time_input_text_size"
android:text="12:00 AM"
android:background="@null"
style="@style/TextAppearance.AppCompat.Inverse"/>
</RelativeLayout>
<com.philliphsu.clock2.editalarm.NumpadTimePicker <com.philliphsu.clock2.editalarm.NumpadTimePicker
android:id="@+id/number_grid" android:id="@+id/number_grid"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/numpad_height" android:layout_height="@dimen/numpad_height"/>
android:layout_below="@id/divider"/>
<LinearLayout </LinearLayout>
android:id="@+id/actions"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_below="@id/number_grid">
<Button
android:id="@+id/cancel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="CANCEL"
style="@style/Widget.AppCompat.Button.Borderless.Colored"/>
<Button
android:id="@+id/ok"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="OK"
style="@style/Widget.AppCompat.Button.Borderless.Colored"/>
</LinearLayout>
</RelativeLayout>

View File

@ -15,5 +15,6 @@
<!-- NumpadTimePickerDialog --> <!-- NumpadTimePickerDialog -->
<dimen name="header_height">72dp</dimen> <dimen name="header_height">72dp</dimen>
<dimen name="numpad_height">270dp</dimen> <dimen name="numpad_height">270dp</dimen>
<dimen name="time_input_text_size">40sp</dimen> <dimen name="time_input_text_size">45sp</dimen>
<dimen name="cancel_icon_size">56dp</dimen>
</resources> </resources>