ViewPager
可以实现多个界面的左右滑动。
布局文件
适配器,需要继承PagerAdapter
类
public static class DemoPageAdapter extends PagerAdapter {
private List mViewList = new ArrayList<>();
public DemoPageAdapter(Context context) {
for (int index = 0; index < 4; index++) {
TextView view = (TextView) View.inflate(context, R.layout.view_pager_text, null);
view.setText("第" + index + "页");
mViewList.add(view);
}
}
// 返回界面数量
@Override
public int getCount() {
return mViewList.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
// 添加界面,一般会添加当前页和左右两边的页面
@Override
public Object instantiateItem(ViewGroup container, int position) {
container.addView(mViewList.get(position));
return mViewList.get(position);
}
// 去除页面
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(mViewList.get(position));
}
}
设置适配器
ViewPager viewPager = findViewById(R.id.view_pager);
viewPager.setAdapter(new DemoPageAdapter(this));
OnPageChangeListener
有三个方法
onPageScrolled(int, float, int)
方法,显示滑动时页面状态。
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
手势从左往右滑动,position
为前一页面,positionOffset
从1到0。
手势从右往左滑动,position
为当前页面,positionOffset
从0到1。
onPageSelected(int)
方法,position
是被选择页面
public void onPageSelected(int position)
onPageScrollStateChanged(int)
方法,
public void onPageScrollStateChanged(int state)
state
有三种状态
SCROLL_STATE_IDLE
,静止状态。SCROLL_STATE_DRAGGING
,开始拖曳。SCROLL_STATE_SETTLING
,停止拖曳。如何实现循环的ViewPager
,我们需要在边界的时候做一些特殊处理。
在第一个页面之前和最后一个页面之后,分别添加一个界面,这样才能实现循环。
public static class CyclePageAdapter extends PagerAdapter {
private List mViewList = new ArrayList<>();
public CyclePageAdapter(Context context) {
for (int index = 0; index < 4; index++) {
TextView view = (TextView) View.inflate(context, R.layout.view_pager_text, null);
view.setText("第" + index + "页");
mViewList.add(view);
}
}
// 返回界面数量+2
@Override
public int getCount() {
return mViewList.size() + 2;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
View view;
if (position == 0) {
// 第一个界面,选择原来的最后一个界面
view = mViewList.get(mViewList.size() - 1);
} else if (position == mViewList.size() + 1) {
// 最后一个界面,选择原来的第一个界面
view = mViewList.get(0);
} else {
// 原有的依次从0开始
view = mViewList.get(position - 1);
}
// 页面如果重复添加,会发生异常
try {
container.addView(view);
} catch (Exception e) {
}
return view;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
// 不在删除页面
}
}
到达实际边界以后,切换当前页。
final ViewPager viewPager = findViewById(R.id.view_pager);
final PagerAdapter adapter = new CyclePageAdapter(this);
viewPager.setAdapter(adapter);
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) {
if (state == ViewPager.SCROLL_STATE_IDLE) {
int position = viewPager.getCurrentItem();
if (position == 0) {
// 第一个界面,切换到原来的最后一个界面
viewPager.setCurrentItem(adapter.getCount() - 2, false);
} else if (position == adapter.getCount() - 1) {
// 最后一个界面,切换到原来的第一个界面
viewPager.setCurrentItem(1, false);
}
}
}
});
// 初始页为1
viewPager.setCurrentItem(1);
自定义切换动画需继承PageTransformer
,并覆盖transformPage(View page, float position)
方法,实现不一样的动画,
position
从0->-1,而下一页面position
从1->0。position
为0->1,而前一页面position
从-1->0。定义一个动画,前一页面左右移动,而后一页面位置不变但伸缩显示。
private class DemoPageTransformer implements ViewPager.PageTransformer {
@Override
public void transformPage(View page, float position) {
if (position < -1) {
page.setAlpha(0);
} else if (position <= 0) {
// 左右移动,并且移除时变透明
page.setAlpha(1 + position);
} else if (position < 1) {
// 去除左右移动效果
page.setTranslationX(-page.getWidth() * position);
// 进入时变大,移除时变小
page.setScaleX(1 - position/2);
page.setScaleY(1 - position/2);
page.setAlpha(1 - position);
} else {
page.setAlpha(0);
}
}
}
效果如下
广告页长被用于首页,可以自己切换,也可以手动切换。
使用ViewPager
实现广告页,主要是要判断是否在手动切换,可以添加OnPageChangeListener
来判断。
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
private boolean mDragging = false;
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
if (state == ViewPager.SCROLL_STATE_IDLE && mDragging) {
mHandler.sendEmptyMessageDelayed(MOVE_TO_NEXT, 3000);
mDragging = false;
} else if (state == ViewPager.SCROLL_STATE_DRAGGING){
mHandler.removeMessages(MOVE_TO_NEXT);
mDragging = true;
}
}
});
mHandler.sendEmptyMessageDelayed(MOVE_TO_NEXT, 3000);
Handler
类处理自动切换事件
private static final int MOVE_TO_NEXT = 1;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == MOVE_TO_NEXT) {
int item = mViewPager.getCurrentItem();
if (++item >= mAdapter.getCount()) {
item = 0;
}
mViewPager.setCurrentItem(item);
mHandler.sendEmptyMessageDelayed(MOVE_TO_NEXT, 3000);
}
}
};
可以利用clipChildren
属性实现画廊效果。详见Android clipChildren属性