From 4d2ef227b6493fbe48a96eb511e58dcc7b731de9 Mon Sep 17 00:00:00 2001 From: Phillip Hsu Date: Wed, 6 Jul 2016 03:42:45 -0700 Subject: [PATCH] Alarm adding moved back to onActivityResult --- .../clock2/AsyncItemChangeHandler.java | 9 +++- .../clock2/alarms/AlarmsFragment.java | 52 +++++++++++++++++-- .../clock2/alarms/ScrollHandler.java | 15 ++++++ .../clock2/editalarm/EditAlarmActivity.java | 8 +-- 4 files changed, 72 insertions(+), 12 deletions(-) create mode 100644 app/src/main/java/com/philliphsu/clock2/alarms/ScrollHandler.java diff --git a/app/src/main/java/com/philliphsu/clock2/AsyncItemChangeHandler.java b/app/src/main/java/com/philliphsu/clock2/AsyncItemChangeHandler.java index 49b1649..a48e286 100644 --- a/app/src/main/java/com/philliphsu/clock2/AsyncItemChangeHandler.java +++ b/app/src/main/java/com/philliphsu/clock2/AsyncItemChangeHandler.java @@ -5,6 +5,7 @@ import android.os.AsyncTask; import android.support.design.widget.Snackbar; import android.view.View; +import com.philliphsu.clock2.alarms.ScrollHandler; import com.philliphsu.clock2.model.DatabaseManager; import com.philliphsu.clock2.util.AlarmUtils; @@ -14,16 +15,20 @@ import com.philliphsu.clock2.util.AlarmUtils; * TODO: Generify this class for any item. */ public final class AsyncItemChangeHandler { + private static final String TAG = "AsyncItemChangeHandler"; private final Context mContext; private final View mSnackbarAnchor; + private final ScrollHandler mScrollHandler; /** * @param snackbarAnchor an optional anchor for a Snackbar to anchor to + * @param scrollHandler */ - public AsyncItemChangeHandler(Context context, View snackbarAnchor) { + public AsyncItemChangeHandler(Context context, View snackbarAnchor, ScrollHandler scrollHandler) { mContext = context.getApplicationContext(); // to prevent memory leaks mSnackbarAnchor = snackbarAnchor; + mScrollHandler = scrollHandler; } public void asyncAddAlarm(final Alarm alarm) { @@ -38,6 +43,8 @@ public final class AsyncItemChangeHandler { // TODO: Snackbar/Toast here? If so, remove the code in AlarmUtils.scheduleAlarm() that does it. // Then, consider scheduling the alarm in the background. AlarmUtils.scheduleAlarm(mContext, alarm, true); + // Prepare to scroll to the newly added alarm + mScrollHandler.setScrollToStableId(aLong); } }.execute(); } diff --git a/app/src/main/java/com/philliphsu/clock2/alarms/AlarmsFragment.java b/app/src/main/java/com/philliphsu/clock2/alarms/AlarmsFragment.java index 721711f..3e72330 100644 --- a/app/src/main/java/com/philliphsu/clock2/alarms/AlarmsFragment.java +++ b/app/src/main/java/com/philliphsu/clock2/alarms/AlarmsFragment.java @@ -5,6 +5,7 @@ import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.os.Bundle; +import android.os.Handler; import android.support.design.widget.Snackbar; import android.support.v4.app.Fragment; import android.support.v4.app.LoaderManager.LoaderCallbacks; @@ -17,6 +18,7 @@ import android.view.View; import android.view.ViewGroup; import com.philliphsu.clock2.Alarm; +import com.philliphsu.clock2.AsyncItemChangeHandler; import com.philliphsu.clock2.OnListItemInteractionListener; import com.philliphsu.clock2.R; import com.philliphsu.clock2.editalarm.EditAlarmActivity; @@ -30,12 +32,14 @@ import butterknife.ButterKnife; // TODO: Use native fragments since we're targeting API >=19? // TODO: Use native LoaderCallbacks. public class AlarmsFragment extends Fragment implements LoaderCallbacks, - OnListItemInteractionListener { + OnListItemInteractionListener, ScrollHandler { private static final int REQUEST_EDIT_ALARM = 0; public static final int REQUEST_CREATE_ALARM = 1; private static final String TAG = "AlarmsFragment"; private AlarmsCursorAdapter mAdapter; + private AsyncItemChangeHandler mAsyncItemChangeHandler; + private long mScrollToStableId = RecyclerView.NO_ID; @Bind(R.id.list) RecyclerView mList; @@ -77,6 +81,9 @@ public class AlarmsFragment extends Fragment implements LoaderCallbacks, mList.setLayoutManager(new LinearLayoutManager(context)); mAdapter = new AlarmsCursorAdapter(this); mList.setAdapter(mAdapter); + + mAsyncItemChangeHandler = new AsyncItemChangeHandler(getActivity(), + getActivity().findViewById(R.id.main_content), this); return view; } @@ -106,6 +113,8 @@ public class AlarmsFragment extends Fragment implements LoaderCallbacks, @Override public void onLoadFinished(Loader loader, Cursor data) { mAdapter.swapCursor(data); + // Scroll to the last modified alarm + performScrollToStableId(); } @Override @@ -122,9 +131,17 @@ public class AlarmsFragment extends Fragment implements LoaderCallbacks, switch (requestCode) { case REQUEST_CREATE_ALARM: - // TODO: Should we still do the async add here? - // We must if we want the async handler to post the toast/snackbar - // for us. + if (data != null) { + final Alarm createdAlarm = data.getParcelableExtra(EditAlarmActivity.EXTRA_MODIFIED_ALARM); + if (createdAlarm != null) { + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + mAsyncItemChangeHandler.asyncAddAlarm(createdAlarm); + } + }, 300); + } + } break; case REQUEST_EDIT_ALARM: Alarm deletedAlarm; @@ -148,6 +165,33 @@ public class AlarmsFragment extends Fragment implements LoaderCallbacks, startActivityForResult(intent, REQUEST_EDIT_ALARM); } + @Override + public void setScrollToStableId(long id) { + mScrollToStableId = id; + } + + @Override + public void scrollToPosition(int position) { + mList.smoothScrollToPosition(position); + } + + private void performScrollToStableId() { + if (mScrollToStableId != RecyclerView.NO_ID) { + int position = -1; + for (int i = 0; i < mAdapter.getItemCount(); i++) { + if (mAdapter.getItemId(i) == mScrollToStableId) { + position = i; + break; + } + } + if (position >= 0) { + scrollToPosition(position); + } + } + // Reset + mScrollToStableId = RecyclerView.NO_ID; + } + // TODO: This doesn't need to be defined in the interface. // TODO: Rename to showDeletedSnackbar() or something // TODO: This needs to prompt a reload of the list. diff --git a/app/src/main/java/com/philliphsu/clock2/alarms/ScrollHandler.java b/app/src/main/java/com/philliphsu/clock2/alarms/ScrollHandler.java new file mode 100644 index 0000000..6f167f1 --- /dev/null +++ b/app/src/main/java/com/philliphsu/clock2/alarms/ScrollHandler.java @@ -0,0 +1,15 @@ +package com.philliphsu.clock2.alarms; + +/** + * Created by Phillip Hsu on 7/6/2016. + */ +public interface ScrollHandler { + /** + * Specifies the stable id of the item we should scroll to in the list. + * This does not scroll the list. This is useful for preparing to scroll + * to the item when it does not yet exist in the list. + */ + void setScrollToStableId(long id); + + void scrollToPosition(int position); +} diff --git a/app/src/main/java/com/philliphsu/clock2/editalarm/EditAlarmActivity.java b/app/src/main/java/com/philliphsu/clock2/editalarm/EditAlarmActivity.java index 8c2ade1..1427bf1 100644 --- a/app/src/main/java/com/philliphsu/clock2/editalarm/EditAlarmActivity.java +++ b/app/src/main/java/com/philliphsu/clock2/editalarm/EditAlarmActivity.java @@ -26,7 +26,6 @@ import android.widget.Toast; import android.widget.ToggleButton; import com.philliphsu.clock2.Alarm; -import com.philliphsu.clock2.AsyncItemChangeHandler; import com.philliphsu.clock2.BaseActivity; import com.philliphsu.clock2.DaysOfWeek; import com.philliphsu.clock2.R; @@ -69,7 +68,6 @@ public class EditAlarmActivity extends BaseActivity implements AlarmNumpad.KeyLi private Uri mSelectedRingtoneUri; private Alarm mOldAlarm; private DatabaseManager mDatabaseManager; - private AsyncItemChangeHandler mAsyncItemChangeHandler; @Bind(R.id.save) Button mSave; @Bind(R.id.delete) Button mDelete; @@ -100,8 +98,6 @@ public class EditAlarmActivity extends BaseActivity implements AlarmNumpad.KeyLi showDetails(); } setTimeTextHint(); // TODO: private access - - mAsyncItemChangeHandler = new AsyncItemChangeHandler(this, null); } @Override @@ -250,15 +246,13 @@ public class EditAlarmActivity extends BaseActivity implements AlarmNumpad.KeyLi mDatabaseManager.updateAlarm(mOldAlarm.id(), alarm); } else { //mDatabaseManager.insertAlarm(alarm); - mAsyncItemChangeHandler.asyncAddAlarm(alarm); - //intent.putExtra(EXTRA_MODIFIED_ALARM, alarm); + intent.putExtra(EXTRA_MODIFIED_ALARM, alarm); } if (alarm.isEnabled()) { //scheduleAlarm(alarm); } - // TODO: Remove intent setResult(RESULT_OK, intent); showEditorClosed(); }