这篇文章主要讲解一个翻转切换内容的卡片效果,主要利用Camera和Matrix来实现,主要是为了加深对Camera和Matrix的理解,如果对Camera和Matrix不清楚地童鞋可以看我的上篇文章:Android中利用Camera与Matrix实现3D效果详解

好了,我们先看下效果吧 (效果的灵感来自:Dribbble):

项目github地址

欢迎star、fork。

实现思路:

一、主要应用Animation进行实现,创建一个继承自Animation的自定义动画,在applyTransformation()方法中进行逻辑判断。

二 、考虑到旋转180度后控件文字会是倒过来显示的,并且旋转360度后虽然文字正常显示了但效果不好,所以在applyTransformation方法中对角度进行动态的修改。

三、为了使外部可以在控件翻转过程中修改内容,在自定义的Animation中添加了监听接口,用于监听内容变化的时机。

四、外部控件调用startAnimation()方法即可使用。

具体实现

当然我们也可以用自定义控件的方式实现,但考虑到实现的复杂性和使用性,我没有选择。

知道了实现思路,那么我们开始着手开始吧:

第一步:自定义Animation,覆写initialize和applyTransformation方法

public class FlipCardAnimation extends Animation{
 @Override
    public void initialize(int width, int height, int parentWidth, int parentHeight) {

        super.initialize(width, height, parentWidth, parentHeight);
        mCamera = new Camera();
    }
    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {

    }
}

在initialize方法中初始化Camera对象。

第二步:在applyTransformation方法中实现逻辑:

  @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {

        final float fromDegrees = mFromDegrees;

        float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime);

        final float centerX = mCenterX;

        final float centerY = mCenterY;

        final Camera camera = mCamera;

        final Matrix matrix = t.getMatrix();

        camera.save();

        if (degrees>90 || degrees<-90){
            if (!isContentChange){
                if(listener!=null){
                    listener.contentChange();
                }
                isContentChange = true;
            }

            if (degrees>0) {
                degrees = 270 + degrees - 90;
            }else if (degrees<0){
                degrees = -270+(degrees+90);
            }
        }

        camera.rotateX(degrees);

        camera.getMatrix(matrix);

        camera.restore();

        matrix.preTranslate(-centerX, -centerY);

        matrix.postTranslate(centerX, centerY);
    }

在这里需要注意的地方是,当卡片顺时针或者逆时针旋转的时候对角度进行判断,当旋转大于90度或者小于-90度时,将之后的角度调整为270度到360度或者-270度到-360度之间,以此来实现卡片内容正常显示,如果不做处理,我们翻转过后的文字是倒过来显示的。

第三步:设置内容变化监听,方便外部对卡片内容做修改

 private OnContentChangeListener listener;

    public void setOnContentChangeListener(OnContentChangeListener listener) {
        this.listener = listener;
    }

    public interface OnContentChangeListener{
        void contentChange();
    }

为了确保外部每次开启动画内容都会变动,务必在开始之前调用方法setCanContentChange():

animation.setCanContentChange();

如果设置循环动画,则要在监听中设置setCanContentChange()方法:

animation.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {
                }
                @Override
                public void onAnimationEnd(Animation animation) {
                }
                @Override
                public void onAnimationRepeat(Animation animation) {
                    ((FlipCardAnimation)animation).setCanContentChange();
                }
            });

第四步:为控件设置并开启动画

这一步就比较简单了,都是常用的对Animation的设置:

animation = new FlipCardAnimation(0, degree, width, height);
            animation.setInterpolator(new AnticipateOvershootInterpolator());
            animation.setDuration(3000);
            animation.setFillAfter(false);
            animation.setRepeatCount(-1);//设置无限循环
            animation.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {
                }
                @Override
                public void onAnimationEnd(Animation animation) {
                }
                @Override
                public void onAnimationRepeat(Animation animation) {
                    ((FlipCardAnimation)animation).setCanContentChange();//如果设置循环,务必在这里添加这行代码
                }
            });
            animation.setOnContentChangeListener(new FlipCardAnimation.OnContentChangeListener() {
                @Override
                public void contentChange() {
                    if (iv_pro == null) {
                        return;
                    }
                    iv_pro.setBackgroundResource(DRAWABLE[num]);
                    tv_item.setText("¥" + new Random().nextInt(500));
                    tv_price_item.setText("Discount");
                }
            });
            llyt_item.startAnimation(animation);

到此,其实我们的翻转卡片效果就已经差不多完成了。在设置Animation的时候有setInterpolator()这个方法,interpolator插补器可以用来设置动画运动时的速率,插补器的原理就是通过改变实际执行动画的时间点,提前/延迟执行默认的时间点来达到加速/减速的效果。这里再多说下Interpolator的几个子类,也是为了自己以后记忆和查找,大家可以设置不同的插补器看下效果。

AccelerateDecelerateInterpolator 在动画开始与介绍的地方速率改变比较慢,在中间的时侯加速

AccelerateInterpolator 在动画开始的地方速率改变比较慢,然后开始加速

CycleInterpolator 动画循环播放特定的次数,速率改变沿着正弦曲线

DecelerateInterpolator 动画开始的地方快然后慢

LinearInterpolator 在动画的以均匀的速率改变

AnticipateInterpolator 向前插补器,开始的时候向后然后向前甩

AnticipateOvershootInterpolator 向前向后插补器,开始的时候向后然后向前甩,结束时向前甩一定值后再返回最后的值

OvershootInterpolator 超出插补器,结束时向前甩一定值后再回到原来位置

BounceInterpolator 动画结束的时候弹起

项目github地址:https://github.com/zhangke3016/FlipCards】如果觉得有趣欢迎star、fork。

利用Camera和Matrix实现有趣的卡片效果的更多相关文章

  1. Android中利用Camera与Matrix实现3D效果详解

    本文行文目录: 一.Camera与Matrix初步认识 二.Camera与Matrix旋转效果拆分介绍 三.Camera与Matrix实现立体3D切换效果 [csdn地址:http://blog.cs ...

  2. (转)利用 SVG 和 CSS3 实现有趣的边框动画

    目录 SVG 学习<一>基础图形及线段 SVG 学习<二>进阶 SVG世界,视野,视窗 stroke属性 svg分组 SVG 学习<三>渐变 SVG 学习<四 ...

  3. 60.自己定义View练习(五)高仿小米时钟 - 使用Camera和Matrix实现3D效果

    *本篇文章已授权微信公众号 guolin_blog (郭霖)独家公布 本文出自:猴菇先生的博客 http://blog.csdn.net/qq_31715429/article/details/546 ...

  4. 发现两个有趣的CSS3效果

    一.CSS3画机器猫 http://keleyi.com/keleyi/phtml/html5/3.htm 哆啦A梦效果图: 可用于浏览器对CSS3支持情况的测试 但最近有人对这个测试表示怀疑,指该测 ...

  5. ligerui_实际项目_001:利用ligerLayout、ligerAccordion实现可折叠的菜单效果

    效果:利用ligerLayout.ligerAccordion实现可折叠的菜单效果 可能用到的js.css.images等,可到官网下载: 第01步:引入相应的文件 <head><l ...

  6. 利用jquery+iframe做一个ajax上传效果

    以下是自学it网--中级班上课笔记 网址:www.zixue.it html页面 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict ...

  7. 实现卡片效果【DIV+CSS3】

    一.文字卡片效果 <html> <head> meta<charset="utf-8"> <title>文字卡片效果</tit ...

  8. WPF 有趣的动画效果

    WPF 有趣的动画效果         这一次我要呈上一个简单的文章,关于给你的WPF apps加入美丽的光线动画,可是我对动画这东西可能有点入迷了.         实际上.我对动画如此的入迷,以至 ...

  9. 利用 html2canvas 做个简单的诗词卡片生成器

    html2canvas 简介 html2canvas 顾名思义,就是一个可以把 DOM 元素转换成图片的类库,常用于网页截图.网页截图常见的应用场景是,在意见反馈里对当前页面进行截图,方便反馈页面出现 ...

随机推荐

  1. FZU 2158

    在密室逃脱游戏中,大家被困在一个密室中,为了逃出密室,需要找到正确的数字密码,于是大家分头行动,分别找到了密码的子序列,而后大家将得到的线索集中整理分析,大家想知道密码最少是多少位.  Input 第 ...

  2. python中不能写n++

    初学python发现写n++编译器直接报错,很纳闷,后来想起来python中的变量不像c那样事先定义好变量类型,在内存中开辟指定的空间,然后再开始赋值.在Python中,以字符串为例:事先在内存划分空 ...

  3. 网易互联网&网易游戏产品经理面试经验

    网易是分网易游戏和网易互联网的,本人都参加了校园招聘面试,最后均拿到了产品经理的offer. 网易是分网易游戏和网易互联网的,先说网易互联网吧,当时是去杭州总部进行面试,我觉得这是我面的最难的面试了. ...

  4. Postgresql查询最近12个月、最近30天数据

    -- 最近 12 个月 SELECT * FROM 表名 WHERE 日期字段 BETWEEN (now() - INTERVAL '12 months') AND now() -- 最近 30 天 ...

  5. jdk1.7和jdk1.8区别

    转自:http://www.2cto.com/kf/201307/225968.html 本文是我学习了解了jdk7和jdk8的一些新特性的一些资料,有兴趣的大家可以浏览下下面的内容. 官方文档:ht ...

  6. redis的基本数据类型

    一:redis是一个开源的,使用C语言编写,支持网络,可基于内存亦可持久化的日志型,key-value方式存储的nosql数据库.作为缓存服务器,速度效率都很快,和memcache相似 redis支持 ...

  7. 如何改变hr颜色

    html中用css改变颜色,<hr style="border:0;background-color:#ff0000;height:1px;">如果不加border:0 ...

  8. 深入理解Oracle中的随机函数

    --Oracle中取随机值的函数 .dbms_random包 dbms_random包提供了一系列的随机值获取函数以及相关存储过程.下面详细讲解常用的函数和过程. ()dbms_random.rand ...

  9. Qt与FFmpeg联合开发指南(二)——解码(2):封装和界面设计

    与解码相关的主要代码在上一篇博客中已经做了介绍,本篇我们会先讨论一下如何控制解码速度再提供一个我个人的封装思路.最后回归到界面设计环节重点看一下如何保证播放器界面在缩放和拖动的过程中保证视频画面的宽高 ...

  10. ACM Red and Black

    有一个矩形的房间,覆盖着方砖. 每个瓷砖都是红色或黑色. 一个男人站在黑色的瓷砖上,他可以移动到四个相邻的瓷砖之一.  但他不能在红砖上移动,他只能在黑砖上移动. 编写一个程序来计算他可以通过重复上述 ...