日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > Android >内容正文

Android

android 从底部网上的平移动画_Android属性动画,看完这篇够用了吧

發(fā)布時(shí)間:2025/3/21 Android 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android 从底部网上的平移动画_Android属性动画,看完这篇够用了吧 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

轉(zhuǎn)載自作者新小夢(mèng)

隨著APP的開發(fā)周期演進(jìn),APP不再滿足基礎(chǔ)的功能保障,需要有較好視覺體驗(yàn)和交互操作。那么動(dòng)畫效果是必不可少的,動(dòng)畫有幀動(dòng)畫,補(bǔ)間動(dòng)畫,屬性動(dòng)畫等等。

本文通過(guò)一些簡(jiǎn)單常見的動(dòng)畫效果,和大家重溫屬性動(dòng)畫的相關(guān)知識(shí)點(diǎn)。旨在通過(guò)全文,全面掌握屬性動(dòng)畫~如果看完本文,還需要查閱其他文章,說(shuō)明本文總結(jié)得還不夠好,歡迎留言補(bǔ)充。

一、屬性動(dòng)畫概覽

顧名思義,通過(guò)控制對(duì)象的屬性,來(lái)實(shí)現(xiàn)動(dòng)畫效果。官方定義:定義一個(gè)隨著時(shí)間 (注:停個(gè)頓)更改任何對(duì)象屬性的動(dòng)畫,無(wú)論其是否繪制到屏幕上。

可以控制對(duì)象什么屬性呢?什么屬性都可以,理論是通過(guò)set和get某個(gè)屬性來(lái)達(dá)到動(dòng)畫效果。例如常用下面一些屬性來(lái)實(shí)現(xiàn)View對(duì)象的一些動(dòng)畫效果。

  • 位移:translationX、translationY、translationZ
  • 透明度:alpha,透明度全透明到不透明:0f->1f
  • 旋轉(zhuǎn):rotation,旋轉(zhuǎn)一圈:0f->360f
  • 縮放:水平縮放scaleX,垂直縮放scaleY

簡(jiǎn)單的效果圖:

二、基本使用

簡(jiǎn)單介紹View對(duì)象幾個(gè)屬性動(dòng)畫的使用。

1、位移屬性動(dòng)畫

效果圖:

先看一下布局代碼的實(shí)現(xiàn):

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@color/colorPrimary"><LinearLayoutandroid:id="@+id/llAddAccount"android:layout_width="wrap_content"android:layout_height="35dp"android:layout_alignParentRight="true"android:layout_marginTop="100dp"android:layout_marginRight="-70dp"//將現(xiàn)有視圖藏在屏幕的右邊android:background="@drawable/bg_10_10_fff"><ImageViewandroid:id="@+id/ivMakeNote"android:layout_width="35dp"android:layout_height="30dp"android:layout_gravity="center_vertical"android:paddingLeft="2dp"android:paddingTop="2dp"android:paddingBottom="2dp"android:src="@mipmap/ic_account_add" /><TextViewandroid:id="@+id/tvAddAccount"android:layout_width="wrap_content"android:layout_height="match_parent"android:gravity="center_vertical"android:paddingRight="12dp"android:text="添加賬戶"android:textColor="@color/colorPrimary"android:textSize="14sp" /></LinearLayout> </RelativeLayout>

上面只是簡(jiǎn)單實(shí)現(xiàn)了布局,下面看看屬性動(dòng)畫代碼的實(shí)現(xiàn):

llAddAccount.setOnClickListener {val objectAnimation =ObjectAnimator.ofFloat(llAddAccount, "translationX", 0f, -70f)objectAnimation.start() }

到這里,我們才真正看到屬性動(dòng)畫的影子。通過(guò)ObjectAnimator的工廠方法ofFloat我們得到一個(gè)ObjectAnimator對(duì)象,并通過(guò)該對(duì)象的start()方法,開啟動(dòng)畫效果。

ofFloat()方法的第一個(gè)參數(shù)為要實(shí)現(xiàn)動(dòng)畫效果的View,例如這里整體效果的LinearLayout;第二個(gè)參數(shù)為屬性名,也就是前面所說(shuō)的:translationX,translationY,alpha,rotation,scaleX,scaleY等,這里要實(shí)現(xiàn)的是水平平移效果,所以我們采用了translationX;第三參數(shù)為可變長(zhǎng)參數(shù),第一個(gè)值為動(dòng)畫開始的位置,第二個(gè)值為結(jié)束值得位置,如果數(shù)組大于3位數(shù),那么前者將是后者的起始位置。

注意事項(xiàng):如果可變長(zhǎng)參數(shù)只有一個(gè)值,那么ObjectAnimator的工廠方法會(huì)將值作為動(dòng)畫結(jié)束值,此時(shí)屬性必須擁有初始化值和getXXX方法。

translationX和translationY這里涉及到的位移都是相對(duì)自身位置而言。例如 View在點(diǎn)A(x,y)要移動(dòng)到點(diǎn)B(x1,y1),那么ofFloat()方法的可變長(zhǎng)參數(shù),第一個(gè)值應(yīng)該0f,第二個(gè)值應(yīng)該x1-x。

XML布局實(shí)現(xiàn):

在res/animator文件夾下,創(chuàng)建animator_translation.xml文件,內(nèi)容如下:

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"android:propertyName="translationX"android:valueFrom="0dp"android:valueTo="-70dp"android:valueType="floatType" />

在代碼上調(diào)用:

llAddAccount.setOnClickListener {val objectAnimation =AnimatorInflater.loadAnimator(this,R.animator.animator_translation)objectAnimation.setTarget(llAddAccount)objectAnimation.start() }

2、透明屬性動(dòng)畫

透明度屬性動(dòng)畫比較簡(jiǎn)單,即控制View的可見度實(shí)現(xiàn)視覺差動(dòng)畫效果。這里展示效果是從不透明到透明,再到不透明。

代碼如下:

tvText.setOnClickListener {val objectAnimation =ObjectAnimator.ofFloat(tvText, "alpha", 1f,0f,1f)objectAnimation.duration=3000objectAnimation.start() }

ofFloat()方法將屬性名換成了透明度alpha,并且可變長(zhǎng)參數(shù)增加到了3個(gè)。給ObjectAnimator對(duì)象的duration屬性設(shè)置了動(dòng)畫展示時(shí)間3秒,默認(rèn)情況下300毫秒。

3、縮放屬性動(dòng)畫

縮放可以通過(guò)控制scaleX和scaleY分別在X軸和Y軸上進(jìn)行縮放,如下圖在X軸中進(jìn)行兩次兩倍縮放。

代碼如下:

tvText.setOnClickListener {val objectAnimation =ObjectAnimator.ofFloat(tvText, "scaleX", 1f,2f)objectAnimation.duration=3000objectAnimation.repeatCount=2objectAnimation.repeatMode=ValueAnimator.REVERSEobjectAnimation.start() }

ofFloat()方法傳入?yún)?shù)屬性為scaleX和scaleY時(shí),動(dòng)態(tài)參數(shù)表示縮放的倍數(shù)。設(shè)置ObjectAnimator對(duì)象的repeatCount屬性來(lái)控制動(dòng)畫執(zhí)行的次數(shù),設(shè)置為ValueAnimator.INFINITE表示無(wú)限循環(huán)播放動(dòng)畫;通過(guò)repeatMode屬性設(shè)置動(dòng)畫重復(fù)執(zhí)行的效果,取值為:ValueAnimator.RESTART和ValueAnimator.REVERSE。

ValueAnimator.RESTART效果:(即每次都重頭開始)

ValueAnimator.REVERSE效果:(即和上一次效果反著來(lái))

4、旋轉(zhuǎn)屬性動(dòng)畫

旋轉(zhuǎn)動(dòng)畫也比較簡(jiǎn)單,將一個(gè)View進(jìn)行順時(shí)針或逆時(shí)針旋轉(zhuǎn)。

代碼如下

tvText.setOnClickListener {val objectAnimation =ObjectAnimator.ofFloat(tvText, "rotation", 0f,180f,0f)objectAnimation.duration=3000objectAnimation.start() }

ofFloat()方法的可變長(zhǎng)參數(shù),如果后者的值大于前者,那么順時(shí)針旋轉(zhuǎn),小于前者,則逆時(shí)針旋轉(zhuǎn)。

三、AnimatorSet

如果想要一個(gè)動(dòng)畫結(jié)束后播放另外一個(gè)動(dòng)畫,或者同時(shí)播放,可以通過(guò)AnimatorSet來(lái)編排。

val aAnimator=ObjectAnimator.ofInt(1) val bAnimator=ObjectAnimator.ofInt(1) val cAnimator=ObjectAnimator.ofInt(1) val dAnimator=ObjectAnimator.ofInt(1)AnimatorSet().apply {play(aAnimator).before(bAnimator)//a 在b之前播放play(bAnimator).with(cAnimator)//b和c同時(shí)播放動(dòng)畫效果play(dAnimator).after(cAnimator)//d 在c播放結(jié)束之后播放start() }

或者

AnimatorSet().apply {playSequentially(aAnimator,bAnimator,cAnimator,dAnimator) //順序播放start() }AnimatorSet().apply {playTogether(animator,bAnimator,cAnimator,dAnimator) //同時(shí)播放start() }

另有:

AnimatorSet ().apply {play(aAnimator).after(1000) //1秒后播放a動(dòng)畫start() }

四、ViewPropertyAnimator

如果只是針對(duì)View對(duì)象的特定屬性同時(shí)播放動(dòng)畫,我們也可以采用ViewPropertyAnimator。

例如:

tvText.animate().translationX(100f).translationY(100f).start()

支持屬性:

  • translationX、translationY、translationZ
  • x、y、z
  • alpha
  • scaleX、scaleY

注意到ViewPropertyAnimator對(duì)象具有property(Float)和propertyBy(Float)方法,其中property(Float)是指屬性變化多少(可以理解一次有效),而propertyBy(Float)每次變化多少(可以理解多次有效)。

舉例說(shuō)明:

translationX

tvText.setOnClickListener {val animator = tvText.animate()animator.duration=1000animator.translationX(100f)//點(diǎn)擊一次會(huì)向右偏移,再點(diǎn)擊沒效果animator.start() }

translationXBy

tvText.setOnClickListener {val animator = tvText.animate()animator.duration=1000animator.translationXBy(100f)//每次點(diǎn)擊都會(huì)向右偏移animator.start() }

五、ValueAnimator與ObjectAnimator

ValueAnimator作為ObjectAnimator的父類,主要?jiǎng)討B(tài)計(jì)算目標(biāo)對(duì)象屬性的值,然后設(shè)置給對(duì)象屬性,達(dá)到動(dòng)畫效果,而ObjectAnimator則在ValueAnimator的基礎(chǔ)上極大地簡(jiǎn)化對(duì)目標(biāo)對(duì)象的屬性值的計(jì)算和添加效果,融合了 ValueAnimator 的計(jì)時(shí)引擎和值計(jì)算以及為目標(biāo)對(duì)象的命名屬性添加動(dòng)畫效果這一功能。

舉個(gè)栗子,通過(guò)ValueAnimator的工廠方法ofFloat、ofInt、ofArgb、ofObject來(lái)實(shí)現(xiàn)動(dòng)畫效果:

代碼如下:

//ValueAnimator實(shí)現(xiàn)tvText.setOnClickListener {val valueAnimator = ValueAnimator.ofFloat(0f, 180f)valueAnimator.addUpdateListener {tvText.rotationY = it.animatedValue as Float //手動(dòng)賦值}valueAnimator.start()}//ObjectAnimator實(shí)現(xiàn)ObjectAnimator.ofFloat(tvText, "rotationY", 0f, 180f).apply { start() }

從上面代碼可以看出,使用ValueAnimator實(shí)現(xiàn)動(dòng)畫,需要手動(dòng)賦值給目標(biāo)對(duì)象tvText的rotationY,而ObjectAnimator則是自動(dòng)賦值,不需要手動(dòng)賦值就可以達(dá)到效果。

動(dòng)畫過(guò)程可以通過(guò)AnimatorUpdateListener和AnimatorListener來(lái)監(jiān)聽。

ObjectAnimator.ofFloat(tvText, "translationX", 0f, 780f, 0f).apply {duration=3000//完成動(dòng)畫所需要時(shí)間repeatCount=ValueAnimator.INFINITE //重復(fù)次數(shù):無(wú)限循環(huán)repeatMode=ValueAnimator.RESTART //重復(fù)模式:重頭開始addUpdateListener { //監(jiān)聽值變化tvText.translationX= it.animatedValue as Float}addListener(object:Animator.AnimatorListener{override fun onAnimationRepeat(animation: Animator?) {//動(dòng)畫重復(fù)}override fun onAnimationEnd(animation: Animator?) {//動(dòng)畫結(jié)束}override fun onAnimationCancel(animation: Animator?) {//動(dòng)畫取消}override fun onAnimationStart(animation: Animator?) {//動(dòng)畫開始}})}

動(dòng)畫可調(diào)用start()方法開始,也可調(diào)用cancel()方法取消。

那么,要正確使屬性動(dòng)畫實(shí)現(xiàn)動(dòng)畫效果,那么目標(biāo)對(duì)象應(yīng)該注意什么?

  • 屬性必須具有 set<PropertyName>() 形式的 setter 函數(shù)(采用駝峰式大小寫形式),例如,如果屬性名稱為 text,則需要使用 setText() 方法。
  • 如果ObjectAnimator的一個(gè)工廠方法中僅為 values... 參數(shù)指定了一個(gè)值,那么該參數(shù)需要提供初始值和getPropertyName()方法。
  • 屬性的初始值和結(jié)束值之間必須保持類型相同。
  • 可能需要在UpdateListener對(duì)象中調(diào)用invalidate() 方法,來(lái)刷新屬性作用后的效果。

六、XML實(shí)現(xiàn)

本文一開始介紹位移屬性動(dòng)畫時(shí),有提到通過(guò)XML文件來(lái)實(shí)現(xiàn)動(dòng)畫效果,在這里進(jìn)一步細(xì)講。

在res/animator文件夾下,創(chuàng)建animator_translation.xml文件。XML文件有四個(gè)標(biāo)簽可用,要注意到propertyValuesHolder標(biāo)簽的Android 版本適配。

<?xml version="1.0" encoding="utf-8"?> <set> =>AnimatorSet<animator/> =>ValueAnimator<objectAnimator> =>ObjectAnimator<propertyValuesHolder/> =>PropertyValuesHolder</objectAnimator> </set>

set標(biāo)簽對(duì)應(yīng)代碼的AnimatorSet,只有一個(gè)屬性可以設(shè)置:android:ordering,取值:同時(shí)播放together、順序播放sequentially。

animator標(biāo)簽對(duì)應(yīng)代碼的ValueAnimator,可以設(shè)置如下屬性:

  • android:duration:動(dòng)畫時(shí)長(zhǎng)
  • android:valueType:屬性類型,intType、floatType、colorType
  • android:valueFrom:屬性初始值
  • android:valueTo:屬性結(jié)束值
  • android:repeatCount:重復(fù)次數(shù)
  • android:repeatMode:重復(fù)模式
  • android:interpolator:插值器,可看下一節(jié)默認(rèn)插值器。
  • android:startOffset:延遲,對(duì)應(yīng)startOffset()延遲多少毫秒執(zhí)行

示例:

<animatorandroid:duration="1000"android:valueType="floatType"android:valueFrom="0f"android:valueTo="100f"android:repeatCount="infinite"android:repeatMode="restart"android:interpolator="@android:interpolator/linear"android:startOffset="100"/>

objectAnimator屬性對(duì)應(yīng)代碼ObjectAnimator,由于繼承自ValueAnimator,所以屬性相對(duì)多了` android:propertyName。

七、估值器與插值器

看到這里,不知道小伙伴們有沒有這個(gè)疑問(wèn),屬性動(dòng)畫是如何計(jì)算屬性的值的?

這份工作由類型估值器TypeEvaluator與時(shí)間插值器TimeInterpolator來(lái)完成的。

插值器:根據(jù)時(shí)間流逝的百分比計(jì)算出當(dāng)前屬性值改變的百分比。

估值器:根據(jù)當(dāng)前屬性改變的百分比來(lái)計(jì)算改變后的屬性值。

從它兩的已定義,也可以看出它們之間的協(xié)調(diào)關(guān)系,先由插值器根據(jù)時(shí)間流逝的百分比計(jì)算出目標(biāo)對(duì)象的屬性改變的百分比,再由估值器根據(jù)插值器計(jì)算出來(lái)的屬性改變的百分比計(jì)算出目標(biāo)對(duì)象屬性對(duì)應(yīng)類型的值。

從估值器和插值器可以看出屬性動(dòng)畫的工作原理,下面看看官方對(duì)工作原理的解析:

估值器

SDK中默認(rèn)帶有的估值器有: IntEvaluator、FloatEvaluator、ArgbEvaluator,他們分別對(duì)應(yīng)前面我們調(diào)用 ValueAnimator對(duì)象所有對(duì)應(yīng)的ofInt、ofFloat、ofArgb函數(shù)的估值器,分別用在Int類型,Float,顏色值類型之間計(jì)算。而ofObject函數(shù)則對(duì)應(yīng)我們自定義類型的屬性計(jì)算。

當(dāng)估值器的類型不滿足需求,就需要自定義類型估值器。例如我們要實(shí)現(xiàn)下面效果:

這個(gè)效果可以通過(guò)AnimatorSet來(lái)實(shí)現(xiàn),但我們這里采用自定義TypeEvaluator來(lái)實(shí)現(xiàn)TextView從屏幕左上角斜線滑到屏幕右下角。

  • 定義Point類,我們操作的對(duì)象。
  • data class Point(var x: Float, var y: Float)
  • 定義PointEvaluator估值器,繼承自TypeEvaluator,泛型參數(shù)為Point類型。通過(guò)實(shí)現(xiàn)evaluate()方法,可以實(shí)現(xiàn)很多復(fù)制的動(dòng)畫效果,我們這里實(shí)現(xiàn)上面簡(jiǎn)單算法。
  • class PointEvaluator : TypeEvaluator<Point> {/*** 根據(jù)插值器計(jì)算出當(dāng)前對(duì)象的屬性的百分比f(wàn)raction,估算去屬性當(dāng)前具體的值* @param fraction 屬性改變的百分比* @param startValue 對(duì)象開始的位置,例如這里點(diǎn)坐標(biāo)開始位置:屏幕左上角位置* @param endValue 對(duì)象結(jié)束的位置,例如這里點(diǎn)坐標(biāo)結(jié)束的位置:屏幕右下角位置*/override fun evaluate(fraction: Float, startValue: Point?, endValue: Point?): Point {if (startValue == null || endValue == null) {return Point(0f, 0f)}return Point(fraction * (endValue.x - startValue.x),fraction * (endValue.y - startValue.y))} }
  • 使用
  • val animator= ValueAnimator.ofObject(PointEvaluator(), Point(0f, 0f),//動(dòng)畫開始屬性值Point(ScreenUtils.getScreenWidth(this).toFloat(),ScreenUtils.getScreenHeight(this).toFloat())//動(dòng)畫結(jié)束值)animator.addUpdateListener {//手動(dòng)更新TextView的x和y 屬性val point = it.animatedValue as PointtvText.x = point.xtvText.y = point.y logError("point:${point}")}animator.duration = 5000btnStart.setOnClickListener {animator.start()}

    一個(gè)簡(jiǎn)單的自定義估值器就算完成了。數(shù)學(xué)學(xué)的好,任何復(fù)雜效果都不是問(wèn)題。

    插值器

    TypeEvaluator對(duì)象的evaluate()方法的fraction參數(shù)就是插值器計(jì)算得來(lái),SDK中默認(rèn)的時(shí)間插值器有:

    • LinearInterpolator 線性(勻速)
    • AccelerateInterpolator 持續(xù)加速
    • DecelerateInterpolator 持續(xù)減速
    • AccelerateDecelerateInterpolator 先加速后減速
    • OvershootInterpolator 結(jié)束時(shí)回彈一下
    • AnticipateInterpolator 開始回拉一下
    • BounceInterpolator 結(jié)束時(shí)Q彈一下
    • CycleInterpolator 來(lái)回循環(huán)

    看看效果:

    LinearInterpolator

    AccelerateInterpolator

    DecelerateInterpolator

    AccelerateDecelerateInterpolator

    OvershootInterpolator

    AnticipateInterpolator

    BounceInterpolator

    CycleInterpolator

    正常情況下,默認(rèn)的插值器已經(jīng)夠用,如果自己數(shù)學(xué)厲害,想顯擺一下,也是通過(guò)實(shí)現(xiàn)TimeInterpolator接口的getInterpolation()自定義的。

    /*** A time interpolator defines the rate of change of an animation. This allows animations* to have non-linear motion, such as acceleration and deceleration.*/ public interface TimeInterpolator {/*** Maps a value representing the elapsed fraction of an animation to a value that represents* the interpolated fraction. This interpolated value is then multiplied by the change in* value of an animation to derive the animated value at the current elapsed animation time.** @param input A value between 0 and 1.0 indicating our current point* in the animation where 0 represents the start and 1.0 represents* the end* @return The interpolation value. This value can be more than 1.0 for* interpolators which overshoot their targets, or less than 0 for* interpolators that undershoot their targets.*/float getInterpolation(float input); }

    八、Keyframe

    要控制動(dòng)畫速率的變化,就得去自定義插值器或估值器,對(duì)我這種數(shù)學(xué)渣渣來(lái)說(shuō),簡(jiǎn)直比上天一樣難的。

    所以渣渣們可以考慮用關(guān)鍵幀Keyframe對(duì)象來(lái)實(shí)現(xiàn)。Keyframe讓我們可以指定某個(gè)屬性百分比時(shí)對(duì)象的屬性值。

    tvText.setOnClickListener {val start = Keyframe.ofFloat(0f, 0f)val middle = Keyframe.ofFloat(0.3f, 400f)val end = Keyframe.ofFloat(1f, 700f)val holder=PropertyValuesHolder.ofKeyframe("translationX",start,middle,end)ObjectAnimator.ofPropertyValuesHolder(tvText,holder).apply {duration=2000start()}}

    上面代碼分別定義了三個(gè)關(guān)鍵幀,分別在屬性百分比為0f、0.3f、1f對(duì)應(yīng)的translationX的值。

    動(dòng)畫效果:

    可以看到效果先快后慢。

    Keyframe同樣支持ofFloat、ofInt、ofObject。使用關(guān)鍵幀,至少需要有兩個(gè)關(guān)鍵幀,不然坐等崩潰吧。PropertyValuesHolder對(duì)象是用來(lái)保存動(dòng)畫過(guò)程所操作的屬性和對(duì)應(yīng)的值。

    九、總結(jié)

    通過(guò)ObjectAnimator的工廠方法可以快速實(shí)現(xiàn)一個(gè)屬性動(dòng)畫,但默認(rèn)的屬性動(dòng)畫不滿足自己的需求是,可以通過(guò)ValueAnimator對(duì)象來(lái)定義自己的屬性,注意屬性的要求。可以通過(guò)AnimatorSet來(lái)實(shí)現(xiàn)屬性組合播放效果。

    動(dòng)畫的原理是通過(guò)時(shí)間插值器與類型估值器配置使用,控制對(duì)象的屬性來(lái)實(shí)現(xiàn)動(dòng)畫效果。

    總結(jié)

    以上是生活随笔為你收集整理的android 从底部网上的平移动画_Android属性动画,看完这篇够用了吧的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。