九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
8.4.3 Android動(dòng)畫合集之屬性動(dòng)畫

本節(jié)引言:

本節(jié)給帶來的是Android動(dòng)畫中的第三種動(dòng)畫——屬性動(dòng)畫(Property Animation),記得在上一節(jié)8.4.2 Android動(dòng)畫合集之補(bǔ)間動(dòng)畫為Fragment設(shè)置過渡動(dòng)畫的時(shí)候,說過,App包和V4包下的Fragment調(diào)用setCustomAnimations()對(duì)應(yīng)的動(dòng)畫類型是不一樣的,v4包下的是Animation,而app包下的是Animator

Animation一般動(dòng)畫就是我們前面學(xué)的幀動(dòng)畫和補(bǔ)間動(dòng)畫!Animator則是本節(jié)要講的屬性動(dòng)畫!

關(guān)于屬性動(dòng)畫,大牛郭大叔已經(jīng)寫了三篇非常好的總結(jié)文,寫得非常贊,就沒必要重復(fù)造輪子了,不過這里還是過一遍,大部分內(nèi)容參考的下面三篇文章:

Android屬性動(dòng)畫完全解析(上),初識(shí)屬性動(dòng)畫的基本用法

Android屬性動(dòng)畫完全解析(中),ValueAnimator和ObjectAnimator的高級(jí)用法

Android屬性動(dòng)畫完全解析(下),Interpolator和ViewPropertyAnimator的用法

寫的非常好,或者說你可以直接跳過本文去看上面的三篇文章~

當(dāng)然,你愿意看我叨叨逼的話,也很歡迎,好了,開始本節(jié)內(nèi)容吧~


1.屬性動(dòng)畫概念叨叨逼


不BB,直接上圖,就是這么暴力~


2.ValueAnimator簡(jiǎn)單使用

使用流程

  • 1.調(diào)用ValueAnimator的ofInt(),ofFloat()或ofObject()靜態(tài)方法創(chuàng)建ValueAnimator實(shí)例
  • 2.調(diào)用實(shí)例的setXxx方法設(shè)置動(dòng)畫持續(xù)時(shí)間,插值方式,重復(fù)次數(shù)等
  • 3.調(diào)用實(shí)例的addUpdateListener添加AnimatorUpdateListener監(jiān)聽器,在該監(jiān)聽器中可以獲得ValueAnimator計(jì)算出來的值,你可以值應(yīng)用到指定對(duì)象上~
  • 4.調(diào)用實(shí)例的start()方法開啟動(dòng)畫!另外我們可以看到ofInt和ofFloat都有個(gè)這樣的參數(shù):float/int... values代表可以多個(gè)值!

使用示例

代碼實(shí)現(xiàn)

布局文件:activity_main.xml,非常簡(jiǎn)單,四個(gè)按鈕,一個(gè)ImageView

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/ly_root"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical">    <Button        android:id="@+id/btn_one"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="動(dòng)畫1" />    <Button        android:id="@+id/btn_two"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="動(dòng)畫2" />    <Button        android:id="@+id/btn_three"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="動(dòng)畫3" />    <Button        android:id="@+id/btn_four"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="動(dòng)畫4" />    <ImageView        android:id="@+id/img_babi"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_gravity="center"        android:background="@mipmap/img_babi" /></LinearLayout>

接著到MainActivity.java,首先需要一個(gè)修改View位置的方法,這里調(diào)用moveView()設(shè)置左邊和上邊的起始坐標(biāo)以及寬高!

接著定義了四個(gè)動(dòng)畫,分別是:直線移動(dòng),縮放,旋轉(zhuǎn)加透明,以及圓形旋轉(zhuǎn)!

然后通過按鈕觸發(fā)對(duì)應(yīng)的動(dòng)畫~

public class MainActivity extends AppCompatActivity implements View.OnClickListener {    private Button btn_one;    private Button btn_two;    private Button btn_three;    private Button btn_four;    private LinearLayout ly_root;    private ImageView img_babi;    private int width;    private int height;    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        bindViews();    }    private void bindViews() {        ly_root = (LinearLayout) findViewById(R.id.ly_root);        btn_one = (Button) findViewById(R.id.btn_one);        btn_two = (Button) findViewById(R.id.btn_two);        btn_three = (Button) findViewById(R.id.btn_three);        btn_four = (Button) findViewById(R.id.btn_four);        img_babi = (ImageView) findViewById(R.id.img_babi);        btn_one.setOnClickListener(this);        btn_two.setOnClickListener(this);        btn_three.setOnClickListener(this);        btn_four.setOnClickListener(this);        img_babi.setOnClickListener(this);    }    @Override    public void onClick(View v) {        switch (v.getId()) {            case R.id.btn_one:                lineAnimator();                break;            case R.id.btn_two:                scaleAnimator();                break;            case R.id.btn_three:                raAnimator();                break;            case R.id.btn_four:                circleAnimator();                break;            case R.id.img_babi:                Toast.makeText(MainActivity.this, "不愧是coder-pig~", Toast.LENGTH_SHORT).show();                break;        }    }    //定義一個(gè)修改ImageView位置的方法    private void moveView(View view, int rawX, int rawY) {        int left = rawX - img_babi.getWidth() / 2;        int top = rawY - img_babi.getHeight();        int width = left + view.getWidth();        int height = top + view.getHeight();        view.layout(left, top, width, height);    }    //定義屬性動(dòng)畫的方法:    //按軌跡方程來運(yùn)動(dòng)    private void lineAnimator() {        width = ly_root.getWidth();        height = ly_root.getHeight();        ValueAnimator xValue = ValueAnimator.ofInt(height,0,height / 4,height / 2,height / 4 * 3 ,height);        xValue.setDuration(3000L);        xValue.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                // 軌跡方程 x = width / 2                int y = (Integer) animation.getAnimatedValue();                int x = width / 2;                moveView(img_babi, x, y);            }        });        xValue.setInterpolator(new LinearInterpolator());        xValue.start();    }    //縮放效果    private void scaleAnimator(){            //這里故意用兩個(gè)是想讓大家體會(huì)下組合動(dòng)畫怎么用而已~        final float scale = 0.5f;        AnimatorSet scaleSet = new AnimatorSet();        ValueAnimator valueAnimatorSmall = ValueAnimator.ofFloat(1.0f, scale);        valueAnimatorSmall.setDuration(500);        ValueAnimator valueAnimatorLarge = ValueAnimator.ofFloat(scale, 1.0f);        valueAnimatorLarge.setDuration(500);        valueAnimatorSmall.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                float scale = (Float) animation.getAnimatedValue();                img_babi.setScaleX(scale);                img_babi.setScaleY(scale);            }        });        valueAnimatorLarge.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                float scale = (Float) animation.getAnimatedValue();                img_babi.setScaleX(scale);                img_babi.setScaleY(scale);            }        });        scaleSet.play(valueAnimatorLarge).after(valueAnimatorSmall);        scaleSet.start();        //其實(shí)可以一個(gè)就搞定的//        ValueAnimator vValue = ValueAnimator.ofFloat(1.0f, 0.6f, 1.2f, 1.0f, 0.6f, 1.2f, 1.0f);//        vValue.setDuration(1000L);//        vValue.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {//            @Override//            public void onAnimationUpdate(ValueAnimator animation) {//                float scale = (Float) animation.getAnimatedValue();//                img_babi.setScaleX(scale);//                img_babi.setScaleY(scale);//            }//        });//        vValue.setInterpolator(new LinearInterpolator());//        vValue.start();    }    //旋轉(zhuǎn)的同時(shí)透明度變化    private void raAnimator(){        ValueAnimator rValue = ValueAnimator.ofInt(0, 360);        rValue.setDuration(1000L);        rValue.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                int rotateValue = (Integer) animation.getAnimatedValue();                img_babi.setRotation(rotateValue);                float fractionValue = animation.getAnimatedFraction();                img_babi.setAlpha(fractionValue);            }        });        rValue.setInterpolator(new DecelerateInterpolator());        rValue.start();    }    //圓形旋轉(zhuǎn)    protected void circleAnimator() {        width = ly_root.getWidth();        height = ly_root.getHeight();        final int R = width / 4;        ValueAnimator tValue = ValueAnimator.ofFloat(0,                (float) (2.0f * Math.PI));        tValue.setDuration(1000);        tValue.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                // 圓的參數(shù)方程 x = R * sin(t) y = R * cos(t)                float t = (Float) animation.getAnimatedValue();                int x = (int) (R * Math.sin(t) + width / 2);                int y = (int) (R * Math.cos(t) + height / 2);                moveView(img_babi, x, y);            }        });        tValue.setInterpolator(new DecelerateInterpolator());        tValue.start();    }}

好的,使用的流程非常簡(jiǎn)單,先創(chuàng)建ValueAnimator對(duì)象,調(diào)用ValueAnimator.ofInt/ofFloat獲得,然后設(shè)置動(dòng)畫持續(xù)時(shí)間,addUpdateListener添加AnimatorUpdateListener事件監(jiān)聽,然后使用參數(shù)animationgetAnimatedValue()獲得當(dāng)前的值,然后我們可以拿著這個(gè)值來修改View的一些屬性,從而形成所謂的動(dòng)畫效果,接著設(shè)置setInterpolator動(dòng)畫渲染模式,最后調(diào)用start()開始動(dòng)畫的播放~

臥槽,直線方程,圓的參數(shù)方程,我都開始方了,這不是高數(shù)的東西么,掛科學(xué)渣連三角函數(shù)都忘了...

例子參考自github:
這里就是不斷改變alpha的值,從1f - 0f,然后對(duì)象根據(jù)屬性值的變化來刷新界面顯示,從而展現(xiàn)出淡入淡出的效果,而在TextView類中并沒有alpha這個(gè)屬性,ObjectAnimator內(nèi)部機(jī)制是:尋找傳輸?shù)膶傩悦麑?duì)應(yīng)的get和set方法~,而非找這個(gè)屬性值!不信的話你可以到TextView的源碼里找找是否有alpha這個(gè)屬性!好的,下面我們利用ObjectAnimator來實(shí)現(xiàn)四種補(bǔ)間動(dòng)畫的效果吧~

運(yùn)行效果圖

代碼實(shí)現(xiàn)

布局直接用的上面那個(gè)布局,加了個(gè)按鈕,把ImageView換成了TextView,這里就不貼代碼了,直接上MainActivity.java部分的代碼,其實(shí)都是大同小異的~

public class MainActivity extends AppCompatActivity implements View.OnClickListener {    private Button btn_one;    private Button btn_two;    private Button btn_three;    private Button btn_four;    private Button btn_five;    private LinearLayout ly_root;    private TextView tv_pig;    private int height;    private ObjectAnimator animator1;    private ObjectAnimator animator2;    private ObjectAnimator animator3;    private ObjectAnimator animator4;    private AnimatorSet animSet;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        bindViews();        initAnimator();    }    private void bindViews() {        ly_root = (LinearLayout) findViewById(R.id.ly_root);        btn_one = (Button) findViewById(R.id.btn_one);        btn_two = (Button) findViewById(R.id.btn_two);        btn_three = (Button) findViewById(R.id.btn_three);        btn_four = (Button) findViewById(R.id.btn_four);        btn_five = (Button) findViewById(R.id.btn_five);        tv_pig = (TextView) findViewById(R.id.tv_pig);        height = ly_root.getHeight();        btn_one.setOnClickListener(this);        btn_two.setOnClickListener(this);        btn_three.setOnClickListener(this);        btn_four.setOnClickListener(this);        btn_five.setOnClickListener(this);        tv_pig.setOnClickListener(this);    }    //初始化動(dòng)畫    private void initAnimator() {        animator1 = ObjectAnimator.ofFloat(tv_pig, "alpha", 1f, 0f, 1f, 0f, 1f);        animator2 = ObjectAnimator.ofFloat(tv_pig, "rotation", 0f, 360f, 0f);        animator3 = ObjectAnimator.ofFloat(tv_pig, "scaleX", 2f, 4f, 1f, 0.5f, 1f);        animator4 = ObjectAnimator.ofFloat(tv_pig, "translationY", height / 8, -100, height / 2);    }    @Override    public void onClick(View v) {        switch (v.getId()) {            case R.id.btn_one:                animator1.setDuration(3000l);                animator1.start();                break;            case R.id.btn_two:                animator2.setDuration(3000l);                animator2.start();                break;            case R.id.btn_three:                animator3.setDuration(3000l);                animator3.start();                break;            case R.id.btn_four:                animator4.setDuration(3000l);                animator4.start();                break;            case R.id.btn_five:                //將前面的動(dòng)畫集合到一起~                animSet = new AnimatorSet();                animSet.play(animator4).with(animator3).with(animator2).after(animator1);                animSet.setDuration(5000l);                animSet.start();                break;            case R.id.tv_pig:                Toast.makeText(MainActivity.this, "不愧是coder-pig~", Toast.LENGTH_SHORT).show();                break;        }    }}

用法也非常簡(jiǎn)單,上面涉及到的組合動(dòng)畫我們下面講~


4.組合動(dòng)畫與AnimatorListener

從上面兩個(gè)例子中我們都體驗(yàn)了一把組合動(dòng)畫,用到了AnimatorSet這個(gè)類!

我們調(diào)用的play()方法,然后傳入第一個(gè)開始執(zhí)行的動(dòng)畫,此時(shí)他會(huì)返回一個(gè)Builder類給我們:

接下來我們可以調(diào)用Builder給我們提供的四個(gè)方法,來組合其他的動(dòng)畫:

嗯,很簡(jiǎn)單,接下來要說下動(dòng)畫事件的監(jiān)聽,上面我們ValueAnimator的監(jiān)聽器是AnimatorUpdateListener,當(dāng)值狀態(tài)發(fā)生改變時(shí)候會(huì)回調(diào)onAnimationUpdate方法!

除了這種事件外還有:動(dòng)畫進(jìn)行狀態(tài)的監(jiān)聽~ AnimatorListener,我們可以調(diào)用addListener方法添加監(jiān)聽器,然后重寫下面四個(gè)回調(diào)方法:

沒錯(cuò),加入你真的用AnimatorListener的話,四個(gè)方法你都要重寫,當(dāng)然和前面的手勢(shì)那一節(jié)一樣,Android已經(jīng)給我們提供好一個(gè)適配器類:AnimatorListenerAdapter,該類中已經(jīng)把每個(gè)接口方法都實(shí)現(xiàn)好了,所以我們這里只寫一個(gè)回調(diào)方法也可以額!


5.使用XML來編寫動(dòng)畫

使用XML來編寫動(dòng)畫,畫的時(shí)間可能比Java代碼長(zhǎng)一點(diǎn),但是重用起來就輕松很多!對(duì)應(yīng)的XML標(biāo)簽分別為:<animator><objectAnimator><set>相關(guān)的屬性解釋如下:

使用例子如下

從0到100平滑過渡的動(dòng)畫

<animator xmlns:android="http://schemas.android.com/apk/res/android"      android:valueFrom="0"      android:valueTo="100"      android:valueType="intType"/>

將一個(gè)視圖的alpha屬性從1變成0

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"      android:valueFrom="1"      android:valueTo="0"      android:valueType="floatType"      android:propertyName="alpha"/>

set動(dòng)畫使用演示

<set android:ordering="sequentially" >    <set>        <objectAnimator            android:duration="500"            android:propertyName="x"            android:valueTo="400"            android:valueType="intType" />        <objectAnimator            android:duration="500"            android:propertyName="y"            android:valueTo="300"            android:valueType="intType" />    </set>    <objectAnimator        android:duration="500"        android:propertyName="alpha"        android:valueTo="1f" /></set>

加載我們的動(dòng)畫文件

AnimatorSet set = (AnimatorSet)AnimatorInflater.loadAnimator(mContext,              R.animator.property_animator);  animator.setTarget(view);  animator.start();  

6.本節(jié)示例代碼下載:

AnimatorDemo1.zip

AnimatorDemo2.zip


本節(jié)小結(jié):

好的,本節(jié)給大家捋了一捋安卓中屬性動(dòng)畫的基本用法,不知道你get了沒,內(nèi)容還是比較簡(jiǎn)單的,而且例子比較有趣,相信大家會(huì)喜歡,嗯,就說這么多,謝謝~

感謝郭神的文章~

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
【Android API指南】動(dòng)畫和圖像(1) - 屬性動(dòng)畫
Android屬性動(dòng)畫完全解析(上),初識(shí)屬性動(dòng)畫的基本用法
Android動(dòng)畫學(xué)習(xí)Demo(2) 關(guān)于Property Animation的用法及總結(jié)
android 屬性動(dòng)畫完全解析(中)
Android中的動(dòng)畫總結(jié)
Android動(dòng)畫學(xué)習(xí)筆記
更多類似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服