New update and delete callbacks for OnListItemInteractionListener
This commit is contained in:
parent
9561388425
commit
5ac5b34640
@ -14,4 +14,5 @@ package com.philliphsu.clock2;
|
|||||||
public interface OnListItemInteractionListener<T> {
|
public interface OnListItemInteractionListener<T> {
|
||||||
void onListItemClick(T item, int position);
|
void onListItemClick(T item, int position);
|
||||||
void onListItemDeleted(T item);
|
void onListItemDeleted(T item);
|
||||||
|
void onListItemUpdate(T item, int position);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -84,7 +84,6 @@ public abstract class RecyclerViewFragment<
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected int contentLayout() {
|
protected int contentLayout() {
|
||||||
// TODO: Rename to fragment_recycler_view
|
return R.layout.fragment_recycler_view;
|
||||||
return R.layout.fragment_alarms;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,13 +26,15 @@ public class AlarmsFragment extends RecyclerViewFragment<
|
|||||||
Alarm,
|
Alarm,
|
||||||
BaseAlarmViewHolder,
|
BaseAlarmViewHolder,
|
||||||
AlarmCursor,
|
AlarmCursor,
|
||||||
AlarmsCursorAdapter> implements ScrollHandler {
|
AlarmsCursorAdapter> implements ScrollHandler { // TODO: Move interface to base class
|
||||||
private static final String TAG = "AlarmsFragment";
|
private static final String TAG = "AlarmsFragment";
|
||||||
private static final int REQUEST_EDIT_ALARM = 0;
|
private static final int REQUEST_EDIT_ALARM = 0;
|
||||||
// Public because MainActivity needs to use it.
|
// 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;
|
public static final int REQUEST_CREATE_ALARM = 1;
|
||||||
|
|
||||||
// private AlarmsCursorAdapter mAdapter;
|
// private AlarmsCursorAdapter mAdapter;
|
||||||
|
// TODO: Since we only use this in onActivityResult(), we also don't need this anymore.
|
||||||
private AsyncItemChangeHandler mAsyncItemChangeHandler;
|
private AsyncItemChangeHandler mAsyncItemChangeHandler;
|
||||||
private AlarmController mAlarmController;
|
private AlarmController mAlarmController;
|
||||||
private Handler mHandler = new Handler();
|
private Handler mHandler = new Handler();
|
||||||
@ -91,6 +93,7 @@ public class AlarmsFragment extends RecyclerViewFragment<
|
|||||||
super.onLoadFinished(loader, data);
|
super.onLoadFinished(loader, data);
|
||||||
// This may have been a requery due to content change. If the change
|
// This may have been a requery due to content change. If the change
|
||||||
// was an insertion, scroll to the last modified alarm.
|
// was an insertion, scroll to the last modified alarm.
|
||||||
|
// TODO: If the change was an update, this presents a problem.
|
||||||
performScrollToStableId();
|
performScrollToStableId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,6 +112,8 @@ public class AlarmsFragment extends RecyclerViewFragment<
|
|||||||
return new AlarmsCursorAdapter(this, mAlarmController);
|
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
|
@Override
|
||||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
Log.d(TAG, "onActivityResult()");
|
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
|
@Override
|
||||||
public void setScrollToStableId(long id) {
|
public void setScrollToStableId(long id) {
|
||||||
mScrollToStableId = id;
|
mScrollToStableId = id;
|
||||||
@ -181,21 +206,20 @@ public class AlarmsFragment extends RecyclerViewFragment<
|
|||||||
}
|
}
|
||||||
if (position >= 0) {
|
if (position >= 0) {
|
||||||
scrollToPosition(position);
|
scrollToPosition(position);
|
||||||
// We were called because of a requery due to an insertion.
|
// We were called because of a requery. If it was due to an insertion,
|
||||||
getAdapter().expand(position);
|
// 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
|
// Reset
|
||||||
mScrollToStableId = RecyclerView.NO_ID;
|
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 {
|
private static abstract class BaseAsyncItemChangeRunnable {
|
||||||
// TODO: Will holding onto this cause a memory leak?
|
// TODO: Will holding onto this cause a memory leak?
|
||||||
private final AsyncItemChangeHandler mAsyncItemChangeHandler;
|
private final AsyncItemChangeHandler mAsyncItemChangeHandler;
|
||||||
|
|||||||
@ -38,6 +38,7 @@ public class CollapsedAlarmViewHolder extends BaseAlarmViewHolder implements Ala
|
|||||||
@Override
|
@Override
|
||||||
public void onBind(Alarm alarm) {
|
public void onBind(Alarm alarm) {
|
||||||
super.onBind(alarm);
|
super.onBind(alarm);
|
||||||
|
// TOneverDO: do custom binding before super call, or else NPEs.
|
||||||
bindCountdown(alarm.isEnabled(), alarm.ringsIn());
|
bindCountdown(alarm.isEnabled(), alarm.ringsIn());
|
||||||
bindDays(alarm);
|
bindDays(alarm);
|
||||||
}
|
}
|
||||||
@ -62,7 +63,14 @@ public class CollapsedAlarmViewHolder extends BaseAlarmViewHolder implements Ala
|
|||||||
protected void bindLabel(boolean visible, String label) {
|
protected void bindLabel(boolean visible, String label) {
|
||||||
// Should also be visible even if label has zero length so mCountdown is properly positioned
|
// 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.
|
// 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) {
|
private void bindDays(Alarm alarm) {
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package com.philliphsu.clock2.alarms;
|
|||||||
|
|
||||||
import android.media.RingtoneManager;
|
import android.media.RingtoneManager;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.CheckBox;
|
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})
|
@Bind({R.id.day0, R.id.day1, R.id.day2, R.id.day3, R.id.day4, R.id.day5, R.id.day6})
|
||||||
ToggleButton[] mDays;
|
ToggleButton[] mDays;
|
||||||
|
|
||||||
public ExpandedAlarmViewHolder(ViewGroup parent, OnListItemInteractionListener<Alarm> listener,
|
public ExpandedAlarmViewHolder(ViewGroup parent, final OnListItemInteractionListener<Alarm> listener,
|
||||||
AlarmController controller) {
|
AlarmController controller) {
|
||||||
super(parent, R.layout.item_expanded_alarm, listener, 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
|
@Override
|
||||||
@ -52,10 +67,10 @@ public class ExpandedAlarmViewHolder extends BaseAlarmViewHolder {
|
|||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnClick(R.id.delete)
|
// @OnClick(R.id.delete)
|
||||||
void delete() {
|
// void delete() {
|
||||||
// TODO
|
// // TODO
|
||||||
}
|
// }
|
||||||
|
|
||||||
@OnClick(R.id.ringtone)
|
@OnClick(R.id.ringtone)
|
||||||
void showRingtonePickerDialog() {
|
void showRingtonePickerDialog() {
|
||||||
|
|||||||
@ -54,4 +54,9 @@ public class TimersFragment extends RecyclerViewFragment<
|
|||||||
public void onListItemDeleted(Timer item) {
|
public void onListItemDeleted(Timer item) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onListItemUpdate(Timer item, int position) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,13 +9,17 @@
|
|||||||
-->
|
-->
|
||||||
<!-- TODO: Write a layout for v21 that instead uses the elevation attribute normally.
|
<!-- 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.
|
- 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"
|
<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_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
app:cardElevation="2dp"
|
app:cardElevation="2dp"
|
||||||
app:cardCornerRadius="0dp">
|
app:cardCornerRadius="0dp"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginBottom="8dp">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user