Android 精华读书Android技术知识

Hacks动画篇-Hack5 附加Ken Burns特效的幻灯片

2016-05-13  本文已影响499人  diygreen
Ken Burns特效

作者:李旺成

时间:2016年5月12日


在该 Hack 中将介绍如何实现 Ken Burns 特效来展示图片。

Ken Burns 特效

先来理解一下概念,什么是 Ken Burns 特效?

Ken Burns 特效,是视频产品中使用的一种平移和缩放的静态图片的特效。想了解更多,Wiki 上有比较详细的介绍:Ken Burns effect

这不是我们的重点,重点是这到底是一种什么样的效果?Wiki 上给出下面的示意图:

Ken Burns 特效

还是没概念?是的,最直观的方式是看真实的效果,可以去看看这段视频:Wiki Ken Burns effect 视频

简而言之
Ken Burns 特效是一种图片在切换之前,会缓慢在页面移动或者放大缩小,然后再慢慢切换过去。这样的效果使得每一张静止图片都有动态的效果感觉。类似的效果在电子相册,或者在电影视频对静态图片的处理中经常可见。(参考自:KenBurnsView:实现Ken Burns effect图片展示效果的效果android控件

模拟 Ken Burns 特效

先看效果:

Ken Burns特效

要实现上面的效果,需要用到 JakeWharton 大牛的 NineOldAndroids 库。该库的作用是可以让老版本的 Android (3.0 以下的版本)使用属性动画。当然,如果你不考虑兼容 Android 3.0 以下版本就用不到这个库了。

思路分析

先分析一下 Ken Burns 特效:使用缩放动画,可能同时伴随平移动画来展示当前图片,当该图片的动画展示显示完毕之后,就开始显示下一张图片并展示动画。

那么有个简单的思路:使用 ImageView 展示图片,为该 ImageView 设置一些动画,当该图片的动画结束后,切换下一张图片。

创建 Ken Burns 特效

1、创建布局
主布局使用 FrameLayout,直接把 ImageView 添加到布局中填充整个父控件。这里采用代码的方式创建,看代码:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mContainer = new FrameLayout(this);
    mContainer.setLayoutParams(new FrameLayout.LayoutParams(
            FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT));

    mView = createNewView();
    mContainer.addView(mView);

    setContentView(mContainer);
}

private ImageView createNewView() {
    ImageView ret = new ImageView(this);
    ret.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
            FrameLayout.LayoutParams.MATCH_PARENT));
    ret.setScaleType(ImageView.ScaleType.FIT_XY);
    ret.setImageResource(PHOTOS[mIndex]);
    mIndex = (mIndex + 1 < PHOTOS.length) ? mIndex + 1 : 0;
    return ret;
}

代码比较简单
首先,创建一个 FrameLayout 布局容器
然后,创建 ImageView,从保存图片资源 ID 的数组中根据索引取出图片,将其设置给 ImageView
最后,将 ImageView 添加到 FrameLayout 中,将该 FrameLayout 设置为 Activity 的 ContentView。

2、开始播放动画
在 Activity onResume 的时候开始播放动画:

@Override
protected void onResume() {
    super.onResume();
    nextAnimation();
}

看看负责播放动画的代码:

private void nextAnimation() {
    AnimatorSet anim = new AnimatorSet();
    // 生成随机数,实现随机播放动画
    final int index = mRandom.nextInt(ANIM_COUNT);
    switch (index) {
        case 0:
            // 缩放动画
            anim.playTogether(
                    ObjectAnimator.ofFloat(mView, "scaleX", 1.5f, 1f),
                    ObjectAnimator.ofFloat(mView, "scaleY", 1.5f, 1f));
            break;
        case 1:
            // 缩放动画
            anim.playTogether(
                    ObjectAnimator.ofFloat(mView, "scaleX", 1, 1.5f),
                    ObjectAnimator.ofFloat(mView, "scaleY", 1, 1.5f));
            break;
        case 2:
            AnimatorProxy.wrap(mView).setScaleX(1.5f);
            AnimatorProxy.wrap(mView).setScaleY(1.5f);
            // 位移动画
            anim.playTogether(ObjectAnimator.ofFloat(mView,
                    "translationY", 80f, 0f));
            break;
        case 3:
        default:
            AnimatorProxy.wrap(mView).setScaleX(1.5f);
            AnimatorProxy.wrap(mView).setScaleY(1.5f);
            // 位移动画
            anim.playTogether(ObjectAnimator.ofFloat(mView,
                    "translationX", 0f, 40f));
            break;
    }
    // 设置动画持续时间
    anim.setDuration(3000);
    // 设置动画监听器
    anim.addListener(this);
    // 播放动画
    anim.start();
}

上面的代码就是设置一些属性动画,对这方面不是很了解的,后面我会专门写几篇关于动画方面学习的总结(AndroidStudyDemo 系列)。

补充说明:
AnimatorProxy 类,是 NineOldAndroids 库中的一个工具类,用于修改 View 对象的属性。该动画框架的基础是:视图的属性随时间的推移而改变(所谓的属性动画,就是随着时间的推移改变对象的属性,而产生动画效果)。之所以使用AnimatorProxy类,是因为在 Android 3.0 以下版本,有些属性没有 setters 或 getters 方法。(参考自:《50 Android Hacks》)

3、切换图片播放下一张图片
这里是这样处理的,监听动画播放,当动画结束时,删除当前的 ImageView,添加新的 ImageView,然后播放动画。代码如下:

// 实现动画监听接口
public class KenBurnsActivity extends AppCompatActivity implements Animator.AnimatorListener

...

// 实现接口中的方法
@Override
public void onAnimationCancel(Animator arg0) {
}

@Override
public void onAnimationEnd(Animator animator) {
    mContainer.removeView(mView);
    mView = createNewView();
    mContainer.addView(mView);
    nextAnimation();
}

@Override
public void onAnimationRepeat(Animator arg0) {
}

@Override
public void onAnimationStart(Animator arg0) {
}

小结

这里用到了两个技术:

项目地址

AndroidHacks合集
动画篇

项目示例代码:
KenBurnsActivity.java

参考

Ken Burns effect
KenBurnsView:实现Ken Burns effect图片展示效果的效果android控件

上一篇下一篇

猜你喜欢

热点阅读