11package me .angeldevil .autoscrollviewpager ;
22
33import android .content .Context ;
4+ import android .database .DataSetObserver ;
45import android .os .Handler ;
56import android .os .Message ;
6- import android .support .v4 .view .MotionEventCompat ;
77import android .support .v4 .view .PagerAdapter ;
88import android .support .v4 .view .ViewPager ;
99import android .util .AttributeSet ;
1212import android .view .animation .Interpolator ;
1313
1414import java .lang .reflect .Field ;
15+ import java .util .LinkedList ;
16+ import java .util .List ;
1517
16- // TODO add attr support?
1718public 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