Skip to content

Commit 52da748

Browse files
author
Sira Lam
committed
Solved a bug where getSelectinIndicatorPosition() is returning wrong value
1 parent ab60f24 commit 52da748

File tree

7 files changed

+99
-43
lines changed

7 files changed

+99
-43
lines changed

README.md

+20-2
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,6 @@ And here is an example using [PageIndicatorView](https://github.com/romandanylyk
174174
viewPager.setIndicatorPageChangeListener(new LoopingViewPager.IndicatorPageChangeListener() {
175175
@Override
176176
public void onIndicatorProgress(int selectingPosition, float progress) {
177-
indicatorView.setProgress(selectingPosition, progress);
178177
}
179178

180179
@Override
@@ -192,7 +191,26 @@ indicatorView.setCount(viewPager.getIndicatorCount());
192191

193192
By implementing this way, you can basically use any indicators you like, as long as that indicator allows you to configure programmatically (1) The number of indicators; (2) Which indicator is selected. And even, if it supports, (3) The progress of indicator transition effect.
194193

195-
**P.S.** However, due to [this bug of PageIndicatorView](https://github.com/romandanylyk/PageIndicatorView/issues/51), the transition effect on indicators cannot be shown until the author release [his fix in development branch](https://github.com/romandanylyk/PageIndicatorView/commit/3df8093276afa1e4d1f477444df3a20ce801a235).
194+
### Wait, if you want interactive indicator transition effect, please read this section
195+
196+
However, due to [this bug of PageIndicatorView](https://github.com/romandanylyk/PageIndicatorView/issues), the interactive transition effect on indicators cannot work properly.
197+
198+
LoopingViewPager will trigger `onIndicatorProgress()` when scroll state of `LoopingViewPager` is `SCROLL_STATE_DRAGGING`.
199+
It will not trigger `onIndicatorProgress()` if scroll state is `SCROLL_STATE_SETTLING`.
200+
In fact, when user releases his finger during swiping (where scroll state changes from `SCROLL_STATE_DRAGGING` to `SCROLL_STATE_SETTLING`), `onPageSelected()` will be called and therefore `onIndicatorPageChange()`.
201+
LoopingViewPager expects the indicator will be able to **finish the animation by itself** after `indicatorView.setSelection()` (Or corresponding method of other libraries).
202+
203+
(In fact, I tried to trigger `onIndicatorProgress()` even when scroll state is `SCROLL_STATE_SETTLING`. At first it seems to work good.
204+
However, I cannot find a way to avoid problems that occur when user swipe fastly, i.e. from `SCROLL_STATE_SETTLING` directly to `SCROLL_STATE_DRAGGING` again **before the next page is selected**. So I decided to let indicator handles this.)
205+
206+
For now, if you use [PageIndicatorView](https://github.com/romandanylyk/PageIndicatorView/), do not call anything in `onIndicatorProgress()`.
207+
If you really want the interactive transition effect during `SCROLL_STATE_DRAGGING`, I would suggest you use another library or implement your own one.
208+
209+
## Release notes
210+
211+
v1.0.1
212+
- Fixed a bug where getSelectingIndicatorPosition() is returning incorrect value.
213+
- Updated README.md according to PageIndicatorView v1.0.0 update.
196214

197215
## License
198216

app/build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ dependencies {
2222
implementation fileTree(include: ['*.jar'], dir: 'libs')
2323
implementation 'com.android.support:appcompat-v7:26.1.0'
2424
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
25-
implementation 'com.romandanylyk:pageindicatorview:0.2.0'
25+
implementation 'com.romandanylyk:pageindicatorview:1.0.0'
2626
testImplementation 'junit:junit:4.12'
2727
androidTestImplementation 'com.android.support.test:runner:1.0.1'
2828
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'

app/src/main/java/com/asksira/loopingviewpagerdemo/MainActivity.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public void onClick(View v) {
4242
viewPager.setIndicatorPageChangeListener(new LoopingViewPager.IndicatorPageChangeListener() {
4343
@Override
4444
public void onIndicatorProgress(int selectingPosition, float progress) {
45-
indicatorView.setProgress(selectingPosition, progress);
45+
// indicatorView.setProgress(selectingPosition, progress);
4646
}
4747

4848
@Override

app/src/main/res/layout/activity_main.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
app:layout_constraintLeft_toLeftOf="parent"
1515
app:layout_constraintRight_toRightOf="parent"
1616
app:isInfinite="true"
17-
app:autoScroll="true"
17+
app:autoScroll="false"
1818
app:scrollInterval="2000"
1919
app:wrap_content="true"/>
2020

loopingviewpager/build.gradle

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ android {
88
defaultConfig {
99
minSdkVersion 14
1010
targetSdkVersion 26
11-
versionCode 1
12-
versionName "1.0"
11+
versionCode 101
12+
versionName "1.0.1"
1313

1414
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
1515

@@ -42,7 +42,7 @@ ext {
4242
siteUrl = 'https://github.com/siralam/LoopingViewPager'
4343
gitUrl = 'https://github.com/siralam/LoopingViewPager.git'
4444

45-
libraryVersion = '1.0.0'
45+
libraryVersion = '1.0.1'
4646

4747
developerId = 'siralam'
4848
developerName = 'Sira Lam'

loopingviewpager/src/main/java/com/asksira/loopingviewpager/LoopingPagerAdapter.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,10 @@ private int getListPosition (int position) {
110110
}
111111

112112
public int getLastItemPosition() {
113-
return itemList == null ? 0 : itemList.size();
113+
if (isInfinite) {
114+
return itemList == null ? 0 : itemList.size();
115+
} else {
116+
return itemList == null ? 0 : itemList.size()-1;
117+
}
114118
}
115119
}

loopingviewpager/src/main/java/com/asksira/loopingviewpager/LoopingViewPager.java

+68-34
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import android.support.v4.view.PagerAdapter;
77
import android.support.v4.view.ViewPager;
88
import android.util.AttributeSet;
9+
import android.util.Log;
910
import android.view.View;
1011

1112
/**
@@ -38,6 +39,7 @@ public void run() {
3839

3940
private IndicatorPageChangeListener indicatorPageChangeListener;
4041

42+
private int scrollState = SCROLL_STATE_IDLE;
4143

4244
public LoopingViewPager(Context context) {
4345
super(context);
@@ -52,6 +54,27 @@ public LoopingViewPager(Context context, AttributeSet attrs) {
5254
isAutoScroll = a.getBoolean(R.styleable.LoopingViewPager_autoScroll, false);
5355
wrapContent = a.getBoolean(R.styleable.LoopingViewPager_wrap_content, true);
5456
interval = a.getInt(R.styleable.LoopingViewPager_scrollInterval, 5000);
57+
setPageTransformer(true, new PageTransformer() {
58+
@Override
59+
public void transformPage(View page, float position) {
60+
boolean isToTheRight;
61+
if (position < -1) {
62+
isToTheRight = true;
63+
} else if (position <= 1) {
64+
return;
65+
} else {
66+
isToTheRight = false;
67+
}
68+
69+
int realPosition = getSelectingIndicatorPosition(isToTheRight);
70+
71+
if (indicatorPageChangeListener != null && scrollState == SCROLL_STATE_DRAGGING) {
72+
indicatorPageChangeListener.onIndicatorProgress(realPosition, Math.abs(position) - 1);
73+
Log.i("indicator", "Progress: " + realPosition + ", " + String.valueOf(Math.abs(position)-1)
74+
+ ", ScrollState: " + scrollState + ", currentPagePosition: " + currentPagePosition);
75+
}
76+
}
77+
});
5578
} finally {
5679
a.recycle();
5780
}
@@ -92,24 +115,24 @@ private int measureHeight(int measureSpec, View view) {
92115
return result;
93116
}
94117

95-
protected void init () {
118+
protected void init() {
96119
addOnPageChangeListener(new OnPageChangeListener() {
97120
@Override
98121
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
99-
int realPosition = getIndicatorPosition(true);
100-
if (indicatorPageChangeListener != null) indicatorPageChangeListener.onIndicatorProgress(realPosition, positionOffset);
101122
}
102123

103124
@Override
104125
public void onPageSelected(int position) {
105126
currentPagePosition = position;
106-
if (indicatorPageChangeListener != null) indicatorPageChangeListener.onIndicatorPageChange(getIndicatorPosition(false));
127+
if (indicatorPageChangeListener != null)
128+
indicatorPageChangeListener.onIndicatorPageChange(getIndicatorPosition());
107129
autoScrollHandler.removeCallbacks(autoScrollRunnable);
108130
autoScrollHandler.postDelayed(autoScrollRunnable, interval);
109131
}
110132

111133
@Override
112134
public void onPageScrollStateChanged(int state) {
135+
scrollState = state;
113136
if (!isInfinite) return;
114137
//Below are code to achieve infinite scroll.
115138
//We silently and immediately flip the item to the first / last.
@@ -121,7 +144,7 @@ public void onPageScrollStateChanged(int state) {
121144
}
122145
int index = getCurrentItem();
123146
if (index == 0) {
124-
setCurrentItem(itemCount-2, false); //Real last item
147+
setCurrentItem(itemCount - 2, false); //Real last item
125148
} else if (index == itemCount - 1) {
126149
setCurrentItem(1, false); //Real first item
127150
}
@@ -137,56 +160,66 @@ public void setAdapter(PagerAdapter adapter) {
137160
if (isInfinite) setCurrentItem(1, false);
138161
}
139162

140-
public void resumeAutoScroll () {
163+
public void resumeAutoScroll() {
141164
autoScrollHandler.postDelayed(autoScrollRunnable, interval);
142165
}
143166

144-
public void pauseAutoScroll () {
167+
public void pauseAutoScroll() {
145168
autoScrollHandler.removeCallbacks(autoScrollRunnable);
146169
}
147170

148171

149172
/**
150173
* A method that helps you integrate a ViewPager Indicator.
151174
* This method returns the expected position (Starting from 0) of indicators.
175+
* This method should be used after currentPagePosition is updated.
152176
*/
153-
public int getIndicatorPosition (boolean notYetSelected) {
154-
if (notYetSelected) { //Selection is in progress. currentPagePosition is not yet updated.
155-
if (!isInfinite) {
156-
return currentPagePosition+1;
177+
public int getIndicatorPosition() {
178+
if (!isInfinite) {
179+
return currentPagePosition;
180+
} else {
181+
if (!(getAdapter() instanceof LoopingPagerAdapter)) return currentPagePosition;
182+
if (currentPagePosition == 0) { //Dummy last item is selected. Indicator should be at the last one
183+
return ((LoopingPagerAdapter) getAdapter()).getListCount()-1;
184+
} else if (currentPagePosition == ((LoopingPagerAdapter) getAdapter()).getLastItemPosition() + 1) {
185+
//Dummy first item is selected. Indicator should be at the first one
186+
return 0;
157187
} else {
158-
if (!(getAdapter() instanceof LoopingPagerAdapter)) return currentPagePosition;
159-
if (currentPagePosition == 1) {
160-
return ((LoopingPagerAdapter)getAdapter()).getLastItemPosition() -1;
161-
} else if (currentPagePosition == ((LoopingPagerAdapter)getAdapter()).getLastItemPosition()) {
162-
return 0;
163-
} else {
164-
return currentPagePosition;
165-
}
188+
return currentPagePosition - 1;
166189
}
167-
} else { //onPageSelectedIsTriggered. Now currentPagePosition has been updated to the new position.
168-
if (!isInfinite) {
169-
return currentPagePosition;
190+
}
191+
}
192+
193+
/**
194+
* A method that helps you integrate a ViewPager Indicator.
195+
* This method returns the expected position (Starting from 0) of indicators.
196+
* This method should be used before currentPagePosition is updated, when user is trying to
197+
* select a different page, i.e. onPageScrolled() is triggered.
198+
*/
199+
public int getSelectingIndicatorPosition (boolean isToTheRight) {
200+
int delta = isToTheRight ? 1 : -1;
201+
if (isInfinite) {
202+
if (!(getAdapter() instanceof LoopingPagerAdapter)) return currentPagePosition + delta;
203+
if (currentPagePosition == 1 && !isToTheRight) { //Special case for first page to last page
204+
return ((LoopingPagerAdapter)getAdapter()).getLastItemPosition() -1;
205+
} else if (currentPagePosition == ((LoopingPagerAdapter)getAdapter()).getLastItemPosition()
206+
&& isToTheRight) { //Special case for last page to first page
207+
return 0;
170208
} else {
171-
if (!(getAdapter() instanceof LoopingPagerAdapter)) return currentPagePosition;
172-
if (currentPagePosition == 0) {
173-
return ((LoopingPagerAdapter)getAdapter()).getLastItemPosition();
174-
} else if (currentPagePosition == ((LoopingPagerAdapter)getAdapter()).getLastItemPosition()+1) {
175-
return 0;
176-
} else {
177-
return currentPagePosition-1;
178-
}
209+
return currentPagePosition + delta - 1;
179210
}
211+
} else {
212+
return currentPagePosition + delta;
180213
}
181214
}
182215

183216
/**
184217
* A method that helps you integrate a ViewPager Indicator.
185218
* This method returns the expected count of indicators.
186219
*/
187-
public int getIndicatorCount () {
220+
public int getIndicatorCount() {
188221
if (getAdapter() instanceof LoopingPagerAdapter) {
189-
return ((LoopingPagerAdapter)getAdapter()).getListCount();
222+
return ((LoopingPagerAdapter) getAdapter()).getListCount();
190223
} else {
191224
return getAdapter().getCount();
192225
}
@@ -195,7 +228,7 @@ public int getIndicatorCount () {
195228

196229
/**
197230
* This function needs to be called if dataSet has changed,
198-
* in order to reset current selected item and currentPagePosition.
231+
* in order to reset current selected item and currentPagePosition and autoPageSelectionLock.
199232
*/
200233
public void reset() {
201234
if (isInfinite) {
@@ -207,12 +240,13 @@ public void reset() {
207240
}
208241
}
209242

210-
public void setIndicatorPageChangeListener (IndicatorPageChangeListener callback) {
243+
public void setIndicatorPageChangeListener(IndicatorPageChangeListener callback) {
211244
this.indicatorPageChangeListener = callback;
212245
}
213246

214247
public interface IndicatorPageChangeListener {
215248
void onIndicatorProgress(int selectingPosition, float progress);
249+
216250
void onIndicatorPageChange(int newIndicatorPosition);
217251
}
218252

0 commit comments

Comments
 (0)