仿格瓦拉转场动画

2024-02-03 18:40
文章标签 动画 转场 格瓦拉

本文主要是介绍仿格瓦拉转场动画,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

下载地址:Demo

2016-04-21 问题记录
init 方法中初始化画布的宽度和高度: 适配所有手机
canvaswWidth = context.getResources().getDisplayMetrics().widthPixels;
canvasHeight = context.getResources().getDisplayMetrics().heightPixels;

转场动画效果图:
转场动画

xfermode遮罩层效果图:


显示逻辑:
1,图片的平移动画 时间:2s
2,1s的时候,执行add Frament
3,平移动画执行结束,执行放大圆的绘制

隐藏逻辑:
1,缩小圆的绘制
2,图片还原动画

系统要求和主要类

android系统:2.2
第三方图片框架:glide-3.7.0.jar
view完整效果:
FlyCircleActivity+FlyCircleAnimView+FlyCircleDetailsFragment

FlyCircleAnimView

package com.heaven.circleanimview.views.flowview;/*** 画布的宽度高度需要初始化<br>* 圆点坐标和图片的宽高也是需要初始化的,这个跟详情界面的图片位置有关<br>* maxRadius根据圆心点算出<br>*/
public class FlyCircleAnimView  extends RelativeLayout{protected Handler handler;protected FlyBean fly;public ImageView iv_fly;private Canvas myCanvas; // 画布private Bitmap originalBitmap; // 画布bitmap/*** 画笔*/protected Paint paint = null ;/*** 画布重叠部分的显示模式*/private Xfermode xfermode ;/*** 圆的半径*/private int radius = 2100;/*** 最大半径,根据圆心点坐标算出*/private int maxRadius = 2000;/*** 默认半径*/private int defaultRadius = 200;/*** 放大 step   值越大执行的时间越短*/private int step = 150;/*** 图片的宽度*/private int imgWidth = 312;/*** 图盘的高度*/private int imgHeight = 420;/*** 图片距离左边的距离*/private int imgLeft = 36; // 和FlowViewHelper中的left值一样/*** 图片距离上边的距离*/private int imgTop = 624;/*** 圆的中心点 x坐标*/private int cx=imgLeft+imgWidth/2; // 32  312/*** 圆的中心点 y坐标*/private int cy=imgTop+imgHeight/2; // 624  420/*** 画布的宽度*/private int canvaswWidth = 1080;/*** 画布的高度*/private int canvasHeight = 1920;/*** 遮罩层颜色*/private int maskColor = Color.RED;/*** 放大还是收缩  true 放大,false 收缩*/boolean isBigZoom = true;/*** 图片的点击位置*/protected Rect localRect = null;/*** false 不绘制圆。 true 绘制*/protected boolean isCircleAnim = false;public FlyCircleAnimView(Context context, AttributeSet attrs) {super(context, attrs);LayoutInflater.from(context).inflate(R.layout.flow_layout,this);iv_fly = (ImageView)findViewById(R.id.iv_fly);init(context);}public FlyCircleAnimView(Context context) {super(context);init(context);}public FlyCircleAnimView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context);}/*** 可以不用初始化,在外部初始化数据* @param context*/private void init(Context context){this.setWillNotDraw(false);setClipChildren(false);paint = new Paint();paint.setAntiAlias(true);paint.setStyle(Style.FILL);xfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_OUT);maskColor = Color.parseColor("#c8c8c8");originalBitmap = Bitmap.createBitmap(canvaswWidth, canvasHeight, Bitmap.Config.ARGB_4444);myCanvas = new Canvas(originalBitmap);
//      myCanvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG));myCanvas.drawColor(maskColor); // 默认背景/*** 根据圆心点坐标算出  maxRadius  向上取整,保证圆的边界要在屏幕外。* 有些底部导航栏可以隐藏的,获取的高度是不准确的,要有对应的高度调整逻辑。*/maxRadius = (int) Math.ceil(Math.sqrt((canvaswWidth - cx)*(canvaswWidth - cx) +(canvasHeight - cy)*(canvasHeight - cy)));System.out.println("maxRadius = "+ maxRadius);radius = maxRadius+10; // 只是为了开始的时候不绘制// 初始化图片的宽度和高度,图片的左上点坐标imgWidth = (int) context.getResources().getDimension(R.dimen.flycircle_img_width);imgHeight = (int) context.getResources().getDimension(R.dimen.flycircle_img_height);imgLeft = (int) context.getResources().getDimension(R.dimen.flycircle_img_left);;imgTop = (int) context.getResources().getDimension(R.dimen.flycircle_img_top);;cx=imgLeft+imgWidth/2; // 32  312cy=imgTop+imgHeight/2; // 624  420LogUtil.e(this, "imgWidth = "+ imgWidth + " imgHeight="+imgHeight + " imgLeft"+imgLeft + " imgTop="+imgTop+ " cx"+cx + " cy="+cy);}@Overrideprotected void onDraw(Canvas canvas) {/*if (isCircleAnim){canvas.drawColor(Color.parseColor("#c8c8c8"));LogUtil.e(this, "onDraw = ========== isCircleAnim = " +isCircleAnim + " w = "+ PhoneInfoUtil.widthPixels + " h = "+PhoneInfoUtil.heightPixels);paint.setXfermode(null);paint.setColor(getContext().getResources().getColor(R.color.c5));if(radius < PhoneInfoUtil.widthPixels/2){canvas.drawCircle(PhoneInfoUtil.widthPixels/2,PhoneInfoUtil.heightPixels/2,radius,paint);radius +=10;invalidate();}else{paint.setColor(Color.parseColor("#ffff0000"));canvas.drawCircle(PhoneInfoUtil.widthPixels/2,PhoneInfoUtil.heightPixels/2,radius,paint);sendMessage(fly,100);}}else { zoomDraw(canvas);}*/if(isCircleAnim){zoomDraw(canvas);}else{}}/*** 110 放大圆绘制完毕   111 缩小圆绘制完毕*/private void sendMessage(FlyBean fly,int what) {if(handler!=null){Message msg = handler.obtainMessage();msg.obj = fly;msg.what = what;handler.sendMessage(msg);}}/*** @param canvas*/private void zoomDraw(Canvas canvas) {try {// 记得还原透明背景,否则绘制圆的操作不显示(背景一直是灰色的)setBackgroundColor(Color.parseColor("#00000000"));
//          canvas.drawColor(maskColor);LogUtil.e(this, "zoomDraw isBigZoom = "+isBigZoom + " radius ="+radius);if(isBigZoom){if(radius<=maxRadius){ // 放大paint.setXfermode(null);paint.setColor(maskColor);myCanvas.drawRect(0, 0, canvaswWidth, canvasHeight, paint);// 和之前的画布做交互处理。 在该步骤之前可以重绘画布paint.setXfermode(xfermode);
//                  paint.setColor(Color.BLUE);//可以不用设置颜色myCanvas.drawCircle(cx, cy, radius, paint);radius+=step;invalidate();}else{sendMessage(fly,110);}}else{// 缩小if(radius<=maxRadius && radius >=0){paint.setXfermode(null); // 如果不设置为null,每次都会和之前的画布做重叠运算操作。 paint.setColor(maskColor); myCanvas.drawRect(0, 0, canvaswWidth, canvasHeight, paint);// SRC_IN  取两层绘制交集,显示上层(后来画的)    DST_IN    取两层绘制交集。显示下层。// DST_OUT  取下层绘制非交集部分。    SRC_OUT  取上层绘制非交集部分(上层的非交集部分)
//                  paint.setColor(Color.BLUE);  // out 下层颜色设置无效paint.setXfermode(xfermode);myCanvas.drawCircle(cx, cy, radius, paint);radius-=step;
//                  Thread.sleep(1000);invalidate();}else{paint.setXfermode(null);paint.setColor(maskColor);myCanvas.drawRect(0, 0, canvaswWidth, canvasHeight, paint);paint.setXfermode(xfermode);myCanvas.drawCircle(cx, cy, maxRadius, paint);
//                  myCanvas.drawColor(maskColor);sendMessage(fly,111);}}
//          Thread.sleep(1000);canvas.drawBitmap(originalBitmap, 0, 0, null);} catch (Exception e) {e.printStackTrace();}}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {LogUtil.e(this, "onLayout = " + l + " = " + l + " t = " + t + " r=" + r + " b = " + b + " ");super.onLayout(changed, l, t, r, b);if (localRect != null) {ViewGroup vg = (ViewGroup) getChildAt(0);// 固定图片的位置vg.getChildAt(0).layout(localRect.left, localRect.top, localRect.right, localRect.bottom);LogUtil.e(this, "onLayout = " + l + " = " + l + " t = " + t + " r=" + r + " b = " + b + " iv = " + vg.getChildAt(0));LogUtil.e(this, "onLayout  width = " + vg.getChildAt(0).getWidth() + " height = "+ vg.getChildAt(0).getHeight());}}/*** 执行动画。 通过handler发送消息: what==2 添加fragment  what ==100 动画执行结束* @param fly* @param handler*/public void setVisibility(FlyBean fly,Handler handler ) {this.handler = handler;this.localRect = fly.rect;this.fly = fly;isCircleAnim = false;radius = defaultRadius;LogUtil.e(this, "setVisibility rect = " + localRect.toString());setBackgroundColor(maskColor); setVisibility(View.VISIBLE);FlowViewHelper.startAnim(getContext(),fly,this,handler);GlideUtil.displayImage(getContext(), fly.movie.movie_img_url,iv_fly);requestLayout();invalidate();}public void revertAnim(FlyBean fly,Handler handler){isCircleAnim = false;FlowViewHelper.revertAnim(getContext(),fly,this,handler);}public void startCircleAnim(Handler handler){this.handler = handler;isCircleAnim = false;invalidate();}/*** * @param tag   1 放大    0 缩小*/public void startAnim(int tag){isCircleAnim = true;if(tag == 1){isBigZoom = true;System.out.println("startAnim==============放大");radius = defaultRadius;invalidate();}else{setVisibility(View.VISIBLE);isBigZoom = false;System.out.println("startAnim==============收缩");radius = maxRadius;invalidate();}}/*** @return the imgLeft*/public int getImgLeft() {return imgLeft;}/*** @param imgLeft the imgLeft to set*/public void setImgLeft(int imgLeft) {this.imgLeft = imgLeft;}/*** @return the imgTop*/public int getImgTop() {return imgTop;}/*** @param imgTop the imgTop to set*/public void setImgTop(int imgTop) {this.imgTop = imgTop;}     
}

下载地址:Demo

这篇关于仿格瓦拉转场动画的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/675039

相关文章

最好用的WPF加载动画功能

《最好用的WPF加载动画功能》当开发应用程序时,提供良好的用户体验(UX)是至关重要的,加载动画作为一种有效的沟通工具,它不仅能告知用户系统正在工作,还能够通过视觉上的吸引力来增强整体用户体验,本文给... 目录前言需求分析高级用法综合案例总结最后前言当开发应用程序时,提供良好的用户体验(UX)是至关重要

基于Python实现PDF动画翻页效果的阅读器

《基于Python实现PDF动画翻页效果的阅读器》在这篇博客中,我们将深入分析一个基于wxPython实现的PDF阅读器程序,该程序支持加载PDF文件并显示页面内容,同时支持页面切换动画效果,文中有详... 目录全部代码代码结构初始化 UI 界面加载 PDF 文件显示 PDF 页面页面切换动画运行效果总结主

Qt QWidget实现图片旋转动画

《QtQWidget实现图片旋转动画》这篇文章主要为大家详细介绍了如何使用了Qt和QWidget实现图片旋转动画效果,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 一、效果展示二、源码分享本例程通过QGraphicsView实现svg格式图片旋转。.hpjavascript

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

Flutter 进阶:绘制加载动画

绘制加载动画:由小圆组成的大圆 1. 定义 LoadingScreen 类2. 实现 _LoadingScreenState 类3. 定义 LoadingPainter 类4. 总结 实现加载动画 我们需要定义两个类:LoadingScreen 和 LoadingPainter。LoadingScreen 负责控制动画的状态,而 LoadingPainter 则负责绘制动画。

用Unity2D制作一个人物,实现移动、跳起、人物静止和动起来时的动画:中(人物移动、跳起、静止动作)

上回我们学到创建一个地形和一个人物,今天我们实现一下人物实现移动和跳起,依次点击,我们准备创建一个C#文件 创建好我们点击进去,就会跳转到我们的Vision Studio,然后输入这些代码 using UnityEngine;public class Move : MonoBehaviour // 定义一个名为Move的类,继承自MonoBehaviour{private Rigidbo

动画AnimationDrawable、转动

现实开发中:很多地方都用到 点击动画的特效; 本案例本人做了三个关于“动” 画 的效果; 先上图: 总体图: A: B: 1:点击图片按钮,效果是:图片闪动; 通过在xml中定义:标签:animation-list来实现点击动画的效果;  是否循环标签:oneshot ;   时间间隔标签:duration ; 要显示的图片标签:drawable ;

13 transition数组的动画使用

划重点 动画:transitiontransition-group :数组动画数组的 添加 / 删除 豆腐粉丝汤 清淡又健康 <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><me

12 动画transition的使用2

划重点 Vue 动画:transition / transform在动画周期中执行动动画(上一篇是通过动画样式控制动画) 清蒸扇贝 <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><

【前端】animation动画以及利用vue制作简单的透明度改变动画,包含vue生命周期实现

一. 问题描述 想做一个文字透明度从1到0然后再从0到1的css动画。 二. 代码写法 2.1 animation写法 2.1.1 animation属性key 2.1.2 代码展示 <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=de