Skip to content

Commit 4c66947

Browse files
author
liujianyue
committed
Stop scroll when window lose focus. fix crashes when adapter content changed
1 parent c238169 commit 4c66947

File tree

1 file changed

+93
-41
lines changed

1 file changed

+93
-41
lines changed

library/src/main/java/me/angeldevil/autoscrollviewpager/AutoScrollViewPager.java

Lines changed: 93 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
package me.angeldevil.autoscrollviewpager;
22

33
import android.content.Context;
4+
import android.database.DataSetObserver;
45
import android.os.Handler;
56
import android.os.Message;
6-
import android.support.v4.view.MotionEventCompat;
77
import android.support.v4.view.PagerAdapter;
88
import android.support.v4.view.ViewPager;
99
import android.util.AttributeSet;
@@ -12,8 +12,9 @@
1212
import android.view.animation.Interpolator;
1313

1414
import java.lang.reflect.Field;
15+
import java.util.LinkedList;
16+
import java.util.List;
1517

16-
// TODO add attr support?
1718
public class AutoScrollViewPager extends ViewPager {
1819

1920
public interface OnPageClickListener {
@@ -25,10 +26,13 @@ public interface OnPageClickListener {
2526

2627
private PagerAdapter wrappedPagerAdapter;
2728
private PagerAdapter wrapperPagerAdapter;
28-
private InnerOnPageChangeListener listener;
29+
private OnPageChangeListener mOnPageChangeListener;
30+
private List<OnPageChangeListener> mOnPageChangeListeners = new LinkedList<>();
2931
private AutoScrollFactorScroller scroller;
3032
private H handler;
3133

34+
private InnerDataSetObserver mObserver = new InnerDataSetObserver();
35+
3236
private boolean autoScroll = false;
3337
private int intervalInMillis;
3438

@@ -65,8 +69,7 @@ public AutoScrollViewPager(Context context, AttributeSet attrs) {
6569
}
6670

6771
private void init() {
68-
listener = new InnerOnPageChangeListener();
69-
super.setOnPageChangeListener(listener);
72+
super.addOnPageChangeListener(new InnerOnPageChangeListener());
7073

7174
handler = new H();
7275
touchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
@@ -75,7 +78,7 @@ private void init() {
7578
@Override
7679
protected void onDetachedFromWindow() {
7780
super.onDetachedFromWindow();
78-
handler.removeMessages(MSG_AUTO_SCROLL);
81+
pauseAutoScroll();
7982
}
8083

8184
public void startAutoScroll() {
@@ -87,14 +90,14 @@ public void startAutoScroll(int intervalInMillis) {
8790
if (getCount() > 1) {
8891
this.intervalInMillis = intervalInMillis;
8992
autoScroll = true;
90-
handler.removeMessages(MSG_AUTO_SCROLL);
93+
pauseAutoScroll();
9194
handler.sendEmptyMessageDelayed(MSG_AUTO_SCROLL, intervalInMillis);
9295
}
9396
}
9497

9598
public void stopAutoScroll() {
9699
autoScroll = false;
97-
handler.removeMessages(MSG_AUTO_SCROLL);
100+
pauseAutoScroll();
98101
}
99102

100103
public void setInterval(int intervalInMillis) {
@@ -106,14 +109,52 @@ public void setScrollFactgor(double factor) {
106109
scroller.setFactor(factor);
107110
}
108111

112+
public OnPageClickListener getOnPageClickListener() {
113+
return onPageClickListener;
114+
}
115+
116+
public void setOnPageClickListener(OnPageClickListener onPageClickListener) {
117+
this.onPageClickListener = onPageClickListener;
118+
}
119+
120+
@Override
121+
public void onWindowFocusChanged(boolean hasWindowFocus) {
122+
super.onWindowFocusChanged(hasWindowFocus);
123+
if (autoScroll) {
124+
if (hasWindowFocus) {
125+
startAutoScroll();
126+
} else {
127+
pauseAutoScroll();
128+
}
129+
}
130+
}
131+
132+
@SuppressWarnings("deprecation")
109133
@Override
110134
public void setOnPageChangeListener(OnPageChangeListener listener) {
111-
this.listener.setOnPageChangeListener(listener);
135+
mOnPageChangeListener = listener;
136+
}
137+
138+
@Override
139+
public void addOnPageChangeListener(OnPageChangeListener listener) {
140+
mOnPageChangeListeners.add(listener);
141+
}
142+
143+
@Override
144+
public void clearOnPageChangeListeners() {
145+
super.clearOnPageChangeListeners();
146+
mOnPageChangeListeners.clear();
112147
}
113148

114149
@Override
115150
public void setAdapter(PagerAdapter adapter) {
151+
if (wrappedPagerAdapter != null && mObserver != null) {
152+
wrappedPagerAdapter.unregisterDataSetObserver(mObserver);
153+
}
116154
wrappedPagerAdapter = adapter;
155+
if (wrappedPagerAdapter != null && mObserver != null) {
156+
wrappedPagerAdapter.registerDataSetObserver(mObserver);
157+
}
117158
wrapperPagerAdapter = (wrappedPagerAdapter == null) ? null : new AutoScrollPagerAdapter(adapter);
118159
super.setAdapter(wrapperPagerAdapter);
119160

@@ -158,31 +199,24 @@ public int getCurrentItem() {
158199
return curr;
159200
}
160201

161-
public OnPageClickListener getOnPageClickListener() {
162-
return onPageClickListener;
163-
}
164-
165-
public void setOnPageClickListener(OnPageClickListener onPageClickListener) {
166-
this.onPageClickListener = onPageClickListener;
167-
}
168-
169202
@Override
170203
public boolean onTouchEvent(MotionEvent ev) {
171-
switch (MotionEventCompat.getActionMasked(ev)) {
204+
switch (ev.getActionMasked()) {
172205
case MotionEvent.ACTION_DOWN:
173206
if (getCurrentItemOfWrapper() + 1 == getCountOfWrapper()) {
174207
setCurrentItem(0, false);
175208
} else if (getCurrentItemOfWrapper() == 0) {
176209
setCurrentItem(getCount() - 1, false);
177210
}
178-
handler.removeMessages(MSG_AUTO_SCROLL);
211+
pauseAutoScroll();
179212
mInitialMotionX = ev.getX();
180213
mInitialMotionY = ev.getY();
181214
break;
182215
case MotionEvent.ACTION_MOVE:
183216
mLastMotionX = ev.getX();
184217
mLastMotionY = ev.getY();
185-
if ((int) Math.abs(mLastMotionX - mInitialMotionX) > touchSlop || (int) Math.abs(mLastMotionY - mInitialMotionY) > touchSlop) {
218+
if ((int) Math.abs(mLastMotionX - mInitialMotionX) > touchSlop
219+
|| (int) Math.abs(mLastMotionY - mInitialMotionY) > touchSlop) {
186220
mInitialMotionX = 0.0f;
187221
mInitialMotionY = 0.0f;
188222
}
@@ -266,19 +300,14 @@ private void setScrollerIfNeeded() {
266300
}
267301
}
268302

269-
private class InnerOnPageChangeListener implements OnPageChangeListener {
270-
private OnPageChangeListener listener;
271-
private int lastSelectedPage = -1;
272-
273-
public InnerOnPageChangeListener() {
274-
}
303+
private void pauseAutoScroll() {
304+
handler.removeMessages(MSG_AUTO_SCROLL);
305+
}
275306

276-
public InnerOnPageChangeListener(OnPageChangeListener listener) {
277-
setOnPageChangeListener(listener);
278-
}
307+
private class InnerOnPageChangeListener implements OnPageChangeListener {
308+
private int mLastSelectedPage = -1;
279309

280-
public void setOnPageChangeListener(OnPageChangeListener listener) {
281-
this.listener = listener;
310+
private InnerOnPageChangeListener() {
282311
}
283312

284313
@Override
@@ -292,22 +321,27 @@ public void onPageScrollStateChanged(int state) {
292321
setCurrentItem(0, false);
293322
}
294323
}
295-
if (listener != null) {
296-
listener.onPageScrollStateChanged(state);
324+
if (mOnPageChangeListener != null) {
325+
mOnPageChangeListener.onPageScrollStateChanged(state);
326+
}
327+
for (OnPageChangeListener onPageChangeListener : mOnPageChangeListeners) {
328+
onPageChangeListener.onPageScrollStateChanged(state);
297329
}
298330
}
299331

300332
@Override
301333
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
302-
if (listener != null && position > 0 && position < getCount()) {
303-
listener.onPageScrolled(position - 1, positionOffset, positionOffsetPixels);
334+
if (mOnPageChangeListener != null && position > 0 && position < getCount()) {
335+
mOnPageChangeListener.onPageScrolled(position - 1, positionOffset, positionOffsetPixels);
336+
}
337+
for (OnPageChangeListener onPageChangeListener : mOnPageChangeListeners) {
338+
onPageChangeListener.onPageScrolled(position - 1, positionOffset, positionOffsetPixels);
304339
}
305340
}
306341

307342
@Override
308343
public void onPageSelected(final int position) {
309-
// if (listener != null && position != 0 && position < wrappedPagerAdapter.getCount() + 1) {
310-
if (listener != null) {
344+
if (mOnPageChangeListener != null) {
311345
final int pos;
312346
// Fix position
313347
if (position == 0) {
@@ -320,17 +354,35 @@ public void onPageSelected(final int position) {
320354

321355
// Comment this, onPageSelected will be triggered twice for position 0 and getCount -1.
322356
// Uncomment this, PageIndicator will have trouble.
323-
// if (lastSelectedPage != pos) {
324-
lastSelectedPage = pos;
357+
// if (mLastSelectedPage != pos) {
358+
mLastSelectedPage = pos;
325359
// Post a Runnable in order to be compatible with ViewPagerIndicator because
326360
// onPageSelected is invoked before onPageScrollStateChanged.
327361
AutoScrollViewPager.this.post(new Runnable() {
328362
@Override
329363
public void run() {
330-
listener.onPageSelected(pos);
364+
mOnPageChangeListener.onPageSelected(pos);
365+
for (OnPageChangeListener onPageChangeListener : mOnPageChangeListeners) {
366+
onPageChangeListener.onPageSelected(pos);
367+
}
331368
}
332369
});
333-
// }
370+
}
371+
}
372+
}
373+
374+
private class InnerDataSetObserver extends DataSetObserver {
375+
@Override
376+
public void onChanged() {
377+
if (wrapperPagerAdapter != null) {
378+
wrapperPagerAdapter.notifyDataSetChanged();
379+
}
380+
}
381+
382+
@Override
383+
public void onInvalidated() {
384+
if (wrapperPagerAdapter != null) {
385+
wrapperPagerAdapter.notifyDataSetChanged();
334386
}
335387
}
336388
}

0 commit comments

Comments
 (0)