Android Animation实战之一个APP的ListView的动画效果

熟悉了基础动画的实现后,便可以试着去实现常见APP中出现过的那些精美的动画。今天我主要给大家引入一个APP的ListView的动画效果: 当展示ListView时,Listview的每一个列表项都按照规定的动画显示出来。
说起来比较抽象,先给大家看一个动画效果,这是APP窝牛装修的ListView显示动画:

有木有觉得很酷炫?有木有啊!?

一、Layout Animation
    所谓的布局动画,其实就是为ViewGroup添加显示动画效果,主要用过LayoutAnimationController来控制实现。LayoutAnimationController用于为一个Layout里面的控件,或者是一个ViewGroup里面的控件设置动画效果,可以在XML文件中设置,亦可以在Java代码中设置。

1.1 在XML文件中设置布局动画

首先,我们在res/anim文件夹下建立一个list_anim_layout.xml文件,该文件就是布局动画控制器。

<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
  android:delay="30%"
  android:animationOrder="random"
  android:animation="@anim/slide_right" />

android:delay  子类动画时间间隔 (延迟)   70% 也可以是一个浮点数 如“1.2”等。
android:animationOrder="random"   子类的显示方式 random表示随机。
android:animationOrder 的取值有

  •      normal 0    默认
  •      reverse 1 倒序
  •      random 2   随机

android:animation="@anim/slide_right" 表示列表项显示时的具体动画是什么!
下面,我们定义每一个列表项显示时的动画效果吧,及slide_right.xml:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
  android:interpolator="@android:anim/accelerate_interpolator"> 

  <translate
    android:duration="3000"
    android:fromXDelta="100%p"
    android:toXDelta="0%p" />
</set>

显示的效果为ListView第一次出现的时候为 item随机出现 每个Item都是从右边的区域向左滑动到显示的地方。
接下来,你只需要把这个布局动画,指定到ViewGroup上就好了:

<ListView
    android:id="@+id/listView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layoutAnimation="@anim/list_anim_layout"
    >
</ListView>

就这么简单就完成了,快来看下效果吧:

1.2 在Java代码中实现布局动画
    在Java代码中实现布局动画并无难度,只要熟悉几个API的使用即可。 关于动画的定义和上文一致,只是,你不需要再在把控制动画应用到listview中了,即android:layoutAnimation="@anim/list_anim_layout"这行代码可以删除。
    接下来,需要在Java代码中进行配置:

private void startLayoutAnim() {
  //通过加载XML动画设置文件来创建一个Animation对象;
  Animation animation = AnimationUtils.loadAnimation(this, R.anim.slide_right);
  //得到一个LayoutAnimationController对象;
  LayoutAnimationController lac = new LayoutAnimationController(animation);
  //设置控件显示的顺序;
  lac.setOrder(LayoutAnimationController.ORDER_REVERSE);
  //设置控件显示间隔时间;
  lac.setDelay(1);
  //为ListView设置LayoutAnimationController属性;
  listView.setLayoutAnimation(lac);
}

观察下,效果和之前使用xml文件肯定是一致的了。

介绍到这里,可能有人会有疑问了,博文一开始介绍的“窝牛装修”的那种效果,是每一个列表项显示的时候才会显示动画。我们这个确实所有的列表项的动画一起都显示了,只是显示顺序不同而已。 通过我们这种方法,怎么可能会达到那种效果呢?
    确实,通过布局动画,没办法控制每一个Item在加载时才显示动画。那该如何是好呢?
    兄弟们,换个思路吧,如果布局动画完成不了,何必不直接用简单的补间动画,再结合每个列表项的显示控制,来实现窝牛装修列表显示的效果呢? 
    那有人会问了,怎么知道每一个列表项何时才加载么?
    你难道忘了BaseAdapter的getView()方法了么?
    没错,每当一个列表项显示时,都会主动调用BaseAdaper的getView()方法。

二、仿窝牛装修List列表的动画效果
    首先,我们定义一个动画资源,该动画即是列表项显示时的动画:woniu_list_item.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
  android:interpolator="@android:anim/accelerate_interpolator"
  >
  <!--  woniu list item animation  --> 

  <translate
    android:duration="500"
    android:fromXDelta="0"
    android:fromYDelta="100"
    android:toXDelta="0"
    android:toYDelta="0" />
</set>

该平移动画表示,从下往上,垂直平移100px,时间为500毫秒。
    接下来,我们需要在BaseAdapter的getView()方法里,去使用该动画:

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView; 

import java.util.List; 

public class WoniuListAdapter extends BaseAdapter { 

  private Context mContext; 

  private LayoutInflater mInflater; 

  private List<WoniuSimple> mDatas; 

  private Animation animation; 

  public WoniuListAdapter(Context context, List<WoniuSimple> datas) {
    mContext = context;
    mInflater = LayoutInflater.from(mContext);
    mDatas = datas; 

    animation = AnimationUtils.loadAnimation(mContext, R.anim.woniu_list_item);
  } 

  @Override
  public int getCount() {
    return (mDatas != null ? mDatas.size() : 0);
  } 

  @Override
  public Object getItem(int position) {
    return (mDatas != null ? mDatas.get(position) : null);
  } 

  @Override
  public long getItemId(int position) {
    return position;
  } 

  @Override
  public View getView(final int position, View convertView, ViewGroup parent) {
    ViewHolder holder = null;
    int type = getItemViewType(position);
    if (convertView == null) { 

      // 下拉项布局
      convertView = mInflater.inflate(R.layout.list_item_woniu, null); 

      holder = new ViewHolder(); 

      holder.tem_img = (ImageView) convertView.findViewById(R.id.tem_img);
      holder.text_name = (TextView) convertView.findViewById(R.id.text_name);
      holder.text_name = (TextView) convertView.findViewById(R.id.text_name); 

      convertView.setTag(holder); 

    } else {
      holder = (ViewHolder) convertView.getTag();
    } 

    convertView.startAnimation(animation); 

    final WoniuSimple materialSimple = mDatas.get(position); 

    if (materialSimple != null) {
//      holder.tem_img.setImageResource(R.mipmap.assist_default_img);
//      holder.text_name.setText(materialSimple.name);
//      holder.text_mobile.setText(materialSimple.mobile);
    } 

    return convertView;
  } 

  class ViewHolder { 

    ImageView tem_img; 

    TextView text_name; 

    TextView text_mobile;
  } 

}

我们来简要分析应用动画的地方: 1、我们Adapter的构造方法里加载了之前定义的动画,活的Animation对象。 2、 我们在getView方法里,为convertView设置并启动Animation,即convertView.startAnimation(animation)。
    够简单吧,只是这么两行代码,就可以实现在加载每一个View Item时启动动画效果。
    可是,我们发现,这并不是非常完美的实现,为啥这么说呢?
    因为你此刻往上滑动列表,会发现,已经加载过的Item的动画还会再次启动执行一次。这个体验太糟糕了。为啥会出现这种情况啊?
    因为getVIew方法的调用时机会对动画产生影响。Adapter中的getView方法,会在每一个item处于可见状态时调用,所以无论你上滑还是下滑,都会重复调用getView方法(这也是ListView为啥在使用时要进行优化的地方)。
    所以,为了解决刚刚发生的问题,我们可以设置标识,进行判断,已经加载过的view的动画不再进行启动加载。
    完整的代码如下:

package com.lnyp.layoutanimation; 

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView; 

import java.util.HashMap;
import java.util.List;
import java.util.Map; 

public class WoniuListAdapter extends BaseAdapter { 

  private Context mContext; 

  private LayoutInflater mInflater; 

  private List<WoniuSimple> mDatas; 

  private Animation animation; 

  private Map<Integer, Boolean> isFrist; 

  public WoniuListAdapter(Context context, List<WoniuSimple> datas) {
    mContext = context;
    mInflater = LayoutInflater.from(mContext);
    mDatas = datas; 

    animation = AnimationUtils.loadAnimation(mContext, R.anim.woniu_list_item);
    isFrist = new HashMap<Integer, Boolean>();
  } 

  @Override
  public int getCount() {
    return (mDatas != null ? mDatas.size() : 0);
  } 

  @Override
  public Object getItem(int position) {
    return (mDatas != null ? mDatas.get(position) : null);
  } 

  @Override
  public long getItemId(int position) {
    return position;
  } 

  @Override
  public View getView(final int position, View convertView, ViewGroup parent) {
    ViewHolder holder = null;
    int type = getItemViewType(position);
    if (convertView == null) { 

      // 下拉项布局
      convertView = mInflater.inflate(R.layout.list_item_woniu, null); 

      holder = new ViewHolder(); 

      holder.tem_img = (ImageView) convertView.findViewById(R.id.tem_img);
      holder.text_name = (TextView) convertView.findViewById(R.id.text_name);
      holder.text_name = (TextView) convertView.findViewById(R.id.text_name); 

      convertView.setTag(holder); 

    } else {
      holder = (ViewHolder) convertView.getTag();
    } 

    // 如果是第一次加载该view,则使用动画
    if (isFrist.get(position) == null || isFrist.get(position)) { 

      convertView.startAnimation(animation);
      isFrist.put(position, false);
    } 

    final WoniuSimple materialSimple = mDatas.get(position); 

    if (materialSimple != null) {
//      holder.tem_img.setImageResource(R.mipmap.assist_default_img);
//      holder.text_name.setText(materialSimple.name);
//      holder.text_mobile.setText(materialSimple.mobile);
    } 

    return convertView;
  } 

  class ViewHolder { 

    ImageView tem_img; 

    TextView text_name; 

    TextView text_mobile;
  } 

}

看到了么,加了一个isFirst进行判断,这样,就可以有效控制动画的显示了。效果如下:

本文我主要介绍了两个部分,一个是Layout Animation布局动画,使用布局动画可以控制VIew Groups中的每一个数据的显示动画; 还一个就是实战,仿“窝牛装修”ListView滑动时每一个Item滑动进入可见状态的动画效果。通过这两个动画示例,我相信可以帮助大家更好的处理动画,克服“动画恐惧症”。

希望本文所述对大家学习有所帮助,大家也会喜欢,小编一定会再接再厉,为大家分享更多精彩的文章。

(0)

相关推荐

  • LayoutAnimation给ListView中的item设置动态出场效果(实例)

    LayoutAnimation作用于ViewGroup,为ViewGroup指定一个动画,当它的子元素出场时都按照这个动画出场. LayoutAnimation作用于viewgroup有两种方式: 1. 静态的使用xml文件实现. 2. 在代码中动态实现. 下面用ListView中的item设置动态出场效果来分别介绍两种方式: 静态的使用xml文件实现,分为三步 1. 在res的anim目录(res的文件夹下没有anim文件夹自己新建一个)下定义LayoutAnimation命名为anim_la

  • Android Animation实战之一个APP的ListView的动画效果

    熟悉了基础动画的实现后,便可以试着去实现常见APP中出现过的那些精美的动画.今天我主要给大家引入一个APP的ListView的动画效果: 当展示ListView时,Listview的每一个列表项都按照规定的动画显示出来. 说起来比较抽象,先给大家看一个动画效果,这是APP窝牛装修的ListView显示动画: 有木有觉得很酷炫?有木有啊!? 一.Layout Animation     所谓的布局动画,其实就是为ViewGroup添加显示动画效果,主要用过LayoutAnimationContro

  • Android studio创建第一个app

    本文实例为大家介绍了Android studio创建第一个app的详细步骤,供大家参考,具体内容如下 1.创建HelloWorld项目 任何编程语言写出的第一个程序毫无疑问都会是Hello World,这已经是自20世纪70年代一直流传下来的传统,在编程界已成为永恒的经典,那么今天就来使用Android studio创建第一个app(Hello World). 首先运行Android studio,在弹出的快捷窗口中新建一个项目. 点击上面截图中的"Star a new Android Stud

  • Android编程实现ViewPager多页面滑动切换及动画效果的方法

    本文实例讲述了Android编程实现ViewPager多页面滑动切换及动画效果的方法.分享给大家供大家参考,具体如下: 一.首先,我们来看一下效果图,这是新浪微博的Tab滑动效果.我们可以手势滑动,也可以点击上面的头标进行切换.与此同方式, 白色横条会移动到相应的页卡头标下.这是一个动画效果,白条是缓慢滑动过去的.好了,接下来我们就来实现它. 二.在开始前,我们先要认识一个控件,ViewPager.它是google SDk中自带的一个附加包的一个类,可以用来实现屏幕间的切换. 这个附加包是and

  • Android实现游戏中的渐隐和渐现动画效果

    1实现渐隐的动画 在程序中实现可以通过如下方式 View view = new View(context);//执行动画的View AlphaAnimation aa = new AlphaAnimation(1.0f, 0.0f);//创建一个AlphaAnimation 对象,渐变从1->0 aa.setDuration(1500);//设置持续时间 aa.setFillAfter(true);//设置这个View最后的状态,由于是从1->0,所以最后的是消失状态(最后是看不到见这个Vie

  • Vue仿微信app页面跳转动画效果

    10:14:11独立开发者在开发移动端产品时,为了更高效,通常会使用Web技术来开发移动端项目,可以同时适配Android.iOS.H5,稍加改动还可适配微信小程序. 在使用Vue.js开发移动端页面的时候,默认的组件转场效果过于生硬,根本就没有动画效果.于是我用Vue提供的组件过渡功能,写了个仿微信app页面跳转的动画,以提高用户体验. 废话不多说,直接上图 在600元骁龙632安卓测试机效果流畅. 代码量很少,已上传至GitHub https://github.com/YellowDoing

  • Flutter实战教程之酷炫的开关动画效果

    前言 此动画效果是我在浏览文章时发现的一个非常酷炫的效果,于是就使用 Flutter 实现了. 更多动画效果及Flutter资源: https://github.com/781238222/flutter-do 添加依赖 在项目的 pubspec.yaml 文件中添加依赖: dependencies: wheel_switch: ^0.0.1 执行命令: flutter pub get 使用 WheelSwitch( value: false, ) 组件默认的宽高分别是80.30,也可以指定宽高

  • Android中实现ProgressBar菊花旋转进度条的动画效果

    在一些常见到的加载中需要显示一个加载动画,如旋转的菊花,旋转的圈圈等等动画-,然后我们现在就来说下怎么去试下它吧 一.菊花的旋转动画 1.新建一个drawable文件 在res/drawable下新建一个progressbar_style.xml文件定义一个旋转动画 <animated-rotate xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable

  • 教你用vue实现一个有趣的围绕圆弧动画效果

    目录 1.0 原官网示例 2.0 我们实现的结果 3.0 简单分析下 4.0 代码实现 5.0 总结 前几天在好朋友楼上小黑的介绍下,看到了某个平台的官网,里面有一个人物介绍的模块,里面的动画感觉不错,于是就自己动手写了一个. 1.0 原官网示例 当然这里去掉了具体信息,原网站是里面圆圈中是人物的头像,旁边是介绍信息,每个人物就沿着圆弧移动到指定位置 2.0 我们实现的结果 当点击中间开始时,几个小球一次转动到固定角度 3.0 简单分析下 要让小圆在圆弧上动,我们只需要知道圆心在圆弧上的坐标(x

  • 利用JavaScript制作一个搞怪的兔子动画效果

    目录 前言 实现 效果图 前言 Hello,掘友们好!又是一年新春之际,祝福大家兔年快乐!给大家介绍一个有趣的动效(兼容 IE),页面右下角有一只搞怪的兔子,鼠标在页面中悬停时,兔子会跟着做出不同的动作和表情.然后可以在页面中任意位置(离兔子太近不能发射,会伤到兔子)点击鼠标,将从兔子眼睛里发射炮弹,随之击中的是你的霉 运.压 力.贫 穷.疾 病. 实现 定义一个随机文本块. <p id="p1"></p> 定义兔子的构造函数. function HoverRa

  • Android Animation实战之屏幕底部弹出PopupWindow

    Android动画的一个实战内容,从屏幕底部滑动弹出PopupWindow. 相信这种效果大家在很多APP上都遇到过,比如需要拍照或者从SD卡选择图片,再比如需要分享某些东西时,大多会采用这么一种效果: 那这种效果如何实现呢? 我们仿写一个这种效果的实例吧: 1)我们首先定义一下,弹出窗口的页面布局组件:take_photo_pop.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout

随机推荐