博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
高仿淘票票头像动画
阅读量:6574 次
发布时间:2019-06-24

本文共 6226 字,大约阅读时间需要 20 分钟。

当pm对上一版的马蜂窝头像泡泡动画审美疲劳后,这次又觉得淘票票的头像动画好看,然后。。。 先看看效果吧!

效果原理分析

  1. 布局排列

这里可以同自定义View 或继承ViewGroup去实现 不过自定义View复杂度会高很多 我这里也是继承FrameLayout 通过添加和排列ImageView去实现的

  1. 动画过程

上图已经把整个过程描述很清楚,剩下就是控制动画不断循环执行 以及控制动画的停止、开始 、快慢等一系列操作了

####具体实现

1. 布局的初始化排列相关

public class AmoyTicketLayout extends FrameLayout {   public AmoyTicketLayout(@NonNull Context context) {        this(context, null);    }    public AmoyTicketLayout(@NonNull Context context, @Nullable AttributeSet attrs) {        this(context, attrs, 0);    }    public AmoyTicketLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        initView(context);    }        private void initView(Context context) {        eachWidth = SizeUtils.dp2px(context, 35);        eachMargin = SizeUtils.dp2px(context, 7);        distance = eachWidth - eachMargin;        //先添加0号view        initFirstView();        //循环添加其余子View         for (int i = 5; i >= 0; i--) {            LayoutParams layoutParams = getLayoutParams(i);            ImageView roundedImageView = getImageView();            addView(roundedImageView, layoutParams);        }    }    //添加0号view 并缩放到最小    private void initFirstView() {        ImageView imageView = getImageView();        imageView.setScaleX(0);        imageView.setScaleY(0);        addView(imageView, getLayoutParams(5));    }    private ImageView getImageView() {        ImageView roundedImageView = new ImageView(getContext());        roundedImageView.setScaleType(ImageView.ScaleType.FIT_XY);        return roundedImageView;    }    //每个子View的marginRight距离是相同的     private LayoutParams getLayoutParams(int i) {        LayoutParams layoutParams = new LayoutParams(eachWidth,eachWidth);        layoutParams.gravity = Gravity.RIGHT | Gravity.CENTER_VERTICAL;        int marginRight = (distance) * i;        layoutParams.setMargins(0, 0, marginRight, 0);        return layoutParams;    }}复制代码

数据初始化

public void initData(ArrayList
drawables) { if (null == drawables || drawables.isEmpty()) return; int childCount = getChildCount(); if (childCount == 0) return; int size = drawables.size(); if (size < childCount) return; this.drawables = drawables; //记录图片资源取到哪里 用于循环时标记使用 position = childCount - 1; for (int i = 0; i < childCount; i++) { //以为布局中6号为最后一个View 但是要求显示的要是第一个图片 ImageView imageView = (ImageView) getChildAt(childCount -(i + 1)); imageView.setBackground(drawables.get(i)); } }复制代码

由上操作就完成布局初始排列 和图片资源的加载显示

2. 动画的具体实现

public void startAnimations() {        if (!stopAnimator) return;        if (null == drawables || drawables.isEmpty()) {            stopAnimator = false;            return;        }        ValueAnimator valueAnimator = ValueAnimator.ofFloat(1.0f, 0.0f);        valueAnimator.setDuration(1000);        valueAnimator.setInterpolator(new LinearInterpolator());        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                float animatedValue = (float) animation.getAnimatedValue();                int childCount = getChildCount() - 1;                float v = 1.0f - animatedValue;                //计算每个单元平移的距离                float translationX = distance * (v);                for (int i = 0; i < getChildCount(); i++) {                    ImageView childView = (ImageView) getChildAt(i);                    if (i == childCount) {//当view为最后一个时 也就是6号 做缩小操作                        childView.setScaleX(animatedValue);                        childView.setScaleY(animatedValue);                    } else if (i == 0) {//当view为第一个时 也就是0号 做放大操作                        childView.setScaleX(v);                        childView.setScaleY(v);                    } else {//其他view 就通不断改变marginRight 来做平移动作                        FrameLayout.LayoutParams layoutParams = (LayoutParams) childView.getLayoutParams();                        int marginRight = (distance) * (childCount - i);                        layoutParams.setMargins(0, 0, (int) (marginRight - translationX), 0);                        childView.setLayoutParams(layoutParams);                    }                }            }        });        valueAnimator.addListener(new AnimatorListenerAdapter() {            @Override            public void onAnimationStart(Animator animation) {                //动画开始确定最后一个View的缩放中心点                int childCount = getChildCount() - 1;                ImageView imageView = (ImageView) getChildAt(childCount);                imageView.setPivotX(eachWidth);                imageView.setPivotY(eachWidth / 2);            }            @Override            public void onAnimationEnd(Animator animation) {                int childCount = getChildCount() - 1;                //动画结束删除最后一个View  也就是6号                removeViewAt(childCount);                                //确定获取图片资源的index                position++;                if (position >= drawables.size()) {                    position = 0;                }                                ImageView imageView = getImageView();                imageView.setBackground(drawables.get(position));                imageView.setScaleX(0);                imageView.setScaleY(0);                //动画结束 创建0号View 放到1号后面 其他view的index 将全部加1                addView(imageView, 0, getLayoutParams(5));                //再次启动动画                startAnimation();            }        });        valueAnimator.start();    }复制代码

单次动效

利用Rxjava的timer()实现循环轮播效果

//动画开始  private void startAnimation() {        subscribe = Observable.timer(500, TimeUnit.MILLISECONDS)                .observeOn(AndroidSchedulers.mainThread())                .subscribe(new Consumer
() { @Override public void accept(Long aLong) throws Exception { startAnimations(); } }); }//动画停止操作 public void stopAnimator() { stopAnimator = false; if (null != subscribe) { subscribe.dispose(); subscribe = null; } } 复制代码

最终效果

转载于:https://juejin.im/post/5cbdbaf0f265da0374187b27

你可能感兴趣的文章
java常见面试题及答案 1-10(基础篇)
查看>>
编写程序,输入一个N,返回角谷变换(达到1所需)的次数
查看>>
js的一些注意点
查看>>
PowerShell 方式部署Sharepoint Solution
查看>>
Windows下pip安装包报错:Microsoft Visual C++ 9.0 is required Unable to find vcvarsall.bat
查看>>
文件 md5 查看 命令
查看>>
数据结构实验之栈三:后缀式求值
查看>>
HDU4026 Unlock the Cell Phone [状态压缩DP]
查看>>
java中文转Unicode
查看>>
JAVA操作数据库调试经验
查看>>
Windows内存管理
查看>>
HDU 6034 - Balala Power! | 2017 Multi-University Training Contest 1
查看>>
VS2010 代码自动对齐 快捷键
查看>>
10692 XYM-入门之道
查看>>
Linux+Apache+PHP+MySQL服务器环境(CentOS篇)
查看>>
IDEA整合Spring Boot项目访问jsp文件
查看>>
Linux常用命令总结
查看>>
求最大递增数
查看>>
小程序(仿微信发布说说功能)
查看>>
DOM_05之DOM、BOM常用对象
查看>>