Show alarm set icon in status bar
This commit is contained in:
parent
d171ac9536
commit
c6cfe57e5d
@ -267,7 +267,7 @@ public class MainActivity extends BaseActivity {
|
||||
public Fragment getItem(int position) {
|
||||
switch (position) {
|
||||
case PAGE_ALARMS:
|
||||
return AlarmsFragment.newInstance(1);
|
||||
return new AlarmsFragment();
|
||||
case PAGE_TIMERS:
|
||||
return new TimersFragment();
|
||||
case PAGE_STOPWATCH:
|
||||
|
||||
@ -4,12 +4,15 @@ import android.app.AlarmManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
import com.philliphsu.clock2.MainActivity;
|
||||
import com.philliphsu.clock2.R;
|
||||
import com.philliphsu.clock2.alarms.Alarm;
|
||||
import com.philliphsu.clock2.alarms.ui.AlarmsFragment;
|
||||
import com.philliphsu.clock2.ringtone.AlarmActivity;
|
||||
import com.philliphsu.clock2.ringtone.playback.AlarmRingtoneService;
|
||||
import com.philliphsu.clock2.alarms.background.PendingAlarmScheduler;
|
||||
@ -53,46 +56,56 @@ public final class AlarmController {
|
||||
* Schedules the alarm with the {@link AlarmManager}.
|
||||
* If {@code alarm.}{@link Alarm#isEnabled() isEnabled()}
|
||||
* returns false, this does nothing and returns immediately.
|
||||
*
|
||||
* If there is already an alarm for this Intent scheduled (with the equality of two
|
||||
* intents being defined by filterEquals(Intent)), then it will be removed and replaced
|
||||
* by this one. For most of our uses, the relevant criteria for equality will be the
|
||||
* action, the data, and the class (component). Although not documented, the request code
|
||||
* of a PendingIntent is also considered to determine equality of two intents.
|
||||
*/
|
||||
public void scheduleAlarm(Alarm alarm, boolean showSnackbar) {
|
||||
if (!alarm.isEnabled()) {
|
||||
Log.i(TAG, "Skipped scheduling an alarm because it was not enabled");
|
||||
return;
|
||||
}
|
||||
|
||||
// Does nothing if it's not posted. This is primarily here for when alarms
|
||||
// are updated, instead of newly created, so that we don't leave behind
|
||||
// stray upcoming alarm notifications. This occurs e.g. when a single-use
|
||||
// alarm is updated to recur on a weekday later than the current day.
|
||||
removeUpcomingAlarmNotification(alarm);
|
||||
|
||||
Log.d(TAG, "Scheduling alarm " + alarm);
|
||||
AlarmManager am = (AlarmManager) mAppContext.getSystemService(Context.ALARM_SERVICE);
|
||||
// If there is already an alarm for this Intent scheduled (with the equality of two
|
||||
// intents being defined by filterEquals(Intent)), then it will be removed and replaced
|
||||
// by this one. For most of our uses, the relevant criteria for equality will be the
|
||||
// action, the data, and the class (component). Although not documented, the request code
|
||||
// of a PendingIntent is also considered to determine equality of two intents.
|
||||
|
||||
// WAKEUP alarm types wake the CPU up, but NOT the screen. If that is what you want, you need
|
||||
// to handle that yourself by using a wakelock, etc..
|
||||
// We use a WAKEUP alarm to send the upcoming alarm notification so it goes off even if the
|
||||
// device is asleep. Otherwise, it will not go off until the device is turned back on.
|
||||
final long ringAt = alarm.isSnoozed() ? alarm.snoozingUntil() : alarm.ringsAt();
|
||||
am.setExact(AlarmManager.RTC_WAKEUP, ringAt, alarmIntent(alarm, false));
|
||||
final PendingIntent alarmIntent = alarmIntent(alarm, false);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
Intent viewAlarm = new Intent(mAppContext, MainActivity.class);
|
||||
viewAlarm.putExtra(AlarmsFragment.EXTRA_SCROLL_TO_ALARM_ID, alarm.getId());
|
||||
PendingIntent showIntent = PendingIntent.getActivity(mAppContext,
|
||||
alarm.getIntId(), viewAlarm, FLAG_CANCEL_CURRENT);
|
||||
AlarmManager.AlarmClockInfo info = new AlarmManager.AlarmClockInfo(ringAt, showIntent);
|
||||
am.setAlarmClock(info, alarmIntent);
|
||||
} else {
|
||||
// WAKEUP alarm types wake the CPU up, but NOT the screen;
|
||||
// you would handle that yourself by using a wakelock, etc..
|
||||
am.setExact(AlarmManager.RTC_WAKEUP, ringAt, alarmIntent);
|
||||
// Show alarm in the status bar
|
||||
Intent alarmChanged = new Intent("android.intent.action.ALARM_CHANGED");
|
||||
alarmChanged.putExtra("alarmSet", true/*enabled*/);
|
||||
mAppContext.sendBroadcast(alarmChanged);
|
||||
}
|
||||
|
||||
final int hoursToNotifyInAdvance = AlarmPreferences.hoursBeforeUpcoming(mAppContext);
|
||||
if (hoursToNotifyInAdvance > 0 || alarm.isSnoozed()) {
|
||||
// If snoozed, upcoming note posted immediately.
|
||||
long upcomingAt = ringAt - HOURS.toMillis(hoursToNotifyInAdvance);
|
||||
// We use a WAKEUP alarm to send the upcoming alarm notification so it goes off even if the
|
||||
// device is asleep. Otherwise, it will not go off until the device is turned back on.
|
||||
am.set(AlarmManager.RTC_WAKEUP, upcomingAt, notifyUpcomingAlarmIntent(alarm, false));
|
||||
}
|
||||
|
||||
if (showSnackbar) {
|
||||
String message = mAppContext.getString(R.string.alarm_set_for,
|
||||
DurationUtils.toString(mAppContext, alarm.ringsIn(), false /*abbreviate?*/));
|
||||
// TODO: Consider adding delay to allow the alarm item animation
|
||||
// to finish first before we show the snackbar. Inbox app does this.
|
||||
DurationUtils.toString(mAppContext, alarm.ringsIn(), false/*abbreviate*/));
|
||||
showSnackbar(message);
|
||||
}
|
||||
}
|
||||
@ -104,7 +117,6 @@ public final class AlarmController {
|
||||
* and is enabled.
|
||||
*/
|
||||
public void cancelAlarm(Alarm alarm, boolean showSnackbar, boolean rescheduleIfRecurring) {
|
||||
// TODO: Consider doing this in a new thread.
|
||||
Log.d(TAG, "Cancelling alarm " + alarm);
|
||||
AlarmManager am = (AlarmManager) mAppContext.getSystemService(Context.ALARM_SERVICE);
|
||||
|
||||
@ -112,6 +124,12 @@ public final class AlarmController {
|
||||
if (pi != null) {
|
||||
am.cancel(pi);
|
||||
pi.cancel();
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
// Remove alarm in the status bar
|
||||
Intent alarmChanged = new Intent("android.intent.action.ALARM_CHANGED");
|
||||
alarmChanged.putExtra("alarmSet", false/*enabled*/);
|
||||
mAppContext.sendBroadcast(alarmChanged);
|
||||
}
|
||||
}
|
||||
|
||||
pi = notifyUpcomingAlarmIntent(alarm, true);
|
||||
@ -124,6 +142,7 @@ public final class AlarmController {
|
||||
removeUpcomingAlarmNotification(alarm);
|
||||
|
||||
final int hoursToNotifyInAdvance = AlarmPreferences.hoursBeforeUpcoming(mAppContext);
|
||||
// ------------------------------------------------------------------------------------
|
||||
// TOneverDO: Place block after making value changes to the alarm.
|
||||
if ((hoursToNotifyInAdvance > 0 && showSnackbar
|
||||
// TODO: Consider showing the snackbar for non-upcoming alarms too;
|
||||
@ -134,6 +153,7 @@ public final class AlarmController {
|
||||
formatTime(mAppContext, time));
|
||||
showSnackbar(msg);
|
||||
}
|
||||
// ------------------------------------------------------------------------------------
|
||||
|
||||
if (alarm.isSnoozed()) {
|
||||
alarm.stopSnoozing();
|
||||
@ -195,40 +215,24 @@ public final class AlarmController {
|
||||
}
|
||||
|
||||
private PendingIntent alarmIntent(Alarm alarm, boolean retrievePrevious) {
|
||||
// TODO: Use appropriate subclass instead
|
||||
Intent intent = new Intent(mAppContext, AlarmActivity.class)
|
||||
.putExtra(AlarmActivity.EXTRA_RINGING_OBJECT, alarm);
|
||||
int flag = retrievePrevious ? FLAG_NO_CREATE : FLAG_CANCEL_CURRENT;
|
||||
PendingIntent pi = getActivity(mAppContext, alarm.getIntId(), intent, flag);
|
||||
// Even when we try to retrieve a previous instance that actually did exist,
|
||||
// null can be returned for some reason.
|
||||
/*
|
||||
if (retrievePrevious) {
|
||||
checkNotNull(pi);
|
||||
}
|
||||
*/
|
||||
return pi;
|
||||
// null can be returned for some reason. Thus, we don't checkNotNull().
|
||||
return getActivity(mAppContext, alarm.getIntId(), intent, flag);
|
||||
}
|
||||
|
||||
private PendingIntent notifyUpcomingAlarmIntent(Alarm alarm, boolean retrievePrevious) {
|
||||
Intent intent = new Intent(mAppContext, UpcomingAlarmReceiver.class)
|
||||
.putExtra(UpcomingAlarmReceiver.EXTRA_ALARM, alarm);
|
||||
if (alarm.isSnoozed()) {
|
||||
// TODO: Will this affect retrieving a previous instance? Say if the previous instance
|
||||
// didn't have this action set initially, but at a later time we made a new instance
|
||||
// with it set.
|
||||
intent.setAction(UpcomingAlarmReceiver.ACTION_SHOW_SNOOZING);
|
||||
}
|
||||
int flag = retrievePrevious ? FLAG_NO_CREATE : FLAG_CANCEL_CURRENT;
|
||||
PendingIntent pi = PendingIntent.getBroadcast(mAppContext, alarm.getIntId(), intent, flag);
|
||||
// Even when we try to retrieve a previous instance that actually did exist,
|
||||
// null can be returned for some reason.
|
||||
/*
|
||||
if (retrievePrevious) {
|
||||
checkNotNull(pi);
|
||||
}
|
||||
*/
|
||||
return pi;
|
||||
// null can be returned for some reason. Thus, we don't checkNotNull().
|
||||
return PendingIntent.getBroadcast(mAppContext, alarm.getIntId(), intent, flag);
|
||||
}
|
||||
|
||||
private void showSnackbar(final String message) {
|
||||
|
||||
@ -1,28 +1,22 @@
|
||||
package com.philliphsu.clock2.alarms.ui;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.media.RingtoneManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.philliphsu.clock2.R;
|
||||
import com.philliphsu.clock2.list.RecyclerViewFragment;
|
||||
import com.philliphsu.clock2.dialogs.TimePickerDialogController;
|
||||
import com.philliphsu.clock2.alarms.Alarm;
|
||||
import com.philliphsu.clock2.alarms.data.AlarmCursor;
|
||||
import com.philliphsu.clock2.alarms.data.AlarmsListCursorLoader;
|
||||
import com.philliphsu.clock2.alarms.data.AsyncAlarmsTableUpdateHandler;
|
||||
import com.philliphsu.clock2.alarms.misc.AlarmController;
|
||||
import com.philliphsu.clock2.dialogs.TimePickerDialogController;
|
||||
import com.philliphsu.clock2.list.RecyclerViewFragment;
|
||||
import com.philliphsu.clock2.timepickers.BaseTimePickerDialog;
|
||||
import com.philliphsu.clock2.alarms.data.AlarmCursor;
|
||||
import com.philliphsu.clock2.util.DelayedSnackbarHandler;
|
||||
|
||||
import static com.philliphsu.clock2.util.FragmentTagUtils.makeTag;
|
||||
@ -30,54 +24,19 @@ import static com.philliphsu.clock2.util.FragmentTagUtils.makeTag;
|
||||
public class AlarmsFragment extends RecyclerViewFragment<Alarm, BaseAlarmViewHolder, AlarmCursor,
|
||||
AlarmsCursorAdapter> implements BaseTimePickerDialog.OnTimeSetListener {
|
||||
private static final String TAG = "AlarmsFragment";
|
||||
|
||||
private static final String KEY_EXPANDED_POSITION = "expanded_position";
|
||||
|
||||
// TODO: Delete these constants. We no longer use EditAlarmActivity.
|
||||
// @Deprecated
|
||||
// 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
|
||||
// @Deprecated
|
||||
// public static final int REQUEST_CREATE_ALARM = 1;
|
||||
|
||||
// TODO: Delete this. We no longer use the system's ringtone picker.
|
||||
public static final int REQUEST_PICK_RINGTONE = 1;
|
||||
public static final String EXTRA_SCROLL_TO_ALARM_ID = "com.philliphsu.clock2.alarms.extra.SCROLL_TO_ALARM_ID";
|
||||
|
||||
private AsyncAlarmsTableUpdateHandler mAsyncUpdateHandler;
|
||||
private AlarmController mAlarmController;
|
||||
// TODO: Delete this. If I recall correctly, this was just used for delaying item animations.
|
||||
private Handler mHandler = new Handler();
|
||||
private View mSnackbarAnchor;
|
||||
private TimePickerDialogController mTimePickerDialogController;
|
||||
|
||||
private int mExpandedPosition = RecyclerView.NO_POSITION;
|
||||
|
||||
/**
|
||||
* Mandatory empty constructor for the fragment manager to instantiate the
|
||||
* fragment (e.g. upon screen orientation changes).
|
||||
*/
|
||||
public AlarmsFragment() {}
|
||||
|
||||
// TODO: Customize parameter initialization
|
||||
@SuppressWarnings("unused")
|
||||
public static AlarmsFragment newInstance(int columnCount) {
|
||||
AlarmsFragment fragment = new AlarmsFragment();
|
||||
Bundle args = new Bundle();
|
||||
// TODO Put any arguments in bundle
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
if (getArguments() != null) {
|
||||
// TODO Read arguments
|
||||
}
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
// Restore the value of the last expanded position here.
|
||||
// We cannot tell the adapter to expand this item until onLoadFinished()
|
||||
@ -144,61 +103,8 @@ public class AlarmsFragment extends RecyclerViewFragment<Alarm, BaseAlarmViewHol
|
||||
return R.string.empty_alarms_container;
|
||||
}
|
||||
|
||||
// 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()");
|
||||
if (resultCode != Activity.RESULT_OK || data == null)
|
||||
return;
|
||||
if (requestCode == REQUEST_PICK_RINGTONE) {
|
||||
Uri uri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
|
||||
Log.d(TAG, "Retrieved ringtone URI: " + uri);
|
||||
// TODO: We'll have to create a new Alarm instance with this ringtone value
|
||||
// because we don't have a setter method. Alternatively, write an independent
|
||||
// SQL update statement updating COLUMN_RINGTONE.
|
||||
}
|
||||
|
||||
// final Alarm alarm = data.getParcelableExtra(EditAlarmActivity.EXTRA_MODIFIED_ALARM);
|
||||
// if (alarm == null)
|
||||
// return;
|
||||
//
|
||||
// // http://stackoverflow.com/a/27055512/5055032
|
||||
// // "RecyclerView does not run animations in the first layout
|
||||
// // pass after being attached." A workaround is to postpone
|
||||
// // the CRUD operation to the next frame. A delay of 300ms is
|
||||
// // short enough to not be noticeable, and long enough to
|
||||
// // give us the animation *most of the time*.
|
||||
// switch (requestCode) {
|
||||
// case REQUEST_CREATE_ALARM:
|
||||
// mHandler.postDelayed(
|
||||
// new AsyncAddItemRunnable(mAsyncUpdateHandler, alarm),
|
||||
// 300);
|
||||
// break;
|
||||
// case REQUEST_EDIT_ALARM:
|
||||
// if (data.getBooleanExtra(EditAlarmActivity.EXTRA_IS_DELETING, false)) {
|
||||
// // TODO: Should we delay this too? It seems animations run
|
||||
// // some of the time.
|
||||
// mAsyncUpdateHandler.asyncDelete(alarm);
|
||||
// } else {
|
||||
// // TODO: Increase the delay, because update animation is
|
||||
// // more elusive than insert.
|
||||
// mHandler.postDelayed(
|
||||
// new AsyncUpdateItemRunnable(mAsyncUpdateHandler, alarm),
|
||||
// 300);
|
||||
// }
|
||||
// break;
|
||||
// default:
|
||||
// Log.i(TAG, "Could not handle request code " + requestCode);
|
||||
// break;
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onListItemClick(Alarm item, int position) {
|
||||
// Intent intent = new Intent(getActivity(), EditAlarmActivity.class);
|
||||
// intent.putExtra(EditAlarmActivity.EXTRA_ALARM_ID, item.id());
|
||||
// startActivityForResult(intent, REQUEST_EDIT_ALARM);
|
||||
boolean expanded = getAdapter().expand(position);
|
||||
if (!expanded) {
|
||||
getAdapter().collapse(position);
|
||||
@ -210,7 +116,6 @@ public class AlarmsFragment extends RecyclerViewFragment<Alarm, BaseAlarmViewHol
|
||||
// to the AlarmsCursorAdapter and call these on the save and delete button click bindings.
|
||||
|
||||
@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.
|
||||
@ -223,9 +128,6 @@ public class AlarmsFragment extends RecyclerViewFragment<Alarm, BaseAlarmViewHol
|
||||
// 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);
|
||||
mAsyncUpdateHandler.asyncUpdate(item.getId(), item);
|
||||
}
|
||||
|
||||
@ -233,8 +135,6 @@ public class AlarmsFragment extends RecyclerViewFragment<Alarm, BaseAlarmViewHol
|
||||
|
||||
@Override
|
||||
protected void onScrolledToStableId(long id, int 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
|
||||
@ -300,65 +200,4 @@ public class AlarmsFragment extends RecyclerViewFragment<Alarm, BaseAlarmViewHol
|
||||
private static String makeTimePickerDialogTag() {
|
||||
return makeTag(AlarmsFragment.class, R.id.fab);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// TODO: We won't need these anymore, since we won't handle the db
|
||||
// update in onActivityResult() anymore.
|
||||
|
||||
@Deprecated
|
||||
private static abstract class BaseAsyncItemChangeRunnable {
|
||||
// TODO: Will holding onto this cause a memory leak?
|
||||
private final AsyncAlarmsTableUpdateHandler mAsyncAlarmsTableUpdateHandler;
|
||||
private final Alarm mAlarm;
|
||||
|
||||
BaseAsyncItemChangeRunnable(AsyncAlarmsTableUpdateHandler asyncAlarmsTableUpdateHandler, Alarm alarm) {
|
||||
mAsyncAlarmsTableUpdateHandler = asyncAlarmsTableUpdateHandler;
|
||||
mAlarm = alarm;
|
||||
}
|
||||
|
||||
void asyncAddAlarm() {
|
||||
mAsyncAlarmsTableUpdateHandler.asyncInsert(mAlarm);
|
||||
}
|
||||
|
||||
void asyncUpdateAlarm() {
|
||||
mAsyncAlarmsTableUpdateHandler.asyncUpdate(mAlarm.getId(), mAlarm);
|
||||
}
|
||||
|
||||
void asyncRemoveAlarm() {
|
||||
mAsyncAlarmsTableUpdateHandler.asyncDelete(mAlarm);
|
||||
}
|
||||
}
|
||||
|
||||
private static class AsyncAddItemRunnable extends BaseAsyncItemChangeRunnable implements Runnable {
|
||||
AsyncAddItemRunnable(AsyncAlarmsTableUpdateHandler asyncAlarmsTableUpdateHandler, Alarm alarm) {
|
||||
super(asyncAlarmsTableUpdateHandler, alarm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
asyncAddAlarm();
|
||||
}
|
||||
}
|
||||
|
||||
private static class AsyncUpdateItemRunnable extends BaseAsyncItemChangeRunnable implements Runnable {
|
||||
AsyncUpdateItemRunnable(AsyncAlarmsTableUpdateHandler asyncAlarmsTableUpdateHandler, Alarm alarm) {
|
||||
super(asyncAlarmsTableUpdateHandler, alarm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
asyncUpdateAlarm();
|
||||
}
|
||||
}
|
||||
|
||||
private static class AsyncRemoveItemRunnable extends BaseAsyncItemChangeRunnable implements Runnable {
|
||||
AsyncRemoveItemRunnable(AsyncAlarmsTableUpdateHandler asyncAlarmsTableUpdateHandler, Alarm alarm) {
|
||||
super(asyncAlarmsTableUpdateHandler, alarm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
asyncRemoveAlarm();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,7 +140,8 @@ public abstract class RecyclerViewFragment<
|
||||
}
|
||||
// This may have been a requery due to content change. If the change
|
||||
// was an insertion, scroll to the last modified alarm.
|
||||
performScrollToStableId();
|
||||
performScrollToStableId(mScrollToStableId);
|
||||
mScrollToStableId = RecyclerView.NO_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -167,21 +168,19 @@ public abstract class RecyclerViewFragment<
|
||||
mList.smoothScrollToPosition(position);
|
||||
}
|
||||
|
||||
private void performScrollToStableId() {
|
||||
if (mScrollToStableId != RecyclerView.NO_ID) {
|
||||
protected final void performScrollToStableId(long stableId) {
|
||||
if (stableId != RecyclerView.NO_ID) {
|
||||
int position = -1;
|
||||
for (int i = 0; i < mAdapter.getItemCount(); i++) {
|
||||
if (mAdapter.getItemId(i) == mScrollToStableId) {
|
||||
if (mAdapter.getItemId(i) == stableId) {
|
||||
position = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (position >= 0) {
|
||||
scrollToPosition(position);
|
||||
onScrolledToStableId(mScrollToStableId, position);
|
||||
onScrolledToStableId(stableId, position);
|
||||
}
|
||||
}
|
||||
// Reset
|
||||
mScrollToStableId = RecyclerView.NO_ID;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user