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

Android ViewPager实现动画切换效果

程序员文章站 2024-02-22 11:30:10
概述 viewpager是android开发中使用场景非常频繁的控件,单一的动画效果切换已经越来越不能满足追求个性化的应用中。而viewpager自身也带有一个接口来处理...

概述

viewpager是android开发中使用场景非常频繁的控件,单一的动画效果切换已经越来越不能满足追求个性化的应用中。而viewpager自身也带有一个接口来处理页面间的动画切换,那就是setpagetransformer。下面我们通过代码来学习动画效果的切换。

实现简单动画切换

代码如下:

1.布局文件

<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/view_pager_box"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:orientation="horizontal" >

  <android.support.v4.view.viewpager
    android:id="@+id/viewpager"
    android:layout_margin="10dp"
    android:layout_width="wrap_content"
    android:layout_height="120dp" />

</linearlayout>

mainactivity 中相关 java 代码

import android.app.activity;
import android.os.bundle;
import android.support.v4.view.pageradapter;
import android.support.v4.view.viewpager;
import android.view.view;
import android.view.viewgroup;
import android.widget.imageview;
import android.widget.imageview.scaletype;

public class mainactivity extends activity {

  private viewpager viewpager;
  private int[] imageids = new int[]{r.drawable.pic1,r.drawable.pic2,r.drawable.pic3,r.drawable.pic4,r.drawable.pic5,};
  @override
  protected void oncreate(bundle savedinstancestate) {
    super.oncreate(savedinstancestate);
    setcontentview(r.layout.activity_main);
    viewpager = (viewpager) findviewbyid(r.id.viewpager);

    viewpager.setoffscreenpagelimit(3); //设置内存中预加载页面数

    viewpager.setpagetransformer(true, new depthpagetransformer()); //设置页面切换过渡动画

    viewpager.setadapter(new pageradapter() {

      @override
      public boolean isviewfromobject(view view, object object) {
        return view == object;
      }

      @override
      public int getcount() {
        return imageids.length;
      }

      @override
      public object instantiateitem(viewgroup container, int position) {
        imageview imageview = new imageview(mainactivity.this);
        imageview.setscaletype(scaletype.center_crop);
        imageview.setimageresource(imageids[position]);
        imageview.settag(position); //设置标记
        container.addview(imageview);
        return imageview;
      }

      @override
      public void destroyitem(viewgroup container, int position,
          object object) {
        container.removeview((view)object);
      }
    });
  }
}

3.控制切换动画的类depthpagetransformer的代码

import android.support.v4.view.viewpager;
import android.view.view;

public class depthpagetransformer implements viewpager.pagetransformer {

  private static final float min_scale = 0.75f;

  @override
  public void transformpage(view view, float position) {

    android.util.log.i("yuminfeng", "====view:" + view.gettag()  + ",position:" + 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);
    }
  }

}

上面的代码十分简单,仅仅只是viewpager的初始化配置,然后通过setpagetransformer设置页面切换动画。有一个细节还需要注意,设置setoffscreenpagelimit(3),表示内存中预加载页面为3,这三个页面是不可见的。如果加上当前显示的页面,总共初始化了4个页面。不设置的话,系统使用默认的预加载的页数为1。
第一次启动应用后,我们通过在depthpagetransformer类中记录的日志可以看到,如下:

总共初始化了4个view,其中当前对用户可见view的位置为0,其余都是不可见。所以当position=0时,表示当前的页面。

我们继续操作并向左滑动一页,日志如下:

由此可以看到,之前的view的位置变为-1,它的右边的view位置为0,变成可见。
继续滑动至最后一页后:

我们看到最后一页的view已经展现在用户面前,位置为0,而其他页面位置都是为负,表示所有页面都滑至左边。这时我们注意的话,可以发现view:0,不在日志信息中,难道它没有被初始化?其实它已经被系统回收了,通过adapter中destroyitem方法。因为我们之前设置viewpager中预加载的页数限制为3,系统中最多的存在4个view,所以view:0被回收。

从上面的分析我们可以知道,当view的position处于[-1,1]时,该view能够被用户所见,其他位置便不可见。而pagetransformer的接口中,真是利用了这个特点,根据view的position来对它进行缩放,旋转等动画操作。我们继续分析depthpagetransformer类:
当 position < -1,即[-infinity,-1) 时:
view处于左边不可见中,这里view.setalpha(0); 表示完全透明。
当-1 <= position <= 0 时,该view处于可见区域,:
1.如果view向左滑动,表示当前view逐渐滑出可见区域
2.如果view向右滑动,表示左边的view逐渐划入当前可见区域。
view.setalpha(1),设置透明度,表示完全不透明。
view.settranslationx(0),表示设置view相对于左侧位置的水平位置,距离左边的距离。
view.setscalex(1)和view.setscaley(1),表示view的x,y轴不进行缩放。
当0 < position <= 1 时,该view处于可见区域:
1.如果view向右滑动,表示当前view逐渐滑出可见区域。
2.如果view向左滑动,表示右边的view逐渐滑入可见区域。
view.setalpha(1 - position),根据view滑动的位置,设置view的透明度。position 越接近于0,表明view面对用户显示的越多,所以就越不透明。
view.settranslationx(pagewidth * -position),根据view滑动的位置,设置view相对于左侧位置的水平位置,当position = 0 时,view完全显示,这时相对左边为0,当 position = 1 时,view完全不可见,这时相对左边为view的宽度。
float scalefactor = min_scale + (1 - min_scale) * (1 - math.abs(position));
view.setscalex(scalefactor);
view.setscaley(scalefactor);
根据view的position,设置view的缩放大小。当 position,越大时,越远离用户界面,于是越不可见。
当1< position 时,即(1,+infinity]时:
view.setalpha(0),设置完全透明不可见。

上述代码执行效果如下:

Android ViewPager实现动画切换效果

我们还可以定制其他的动画效果,实现原理和上面一样,这里就不一一列出来了。

实现广告轮播效果图

如图:

Android ViewPager实现动画切换效果

实现上面的效果图,只需要对上面的代码进行一些修改即可:

想要在屏幕上出现多个页面,我们需要设置属性:android:clipchildren=”false”,该属性的意思是在view进行绘制的时候,不去裁切它们的显示范围,即不限制view的显示范围。
我们修改布局文件,如下:

<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/view_pager_box"
  android:layout_width="match_parent"
  android:layout_height="160dp"
  android:gravity="center"
  android:clipchildren="false"
  android:orientation="horizontal" >

  <android.support.v4.view.viewpager
    android:id="@+id/viewpager"
    android:layout_width="match_parent"
    android:layout_margin="30dp"
    android:layout_height="120dp" />

</linearlayout>

在viewpager的外面控件中设置了android:clipchildren=”false”,然后设置viewpager中android:layout_margin属性,留出间距,方便显示左右两边的图片。后面我们还要java代码设置viewpager的属性,如:
viewpager.setpagemargin(40); //设置页面间间距
这样可以让页面之间存在一定的间隔。最后,我们通过setpagetransformer方法设置自己定义的动画即可,与上面一致。
该效果的动画类代码:

import android.support.v4.view.viewpager;
import android.view.view;

public class alphascaletransformer implements viewpager.pagetransformer {

  private static final float default_min_alpha = 0.5f;
  private float mminalpha = default_min_alpha;
  private static final float default_min_scale = 0.85f;
  private float mminscale = default_min_scale;
  public static final float default_center = 0.5f;

  @override
  public void transformpage(view view, float position) {
    int pagewidth = view.getwidth();
    int pageheight = view.getheight();

    view.setscalex(0.999f);// hack
    view.setpivoty(pageheight / 2);
    view.setpivotx(pagewidth / 2);

    if (position < -1) { // [-infinity,-1)
      view.setalpha(mminalpha);
      view.setscalex(mminscale);
      view.setscaley(mminscale);
      view.setpivotx(pagewidth);

    } else if (position <= 1) { // [-1,1]

      if (position < 0) // [0,-1]
      { // [1,min]
        float factor = mminalpha + (1 - mminalpha) * (1 + position);
        float scalefactor = (1 + position) * (1 - mminscale) + mminscale;

        view.setalpha(factor);
        view.setscalex(scalefactor);
        view.setscaley(scalefactor);
        view.setpivotx(pagewidth * (default_center + (default_center * -position)));

      } else// [1,0]
      {
        // [min,1]
        float factor = mminalpha + (1 - mminalpha) * (1 - position);
        float scalefactor = (1 - position) * (1 - mminscale) + mminscale;

        view.setalpha(factor);
        view.setscalex(scalefactor);
        view.setscaley(scalefactor);
        view.setpivotx(pagewidth * ((1 - position) * default_center));

      }
    } else { // (1,+infinity]
      view.setalpha(mminalpha);
      view.setpivotx(0);
      view.setscalex(mminscale);
      view.setscaley(mminscale);
    }
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。