Skip to content

Commit 803c227

Browse files
Added option to control page scroll speed and interpolator
1 parent a76e350 commit 803c227

File tree

2 files changed

+91
-6
lines changed

2 files changed

+91
-6
lines changed

app/src/main/java/com/heinrichreimersoftware/materialintro/demo/CanteenIntroActivity.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ protected void onCreate(Bundle savedInstanceState) {
2424
label.setSpan(labelSpan, 0, label.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
2525
setButtonCtaLabel(label);
2626

27+
setPagerScrollDuration(800);
28+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
29+
setPagerInterpolator(android.R.interpolator.fast_out_slow_in);
30+
}
31+
2732
addSlide(new SimpleSlide.Builder()
2833
.title(R.string.title_canteen_intro1)
2934
.description(R.string.description_canteen_intro1)

library/src/main/java/com/heinrichreimersoftware/materialintro/app/IntroActivity.java

Lines changed: 86 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package com.heinrichreimersoftware.materialintro.app;
22

3+
import android.animation.Animator;
4+
import android.animation.AnimatorListenerAdapter;
35
import android.animation.ArgbEvaluator;
6+
import android.animation.ValueAnimator;
47
import android.annotation.SuppressLint;
58
import android.app.ActivityManager;
69
import android.content.res.ColorStateList;
@@ -18,6 +21,7 @@
1821
import android.support.annotation.ColorRes;
1922
import android.support.annotation.IntDef;
2023
import android.support.annotation.IntRange;
24+
import android.support.annotation.InterpolatorRes;
2125
import android.support.annotation.NonNull;
2226
import android.support.annotation.StringRes;
2327
import android.support.v4.app.Fragment;
@@ -33,6 +37,8 @@
3337
import android.util.TypedValue;
3438
import android.view.View;
3539
import android.view.WindowManager;
40+
import android.view.animation.AnimationUtils;
41+
import android.view.animation.Interpolator;
3642
import android.widget.Button;
3743
import android.widget.ImageButton;
3844
import android.widget.LinearLayout;
@@ -122,10 +128,16 @@ public class IntroActivity extends AppCompatActivity {
122128
private int autoplayCounter;
123129
private long autoplayDelay;
124130

131+
private Interpolator pagerInterpolator;
132+
private long pagerScrollDuration;
133+
125134
@Override
126135
protected void onCreate(Bundle savedInstanceState) {
127136
super.onCreate(savedInstanceState);
128137

138+
pagerInterpolator = AnimationUtils.loadInterpolator(this, android.R.interpolator.accelerate_decelerate);
139+
pagerScrollDuration = getResources().getInteger(android.R.integer.config_shortAnimTime);
140+
129141
if (savedInstanceState != null) {
130142
if (savedInstanceState.containsKey(KEY_CURRENT_ITEM)) {
131143
position = savedInstanceState.getInt(KEY_CURRENT_ITEM, position);
@@ -254,7 +266,7 @@ private void findViews(){
254266

255267
pager.setAdapter(adapter);
256268
pager.addOnPageChangeListener(listener);
257-
pager.setCurrentItem(position);
269+
pager.setCurrentItem(position, false);
258270

259271
pagerIndicator.setViewPager(pager);
260272

@@ -274,12 +286,60 @@ public void onClick(View v) {
274286
CheatSheet.setup(buttonBack);
275287
}
276288

289+
private void smoothScrollPagerTo(final int position) {
290+
ValueAnimator animator = ValueAnimator.ofFloat(pager.getCurrentItem(), position);
291+
animator.addListener(new AnimatorListenerAdapter() {
292+
@Override
293+
public void onAnimationEnd(Animator animation) {
294+
pager.endFakeDrag();
295+
pager.setCurrentItem(position);
296+
}
297+
298+
@Override
299+
public void onAnimationCancel(Animator animation) {
300+
pager.endFakeDrag();
301+
}
302+
});
303+
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
304+
@Override
305+
public void onAnimationUpdate(ValueAnimator animation) {
306+
float position = (Float) animation.getAnimatedValue();
307+
308+
fakeDragToPosition(position);
309+
}
310+
311+
private boolean fakeDragToPosition(float position) {
312+
// The following mimics the underlying calculations in ViewPager
313+
float scrollX = pager.getScrollX();
314+
int pagerWidth = pager.getWidth();
315+
int currentPosition = pager.getCurrentItem();
316+
317+
if (position > currentPosition && Math.floor(position) != currentPosition && position % 1 != 0) {
318+
pager.setCurrentItem((int) Math.floor(position), false);
319+
}
320+
else if (position < currentPosition && Math.ceil(position) != currentPosition && position % 1 != 0) {
321+
pager.setCurrentItem((int) Math.ceil(position), false);
322+
}
323+
324+
if (!pager.isFakeDragging() && !pager.beginFakeDrag())
325+
return false;
326+
327+
pager.fakeDragBy(scrollX - pagerWidth * position);
328+
return true;
329+
}
330+
});
331+
332+
animator.setInterpolator(pagerInterpolator);
333+
animator.setDuration(pagerScrollDuration);
334+
animator.start();
335+
}
336+
277337
public void nextSlide() {
278338
int currentItem = pager.getCurrentItem();
279339
if (currentItem > adapter.getCount() - 1) finishIfNeeded();
280340

281341
if (canGoForward(currentItem, true)) {
282-
pager.setCurrentItem(++currentItem, true);
342+
smoothScrollPagerTo(++currentItem);
283343
}
284344
else {
285345
AnimUtils.applyShakeAnimation(this, buttonNext);
@@ -308,7 +368,7 @@ else if (canGoForward(endPosition, true)) {
308368
if (endPosition == pager.getCurrentItem())
309369
return false;
310370

311-
pager.setCurrentItem(endPosition);
371+
smoothScrollPagerTo(endPosition);
312372

313373
return autoplayCounter != 0;
314374

@@ -319,7 +379,7 @@ public void previousSlide() {
319379
if (currentItem <= 0) return;
320380

321381
if (canGoBackward(currentItem, true)) {
322-
pager.setCurrentItem(--currentItem, true);
382+
smoothScrollPagerTo(--currentItem);
323383
}
324384
else {
325385
AnimUtils.applyShakeAnimation(this, buttonBack);
@@ -334,7 +394,7 @@ private void performButtonBackPress() {
334394
while (endPosition < count && canGoForward(endPosition, true)) {
335395
endPosition++;
336396
}
337-
pager.setCurrentItem(endPosition);
397+
smoothScrollPagerTo(endPosition);
338398
} else if (buttonBackFunction == BUTTON_BACK_FUNCTION_BACK) {
339399
previousSlide();
340400
}
@@ -768,6 +828,26 @@ public boolean isAutoplaying() {
768828
return autoplayCallback != null;
769829
}
770830

831+
public long getPagerScrollDuration() {
832+
return pagerScrollDuration;
833+
}
834+
835+
public void setPagerScrollDuration(@IntRange(from = 1) long pagerScrollDuration) {
836+
this.pagerScrollDuration = pagerScrollDuration;
837+
}
838+
839+
public Interpolator getPagerInterpolator() {
840+
return pagerInterpolator;
841+
}
842+
843+
public void setPagerInterpolator(Interpolator pagerInterpolator) {
844+
this.pagerInterpolator = pagerInterpolator;
845+
}
846+
847+
public void setPagerInterpolator(@InterpolatorRes int interpolatorRes) {
848+
this.pagerInterpolator = AnimationUtils.loadInterpolator(this, interpolatorRes);
849+
}
850+
771851
@SuppressWarnings("unused")
772852
public boolean isFullscreen() {
773853
return fullscreen;
@@ -1122,7 +1202,7 @@ public void onClick(View v) {
11221202
while (endPosition < count && canGoForward(endPosition, true)) {
11231203
endPosition++;
11241204
}
1125-
pager.setCurrentItem(endPosition);
1205+
smoothScrollPagerTo(endPosition);
11261206
}
11271207
}
11281208
}

0 commit comments

Comments
 (0)