From c70b40e213b2c20ebdb3d99ca4ddc2acf7142805 Mon Sep 17 00:00:00 2001 From: Phillip Hsu Date: Thu, 28 Jul 2016 19:17:00 -0700 Subject: [PATCH] Implemented time fields --- .../clock2/edittimer/EditTimerActivity.java | 122 +++++++- .../main/res/layout/activity_edit_timer.xml | 271 +++++++++--------- .../main/res/layout/content_numpad_timer.xml | 51 +--- 3 files changed, 238 insertions(+), 206 deletions(-) diff --git a/app/src/main/java/com/philliphsu/clock2/edittimer/EditTimerActivity.java b/app/src/main/java/com/philliphsu/clock2/edittimer/EditTimerActivity.java index ff0a230..838235c 100644 --- a/app/src/main/java/com/philliphsu/clock2/edittimer/EditTimerActivity.java +++ b/app/src/main/java/com/philliphsu/clock2/edittimer/EditTimerActivity.java @@ -3,31 +3,40 @@ package com.philliphsu.clock2.edittimer; import android.os.Bundle; import android.support.design.widget.FloatingActionButton; import android.support.v7.widget.GridLayout; -import android.widget.Button; -import android.widget.ImageButton; -import android.widget.ProgressBar; +import android.text.InputType; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.EditText; import android.widget.TextView; import com.philliphsu.clock2.BaseActivity; import com.philliphsu.clock2.R; import butterknife.Bind; +import butterknife.OnClick; +import butterknife.OnLongClick; +import butterknife.OnTouch; public class EditTimerActivity extends BaseActivity { + private static final int FIELD_LENGTH = 2; + private final int[] mInput = new int[6]; + private int mCursorAt; + + @Bind(R.id.appbar) ViewGroup mAppBar; @Bind(R.id.label) TextView mLabel; - @Bind(R.id.duration) TextView mDuration; // TODO: Change to something suitable for input fields - @Bind(R.id.add_one_minute) ImageButton mAddOneMinute; + @Bind(R.id.hour) EditText mHour; + @Bind(R.id.minute) EditText mMinute; + @Bind(R.id.second) EditText mSecond; + @Bind(R.id.hour_label) TextView mHourLabel; + @Bind(R.id.minute_label) TextView mMinuteLabel; + @Bind(R.id.second_label) TextView mSecondLabel; + @Bind(R.id.focus_grabber) View mFocusGrabber; @Bind(R.id.fab) FloatingActionButton mFab; - @Bind(R.id.stop) ImageButton mStop; - // TODO: Consider making an abstract EditItemActivity. - // Define these buttons in a layout file that subclasses can include - // into their own activity layouts. Bind OnClick listeners to abstract - // protected methods deleteItem() and saveItem(). - @Bind(R.id.delete) Button mDelete; - @Bind(R.id.save) Button mSave; - @Bind(R.id.numpad) GridLayout mNumpad; // TODO: Actual numpad type - @Bind(R.id.progress_bar) ProgressBar mProgressBar; + // Intentionally not using a (subclass of) GridLayoutNumpad, because + // it is expedient to refrain from adapting it for timers. + @Bind(R.id.numpad) GridLayout mNumpad; @Override protected void onCreate(Bundle savedInstanceState) { @@ -41,6 +50,91 @@ public class EditTimerActivity extends BaseActivity { @Override protected int menuResId() { + // TODO: Define a menu res with a save item return 0; } + + @OnClick({ 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 }) + void onClick(TextView view) { + if (mFocusGrabber.isFocused()) + return; + EditText field = getFocusedField(); + int at = field.getSelectionStart(); + field.getText().replace(at, at + 1, view.getText()); + field.setSelection(at + 1); + if (field.getSelectionStart() == FIELD_LENGTH) { + // At the end of the current field, so try to focus to the next field. + // The search will return null if no view can be focused next. + View next = field.focusSearch(View.FOCUS_RIGHT); + if (next != null) { + next.requestFocus(); + if (next instanceof EditText) { + // Should always start off at the beginning of the field + ((EditText) next).setSelection(0); + } + } + } + } + + @OnTouch({ R.id.hour, R.id.minute, R.id.second }) + boolean captureTouchEvent(EditText field, MotionEvent event) { + int inType = field.getInputType(); // backup the input type + field.setInputType(InputType.TYPE_NULL); // disable soft input + boolean result = field.onTouchEvent(event); // call native handler + field.setInputType(inType); // restore input type (to show cursor) + return result; + } + + @OnClick(R.id.backspace) + void backspace() { + if (mFocusGrabber.isFocused()) { + mAppBar.focusSearch(mFocusGrabber, View.FOCUS_LEFT).requestFocus(); + } + EditText field = getFocusedField(); + if (field == null) + return; + int at = field.getSelectionStart(); + if (at == 0) { + // At the beginning of current field, so move focus + // to the preceding field + View prev = field.focusSearch(View.FOCUS_LEFT); + if (null == prev) { + // Reached the beginning of the hours field + return; + } + if (prev.requestFocus()) { + if (prev instanceof EditText) { + // Always move the cursor to the end when moving focus back + ((EditText) prev).setSelection(FIELD_LENGTH); + } + // Recursively backspace on the newly focused field + backspace(); + } + } else { + field.getText().replace(at - 1, at, "0"); + field.setSelection(at - 1); + } + } + + @OnLongClick(R.id.backspace) + boolean clear() { + mHour.setText("00"); + mMinute.setText("00"); + mSecond.setText("00"); + mHour.requestFocus(); // TOneverDO: call after setSelection(0), or else the cursor returns to the end of the text + mHour.setSelection(0); // always move the cursor WHILE the field is focused, NEVER focus after! + mMinute.setSelection(0); + mSecond.setSelection(0); + return true; + } + + @OnClick(R.id.label) + void openEditLabelDialog() { + // TODO: Show the edit label alert dialog. + } + + public final EditText getFocusedField() { + return (EditText) mAppBar.findFocus(); + } } diff --git a/app/src/main/res/layout/activity_edit_timer.xml b/app/src/main/res/layout/activity_edit_timer.xml index c77b634..0f5482f 100644 --- a/app/src/main/res/layout/activity_edit_timer.xml +++ b/app/src/main/res/layout/activity_edit_timer.xml @@ -1,153 +1,140 @@ - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -