我有一个使用带有两个页面的 ViewPager 的 android 应用程序当活动首次显示时,我想将每个页面依次呈现给用户,以便他们知道他们可以在两个视图之间滑动。我找不到任何描述如何执行此操作的文档。我发现 PageTransformations 听起来很有希望,但用户必须先滑动。一旦 ViewPager 中的第一页显示,我需要我的两个页面自动滚动。怎样才能达到预期的效果?
9 回答
您可以Timer
用于此目的。以下代码是不言自明的:
// ---------------------------------------------------------------------------
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++);
}
}
});
}
}
// ---------------------------------------------------------------------------
注意1:确保pageSwitcher
在设置adapter
为活动的viewPager
正确内部onCreate
方法后调用方法。
注意2:每次viewPager
启动时都会滑动。您必须处理它,以便它只在所有页面上滑动一次(当用户第一次查看viewPager
时)
注意 3:如果您想进一步减慢 的滚动速度viewPager
,可以按照 StackOverflow 上的这个答案进行操作。
如果这不能帮助你,请在评论中告诉我......
这个问题很老,但我希望它可以帮助某人我使用 Runnable 的解决方案
简短的回答
Runnable runnable = new Runnable() {
public void run() {
if (myAdapter.getCount() == page) {
page = 0;
} else {
page++;
}
viewPager.setCurrentItem(page, true);
handler.postDelayed(this, delay);
}
};
长答案 在活动中使用
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);
}
}
我在github上创建了一个开源项目,实现了一个自动滚动的ViewPager,示例图如下:
利用
<cn.trinea.android.view.autoscrollviewpager.AutoScrollViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
代替
<android.support.v4.view.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
调用
startAutoScroll()
开始自动滚动。
stopAutoScroll()
停止自动滚动。
更多:https ://github.com/Trinea/android-auto-scroll-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));
}
}
}
这是xml实现
这是类文件实现
MovieFeaturedAdapter mMovieFeaturedAdapter = new MovieFeaturedAdapter(getActivity(), mCurrentMovies);
vpFeatured.setAdapter(mMovieFeaturedAdapter);
以下方法用于在一段时间后自动切换页面(您可以根据需要修改时间)
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);
}
如果想在 viewpager 中无限滚动,请使用下面提供的链接中的无限滚动 viewpager 类,并在 Runnable 界面中进行细微更改(删除条件)。
runOnUiThread(new Runnable() {
@Override
public void run() {
view.setCurrentItem(currentPage++, true);
}
});
另外,不要忘记取消销毁视图上的计时器。
您可以使用setCurrentItem更改页面
如果您想自动播放 viewpager 页面,但最重要的是解决方案是正确的,但在自动播放第一个项目后会消耗延迟时间,但在自动播放当前项目快速切换后是错误的。我在下面添加我的代码,它可以正常工作自动播放/暂停。
@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;
}
}
});
这是方法:
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);
对于新的 viewPage2,您可以使用以下代码
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
}
如果您要自动切换页面,那么您应该在 ViewPager 上禁用分页/滑动,因为如果您触摸页面并且那个时候页面切换,那么它看起来不太好意味着您观察到页面被击中。
要在 ViewPager 上禁用分页/滑动,您需要在自定义视图分页器中添加以下代码片段。
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);
}
}
之后,从视图寻呼机对象调用方法。
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 类
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));
}
}