补间动画转移后人与动人物xxxxx视频,点击事件的反映为什么还在原本的位置?
那今天咱们就来从源码认知旨趣
一、补间动画补间动画不错在一个视图容器内实践一系列浅易变换(具体的变换形态有:位置、大小、旋转、透明度);
咱们不错通过平移、旋转、缩放、透明度等API进行具体的操作;
补间动画的结束方式不错通过 XML或通过Android代码两种方式 去界说;人与动人物xxxxx视频
1、xml方式结束文献名:animator_translate.xml
<?xml version="1.0" encoding="utf-8"?> <translate xmlns:android="http://schemas.android.com/apk/res/android" android:fromXDelta="0" android:fromYDelta="0" android:toYDelta="0" android:toXDelta="200" android:duration="500" android:fillAfter="true"> </translate>
代码加载xml文献赢得动画
//加载动画 Animation animation = AnimationUtils.loadAnimation(this, R.anim.animator_translate); //实践动画 testBtn.startAnimation(animation);2、代码方式结束
TranslateAnimation translateAnimation = new TranslateAnimation(0,200,0,0); translateAnimation.setDuration(500);//动画实践技艺 translateAnimation.setFillAfter(true);//动画实践完成后保持景象 //实践动画 testBtn.startAnimation(translateAnimation);二、补间动画原表现
人与动人物xxxxx视频
startAnimation(rotateAnimation)设施投入源码;
//View.java public void startAnimation(Animation animation) { animation.setStartTime(Animation.START_ON_FIRST_FRAME); setAnimation(animation); invalidateParentCaches(); invalidate(true); }
领先是通过setStartTime()配置了动画的开动技艺;
//View.java public void setStartTime(long startTimeMillis) { mStartTime = startTimeMillis; mStarted = mEnded = false; mCycleFlip = false; mRepeated = 0; mMore = true; }
这里只是对一些变量进行赋值,再来望望下一个设施;
配置动画setAnimation(animation):人与动人物xxxxx视频
据国外安全媒体报道,一家位于佛罗里达州杰克逊维尔的交通运输行业商业信用报告机构TransCredit 因配置错误致使50万人财务数据泄露。
该工具主要针对的是Shellcode注入技术,可以演示恶意软件在目标系统上执行Shellcode时所使用的技术方法,其中包括:
微软的调查结果为NHS的早期警报提供了新线索,NHS警告称:“攻击者肆意利用VMware Horizon服务器中的Log4Shell漏洞,企图建立Web Shell。”攻击者可以使用这些Web Shell,部署恶意软件和勒索软件以及泄露数据。为了应对这起安全事件,NHS和VMware都敦促用户尽快修补受影响的系统,以及/或者实施安全公告中提到的变通办法。
//View.java public void setAnimation(Animation animation) { mCurrentAnimation = animation; if (animation != null) { if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) { animation.setStartTime(AnimationUtils.currentAnimationTimeMillis()); } animation.reset(); } }
这内部亦然将动画实例赋值给现时的成员变量;
分析startAnimation()设施里的invalidateParentCaches();
//View.java protected void invalidateParentCaches() if (mParent instanceof View) { ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED; } }
不错看到这里只是是配置动画象征,在视图构建大约属性改革时是必要的;
再回到startAnimation()设施内部invalidate(true);
2、invalidate//View.java public void invalidate(boolean invalidateCache) { invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true); } void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache, boolean fullInvalidate) { if (mGhostView != null) { mGhostView.invalidate(true); return; } ................. // Propagate the damage rectangle to the parent view. final AttachInfo ai = mAttachInfo; final ViewParent p = mParent; if (p != null && ai != null && l < r && t < b) { final Rect damage = ai.mTmpInvalRect; damage.set(l, t, r, b); p.invalidateChild(this,yellow免费观看完整 damage); } } }
这里持重看p.invalidateChild(this, damage);
//ViewGroup.java @Deprecated @Override public final void invalidateChild(View child, final Rect dirty) { final AttachInfo attachInfo = mAttachInfo; if (attachInfo != null && attachInfo.mHardwareAccelerated) { // HW accelerated fast path onDescendantInvalidated(child, child); return; } ViewParent parent = this; ......... do { View view = null; if (parent instanceof View) { view = (View) parent; } ......... parent = parent.invalidateChildInParent(location, dirty); } while (parent != null); } }因为ViewParent p = mParent,this是View的子类ViewGroup; 是以p.invalidateChild(this, damage)内部其实是调用了ViewGroup的invalidateChild(); 这里有一个do{}while()轮回,第一次的时候parent = this即ViewGroup,然后调用parent.invalidateChildInParent(location, dirty)设施,当parent == null的时候截止轮回; invalidateChildInParent设施中,只有要求栽植就会复返mParent;
//ViewGroup.java @Deprecated @Override public ViewParent invalidateChildInParent(final int[] location, final Rect dirty) { if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID)) != 0) { ....... return mParent; } return null; }((mPrivateFlags & (PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID)) != 0)是保持栽植的,是以会一直复返mParent,那么评释View的mParent是ViewGroup; ViewGroup的mParent亦然ViewGroup,而do{}while()轮回一直找mParent,而一个View最尖端的mParent是ViewRootImpl,是以临了走到ViewRootImpl的invalidateChildInParent()内部; 在onCreate()设施内部通过setContentView()将布局添加到以DecorView为根布局的一个ViewGroup内部,因为在onResume()实践完成后,WindowManager会实践addView()设施,然后会创建一个ViewRootImpl对象,与DecorView绑定起来,DecorView的mParent配置成ViewRootImpl,ViewRootImpl结束了ViewParent接口,是以ViewRootImpl天然莫得招揽View大约ViewGroup; ViewRootImpl的invalidateChildInParent()设施中;
//ViewRootImpl.java @Override public ViewParent invalidateChildInParent(int[] location, Rect dirty) { checkThread(); if (DEBUG_DRAW) Log.v(mTag, "Invalidate child: " + dirty); if (dirty == null) { invalidate(); return null; } else if (dirty.isEmpty() && !mIsAnimating) { return null; } ....... invalidateRectOnScreen(dirty); return null; }
这里扫数的复返值都变为null了人与动人物xxxxx视频,之前实践的do{}while()循坏也会住手。
3、scheduleTraversals() 接着分析invalidateRectOnScreen(dirty)设施; 投入 scheduleTraversals()设施;//ViewRootImpl.java private void invalidateRectOnScreen(Rect dirty) { ...... if (!mWillDrawSoon && (intersected