New update and delete callbacks for OnListItemInteractionListener

This commit is contained in:
Phillip Hsu 2016-08-01 01:18:44 -07:00
parent 9561388425
commit 5ac5b34640
8 changed files with 76 additions and 20 deletions

View File

@ -14,4 +14,5 @@ package com.philliphsu.clock2;
public interface OnListItemInteractionListener<T> {
void onListItemClick(T item, int position);
void onListItemDeleted(T item);
void onListItemUpdate(T item, int position);
}

View File

@ -84,7 +84,6 @@ public abstract class RecyclerViewFragment<
*/
@Override
protected int contentLayout() {
// TODO: Rename to fragment_recycler_view
return R.layout.fragment_alarms;
return R.layout.fragment_recycler_view;
}
}

View File

@ -26,13 +26,15 @@ public class AlarmsFragment extends RecyclerViewFragment<
Alarm,
BaseAlarmViewHolder,
AlarmCursor,
AlarmsCursorAdapter> implements ScrollHandler {
AlarmsCursorAdapter> implements ScrollHandler { // TODO: Move interface to base class
private static final String TAG = "AlarmsFragment";
private static final int REQUEST_EDIT_ALARM = 0;
// Public because MainActivity needs to use it.
// TODO: private because we handle fab clicks in the fragment now
public static final int REQUEST_CREATE_ALARM = 1;
// private AlarmsCursorAdapter mAdapter;
// TODO: Since we only use this in onActivityResult(), we also don't need this anymore.
private AsyncItemChangeHandler mAsyncItemChangeHandler;
private AlarmController mAlarmController;
private Handler mHandler = new Handler();
@ -91,6 +93,7 @@ public class AlarmsFragment extends RecyclerViewFragment<
super.onLoadFinished(loader, data);
// This may have been a requery due to content change. If the change
// was an insertion, scroll to the last modified alarm.
// TODO: If the change was an update, this presents a problem.
performScrollToStableId();
}
@ -109,6 +112,8 @@ public class AlarmsFragment extends RecyclerViewFragment<
return new AlarmsCursorAdapter(this, mAlarmController);
}
// TODO: We're not using EditAlarmActivity anymore, so move this logic somewhere else.
// We also don't need to delay the change to get animations working.
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(TAG, "onActivityResult()");
@ -160,6 +165,26 @@ public class AlarmsFragment extends RecyclerViewFragment<
}
}
@Override
// TODO: Rename to onListItem***Delete*** because the item hasn't been deleted from our db yet
public void onListItemDeleted(final Alarm item) {
// The corresponding VH will be automatically removed from view following
// the requery, so we don't have to do anything to it.
mAsyncItemChangeHandler.asyncDelete(item);
}
@Override
public void onListItemUpdate(Alarm item, int position) {
// Once we update the relevant row in the db table, the VH will still
// be in view. While the requery will probably update the values displayed
// by the VH, the VH remains in its expanded state from before we were
// called. Tell the adapter reset its expanded position.
// TODO: Implement editing in the expanded VH. Then verify that changes
// while in that VH are saved and updated after the requery.
// getAdapter().collapse(position);
mAsyncItemChangeHandler.asyncUpdate(item.getId(), item);
}
@Override
public void setScrollToStableId(long id) {
mScrollToStableId = id;
@ -181,21 +206,20 @@ public class AlarmsFragment extends RecyclerViewFragment<
}
if (position >= 0) {
scrollToPosition(position);
// We were called because of a requery due to an insertion.
getAdapter().expand(position);
// We were called because of a requery. If it was due to an insertion,
// expand the newly added alarm.
boolean expanded = getAdapter().expand(position);
if (!expanded) {
// Otherwise, it was due to an item update. The VH is expanded
// at this point, so reset it.
getAdapter().collapse(position);
}
}
}
// Reset
mScrollToStableId = RecyclerView.NO_ID;
}
@Deprecated
@Override
public void onListItemDeleted(final Alarm item) {
// TODO: This doesn't need to be defined in the interface.
// TODO: Delete this method.
}
private static abstract class BaseAsyncItemChangeRunnable {
// TODO: Will holding onto this cause a memory leak?
private final AsyncItemChangeHandler mAsyncItemChangeHandler;

View File

@ -38,6 +38,7 @@ public class CollapsedAlarmViewHolder extends BaseAlarmViewHolder implements Ala
@Override
public void onBind(Alarm alarm) {
super.onBind(alarm);
// TOneverDO: do custom binding before super call, or else NPEs.
bindCountdown(alarm.isEnabled(), alarm.ringsIn());
bindDays(alarm);
}
@ -62,7 +63,14 @@ public class CollapsedAlarmViewHolder extends BaseAlarmViewHolder implements Ala
protected void bindLabel(boolean visible, String label) {
// Should also be visible even if label has zero length so mCountdown is properly positioned
// next to mLabel. That is, mCountdown's layout position is dependent on mLabel being present.
super.bindLabel(visible || mCountdown.getVisibility() == VISIBLE, label);
// The countdown is visible if the alarm is enabled. We must keep this invariant in sync
// with our bindCountdown() logic. If we test against the
// visibility of the countdown view itself, we will find it is always visible
// at this point, because bindCountdown() has not been called yet. As such, that is
// not a valid solution. We unfortunately
// cannot change the order of the view binding done in onBind().
super.bindLabel(visible || getAlarm().isEnabled(), label);
}
private void bindDays(Alarm alarm) {

View File

@ -2,6 +2,7 @@ package com.philliphsu.clock2.alarms;
import android.media.RingtoneManager;
import android.net.Uri;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
@ -29,9 +30,23 @@ public class ExpandedAlarmViewHolder extends BaseAlarmViewHolder {
@Bind({R.id.day0, R.id.day1, R.id.day2, R.id.day3, R.id.day4, R.id.day5, R.id.day6})
ToggleButton[] mDays;
public ExpandedAlarmViewHolder(ViewGroup parent, OnListItemInteractionListener<Alarm> listener,
public ExpandedAlarmViewHolder(ViewGroup parent, final OnListItemInteractionListener<Alarm> listener,
AlarmController controller) {
super(parent, R.layout.item_expanded_alarm, listener, controller);
// Manually bind listeners, or else you'd need to write a getter for the
// OnListItemInteractionListener in the BaseViewHolder for use in method binding.
mDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.onListItemDeleted(getAlarm());
}
});
mSave.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.onListItemUpdate(getAlarm(), getAdapterPosition());
}
});
}
@Override
@ -52,10 +67,10 @@ public class ExpandedAlarmViewHolder extends BaseAlarmViewHolder {
// TODO
}
@OnClick(R.id.delete)
void delete() {
// TODO
}
// @OnClick(R.id.delete)
// void delete() {
// // TODO
// }
@OnClick(R.id.ringtone)
void showRingtonePickerDialog() {

View File

@ -54,4 +54,9 @@ public class TimersFragment extends RecyclerViewFragment<
public void onListItemDeleted(Timer item) {
}
@Override
public void onListItemUpdate(Timer item, int position) {
}
}

View File

@ -9,13 +9,17 @@
-->
<!-- TODO: Write a layout for v21 that instead uses the elevation attribute normally.
- You may have to set a non-transparent background on the main view.
- Alternatively, just keep the CardView because that takes care of the non-transparent
- background issue for free.
-->
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:cardElevation="2dp"
app:cardCornerRadius="0dp">
app:cardCornerRadius="0dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp">
<LinearLayout
android:layout_width="match_parent"