I have an android application that employs a ViewPager with two pages When the activity first displays i would like to present each page in turn to the user so that they know they can swipe between to two views. I have failed to find any docs describing how to do this. I have discovered PageTransformations which sounded promising but the user has to swipe first. I need my two pages to scroll automatically as soon as the first page in the ViewPager displays. how can a achieve the desired result?
You can use Timer
for this purpose. The following code is self explanatory:
// ---------------------------------------------------------------------------
Timer timer;
int page = 1;
public void pageSwitcher(int seconds) {
timer = new Timer(); // At this line a new Thread will be created
timer.scheduleAtFixedRate(new RemindTask(), 0, seconds * 1000); // delay
// in
// milliseconds
}
// this is an inner class...
class RemindTask extends TimerTask {
@Override
public void run() {
// As the TimerTask run on a seprate thread from UI thread we have
// to call runOnUiThread to do work on UI thread.
runOnUiThread(new Runnable() {
public void run() {
if (page > 4) { // In my case the number of pages are 5
timer.cancel();
// Showing a toast for just testing purpose
Toast.makeText(getApplicationContext(), "Timer stoped",
Toast.LENGTH_LONG).show();
} else {
mViewPager.setCurrentItem(page++);
}
}
});
}
}
// ---------------------------------------------------------------------------
Note 1: Make sure that you call pageSwitcher
method after setting up adapter
to the viewPager
properly inside onCreate
method of your activity.
Note 2: The viewPager
will swipe every time you launch it. You have to handle it so that it swipes through all pages only once (when the user is viewing the viewPager
first time)
Note 3: If you further want to slow the scrolling speed of the viewPager
, you can follow this answer on StackOverflow.
Tell me in the comments if that could not help you...
minSdk
version to 11, you should modify your code so that on previous versions than 11, the speed should remain default, and on SDK 11
and above you should apply this hack... –
Juniorjuniority The question is old but I hope it helps someone My solution using Runnable
Short answer
Runnable runnable = new Runnable() {
public void run() {
if (myAdapter.getCount() == page) {
page = 0;
} else {
page++;
}
viewPager.setCurrentItem(page, true);
handler.postDelayed(this, delay);
}
};
Long answer Using in an activity
public class activity extends AppCompatActivity {
private Handler handler;
private int delay = 5000; //milliseconds
private ViewPager viewPager;
private int page = 0;
private MyAdapter myAdapter;
Runnable runnable = new Runnable() {
public void run() {
if (myAdapter.getCount() == page) {
page = 0;
} else {
page++;
}
viewPager.setCurrentItem(page, true);
handler.postDelayed(this, delay);
}
};
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
handler = new Handler();
viewPager = (ViewPager) findViewById(R.id.viewPager);
myAdapter = new MyAdapter(getSupportFragmentManager());
viewPager.setAdapter(myAdapter);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
page = position;
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
@Override
protected void onResume() {
super.onResume();
handler.postDelayed(runnable, delay);
}
@Override
protected void onPause() {
super.onPause();
handler.removeCallbacks(runnable);
}
}
I've created a open source project on github, which implements a auto scroll ViewPager, Example diagram below:
use
<cn.trinea.android.view.autoscrollviewpager.AutoScrollViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
replace
<android.support.v4.view.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
call
startAutoScroll()
to start auto scroll.
stopAutoScroll()
to stop auto scroll.
More: https://github.com/Trinea/android-auto-scroll-view-pager
Here is autoscroll view pager
package com.otapp.net.view;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.support.v4.view.MotionEventCompat;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.animation.Interpolator;
import android.widget.Scroller;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
public class AutoScrollViewPager extends ViewPager {
public static final int DEFAULT_INTERVAL = 1500;
public static final int LEFT = 0;
public static final int RIGHT = 1;
public static final int SLIDE_BORDER_MODE_NONE = 0;
public static final int SLIDE_BORDER_MODE_CYCLE = 1;
public static final int SLIDE_BORDER_MODE_TO_PARENT = 2;
private long interval = DEFAULT_INTERVAL;
private int direction = RIGHT;
private boolean isCycle = true;
private boolean stopScrollWhenTouch = true;
private int slideBorderMode = SLIDE_BORDER_MODE_NONE;
private boolean isBorderAnimation = true;
private double autoScrollFactor = 1.0;
private double swipeScrollFactor = 1.0;
private Handler handler;
private boolean isAutoScroll = false;
private boolean isStopByTouch = false;
private float touchX = 0f, downX = 0f;
private float touchY = 0f;
private CustomDurationScroller scroller = null;
public static final int SCROLL_WHAT = 0;
public AutoScrollViewPager(Context paramContext) {
super(paramContext);
init();
}
public AutoScrollViewPager(Context paramContext, AttributeSet paramAttributeSet) {
super(paramContext, paramAttributeSet);
init();
}
private void init() {
handler = new MyHandler(this);
setViewPagerScroller();
}
/**
* start auto scroll, first scroll delay time is {@link #getInterval()}
*/
public void startAutoScroll() {
isAutoScroll = true;
sendScrollMessage((long) (interval + scroller.getDuration() / autoScrollFactor * swipeScrollFactor));
}
/**
* start auto scroll
*
* @param delayTimeInMills first scroll delay time
*/
public void startAutoScroll(int delayTimeInMills) {
isAutoScroll = true;
sendScrollMessage(delayTimeInMills);
}
/**
* stop auto scroll
*/
public void stopAutoScroll() {
isAutoScroll = false;
handler.removeMessages(SCROLL_WHAT);
}
/**
* set the factor by which the duration of sliding animation will change while swiping
*/
public void setSwipeScrollDurationFactor(double scrollFactor) {
swipeScrollFactor = scrollFactor;
}
/**
* set the factor by which the duration of sliding animation will change while auto scrolling
*/
public void setAutoScrollDurationFactor(double scrollFactor) {
autoScrollFactor = scrollFactor;
}
private void sendScrollMessage(long delayTimeInMills) {
/** remove messages before, keeps one message is running at most **/
handler.removeMessages(SCROLL_WHAT);
handler.sendEmptyMessageDelayed(SCROLL_WHAT, delayTimeInMills);
}
/**
* set ViewPager scroller to change animation duration when sliding
*/
private void setViewPagerScroller() {
try {
Field scrollerField = ViewPager.class.getDeclaredField("mScroller");
scrollerField.setAccessible(true);
Field interpolatorField = ViewPager.class.getDeclaredField("sInterpolator");
interpolatorField.setAccessible(true);
scroller = new CustomDurationScroller(getContext(), (Interpolator) interpolatorField.get(null));
scrollerField.set(this, scroller);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* scroll only once
*/
public void scrollOnce() {
PagerAdapter adapter = getAdapter();
int currentItem = getCurrentItem();
int totalCount;
if (adapter == null || (totalCount = adapter.getCount()) <= 1) {
return;
}
int nextItem = (direction == LEFT) ? --currentItem : ++currentItem;
if (nextItem < 0) {
if (isCycle) {
setCurrentItem(totalCount - 1, isBorderAnimation);
}
} else if (nextItem == totalCount) {
if (isCycle) {
setCurrentItem(0, isBorderAnimation);
}
} else {
setCurrentItem(nextItem, true);
}
}
/**
* <ul>
* if stopScrollWhenTouch is true
* <li>if event is down, stop auto scroll.</li>
* <li>if event is up, start auto scroll again.</li>
* </ul>
*/
boolean consumeTouch = false;
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
int action = MotionEventCompat.getActionMasked(ev);
if (stopScrollWhenTouch) {
if ((action == MotionEvent.ACTION_DOWN) && isAutoScroll) {
isStopByTouch = true;
stopAutoScroll();
} else if (ev.getAction() == MotionEvent.ACTION_UP && isStopByTouch) {
startAutoScroll();
}
}
if (slideBorderMode == SLIDE_BORDER_MODE_TO_PARENT || slideBorderMode == SLIDE_BORDER_MODE_CYCLE) {
touchX = ev.getX();
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
downX = touchX;
touchY = ev.getY();
} else if (action == MotionEvent.ACTION_UP) {
consumeTouch = Math.abs(touchY - ev.getY()) > 0;
}
int currentItem = getCurrentItem();
PagerAdapter adapter = getAdapter();
int pageCount = adapter == null ? 0 : adapter.getCount();
/**
* current index is first one and slide to right or current index is last one and slide to left.<br/>
* if slide border mode is to parent, then requestDisallowInterceptTouchEvent false.<br/>
* else scroll to last one when current item is first one, scroll to first one when current item is last
* one.
*/
if ((currentItem == 0 && downX <= touchX) || (currentItem == pageCount - 1 && downX >= touchX)) {
if (slideBorderMode == SLIDE_BORDER_MODE_TO_PARENT) {
getParent().requestDisallowInterceptTouchEvent(false);
} else {
if (pageCount > 1) {
setCurrentItem(pageCount - currentItem - 1, isBorderAnimation);
}
getParent().requestDisallowInterceptTouchEvent(true);
}
return super.dispatchTouchEvent(ev);
}
}
if (consumeTouch) {
getParent().requestDisallowInterceptTouchEvent(true);
} else {
getParent().requestDisallowInterceptTouchEvent(false);
if (stopScrollWhenTouch)
startAutoScroll();
}
return super.dispatchTouchEvent(ev);
}
private static class MyHandler extends Handler {
private final WeakReference<AutoScrollViewPager> autoScrollViewPager;
public MyHandler(AutoScrollViewPager autoScrollViewPager) {
this.autoScrollViewPager = new WeakReference<AutoScrollViewPager>(autoScrollViewPager);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case SCROLL_WHAT:
AutoScrollViewPager pager = this.autoScrollViewPager.get();
if (pager != null) {
pager.scroller.setScrollDurationFactor(pager.autoScrollFactor);
pager.scrollOnce();
pager.scroller.setScrollDurationFactor(pager.swipeScrollFactor);
pager.sendScrollMessage(pager.interval + pager.scroller.getDuration());
}
default:
break;
}
}
}
public long getInterval() {
return interval;
}
public void setInterval(long interval) {
this.interval = interval;
}
public int getDirection() {
return (direction == LEFT) ? LEFT : RIGHT;
}
public void setDirection(int direction) {
this.direction = direction;
}
public boolean isCycle() {
return isCycle;
}
public void setCycle(boolean isCycle) {
this.isCycle = isCycle;
}
public boolean isStopScrollWhenTouch() {
return stopScrollWhenTouch;
}
public void setStopScrollWhenTouch(boolean stopScrollWhenTouch) {
this.stopScrollWhenTouch = stopScrollWhenTouch;
}
public int getSlideBorderMode() {
return slideBorderMode;
}
public void setSlideBorderMode(int slideBorderMode) {
this.slideBorderMode = slideBorderMode;
}
public boolean isBorderAnimation() {
return isBorderAnimation;
}
public void setBorderAnimation(boolean isBorderAnimation) {
this.isBorderAnimation = isBorderAnimation;
}
public class CustomDurationScroller extends Scroller {
private double scrollFactor = 1;
public CustomDurationScroller(Context context) {
super(context);
}
public CustomDurationScroller(Context context, Interpolator interpolator) {
super(context, interpolator);
}
// @SuppressLint("NewApi")
// public CustomDurationScroller(Context context, Interpolator interpolator, boolean flywheel){
// super(context, interpolator, flywheel);
// }
public void setScrollDurationFactor(double scrollFactor) {
this.scrollFactor = scrollFactor;
}
@Override
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
super.startScroll(startX, startY, dx, dy, (int) (duration * scrollFactor));
}
}
}
Here is xml implementation
Here is class file implementation
MovieFeaturedAdapter mMovieFeaturedAdapter = new MovieFeaturedAdapter(getActivity(), mCurrentMovies);
vpFeatured.setAdapter(mMovieFeaturedAdapter);
Below method is use to switch pages automatically after some time (you can modify time as per your requirement)
private void timer() {
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
runOnUiThread(new Runnable() {
@Override
public void run() {
if (currentPage == NUM_PAGES - 1) {
currentPage = 0;
}
view.setCurrentItem(currentPage++, true);
}
});
}
}, 500, 5000);
}
if want to endless scroll in viewpager use infinite scroll viewpager class from below provided link and do minor changes (remove condition) in Runnable interface.
runOnUiThread(new Runnable() {
@Override
public void run() {
view.setCurrentItem(currentPage++, true);
}
});
also,don't forget to cancel timer on Destroy view.
You can use setCurrentItem to change page
If you want to autoplay viewpager pages but above all solution is correct but after autoplay first item consume delay time but it is wrong after autoplay current item switch quickly. I am adding my code below it is working correctly autoplay/pause.
@Override
public void onClick(View v) {
if (!isAutoPlay) {
img_autoplay.setImageResource(R.drawable.pause);
int currentcount = getModel().getCurrentIndex();
currentcount++;
getMainImage().setCurrentItem(currentcount);
autoPlay(getMainImage());
isAutoPlay = true;
} else {
img_autoplay.setImageResource(R.drawable.auto_play);
isAutoPlay = false;
}
}
});
and here is method:
viewPager.postDelayed(new Runnable() {
@Override
public void run() {
try {
if (myAdapter != null
&& viewPager.getAdapter().getCount() > 0
&& isAutoPlay) {
getWindow().addFlags(
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
int currentcount = getModel().getCurrentIndex();
currentcount++;
viewPager.setCurrentItem(currentcount);
if (getModel().isLastCard()) {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
isAutoPlay = false;
packFinished();
getWindow()
.clearFlags(
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
}, 6000);
}
autoPlay(viewPager);
}
} catch (Exception e) {
}
}
}, 6000);
If you are going to switch page automatically then you should disable paging/swiping on ViewPager because if you touch on page and that time page switching then it's not look good means you observed page struck.
To disable paging/swiping on ViewPager,you need to add below code snippet with you custom view pager.
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.animation.Interpolator;
import java.lang.reflect.Field;
public class ViewPagerCustomDuration extends ViewPager {
private boolean swipeable = false;
public ViewPagerCustomDuration(Context context) {
super(context);
postInitViewPager();
}
public ViewPagerCustomDuration(Context context, AttributeSet attrs) {
super(context, attrs);
postInitViewPager();
}
public void setSwipeable(boolean swipeable) {
this.swipeable = swipeable;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (this.swipeable) {
return super.onTouchEvent(event);
}
return false;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (this.swipeable) {
return super.onInterceptTouchEvent(event);
}
return false;
}
private ScrollerCustomDuration mScroller = null;
/**
* Override the Scroller instance with our own class so we can change the
* duration
*/
private void postInitViewPager() {
try {
Field scroller = ViewPager.class.getDeclaredField("mScroller");
scroller.setAccessible(true);
Field interpolator = ViewPager.class.getDeclaredField("sInterpolator");
interpolator.setAccessible(true);
mScroller = new ScrollerCustomDuration(getContext(),
(Interpolator) interpolator.get(null));
scroller.set(this, mScroller);
} catch (Exception e) {
}
}
/**
* Set the factor by which the duration will change
*/
public void setScrollDurationFactor(double scrollFactor) {
mScroller.setScrollDurationFactor(scrollFactor);
}
}
after that,call method from view pager object.
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.widget.Toast;
import java.util.Timer;
import java.util.TimerTask;
public class MainActivity extends AppCompatActivity {
ViewPagerCustomDuration viewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_3);
viewPager = (ViewPagerCustomDuration) findViewById(R.id.viewpager);
viewPager.setScrollDurationFactor(2);
viewPager.setAdapter(new CustomPagerAdapter(this));
viewPager.setSwipeable(false);
pageSwitcher(5);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
Timer timer;
int page = 1;
public void pageSwitcher(int seconds) {
timer = new Timer(); // At this line a new Thread will be created
timer.scheduleAtFixedRate(new RemindTask(), 0, seconds * 1000); // delay
// in
// milliseconds
}
// this is an inner class...
class RemindTask extends TimerTask {
@Override
public void run() {
// As the TimerTask run on a seprate thread from UI thread we have
// to call runOnUiThread to do work on UI thread.
runOnUiThread(new Runnable() {
public void run() {
if (page > 4) { // In my case the number of pages are 5
// timer.cancel();
page = 0;
viewPager.setCurrentItem(page++);
// Showing a toast for just testing purpose
Toast.makeText(getApplicationContext(), "Timer stoped",
Toast.LENGTH_LONG).show();
} else {
viewPager.setCurrentItem(page++);
}
}
});
}
}
Scroller class for scroll page smoothly
import android.annotation.SuppressLint;
import android.content.Context;
import android.view.animation.Interpolator;
import android.widget.Scroller;
public class ScrollerCustomDuration extends Scroller {
private double mScrollFactor = 1;
public ScrollerCustomDuration(Context context) {
super(context);
}
public ScrollerCustomDuration(Context context, Interpolator interpolator) {
super(context, interpolator);
}
@SuppressLint("NewApi")
public ScrollerCustomDuration(Context context, Interpolator interpolator, boolean flywheel) {
super(context, interpolator, flywheel);
}
/**
* Set the factor by which the duration will change
*/
public void setScrollDurationFactor(double scrollFactor) {
mScrollFactor = scrollFactor;
}
@Override
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
super.startScroll(startX, startY, dx, dy, (int) (duration * mScrollFactor));
}
}
For new viewPage2 you can use below code
fun ViewPager2.enableAutoScroll(totalPages: Int): Timer {
val autoTimerTask = Timer()
var currentPageIndex = currentItem
autoTimerTask.schedule(object : TimerTask() {
override fun run() {
currentItem = currentPageIndex++
if (currentPageIndex == totalPages) currentPageIndex = 0
}
}, 0, DELAY_FOUR_SECONDS)
// Stop auto paging when user touch the view
getRecyclerView().setOnTouchListener { _, event ->
if (event.action == MotionEvent.ACTION_DOWN) autoTimerTask.cancel()
false
}
return autoTimerTask // Return the reference for cancel
}
fun ViewPager2.getRecyclerView(): RecyclerView {
val recyclerViewField = ViewPager2::class.java.getDeclaredField("mRecyclerView")
recyclerViewField.isAccessible = true
return recyclerViewField.get(this) as RecyclerView
}
1. define
var currentPage = 0
2. Add the below code
val NUM_PAGES = 5
val handler = Handler()
val update = Runnable {
if (currentPage == NUM_PAGES - 1) {
currentPage = 0
}
binding.viewPager.setCurrentItem(currentPage++, true)
}
Timer().schedule(object : TimerTask() {
override fun run() {
handler.post(update)
}
}, 100, 2500)
© 2022 - 2024 — McMap. All rights reserved.