前言
平常所做的动画大部分是针对View的,而View经常会需要集中动画混合在一起做,因此提供了一个ViewPropertyAnimator类来快速的实现多个动画的混合;
ViewPropertyAnimator从名字就可以看出是专用于View的属性动画,在API12被提供;
ViewPropertyAnimator专用于操作View动画,语法更加简洁,使用更加方便;
今天就来看看怎么用;
一、ViewPropertyAnimator使用详解
1、获取对象
ViewPropertyAnimator 没有构造函数,通过View.animate()方法可以方便的获取;ViewPropertyAnimator 对象,此时获取的动画对象就专用于操作当前view;
public ViewPropertyAnimator animate() {
if (mAnimator == null) {
mAnimator = new ViewPropertyAnimator(this);
}
return mAnimator;
}
2、基本函数属性介绍
alpha(float value) 设置View的透明度,value最终值;
alphaBy(float value) 设置View的透明度,value是在view当前值的基础上的偏移量;rotation(float value):旋转View,正值顺时针,负值逆时针,value最终值;
rotationBy(float value):旋转,在当前值得基础上偏移量;
rotationX(float value):绕x轴旋转;
rotationXBy(float value):当View旋转的基础上以value为偏移量绕X轴旋转;
rotationY(float value):绕Y轴旋转;
rotationYBy(float value):在当前旋转的基础上绕Y轴旋转;
scaleX(float value):缩放view的X轴方向上的大小;
scaleXBy(float value):当前View缩放的基础上,在X轴方向上对view进行缩放;
scaleY(float value):缩放view的Y轴方向上的大小;
scaleYBy(float value):当前View缩放的基础上,对view的Y轴方向进行缩放;
translationX(float value):沿X轴方向平移,value大于0,X轴正方向;
translationXBy(float value):带有偏移量的平移;
translationY(float value):沿Y轴方向平移,value大于0,沿Y轴正方向平移;
translationYBy(float value) :在当前值的基础上,在Y轴方向上平移;
x(float value):在当前值的基础上,修改view 的X坐标;
xBy(float value):在当前值的基础上,修改view 的X坐标;
y(float value):在当前值的基础上,修改View的Y的坐标;
yBy(float value):在当前值的基础上,修改View的Y的坐标;
z(float value):在当前值的基础上,修改View的Z的坐标;
zBy(float value):在当前值的基础上,修改View的Z的坐标;
3、基本使用
常用方法
btnShow.animate()
.setDuration(5000)
//透明度
.alpha(0)
.alphaBy(0)
//旋转
.rotation(360)
.rotationBy(360)
.rotationX(360)
.rotationXBy(360)
.rotationY(360)
.rotationYBy(360)
//缩放
.scaleX(1)
.scaleXBy(1)
.scaleY(1)
.scaleYBy(1)
//平移
.translationX(100)
.translationXBy(100)
.translationY(100)
.translationYBy(100)
.translationZ(100)
.translationZBy(100)
//更改在屏幕上的坐标
.x(10)
.xBy(10)
.y(10)
.yBy(10)
.z(10)
.zBy(10)
//监听及其他设置
.setInterpolator(new BounceInterpolator())
.setStartDelay(1000)
.setListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
})
.setUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
}
})
.withEndAction(new Runnable() {
@Override
public void run() {
Log.i(TAG, "run: end");
}
})
.withStartAction(new Runnable() {
@Override
public void run() {
Log.i(TAG, "run: start");
}
})
.start();
4、添加监听
ViewPropertyAnimator viewPropertyAnimator = gongxiang.animate().setDuration(3000).x(700).y(700).rotation(270).alpha(0.5f).setUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
);
}
}).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationCancel(Animator animation) {
super.onAnimationCancel(animation);
}
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
System.out.println("=========onAnimationEnd=======");
}
@Override
public void onAnimationRepeat(Animator animation) {
super.onAnimationRepeat(animation);
}
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
System.out.println("=========onAnimationStart=======");
}
@Override
public void onAnimationPause(Animator animation) {
super.onAnimationPause(animation);
}
@Override
public void onAnimationResume(Animator animation) {
super.onAnimationResume(animation);
}
});
二、基本原理
1、执行动画基本步骤如下
2、startAnimation()的源码
/**
* Starts the underlying Animator for a set of properties. We use a single animator that
* simply runs from 0 to 1, and then use that fractional value to set each property
* value accordingly.
*/
private void startAnimation() {
if (mRTBackend != null && mRTBackend.startAnimation(this)) {
return;
}
mView.setHasTransientState(true);
//创建ValueAnimator
ValueAnimator animator = ValueAnimator.ofFloat(1.0f);
//clone一份mPendingAnimations赋值给nameValueList
ArrayList<NameValuesHolder> nameValueList =
(ArrayList<NameValuesHolder>) mPendingAnimations.clone();
//赋值完后清空
mPendingAnimations.clear();
//用于标识要执行动画的属性
int propertyMask = 0;
int propertyCount = nameValueList.size();
//遍历所有nameValuesHolder,取出其属性名称mNameConstant,
//执行"|"操作并最终赋值propertyMask
for (int i = 0; i < propertyCount; ++i) {
NameValuesHolder nameValuesHolder = nameValueList.get(i);
propertyMask |= nameValuesHolder.mNameConstant;
}
//创建PropertyBundle,并添加到mAnimatorMap中
mAnimatorMap.put(animator, new PropertyBundle(propertyMask, nameValueList));
if (mPendingSetupAction != null) {
//设置硬件加速
mAnimatorSetupMap.put(animator, mPendingSetupAction);
mPendingSetupAction = null;
}
if (mPendingCleanupAction != null) {
//移除硬件加速
mAnimatorCleanupMap.put(animator, mPendingCleanupAction);
mPendingCleanupAction = null;
}
if (mPendingOnStartAction != null) {
//设置开始的动画(监听器的开始方法中调用)
mAnimatorOnStartMap.put(animator, mPendingOnStartAction);
mPendingOnStartAction = null;
}
if (mPendingOnEndAction != null) {
//设置结束后要进行的下一个动画(监听器的结束方法中调用)
mAnimatorOnEndMap.put(animator, mPendingOnEndAction);
mPendingOnEndAction = null;
}
//添加内部监听器
animator.addUpdateListener(mAnimatorEventListener);
animator.addListener(mAnimatorEventListener);
//判断是否延长开始
if (mStartDelaySet) {
animator.setStartDelay(mStartDelay);
}
//执行动画的实现
if (mDurationSet) {
animator.setDuration(mDuration);
}
//设置插值器
if (mInterpolatorSet) {
animator.setInterpolator(mInterpolator);
}
//开始执行动画
animator.start();
}
2、PropertyBundle
private static class PropertyBundle {
int mPropertyMask;
ArrayList<NameValuesHolder> mNameValuesHolder;
PropertyBundle(int propertyMask, ArrayList<NameValuesHolder> nameValuesHolder) {
mPropertyMask = propertyMask;
mNameValuesHolder = nameValuesHolder;
}
boolean cancel(int propertyConstant) {
if ((mPropertyMask & propertyConstant) != 0 && mNameValuesHolder != null) {
int count = mNameValuesHolder.size();
for (int i = 0; i < count; ++i) {
NameValuesHolder nameValuesHolder = mNameValuesHolder.get(i);
if (nameValuesHolder.mNameConstant == propertyConstant) {
mNameValuesHolder.remove(i);
mPropertyMask &= ~propertyConstant;
return true;
}
}
}
return false;
}
}
3、AnimatorEventListener
private class AnimatorEventListener
implements Animator.AnimatorListener, ValueAnimator.AnimatorUpdateListener {
...
...
}
4、mAnimatorMap
private HashMap<Animator, PropertyBundle> mAnimatorMap =
new HashMap<Animator, PropertyBundle>();
5、onAnimationUpdate
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//取出当前Animator对应用propertyBundle对象
PropertyBundle propertyBundle = mAnimatorMap.get(animation);
if (propertyBundle == null) {
// Shouldn't happen, but just to play it safe
return;
}
//是否开启了硬件加速
boolean hardwareAccelerated = mView.isHardwareAccelerated();
// alpha requires slightly different treatment than the other (transform) properties.
// The logic in setAlpha() is not simply setting mAlpha, plus the invalidation
// logic is dependent on how the view handles an internal call to onSetAlpha().
// We track what kinds of properties are set, and how alpha is handled when it is
// set, and perform the invalidation steps appropriately.
boolean alphaHandled = false;
if (!hardwareAccelerated) {
mView.invalidateParentCaches();
}
//取出当前的估算值(插值器计算值)
float fraction = animation.getAnimatedFraction();
int propertyMask = propertyBundle.mPropertyMask;
if ((propertyMask & TRANSFORM_MASK) != 0) {
mView.invalidateViewProperty(hardwareAccelerated, false);
}
//取出所有要执行的属性动画的封装对象NameValuesHolder
ArrayList<NameValuesHolder> valueList = propertyBundle.mNameValuesHolder;
if (valueList != null) {
int count = valueList.size();
//遍历所有NameValuesHolder,计算变化值,并设置给对应的属性
for (int i = 0; i < count; ++i) {
NameValuesHolder values = valueList.get(i);
float value = values.mFromValue + fraction * values.mDeltaValue;
if (values.mNameConstant == ALPHA) {
alphaHandled = mView.setAlphaNoInvalidation(value);
} else {
setValue(values.mNameConstant, value);
}
}
}
if ((propertyMask & TRANSFORM_MASK) != 0) {
if (!hardwareAccelerated) {
mView.mPrivateFlags |= View.PFLAG_DRAWN; // force another invalidation
}
}
// invalidate(false) in all cases except if alphaHandled gets set to true
// via the call to setAlphaNoInvalidation(), above
if (alphaHandled) {
mView.invalidate(true);
} else {
mView.invalidateViewProperty(false, false);
}
if (mUpdateListener != null) {
mUpdateListener.onAnimationUpdate(animation);
}
}
总结
年底了,有疫情有裁员,大家要努力,一起加油
本文由哈喽比特于2年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/tOCF4Lx0JiQ6PYmIOPmCXw
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。