Chrome 灭霸打响指彩蛋动画 Android实现

github地址

在手机chrome搜索灭霸后,会出现一个手套的图片,点击图片后会出现一个彩蛋,即一半的搜索结果会消失。消失的动画如下图所示:
chrome

可以看到这个动画 大致可以理解为:将当前view分为两份,每一份同时做透明度动画,并且同时向左想右移动。

先来看下我们实现的效果:

在这里插入图片描述
首先是实现的思路:

如何让一个view同时向左右移动呢?我们可以创建两个一模一样的view。但是现在问题来了?如果将原来的view复制一份,合适吗?如果view的层级比较复杂,那么这样做的成本十分巨大。所以我的方案是将当前view的截图保存为Bitmap,然后在一个新的view里创建两个ImageView,将bitmap分别设置给ImageView。然后我们对两个ImageView做动画就可以了。

现在分别看下几个实现细节:

如何拿到View截图

用下面的方法可以拿到对应view的Bitmap,

    private Bitmap loadBitmapFromView(View v) {if (v == null) {return null;}v.setDrawingCacheEnabled(true);v.buildDrawingCache();Bitmap bitmap = Bitmap.createBitmap(v.getDrawingCache());v.setDrawingCacheEnabled(false);return bitmap;}

需要注意的是,这里需要用Bitmap.createBitmap(v.getDrawingCache());来创建一个新的bitmap,而不能直接使用v.getDrawingCache(),因为使用v.getDrawingCache()直接创建的bitmap会被回收掉。

RecyclerView如何实现Item动画

RecyclerView可以通过mRecyclerView.setItemAnimator(disappearAnimation);方法设置Item的动画,Item的动画一共包括四种,分别是addremovemovechange。这四种动画分别是指,添加Item、删除Item、Item移动和Item改变的时候。

那么现在问题来了,我们的这个动画适合remove效果吗?使用remove效果的话,需要执行的逻辑比较啊复杂,首先需要将item中的所有子view全部设置为不可见,然后再添加两个ImageView。这样操作的效率太低了。而且添加ImageView的方式根据item根view的layout不同而不同,这样对原有view的侵入型太强。

所以我们选择使用change效果。
最简单的使用方式,是继承DefaultItemAnimator,然后实现animateChange方法。但是这样会有一个问题,就是动画效果会出现闪一下的bug,这是由于DefaultItemAnimatoranimateChangeImpl方法里对新view做了一个透明度变化的动画,而且这个方法是private的,我们不能覆盖。所以我们就不能直接继承于DefaultItemAnimator
那么我们的解决方案是自己写一个BaseItemAnimator,其中的代码大部分与DefaultItemAnimator相同,但是animateChangeImpl方法设置为public,这样的话我们就可以在子类覆盖animateChangeImpl方法,从而随意定制我们的动画。这里仅贴出子类的代码。BaseItemAnimator的代码太长,可以参阅上面的github地址。

package com.lee.thanos;import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.graphics.Bitmap;
import android.view.View;
import android.view.ViewPropertyAnimator;import androidx.core.view.ViewCompat;
import androidx.core.view.ViewPropertyAnimatorListener;
import androidx.recyclerview.widget.RecyclerView;class DisappearItemAnimation extends BaseItemAnimator {private Bitmap loadBitmapFromView(View v) {if (v == null) {return null;}v.setDrawingCacheEnabled(true);v.buildDrawingCache();Bitmap bitmap = Bitmap.createBitmap(v.getDrawingCache());v.setDrawingCacheEnabled(false);return bitmap;}@Overridepublic void animateChangeImpl(final BaseItemAnimator.ChangeInfo changeInfo) {final RecyclerView.ViewHolder holder = changeInfo.oldHolder;final View view = holder == null ? null : holder.itemView;final RecyclerView.ViewHolder newHolder = changeInfo.newHolder;final View newView = newHolder != null ? newHolder.itemView : null;if (view != null) {final ViewPropertyAnimator oldViewAnim = view.animate().setDuration(getChangeDuration());mChangeAnimations.add(changeInfo.oldHolder);oldViewAnim.translationX(changeInfo.toX - changeInfo.fromX);oldViewAnim.translationY(changeInfo.toY - changeInfo.fromY);oldViewAnim.alpha(0).setListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationStart(Animator animator) {dispatchChangeStarting(changeInfo.oldHolder, true);}@Overridepublic void onAnimationEnd(Animator animator) {oldViewAnim.setListener(null);view.setAlpha(1);view.setTranslationX(0);view.setTranslationY(0);dispatchChangeFinished(changeInfo.oldHolder, true);mChangeAnimations.remove(changeInfo.oldHolder);dispatchFinishedWhenDone();}}).start();}if (newView != null) {newView.setAlpha(1);newView.setTranslationX(0);newView.setTranslationY(0);}if (changeInfo.oldHolder instanceof RecyclerAdapter.ItemViewHolder&& newHolder instanceof RecyclerAdapter.ItemStubViewHolder) {Bitmap bitmap = loadBitmapFromView(changeInfo.oldHolder.itemView);RecyclerAdapter.ItemStubViewHolder stubViewHolder = (RecyclerAdapter.ItemStubViewHolder) newHolder;stubViewHolder.image1.setImageBitmap(bitmap);stubViewHolder.image2.setImageBitmap(bitmap);ViewCompat.animate(stubViewHolder.image1).alpha(0).translationXBy(300).setDuration(2000).start();mChangeAnimations.add(changeInfo.newHolder);ViewCompat.animate(stubViewHolder.image2).alpha(0).translationXBy(-300).setDuration(2000).setListener(new ViewPropertyAnimatorListener() {@Overridepublic void onAnimationStart(View view) {dispatchChangeStarting(changeInfo.newHolder, false);}@Overridepublic void onAnimationEnd(View view) {dispatchChangeFinished(changeInfo.newHolder, false);mChangeAnimations.remove(changeInfo.newHolder);dispatchFinishedWhenDone();}@Overridepublic void onAnimationCancel(View view) {}}).start();}}}

在更新RecyclerView的时候,需要使用notifyItemChanged方法更新。

随机选一半Item

这里提供一种较为简单的方法:每次随机选一个,然后放到Set里,由于Set可以自动去重,随意当Set的大小为原有数据的一半时,那么Set里的数据就是随机一半数据。

    private void randomDisappearAHalf() {if (mList != null && !mList.isEmpty()) {int size = mList.size();HashSet<Integer> set = new HashSet<>();while (set.size() < size / 2) {Random random = new Random();int anInt = random.nextInt(size);set.add(anInt);}for (Integer i : set) {mList.get(i).type = 1;mRecyclerAdapter.notifyItemChanged(i);}}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/1380648.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Vue灭霸打响指效果

版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 https://blog.csdn.net/GreekMrzzJ/article/details/89821464 </div><link rel"stylesheet" href"https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_v…

什么是P2P?

P2P (Peer-to-Peer) 是一种分布式的网络架构&#xff0c;其中各个节点&#xff08;通常被称为“peers”或“节点”&#xff09;直接进行数据共享和交换&#xff0c;而无需依赖中央服务器。P2P 网络强调平等的参与和共享&#xff0c;每个节点既可以是数据的消费者&#xff08;下…

探秘金和OA:解析任意文件读取漏洞的潜在威胁

是喜是悲&#xff0c;但可以慰藉的是&#xff0c;你总不枉在这世界上活了一场&#xff0c;有了这样的认识&#xff0c;你就会珍重生活&#xff0c;而不会玩世不恭&#xff1b;同时也会给人自身注入一种强大的内在力量…… 漏洞复现 访问url&#xff1a; 构造payload /C6/Jh…

教师节,回忆一点(更新完毕)

又到了一年一度的教师节&#xff0c;身处塞北&#xff0c;回想当年&#xff0c;师恩难忘。让点点滴滴的回忆伴我回到学校。 小学的时候&#xff0c;一般只记得老师的姓&#xff0c;不会去问全名&#xff0c;更不会去叫。所以只记得几位老师的姓。一二年级时的班主任姓孙&#x…

Vue过滤器(时间戳转时间)

目录 过滤器 HTML写法&#xff1a; 定义过滤器: 定义全局过滤器&#xff1a; 过滤器串联&#xff1a; 带参数过滤器&#xff1a; 时间戳转时间 过滤器 官方地址&#xff1a;过滤器 — Vue.js (vuejs.org) 过滤器是指Vue.js支持在{{}}插值的尾部添加一个管道符“&#xff0…

人与树林交相辉映的效果

人与树林交相辉映的效果 效果 1.利用通道抠出人物素材&#xff0c;复制背景图层&#xff0c;在通道复制一个蓝色通道图层&#xff0c;调整色阶让黑的更黑一点&#xff0c;白的更白&#xff0c;然后用画笔工具把黑的人物全部涂黑 2.按Ctrl键鼠标左键选中图片&#xff0c;然后按…

qt画笔效果笔锋:铅笔、画笔、钢笔、毛笔、蜡笔

qt画笔效果笔锋&#xff1a;铅笔、画笔、钢笔、毛笔、蜡笔体验 体验demo下载连接&#xff1a;https://download.csdn.net/download/u012532263/87740902?spm1001.2014.3001.5501 emil: 550993637qq.com

Android 仿支付宝蚂蚁森林动画效果

Android 动画可以归纳为以下几种&#xff1a; 视图动画&#xff08;View 动画&#xff09;帧动画&#xff08;Frame 动画、Drawable 动画&#xff09;属性动画触摸反馈动画&#xff08;Ripple Effect&#xff09;揭露动画&#xff08;Reveal Effect&#xff09;转场动画 &…

Babylongjs-高度图,天空盒,图片精灵及K帧动画

我们想把村庄建在山谷里。可以从网格创建山丘&#xff0c;但是还有另一种方法可以为地面网格添加垂直高度。这是使用高度图来实现的&#xff0c;该高度图使用灰色阴影来确定地面的高度。白色区域最高&#xff0c;黑色最低。这个简单的高度图&#xff1a; 中间有一个大的黑色区域…

「Python海龟画图」利用海龟画笔绘制分形树

绘制旋转图形 功能要求 利用函数递归绘制由多条直线组成的旋转图形&#xff0c;每条直线的颜色随机产生&#xff1b;并且隐藏画笔、设置画笔的速度、设置画布的背景色。 实例代码 import turtle # 导入海龟模块import random # 导入随机数turt…

qpython3手机版turtle_使用Python turtle画一片树林

原标题&#xff1a;使用Python turtle画一片树林 使用Python Turtle绘制一片树林代码 这段代码结合了随机函数来使树林更多样化&#xff0c;同时设置了颜色的渐变。几乎每句都有注释&#xff0c;还有不懂的函数可以到官方手册查 示例中的yield语句和pass语句的用法非常精髓&…

DC电源模块关于的电路布局设计

BOSHIDA DC电源模块关于的电路布局设计 DC电源模块是现代电子设备中常用的电源模块之一&#xff0c;其功能是将市电或其他输入电源转换成定电压、定电流的直流电源输出&#xff0c;以满足电子设备的供电需求。电路布局的设计是DC电源模块的重要组成部分&#xff0c;它直接影响…

chrome V3 插件开发 基础

目录 准备popup通信popup 发消息给 backgroundpopup 发消息给 content长期连接 如何页面上添加一个按钮&#xff1f;tabs.onUpdatedcontent-script.jsinject.js 右键菜单chrome.contextMenus举个例子添加关于报错&#xff08;cannot create item with duplicate id XXX&#xf…

论如何科学的看小本子

看本子的问题一直困扰着很多人&#xff0c;有些需要注册&#xff0c;有些没有资源&#xff0c;有些广告很多。 这里&#xff0c;推荐一款用起来比较好的本子应用。 大概长这个样子 这个东西怎么用&#xff1f;我不知道。 这个东西能干什么&#xff1f;我也不知道。 但是&am…

STM32入门——DMA数据搬运工

DMA简介 DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取DMA可以提供外设和存储器或者存储器和存储器之间的高速数据传输&#xff0c;无须CPU干预&#xff0c;节省了CPU的资源12个独立可配置的通道&#xff1a; DMA1&#xff08;7个通道&#xff09;&#xff…

HTML+JavaScript构建一个将C/C++定义的ANSI字符串转换为MASM32定义的DWUniCode字符串的工具

公文一键排版系统基本完成&#xff0c;准备继续完善SysInfo&#xff0c;增加用户帐户信息&#xff0c;其中涉及到Win32_Account结构&#xff0c;其C定义如下&#xff1a; [Dynamic, Provider("CIMWin32"), UUID("{8502C4CC-5FBB-11D2-AAC1-006008C78BC7}"…

分享给大家一个免费使用网络字体的方法

如题&#xff0c;给各位朋友分享一个免费使用字体的方法&#xff0c;因为现在网上的字体大部分都需要付费使用&#xff0c;而我们有时候只需要字体中的一两个字&#xff0c;如果为这一两个字花十几块&#xff0c;还是有点肉疼的&#xff0c;尊重版权的另说&#xff1b; 好了&a…

质心计算公式

求曲线质心&#xff1a; 对于曲线L&#xff0c;设密度公式为F(x,y)&#xff0c;则质心公式为 这是求质心的x坐标&#xff0c;求另外一个坐标类似。同时&#xff0c;这个公式可以推广到多元函数求积分&#xff0c;原理依然是要求的坐标乘以密度公式积分除以密度公式做积分 求区…

能量信号和功率信号

能量信号为功率信号的积分&#xff0c;功率信号为能量信号的密度。对于一个信号&#xff0c;yf(x)&#xff0c;能量相当于曲线和x轴的积分面积&#xff0c;功率相当于y值。当一个信号的积分面积无穷大&#xff0c;但是能找到一个不是无穷大的平均y值&#xff0c;那么这就是功率…

信号能量、功率、功率谱密度、自相关函数公式总结

已知时域求能量与功率 若 x(t) 为能量讯号&#xff0c;其总能量&#xff1a; 若 x(t) 为功率信号&#xff0c;其平均功率&#xff1a; 若 x(t) 为周期信号且基本周期为 &#xff0c;其平均功率&#xff1a; 已知频域求能量 (1)由时域求能量&#xff1a; (2)根据傅立叶逆转…