2015-03-16 11:42:19 luoxianli2011 阅读数 484

BaseAnimation收集网络Android相关动画集合,自定义控件等,近200多种源码 BaseAnimation

下载地址:https://github.com/z56402344/BaseAnimation

1.3 版本更新内容:

1.Splash增加2个动画

2.高仿动画效果增加10个

3.ListView集合增加15个

4.自定义控件集合增加17个

5.页面滑动增加4个

共增加48个动画效果

1.2 版本更新内容:

1.增加Splash动画 (中心打开式效果 )

2.增加Flip折叠效果的集合(13种)

3.增加NineOld集合(18+)

4.高仿系列(6种经典动画)

火车票出票动画淘宝菜单优酷导航菜单图片3D浏览下拉选择框扫雷效果

5.增加新版本消息栏提醒功能

6.优化部分代码

1.1 版本更新内容

首页

1.简单动画(24)

2.复杂动画(43)

3.Splash引导动画(5)


2015-06-27 17:21:41 marktheone 阅读数 8396

official site:http://facebook.github.io/rebound

github : https://github.com/facebook/rebound

Rebound是facebook推出的一个弹性动画库,可以让动画看起来真实自然,像真实世界的物理运动,带有力的效果,使用的参数则是facebook的origami中使用的。

官网上有一个简单的JS版本来做demo,如果说到evernote、LinkedIn、flow等应用也在使用这个动画库,是不是会显得更厉害些呢。

Spring spring = mSpringSystem
        .createSpring()
        .setSpringConfig(SpringConfig.fromOrigamiTensionAndFriction(86, 7))
        .addListener(new SimpleSpringListener() {
            @Override
            public void onSpringUpdate(Spring spring) {
                float value = (float) spring.getCurrentValue();
                ViewHelper.setTranslationX(view, value);
            }
        });

 上面的短短代码就可以给一个view加上自然的从左向右进入回弹效果。

类似地

Spring spring = mSpringSystem
        .createSpring()
        .setSpringConfig(SpringConfig.fromOrigamiTensionAndFriction(86, 7))
        .addListener(new SimpleSpringListener() {
            @Override
            public void onSpringUpdate(Spring spring) {
                float value = (float) spring.getCurrentValue();
                float scale = 1f - value;
                ViewHelper.setScaleX(mItemIconViewList.get(index), scale);
                ViewHelper.setScaleY(mItemIconViewList.get(index), scale);
            }
        });

 就可以给view加上一个从小变大然后略有回弹的效果。

如果想要做很多view的连锁动画怎么办?Rebound也提供了SpringChain这个接口。

for (int i = 0; i < viewCount; i++) {
    final View view = new View(context);
    view.setLayoutParams(
            new TableLayout.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT,
                    1f));
    mSpringChain.addSpring(new SimpleSpringListener() {
        @Override
        public void onSpringUpdate(Spring spring) {
            float value = (float) spring.getCurrentValue();
            view.setTranslationX(value);
        }
    });
    int color = (Integer) evaluator.evaluate((float) i / (float) viewCount, startColor, endColor);
    view.setBackgroundColor(color);
    view.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            return handleRowTouch(v, event);
        }
    });
    mViews.add(view);
    rootView.addView(view);
}

getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        getViewTreeObserver().removeOnGlobalLayoutListener(this);
        List<Spring> springs = mSpringChain.getAllSprings();
        for (int i = 0; i < springs.size(); i++) {
            springs.get(i).setCurrentValue(-mViews.get(i).getWidth());
        }
        postDelayed(new Runnable() {
            @Override
            public void run() {
                mSpringChain
                        .setControlSpringIndex(0)
                        .getControlSpring()
                        .setEndValue(0);
            }
        }, 500);
    }
});

 就做出了一个view和view的牵引位移动画效果。


2017-03-19 23:44:34 github_37977199 阅读数 1121

惊艳的Lottie

前段时间airbnb开源的动画库Lottie得到了不错的反响,旨在解决Android、IOS、RN 上面开发动画成本高、表现不一致的问题,可以说降低了三端动画的开发成本。

项目地址:https://github.com/airbnb/lottie-android

先上几个git上的效果:

img
img

如果需要在3端都分别完成这些动画,可能就需要折磨设计&开发同学了。人肉写出这些效果简直是处女座也无法完成的一件事。
Lottie在这件事上就是来拯救移动开发程序员的。

思路

Lottie借助AE生成动画,再利用AE插件bodymovin来导出可描述的json文件,而Lottie负责在不同端上解析json文件完成动画的绘制。

从设计思路上可以看出,这确实是一个很好的解法,Lottie抹平了各端的差异性,通过统一描述(JSON)来表述动画。这看上去和近年来很火的Weex思路一致。

作为一个Android搬砖程序员,接下来的篇幅主要以Lottie Android SDK(ios也不会呀~~~)来分析一下Lottie的解法。

Lottie Android Useage

先来感受一下用法,感觉还是很清爽的:
Dependency:
java
compile 'com.airbnb.android:lottie:1.5.3'

使用lottie_fileName="hello-world.json"来指定动画路径,也可以使用:setAnimation("hello-world.json")来指定。
java
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/animation_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:lottie_fileName="hello-world.json"
app:lottie_loop="true"
app:lottie_autoPlay="true" />

or
java
LottieAnimationView animationView = (LottieAnimationView) findViewById(R.id.animation_view);
animationView.setAnimation("hello-world.json");
animationView.loop(true);

然后你就可以像使用普通动画对待Lottie了。

原理浅析

绘制

我们先从能接触到的类com.airbnb.lottie.LottieAnimationView看起,所有的逻辑处理、json解析、绘制工作都在这里完成。

img

可以看到这个是AppCompatImageView,里面有个很重要的变量:

LottieDrawable lottieDrawable;

LottieAnimationView在初始化时会调用setImageDrawable(lottieDrawable);方法,使用LottieDrawable作为ImageDrawable。并且同时重写invalidateDrawable方法,当需要invalidate时通知lottieDrawable。

img

LottieDrawable

img

从类结构看,继承自AnimatableLayer,里面实现了Drawable需要实现的方法,主要是public void draw(@NonNull Canvas canvas)用来实现Drawable的绘制工作。

我们先来看看父类 AnimatableLayer 定义了什么行为。

首先当然是来看最重要的:draw

  public void draw(@NonNull Canvas canvas) {
    int saveCount = canvas.save();
    applyTransformForLayer(canvas, this);

    int backgroundAlpha = Color.alpha(backgroundColor);
    ...
    canvas.drawRect(getBounds(), solidBackgroundPaint);
    for (int i = 0; i < layers.size(); i++) {
      layers.get(i).draw(canvas);
    }
    canvas.restoreToCount(saveCount);
  }
  void applyTransformForLayer(@Nullable Canvas canvas, AnimatableLayer layer) {
    ...
    PointF position = layer.transform.getPosition().getValue();
    canvas.translate(position.x, position.y);
     //省略 rotation scale anchorPoint等变换
  }

可以看到,在绘制前,调用applyTransformForLayer对画布canvas进行了transform操作。接着绘制backgroundlayers

而layers的定义是:final List<AnimatableLayer> layers = new ArrayList<>(); 每一层,都是一个AnimatableLayer对象。

我们来看看AnimatableLayer的子类。

img

我们目前大概可以分析出,Lottie 根据JSON 构造了一个树形结构,root节点是LottieDrawable,将绘制的元素添加到了LottieDrawable.layers中。递归的描述每一个元素。

我们接着看“root”:LottieDrawable都做了些什么。

让Drawable“动起来”

由于Drawable本身只是负责绘制工作,并不会像动画一样,有start、end、duration等属性。因此在LottieDrawable引入了一个简单的animator = ValueAnimator.ofFloat(0f, 1f)来解决这个问题。

img

所有对动画的操作(repeat、start),都是对这个ValueAnimator元素的操作。

setProgerss

img

从上面可以看到,调用父类AnimatableLayersetProgerss会通知animations、layers。之前我们已经了解过layers,那么animations是什么呢?来看定义:

private final List

BaseKeyframeAnimation

BaseKeyframeAnimation<?, ?>从字面意思大概是用来描述关键帧的动画。

做过动画的朋友大概清楚“关键帧”的概念。BaseKeyframeAnimation的意义就是存放了一个动画中所有的关键帧,以及每一帧的过度进度。

img

  • listeners可以注册对动画的监听,当外界调用setProgerss时,会通知给监听者。
  • keyframes 存放了当前动画所有关键帧。

最终对外的方法是:

abstract A getValue(Keyframe keyframe, float keyframeProgress);

从入参看很清晰,传入了当前所在的关键帧,以及帧进度。

KeyFrame

KeyFrame是对每一帧的描述,字段如下:

img

  • LottieComposition是当前帧的所有数据,我们后面会讲到。

并且提供了静态工厂方法来生成一个KeyFrame。将JSON文件解析成一个KeyFrame对象。

img

setTransform

前面提到的animations是在何时注册的呢?

我们在AnimatableLayer.setTransform方法中看到了注册方法。具体如下:


KeyframeAnimation.AnimationListener<PointF> pointChangedListener = ()->invalidateSelf();

void setTransform(TransformKeyframeAnimation transform) {
    BaseKeyframeAnimation<?, PointF> anchorPoint = transform.getAnchorPoint();
    ...
    anchorPoint.addUpdateListener(pointChangedListener);
    addAnimation(opacity);
    invalidateSelf();
  }

可以看到,在addAnimation后以及 注册的updatelistener中调用了invalidateSelf()方法。而invalidateSelf()方法会触发draw流程。draw 会递归的调用layers进行绘制。由于每一个layer都拥有当前的 progress,因此就可以正确的绘制出来啦。

JSON 解析

解析工作在调用animationView.setAnimation后,就开始了。

JSON 解析 会用InputStream异步读取json内容,经过处理后封装成LottieComposition对象。

img

当加载完成后,会回调animationView.setComposition方法。animationView会接着调用LottieDrawable.setComposition

void setComposition(LottieComposition composition) {
    ...
    buildLayersForComposition(composition);
     ...
 }

buildLayersForComposition

这里完成了前面提到的 layers的构建:

private void buildLayersForComposition(LottieComposition composition) {
    ...
    LongSparseArray<LayerView> layerMap = new LongSparseArray<>(composition.getLayers().size());
    List<LayerView> layers = new ArrayList<>(composition.getLayers().size());
    LayerView mattedLayer = null;
    for (int i = composition.getLayers().size() - 1; i >= 0; i--) {
      Layer layer = composition.getLayers().get(i);
      LayerView layerView;
      layerView = new LayerView(layer, composition, this, canvasPool);
      layerMap.put(layerView.getId(), layerView);
      if (mattedLayer != null) {
        mattedLayer.setMatteLayer(layerView);
        mattedLayer = null;
      } else {
        layers.add(layerView);
        if (layer.getMatteType() == Layer.MatteType.Add) {
          mattedLayer = layerView;
        } else if (layer.getMatteType() == Layer.MatteType.Invert) {
          mattedLayer = layerView;
        }
      }
    }

    for (int i = 0; i < layers.size(); i++) {
      LayerView layerView = layers.get(i);
      addLayer(layerView);
    }

    for (int i = 0; i < layerMap.size(); i++) {
      long key = layerMap.keyAt(i);
      LayerView layerView = layerMap.get(key);
      LayerView parentLayer = layerMap.get(layerView.getLayerModel().getParentId());
      if (parentLayer != null) {
        layerView.setParentLayer(parentLayer);
      }
    }
  }

里面做了一次转换,构造了一个LayerView对象,这个是关键所在。

LayerView

LayerView也是继承自 AnimatableLayer。 完成了所有Layer类型的转换。

在初始化方式中会调用:setupForModel();方法。

private void setupForModel() {
    ...
    switch (layerModel.getLayerType()) {
      case Shape:
        setupShapeLayer();
        break;
      case PreComp:
        setupPreCompLayer();
        break;
    }
    ...
}


private void setupShapeLayer() {
    List<Object> reversedItems = new ArrayList<>(layerModel.getShapes());
    ...
    for (int i = 0; i < reversedItems.size(); i++) {
      Object item = reversedItems.get(i);
      if (item instanceof ShapeGroup) {
        GroupLayerView groupLayer = new GroupLayerView((ShapeGroup) item, currentFill,
            currentStroke, currentTrim, currentTransform, getCallback());
        addLayer(groupLayer);
      } else if (item instanceof AnimatableTransform) {
        currentTransform = (AnimatableTransform) item;
      }
      ...more
  }

摘取了setupShapeLayer的代码片段,里面会根据不同的数据类型,生成不同的LayerView,这些细节就不再做细究了。

总结

  1. 绘制:Lottie 使用 ImageView.Drawable来处理动画。使用统一Canvas来绘制。
  2. 动画控制:借助一个ValueAnimator来控制动画的进度,通过一系列监听器来通知Drawable进行绘制(draw)。
  3. 资源转换:将JSON文件经过处理得到LottieComposition对象,包括了每一层动画对象、资源(images)等信息。

img

写在最后

首先给Lottie的工程师一个star。

本文只是对Lottie的主要逻辑进行了梳理,没有梳理动画格式之类,里面比较复杂的的部分是不同的Layer的绘制、KeyFrame的计算。这部分由于对AE以及bodymovin不太了解就没有深究了。旨在掌握Lottie的大体设计。如有错误之处,请指出。

最后吐槽一波Lottie的代码结构,虽然源码不多,但是这个一层结构。。。。

img

2015-12-08 19:32:23 u013504718 阅读数 1008

简单实用的Android交互动画库SpringingLayout

一直以来我都对Android界面效果和交互动画特别的着迷,而且每次做工程都需要重写一大堆的组件,动画,感觉颇为繁杂,于是趁着有空闲做了一套交互动画的库,现在只是第一版,支持的交互动画不是特别的多,后续会不断的进行增加和修改Bug,所以先不开源了(jar包引入工程后可以看到代码),只提供示例程序和jar包给大家试用下~

github地址(记得加星哟~): https://github.com/dayiming/SpringingLayout

这里写图片描述

主要支持功能:

  1. 组件的上下左右方向的随手指的弹动
  2. 组件的点击弹动效果
  3. 组件的跳动警告
  4. 组件的旋转警告
  5. 组件指定方向的点击弹出,松手回弹
  6. 5.0水波效果
  7. 透明度变化的显示组件和隐藏组件
  8. 位移变化的显示组件和隐藏组件

主要支持的控件:

  1. Button
  2. EditText
  3. ImageView
  4. ListView
  5. TextView
  6. FrameLayout
  7. HorizontalScrollView
  8. ScrollView
  9. LinearLayout
  10. RelativeLayout

支持4.0以上Android系统(夭寿啊~还需要兼容4.0以下啊)这些功能都可以被随意的组合和添加到我重写的控件上面,如果觉的控件和动画不够使用,可以仿照我的代码重写其他组件和动画,十分的方便,如果发现任何Bug和不足请大家给我评论,我会持续不断的更新和加强这个控件的。

github地址(记得加星哟~): https://github.com/dayiming/SpringingLayout

2019-07-13 09:56:13 SophieBryant 阅读数 53

目录

一:Lottie

二:Spruce Android Animation Library

三:InfiniteCards

 

一:Lottie

简介:Lottie是一个可以播放由AE打包的json动画文件的开源库,使用它,你可以简单实现播放利用AE制作的动画。(其实Lottie的本质就是解析.json文件并通过Canvas方式进行绘制动画)

Start: 2.6 k

支持类型:Anddroid , IOS ,Web

支持功能:支持 Android 系统动画,还可以制作不同的复杂类型动画。

 

二:优缺点

优点:

  1. 能够解析渲染通过 AE 上的 Bodymovin 插件将 AE 中制作好的动画导出成的 json 文件
    (2)数据源多样性—可从assets,sdcard,网络加载动画资源,动态更新
    (3)跨平台—设计稿导出一份动画描述文件,android,ios,react native通用(android使用的api不能低于16)

(4) 同一个通话文件可以在不同的品台上实现动画,极大的加少了开发成本和开发人员的工作量。

 

缺点:开始倒入配置和设置配置比较容易出错;太多层级的时候会出现偶尔的卡顿。

 

 

二:Spruce Android Animation Library

简介:Spruce 是一个轻量级的动画库,可以帮助排版屏幕上的动画。使用有很多不同的动画库时,开发人员需要确保每个视图都能够在适当的时间活动。 Spruce 可以帮助设计师获得复杂的多视图动画,而不是让开发人员在原型阶段就感到畏惧

Start:3.1k

支持类型:Android  IOS

支持功能:可完成复杂的多视图动画

 

二:优缺点

优点:

  1. 能完成复杂类型的动画效果

(2)框架比较轻量级,占用的内存较少

缺点:实现多试图动画添没有处理好排版问题,有可能出现卡顿。

 

 

三:InfiniteCards

简介:可自定义动效的卡片切换试图,该库有助于实现卡片UI ,然后用一个漂亮的动画切换它们。

Start:1.4k

支持类型:Android  

支持功能:单独的实现卡片切换动画效果

 

优点:一个专门实现卡片切换的库,使用简单,效果较好,可实现左右切换和上下切换。

Android Lottie动画库

阅读数 629

Android动画库

阅读数 546

动画库介绍博客

博文 来自: tiankongzaiweixiao
没有更多推荐了,返回首页