利用Camera和Matrix实现有趣的卡片效果_camera setanimationmatrix-程序员宅基地

技术标签: 3d  android进阶之路  android  android进阶  matrix  

FlipCards

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

FlipCards

项目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。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zhangke3016/article/details/52143339

智能推荐

每日一道python题(python数据结构课后习题(第一章1-4题))_一个雇员一周的总薪水,等于其每个小时的时薪,乘以其一周工作的正常小时数,再-程序员宅基地

文章浏览阅读5.1k次,点赞2次,收藏11次。python入门级小白,仅用来自我学习的,写的不恰当的地方请多指教。(python3.)1.编写一个程序,以球体的半径(浮点型)作为输入,并并且输出球体的直径,圆周长和表面积import mathr = float(input('请输入球体半径r:'))d = 2*rc= 4*math.pi*r**2v = 4/3*math.pi*r**3print("球体直径为%f\n球体表面积为%f\n球体体..._一个雇员一周的总薪水,等于其每个小时的时薪,乘以其一周工作的正常小时数,再

RabbitMQ输出日志配置_rabbitmq日志配置-程序员宅基地

文章浏览阅读1.7k次。参考地址。_rabbitmq日志配置

利用Tableau绘制各类图表_tableau图表-程序员宅基地

文章浏览阅读3.4k次,点赞5次,收藏42次。这是可视化Tableau部分汇总的一篇文章,细分可看细分单元。_tableau图表

penuppendown在python中是啥意思_Python turtle.pendown方法代碼示例-程序员宅基地

文章浏览阅读2.9k次。本文整理匯總了Python中turtle.pendown方法的典型用法代碼示例。如果您正苦於以下問題:Python turtle.pendown方法的具體用法?Python turtle.pendown怎麽用?Python turtle.pendown使用的例子?那麽恭喜您, 這裏精選的方法代碼示例或許可以為您提供幫助。您也可以進一步了解該方法所在模塊turtle的用法示例。在下文中一共展示了tu..._pendown在python是什么意思

adb帮助文档_adb中文文档-程序员宅基地

文章浏览阅读3.7k次。adb帮助文档_adb中文文档

解决qt_creator: this file is not part of any project问题-程序员宅基地

文章浏览阅读8.1k次,点赞2次,收藏2次。解决qt_creator: this file is not part of any project问题利用qt_creator导入已经生成好的ros workspace后,在此src下面添加文件会出现warning:this file is not part of any project 同时,代码在编写的时候会有报错,虽然编译可以正常通过并且代码能够正常运行,但是无法使用qt的代码补全功能。ROS_WIKI给出了这样的解释但是没有给出详细的解决方案,根据本人测试结果,通过重新构建整个项目,即可解_this file is not part of any project

随便推点

uni-app开发h5,打开h5自动播放视频_uniapp h5自动播放视频-程序员宅基地

文章浏览阅读3.3k次。使用标签,加上autoplay属性并没有用出于用户体验,节省流量的考虑,移动端禁止自动播放;使用过模拟用户点击操作,等等方法,并没有用。参考https://www.mzwu.com/article.asp?id=4411优酷页面打开后视频不自动播放,需用户点击按钮才开始播放,B站解决方法和优酷一样,爱奇艺页面打开后视频自动开始播放,但声音需用户手工开启,所以暂时不要去想什么hack的方法了,有办法这些大厂早用了,还是老老实实引导用户手工点一下吧。所以,加上静音播放属性muted,就可以打开h5自_uniapp h5自动播放视频

Android Studio中的Android项目调用第三方库so库_android 引用第三方库中的类-程序员宅基地

文章浏览阅读1k次。Android NDK开发中,除了可以通过自己编写C/C++代码来构建动态连接库进行调用之外,还可以通过直接调用现成的so库开进行NDK开发。接下来,我将介绍在Android Studio中如何调用第三方动态连接库。 首先需要考虑的是如何获得so库文件,这里介绍自己编译生成的方法。 在该项目的基础上http://blog.csdn.net/sinat_19385391/a_android 引用第三方库中的类

jvm堆中对象存活算法,内存泄漏,垃圾回收算法_垃圾回收算法,内存泄漏场景-程序员宅基地

文章浏览阅读235次。首先说面:下面所有内容都是针对jvm 中堆区域。堆里面对象的回收jvm自动帮我们实现的,但是我们也需要了解其原理。jvm堆中对象存活算法及其优缺点1 引用计数算法给对象增加引用计数器,每当有一个地方引用它时,计数器值加1;引用失效时,计数器值减1。当计数器的值为0时,代表可以回收了。但是很难解决对象之间的相互循环引用.2 可达性分析算法以一些称为”GC ROOTS”的节点作为起点,从..._垃圾回收算法,内存泄漏场景

网线选购-程序员宅基地

文章浏览阅读98次。如果将网卡比作是车,将交换机比作为立交桥,那么,网线就是路。可以想见,即使拥有高级跑车和现代化的立交桥,如果路况差得一塌胡涂,那么,整体速度也快不到哪儿去!另外,“路”一旦铺就,若欲推掉重来其困难程度可想而知。由此可见,网线的选购在网络建设就显得非常重要。就目前来看,主要可供选择的双绞线大致有两类,即超五类和六类。一、超五类与六类非屏蔽双绞线曾经辉煌..._2. 若网线老旧或网线内部损坏,建议更换新的高规格网线(超玉类网线

httos双向认证配置_NGINX 配置本地HTTPS(双向认证)-程序员宅基地

文章浏览阅读1.8k次。一、SSL协议加密方式SSL协议即用到了对称加密也用到了非对称加密(公钥加密),在建立传输链路时,SSL首先对对称加密的密钥使用公钥进行非对称加密,链路建立好之后,SSL对传输内容使用对称加密。1.对称加密速度高,可加密内容较大,用来加密会话过程中的消息。2.公钥加密加密速度较慢,但能提供更好的身份认证技术,用来加密对称加密的密钥。单向认证Https在建立Socket连接之前,需要进行握手,具体过..._httos″81278 ″osh

通过Zadig给蓝牙适配器安装驱动后,无法恢复的解决办法_csr8510 a10蓝牙驱动-程序员宅基地

文章浏览阅读3.2k次,点赞2次,收藏4次。通过Zadig给蓝牙适配器安装驱动后,无法恢复的解决办法问题描述蓝牙适配器型号是CSR 8510 A10, 在WIN10里可识别为蓝牙适配器。用Zadig给蓝牙适配器安装WinUSB驱动后,蓝牙适配器无法被Win10正常识别,回退驱动是灰色,删除卸载设备和驱动、重启电脑都没有用。解决办法进入设备管理器找到通用串行总线设备里的CSR8510 A10(如果不在这里你就一个个找csr开头的设备,然后通过蓝牙适配器的插拔,定位到是不是你选的驱动)右击选择更新驱动程序选择浏览我的计_csr8510 a10蓝牙驱动

推荐文章

热门文章

相关标签