欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android自定义引导玩转ViewPager的方法详解

程序员文章站 2023-11-28 09:35:37
viewpager简介: viewpager(android.support.v4.view.viewpager)是android扩展包v4包中的类,这个类可以让用户...

viewpager简介:

viewpager(android.support.v4.view.viewpager)是android扩展包v4包中的类,这个类可以让用户左右切换当前的view,实现滑动切换的效果。

注意:

viewpager类直接继承了viewgroup类,也就是说它和我们经常打交道的linearlayout一样,都是一个容器,需要在里面添加我们想要显示的内容。

  viewpager类需要一个pageradapter适配器类给它提供数据,这个和listview类似。

viewpager基础使用

具体步骤:

1.在布局文件里加入

 <android.support.v4.view.viewpager
  android:id="@+id/in_viewpager"
  android:layout_width="match_parent"
  android:layout_height="match_parent">
 </android.support.v4.view.viewpager>

2.在activity中加载要显示的views,通过动态加载布局得到一个个view

  mviewlist = new arraylist<view>();
  layoutinflater lf = getlayoutinflater().from(mainactivity.this);
  view view1 = lf.inflate(r.layout.we_indicator1, null);
  view view2 = lf.inflate(r.layout.we_indicator2, null);
  view view3 = lf.inflate(r.layout.we_indicator3, null);
  mviewlist.add(view1);
  mviewlist.add(view2);
  mviewlist.add(view3);

3.自定义pageradapter,以便将步骤2中的views数据加载到viewpager容器中

public class viewpageradatper extends pageradapter {
 private list<view> mviewlist ;

 public viewpageradatper(list<view> mviewlist ) {
  this.mviewlist = mviewlist;
 }

 @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));
 }
}

4.将viewpager和自定义的pageradapter关联起来

min_vp.setadapter(new viewpageradatper(mviewlist));

通过简单使用viewpager,得到的展示效果,仅仅支持左右滑动,效果比较单一。

Android自定义引导玩转ViewPager的方法详解

viewpager进阶使用——实现跟随式小圆点效果

步骤:

1.添加小圆点

在布局中的设置如下:

<relativelayout
  android:id="@+id/rl_dots"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_alignparentbottom="true"
  android:layout_centerhorizontal="true"
  android:layout_marginbottom="60dp">

  <linearlayout
   android:id="@+id/in_ll"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:orientation="horizontal">
  </linearlayout>

  <imageview
   android:id="@+id/iv_light_dots"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:src="@drawable/light_dot"/>
 </relativelayout>

随后在linearlayout中动态添加3个小黑点,小白点默认覆盖在第一个小黑点的上面。

在activity中的添加小黑点,代码如下:

private void adddots() {
  mone_dot = new imageview(this);
  mone_dot.setimageresource(r.drawable.gray_dot);
  linearlayout.layoutparams layoutparams = new linearlayout.layoutparams(viewgroup.layoutparams.wrap_content, viewgroup.layoutparams.wrap_content);
  layoutparams.setmargins(0, 0, 40, 0);
  min_ll.addview(mone_dot, layoutparams);
  mtwo_dot = new imageview(this);
  mtwo_dot.setimageresource(r.drawable.gray_dot);
  min_ll.addview(mtwo_dot, layoutparams);
  mthree_dot = new imageview(this);
  mthree_dot.setimageresource(r.drawable.gray_dot);
  min_ll.addview(mthree_dot, layoutparams);
  setclicklistener();

 }

2.获得两个点之间的距离

实现小白点动态跟随的思路是:根据页面的移动情况,通过设置小白点的 leftmargin 实现小红点的动态跟随。因此首要的是获得两个点之间的距离,根据页面移动到的位置,进行相应的运算。

需要注意的是:在oncreate()中直接获得小白点的左边距 getleft()结果为0,这是因为view组件布局要在onresume回调后完成。

因此使用另一种方法:

mlight_dots.getviewtreeobserver().addongloballayoutlistener(new viewtreeobserver.ongloballayoutlistener() {
      @override
      public void ongloballayout() {
        //获得两个圆点之间的距离
        mdistance = min_ll.getchildat(1).getleft() - min_ll.getchildat(0).getleft();
        mlight_dots.getviewtreeobserver()
            .removeglobalonlayoutlistener(this);
      }
    });

在布局发生改变或者某个视图的可视状态发生改变时调用该事件。但此方法会被多次调用,因此需要在获取到视图的宽度和高度后执行 remove 方法移除该监听事件。

3.监听页面的移动情况

 min_vp.addonpagechangelistener(new viewpager.onpagechangelistener() {
      @override
      public void onpagescrolled(int position, float positionoffset, int positionoffsetpixels) {
        //页面滚动时小白点移动的距离,并通过setlayoutparams(params)不断更新其位置
        float leftmargin = mdistance * (position + positionoffset);
        relativelayout.layoutparams params = (relativelayout.layoutparams) mlight_dots.getlayoutparams();
        params.leftmargin = (int) leftmargin;
        mlight_dots.setlayoutparams(params); 
      }

      @override
      public void onpageselected(int position) {
        //页面跳转时,设置小圆点的margin
        float leftmargin = mdistance * position;
        relativelayout.layoutparams params = (relativelayout.layoutparams) mlight_dots.getlayoutparams();
        params.leftmargin = (int) leftmargin;
        mlight_dots.setlayoutparams(params);
      }

      @override
      public void onpagescrollstatechanged(int state) {

      }
    });
  }

在页面移动过程中,根据mdistance * (position + positionoffset) 可以实时更新小白点的位置

这部分内容加入了一个新的功能 点击小黑点 可以直接跳转到对应的引导页面,具体逻辑就是在小黑点的点击事件中加入如下代码:

 min_vp.setcurrentitem(1);

在页面选择过程中,根据mdistance * position可以实时小红点的位置

4.跳转按钮的实现

具体逻辑:到引导页到达最后一页时,跳转到主页的按钮出现。其他情况为隐藏状态
因此可以在onpagescrolled(int position, float positionoffset, int positionoffsetpixels)和onpageselected(int position)方法中加入如下代码:

         if(position==2){
          mbtn_next.setvisibility(view.visible);
        }

当按照从第一页到最后一页,然后点击按钮跳转到首页,则以上逻辑足够。

但当用户浏览到最后一页后再回转到前面感兴趣的页面,则会出现按钮依旧出现的情况,不符合要求。因此要完善逻辑,加入新的判断,逻辑如下:

if(position!=2&&mbtn_next.getvisibility()==view.visible){
          mbtn_next.setvisibility(view.gone);
        }

以上逻辑保证了按钮的正常显示,剩下的就可以具体操作,实现跳转到首页的逻辑。

viewpager进阶使用——自定义炫酷动画

viewpager自带了一个setpagetransformer用于设置切换动画~

setpagetransformer (boolean reversedrawingorder, pagetransformer transformer)需要传入两个参数

第一个参数:如果为true,则表明自定义的pagetransformer需要 page view从后到前的顺序绘制,反之则为false。

第二个参数:传入一个自定义的pagetransformer对象

因此实现炫酷动画的关键点就在于:自定义pagetransformer

google官方给我们展示了两个动画例子:depthpagetransformer和zoomoutpagetransformer,比较炫。我们就以google官方的例子来学习自定义pagetransformer,以此为基础,我们可以自定义各种各样的动画实现效果。

1.pagetransformer中position解析

自定义pagetransformer只需要实现一个方法,transformpage(view page, float position),而这个方法实现的关键就是对position的理解。

源码中的注释解释如下:

apply the transformation to this page

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.

我们可以理解为:

  • 0表示当前页面,是当前页面
  • -1表示左侧的页面,是左侧页面
  • 1表示右侧的页面,是右侧页面

在用户滑动界面的时候,position是动态变化的,下面以左滑为例:

  • 选中页面 position:0->-1
  • 前一个item position:-1 -> -2
  • 后一个item position:1 -> 0

但是当viewpager设置pagemargin,设置两个页面之间的距离(通过调用viewpager.setpagemargin()方法设置)后,情况则不同。

如果你设置了pagemargin,前后页面的position需要分别加上(或减去,前减后加)一个偏移量(偏移量的计算方式为pagemargin / pagewidth)。

同样以左滑为例:

  • 选中页面position:0->-1 - pagemargin / pagewidth
  • 前一个item position:-1 - pagemargin / pagewidth -> -2 - pagemargin / pagewidth
  • 后一个item position:1 + pagemargin / pagewidth -> 0

因此我们可以将position的值应用于setalpha(), settranslationx(), 或者 setscaley()等等方法,从而实现自定义的动画效果。

2.实现transformpage(view page, float position)方法

public class depthpagetransformer implements viewpager.pagetransformer {
  private static final float min_scale = 0.75f;
  @override
  public void transformpage(view page, float position) {
    int pagewidth = page.getwidth();
    if (position < -1) { // [-infinity,-1)
      // 页面远离左侧页面
      page.setalpha(0);
    } else if (position <= 0) { // [-1,0]
      // 页面在由中间页滑动到左侧页面 或者 由左侧页面滑动到中间页
      page.setalpha(1);
      page.settranslationx(0);
      page.setscalex(1);
      page.setscaley(1);
    } else if (position <= 1) { // (0,1]
      //页面在由中间页滑动到右侧页面 或者 由右侧页面滑动到中间页
      // 淡入淡出效果
      page.setalpha(1 - position);
      // 反方向移动
      page.settranslationx(pagewidth * -position);
      // 0.75-1比例之间缩放
      float scalefactor = min_scale
          + (1 - min_scale) * (1 - math.abs(position));
      page.setscalex(scalefactor);
      page.setscaley(scalefactor);
    } else { // (1,+infinity]
      // 页面远离右侧页面
      page.setalpha(0);
    }

  }
}

github代码地址

以上是一些viewpager做引导页做用的到一些知识点,希望和大家分享共同学习。由于水平有限,有什么不对的地方欢迎指正。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对的支持。