热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

AndroidViewPager实现动画切换效果

这篇文章主要为大家详细介绍了AndroidViewPager实现动画切换效果的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

概述

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

实现简单动画切换

代码如下:

1.布局文件

<&#63;xml version="1.0" encoding="utf-8"&#63;>


  


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 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 view.setAlpha(0),设置完全透明不可见。

上述代码执行效果如下:

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

实现广告轮播效果图

如图:

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

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

<&#63;xml version="1.0" encoding="utf-8"&#63;>


  



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

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


推荐阅读
  • ListView简单使用
    先上效果:主要实现了Listview的绑定和点击事件。项目资源结构如下:先创建一个动物类,用来装载数据:Animal类如下:packagecom.example.simplelis ... [详细]
  • 本文详细介绍了Java中实现异步调用的多种方式,包括线程创建、Future接口、CompletableFuture类以及Spring框架的@Async注解。通过代码示例和深入解析,帮助读者理解并掌握这些技术。 ... [详细]
  • 本文详细介绍了 Android 开发中 layout_gravity 属性的使用方法及其在不同布局下的效果,旨在帮助开发者更好地理解和利用这一属性来精确控制视图的布局。 ... [详细]
  • 探讨 HDU 1536 题目,即 S-Nim 游戏的博弈策略。通过 SG 函数分析游戏胜负的关键,并介绍如何编程实现解决方案。 ... [详细]
  • HTML基础入门指南
    本文将深入浅出地介绍HTML的基础知识,包括其定义、开发工具、制定机构、特性、基本标签及更多实用内容。 ... [详细]
  • ssm框架整合及工程分层1.先创建一个新的project1.1配置pom.xml ... [详细]
  • 本文探讨了如何在Classic ASP中实现与PHP的hash_hmac('SHA256', $message, pack('H*', $secret))函数等效的哈希生成方法。通过分析不同实现方式及其产生的差异,提供了一种使用Microsoft .NET Framework的解决方案。 ... [详细]
  • Spring Boot 中静态资源映射详解
    本文深入探讨了 Spring Boot 如何简化 Web 应用中的静态资源管理,包括默认的静态资源映射规则、WebJars 的使用以及静态首页的处理方法。通过本文,您将了解如何高效地管理和引用静态资源。 ... [详细]
  • SpringMVC RestTemplate的几种请求调用(转)
    SpringMVCRestTemplate的几种请求调用(转),Go语言社区,Golang程序员人脉社 ... [详细]
  • ArcXML:互联网空间数据交换的专用语言
    ArcXML是一种专为ArcIMS平台设计的数据交换协议,基于XML标准,用于在不同组件之间传输和描述地理空间数据。本文将详细介绍ArcXML的背景、用途及其与XML的关系。 ... [详细]
  • 本文详细介绍如何使用 Python 集成微信支付的三种主要方式:Native 支付、APP 支付和 JSAPI 支付。每种方式适用于不同的应用场景,如 PC 网站、移动端应用和公众号内支付等。 ... [详细]
  • 搭建Jenkins、Ant与TestNG集成环境
    本文详细介绍了如何在Ubuntu 16.04系统上配置Jenkins、Ant和TestNG的集成开发环境,涵盖从安装到配置的具体步骤,并提供了创建Windows Slave节点及项目构建的指南。 ... [详细]
  • 优化Jenkins首次启动速度
    本文详细描述了在启动Jenkins后遇到的长时间加载问题,并提供了一种通过修改更新中心配置文件来显著提升启动速度的有效解决方案。 ... [详细]
  • 远程过程调用(RPC)是一种允许客户端通过网络请求服务器执行特定功能的技术。它简化了分布式系统的交互,使开发者可以像调用本地函数一样调用远程服务,并获得返回结果。本文将深入探讨RPC的工作原理、发展历程及其在现代技术中的应用。 ... [详细]
  • 本文探讨了如何在Java中使用JAXB解组两个具有相同名称但不同结构的对象。我们将介绍一个抽象类Bar及其具体实现,并展示如何正确地解析XML文档以获取正确的对象实例。 ... [详细]
author-avatar
旺仔牛奶糖2702938317
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有