ViewPager继承自viewGroup,用来在一个空间加载多个页面。开发过程中比较常用。
ViewPager的基础实现部分
布局文件
- 在主页面文件中放入 viewpager组件
- 创建每个页面的视图 (这里只写了一个textview)(这里只 创建了一个 需要加载多少就创建多少视图)
在Activity中实现
public class MainActivity extends AppCompatActivity {
private View view1, view2, view3, view4;
private ViewPager mViewPager;
private List mPageList;
private PagerAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
initViewPager();
}
void initData() {
//引入要展示的页面
LayoutInflater inflater=getLayoutInflater();
view1 = inflater.inflate(R.layout.page1, null);
view2 = inflater.inflate(R.layout.page2,null);
view3 = inflater.inflate(R.layout.page3, null);
view4 = inflater.inflate(R.layout.page4, null);
mPageList = new ArrayList();// 将要分页显示的View装入数组中
mPageList.add(view1);
mPageList.add(view2);
mPageList.add(view3);
mPageList.add(view4);
}
void initViewPager() {
//引入ViewPager组件
mViewPager = (ViewPager) findViewById(R.id.viewPager);
//进行适配器的设置
mAdapter = new PagerAdapter() {
@Override
public int getCount() {
return mPageList.size();
}
// TODO: 2018/5/29 和谁进行比较? 判断是否是同一个视图 判断谁和谁是同一个视图
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
// // PagerAdapter只缓存三张要显示的图片,如果此时滑动到第三页时,第一页就会调用该方法去销毁相应的View。
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(mPageList.get(position));
}
// 该方法是按需调用,默认情况先调用三次,将三个即将使用View页面添加到ViewGroup中,当你滑动到第二页View时,
// ViewPager会调用一次该方法将第四个View页面添加到ViewGroup中。
// 该方法返回值作为key和对应位置的View关联起来。用于isViewFromObject方法判断当前View和key是否关联的。
@Override
public Object instantiateItem(ViewGroup container, int position) {
container.addView(mPageList.get(position));
return mPageList.get(position);
}
};
mViewPager.setAdapter(mAdapter);
}
}
ViewPager下面位置指示点的实现
ViewPager 实时更新view
在更新适配器的数据的时候会出现数据虽然删除但是删除的view叠加在后一个view上面 导致这个问题的原因是虽然适配器刷新了 但是其中的View并没有实时删除解决方法是重写下面的方法
//默认的时候
public int getItemPosition(Object object) {
return POSITION_UNCHANGED; // 更新适配器的时候 对应的view不会销毁
return POSITION_NONE // 更新适配器的时候 对应位置的view会销毁
}
ViewPager禁止滑动
@Override
public void scrollTo(int x, int y) {
if (mTotal != 1){ //当总数量1 的时候能进行滑动
// x 和 y 是用户点击滑动的坐标点吗?
super.scrollTo(x, y);
}
}
Viewpager实现自动轮播
实现代码如下
//验证 下面的autoswitch以及怎么判断是用户滑动还是 自己滑动 ?
//看handler 这部分 到现在还是很模糊 ?
//这个地方很有疑惑
private Runnable mAutoSwitchRunnable = new Runnable() {
@Override
public void run() {
if (mTotal > 1 && mCurSwitchMode == AUTO_SWITCH) {
++mCurrentPos;
int item = (mCurrentPos) % mTotal;
CustomViewPager.this.setCurrentItem(item, true);
}
}
};
public void startAutoSwitch() {
if (mTotal > 1 && mCurSwitchMode == AUTO_SWITCH) {
mHandler.postDelayed(mAutoSwitchRunnable, DELAY_TIME);
}
}
ViewPager切换页面速度控制
- 在viewpager里面 有一个成员变量mScroller 来控制切换的速度,所以我们需要把viewPager中的这个变量 转换为我们自己的Scroller变量 可以用java反射做到 实现代码如下
//什么是java反射 怎么使用 ?
//mScroller 这个变量是从哪里来的 是viewpager自己的吗 还是说什么适配器的 ?
//这个功能是怎么实现的 在代码里面
public class ViewPagerScroller extends Scroller {
private int DEFAULT_DURATION = 900; //ms
public ViewPagerScroller(Context context) {
this(context, null);
}
public ViewPagerScroller(Context context, Interpolator interpolator) {
this(context, interpolator, false);
}
public ViewPagerScroller(Context context, Interpolator interpolator, boolean flywheel) {
super(context, interpolator, flywheel);
}
@Override
public void startScroll(int startX, int startY, int dx, int dy) {
super.startScroll(startX, startY, dx, dy, DEFAULT_DURATION);
}
@Override
public void startScroll(int startX, int startY, int dx, int dy, int duration) {
super.startScroll(startX, startY, dx, dy, DEFAULT_DURATION);
}
/**
* 设置切换一个页面的时长,时间越长,切换速度越慢,反之越慢
*/
public void setDuration(int duration) {
DEFAULT_DURATION = duration;
}
//该方法在ViewPager初始化的时候调用即可
public void initViewPagerScroller(ViewPager viewPager) {
try {
Field mScroller = ViewPager.class.getDeclaredField("mScroller");
mScroller.setAccessible(true);
mScroller.set(viewPager, this);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
通过调用和设置setDuration() 来设置切换时间的大小
ViewPager定义页面切换效果
默认情况下viewpager没有切换效果只有简单的scrollTo平移效果,需要自己定义酷炫的动画效果。可以使用viewpager的setPageTransformer(boolean reverseDrawingOrder, PageTransformer transformer) 这个方法来设置viewpager的切换效果。官方有两个示例
示例一
public class DepthPageTransformer implements ViewPager.PageTransformer {
private static final float MIN_SCALE = 0.75f;
public void transformPage(View view, float position) {
int pageWidth = view.getWidth();
if (position < -1) { // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0);
} else if (position <= 0) { // [-1,0]
// Use the default slide transition when moving to the left page
view.setAlpha(1);
view.setTranslationX(0);
view.setScaleX(1);
view.setScaleY(1);
} else if (position <= 1) { // (0,1]
// Fade the page out.
view.setAlpha(1 - position);
// Counteract the default slide transition
view.setTranslationX(pageWidth * -position);
// Scale the page down (between MIN_SCALE and 1)
float scaleFactor = MIN_SCALE
+ (1 - MIN_SCALE) * (1 - Math.abs(position));
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
} else { // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0);
}
}
}
mViewPager.setPageTransformer(true, new DepthPageTransformer());
示例二
public class ZoomOutPageTransformer implements ViewPager.PageTransformer
{
private static final float MIN_SCALE = 0.85f;
private static final float MIN_ALPHA = 0.5f;
@SuppressLint("NewApi")
public void transformPage(View view, float position)
{
int pageWidth = view.getWidth();
int pageHeight = view.getHeight();
Log.e("TAG", view + " , " + position + "");
if (position < -1)
{ // [-Infinity,-1)
// This page is way off-screen to the left.
view.setAlpha(0);
} else if (position <= 1) //a页滑动至b页 ; a页从 0.0 -1 ;b页从1 ~ 0.0
{ // [-1,1]
// Modify the default slide transition to shrink the page as well
float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
float vertMargin = pageHeight * (1 - scaleFactor) / 2;
float horzMargin = pageWidth * (1 - scaleFactor) / 2;
if (position < 0)
{
view.setTranslationX(horzMargin - vertMargin / 2);
} else
{
view.setTranslationX(-horzMargin + vertMargin / 2);
}
// Scale the page down (between MIN_SCALE and 1)
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
// Fade the page relative to its size.
view.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE)
/ (1 - MIN_SCALE) * (1 - MIN_ALPHA));
} else
{ // (1,+Infinity]
// This page is way off-screen to the right.
view.setAlpha(0);
}
}
}
代码调用示例:
mViewPager.setPageTransformer(true, new ZoomOutPageTransformer());
接口和参数介绍
public interface PageTransformer {
/**
* Apply a property transformation to the given page.
*
* @param page Apply the transformation to this page
* @param position Position of page relative to the current front-and-center
* position of the pager. 0 is front and center. 1 is one full
* page position to the right, and -1 is one page position to the left.
*/
void transformPage(View page, float position);
}
page: 正在执行动画的view
position: view的位置表示 取值范围如下
1.(-∞,-1):表示最左边不可见的View page
2. [-1,0]:表示从A切换到B页面时,A页面的position变化
3. ( 0,1]:表示从A切换到B页面时,B页面的pisition变化
4.(1,+∞):表示最右边不可见的View page