<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                最近在看一些關于Material Design的東西,還記得在博客[《你所不知道的Activity轉場動畫——ActivityOptions》](http://blog.csdn.net/qibin0506/article/details/48129139)中,我們介紹了一種優雅的activity過度動畫。如果大家看了最后給出的參考鏈接,會發現還有很多內容是值得我們學習的,所以這篇博客,我們來學習一下這一頁上剩下的東西。 ### 一、觸摸反饋 大家都知道,在Material Design中,觸摸反饋的效果非常絢麗,是一種漣漪的效果,令我們高興的是,這種效果也是可以自定義的。 ~~~ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:orientation="vertical" android:dividerPadding="20dp" tools:context=".MainActivity"> <Button android:background="?android:attr/selectableItemBackground" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" /> <Button android:background="?android:attr/selectableItemBackgroundBorderless" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" /> </LinearLayout> ~~~ 上面的代碼,我們定義了兩個Button,不同的是它們的background屬性,`selectableItemBackground`代表了`當點擊后會在當前Button區域發生一個漣漪效果`,而`selectableItemBackgroundBorderless`的效果`不會局限于Button本身的大小`。當然,雖然是大白話,但是還是不容易理解,我們來看看效果就一目了然了。 ![](https://box.kancloud.cn/2016-02-18_56c55b3c7e677.jpg "") 恩,效果很贊,但是這個背景能不能自定義呢?答案是當然能了,那么這里要引進一個新的`Drawable`-`RippleDrawable`了。`RippleDrawable`是android5新增加的一種`Drawable`,它的效果就是我們一直在提及的漣漪效果,下面我們來學習一下`RippleDrawable`的時候。既然`RippleDrawable`也是一種`Drawable`,那么它肯定也是可以在xml中定義的,來看代碼, ~~~ <?xml version="1.0" encoding="utf-8"?> <!-- drawable/ripple_no_mask.xml--> <ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="#FF00FF00"> <item android:drawable="@mipmap/ic_launcher" /> </ripple> <?xml version="1.0" encoding="utf-8"?> <!-- drawable/ripple_mask.xml--> <ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="#FF00FF00"> <item android:id="@android:id/mask" android:drawable="@mipmap/ic_launcher" /> </ripple> ~~~ 我們在drawable目錄中創建兩個xml文件,這兩個drawable都是ripple類型的,可以看到他們的根節點都是一個ripple。這兩個文件唯一的區別在于第二個的id指定了一個id是`@android:id/mask`,這兩者的區別在于, > 如果不指定id為`@android:id/mask`,那么在顯示的時候會首頁顯示出item指定的drawable。 如果指定id為`@android:id/mask`,那么默認是不會顯示該drawable,而是在點擊的時候出現。 如何使用呢? 只需要指定控件的background就ok. ~~~ <Button android:background="@drawable/ripple_no_mask" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" /> <Button android:background="@drawable/ripple_mask" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" /> ~~~ 看一下效果怎么樣, ![](https://box.kancloud.cn/2016-02-18_56c55b3cb903c.jpg "") 通過觀察效果,我們可以發現, > 1. 漣漪的效果是在我們給item的drawable的非透明區域發生的。 > 1. 當我們指定item的id為`@android:id/mask`時,默認背景是不顯示的。 ok,到這里,我們已經學會自定義點擊的漣漪效果了。我們繼續學習,接下來就來到了一個更贊的效果。 ### 二、Reveal Effect 顯示效果 新的sdk給我們提供了一個類-`ViewAnimationUtils`,該類就提供了一個靜態的方法`createCircularReveal`,通過這個方法,我們可以給任何一個layout或者view一個漣漪的顯示或者消失過程。首先我們來看看要實現的效果, ![](https://box.kancloud.cn/2016-02-18_56c55b3ceb081.jpg "") 效果確實很贊,代碼應該怎么寫呢? 其實也很簡單,主要還是我們將要學習的`ViewAnimationUtils`和它唯一的方法`createCircularReveal`, ~~~ public void change(View view) { int centerX = mImageView.getWidth() / 2; int centerY = mImageView.getHeight() / 2; int maxRadius = Math.max(mImageView.getWidth(), mImageView.getHeight()); if(mImageView.getVisibility() == View.VISIBLE) { Animator anim = ViewAnimationUtils.createCircularReveal(mImageView, centerX, centerY, maxRadius, 0); anim.setDuration(1000); anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); mImageView.setVisibility(View.GONE); } }); anim.start(); }else { Animator anim = ViewAnimationUtils.createCircularReveal(mImageView, centerX, centerY, 0, maxRadius); anim.setDuration(1000); mImageView.setVisibility(View.VISIBLE); anim.start(); } } ~~~ 在解釋代碼之前,我們來看看這個方法的詳細說明: > public static Animator createCircularReveal (View view, int centerX, int centerY, float startRadius, float endRadius) 參數部分, > 1. View view, 指定了為哪個View執行動畫 > 1. int centerX, 漣漪效果的中心x軸位置 > 1. int centerY, 漣漪效果的中心y軸位置 > 1. float startRadius, 開始的半徑 > 1. float endRadius, 結束的半徑 在解釋完了參數之后,發現也不難,那么下面我們就來看上面的代碼了。 首先,我們計算了centerX、centerY,還有一個最大的半徑,最小的半徑就不需要計算了,因為我們知道我們需要的效果就是到0. 接下來一個判斷是判斷ImageView的顯示狀態,如果為顯示狀態,那么肯定就是一個從有到無的動畫,如果是隱藏狀態,那么就是一個從無到有的動畫。 第一個狀態中,我們首先調用`ViewAnimationUtils.createCircularReveal()`方法創建了一個`Animator`,半徑是從`maxRadius`到0的變化。 然后就是對`Animator`的操作了,并且監聽了動畫的結束,在動畫結束后,我們會將該View的狀態設置為隱藏,最后啟動動畫,這里就是我們剛才看到的那個隱藏的效果了。 那么顯示呢?其實和隱藏是一樣的,只不過顯示半徑是從0到`maxRadius`。 ### 三、Activity過度動畫 這一部分我們在前面的博客[《你所不知道的Activity轉場動畫——ActivityOptions》](http://blog.csdn.net/qibin0506/article/details/48129139) 中介紹過了,大家可以去參考這篇博客,這里就不再重復介紹了。 ### 四、路徑動畫 什么是路徑動畫? 其實在官方文檔上,這一節叫自作`Curved Motion`,我把它叫做路徑動畫,是因為這一節的內容的核心是基于`Path`實現的。 Android 5 的sdk中給我們提供了一個新的插值器`PathInterpolator`, 利用該插值器,我們可以輕松的定義出路徑動畫, ~~~ <pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" android:controlX1="0.4" android:controlY1="0" android:controlX2="1" android:controlY2="1"/> ~~~ 這段代碼定義了一個x和y分別從0.4和0到1的動畫,不過我認為這種方式局限性太大,所以這里不過多介紹,重點我們放在在java代碼中如果利用Path去構建一個路徑動畫。 在新的sdk中,`ObjectAnimator`多了很多帶有Path參數的方法,這些方法中我們可以傳遞一個`Path`對象,然后我們就可以在動畫中獲取基于這個`Path`的值。 > public static ObjectAnimator ofFloat(Object target, String xPropertyName, String yPropertyName, Path path); 這個構造中需要我們傳遞兩個屬性值,這里對象這Path中x和y, 最后一個參數就是最重要的那個路徑了。來看看我們的demo,這個demo,我們想讓一段文字沿著一個`Z`的路徑移動,最后還原到原來的位置。 ~~~ TextView tv = (TextView) findViewById(R.id.tv); tv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Path path = new Path(); path.moveTo(100, 100); path.lineTo(600, 100); path.lineTo(100, 600); path.lineTo(600, 600); path.close(); ObjectAnimator anim = ObjectAnimator.ofFloat(v, View.X, View.Y, path); anim.setDuration(5000); anim.start(); } }); ~~~ 代碼很簡單,首先我們構建了一個簡單的`Path`,然后利用`ObjectAnimator`的新的`ofFloat`方法為為該View的x和y指定了沿path移動,最后讓動畫跑起來。 ![](https://box.kancloud.cn/2016-02-18_56c55b3d67496.jpg "") ### 五、View狀態動畫 在之前,我們在使用`selector`定義狀態時,僅僅只能提供一個生硬的狀態變化,在新的sdk中這里發生了改變,我們完全可以定義一個帶動畫效果的狀態! 首先我們定義一個drawable文件, ~~~ <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true"> <set> <objectAnimator android:propertyName="translationZ" android:duration="@android:integer/config_shortAnimTime" android:valueFrom="0" android:valueTo="20dp" android:valueType="floatType"/> </set> </item> <item> <set> <objectAnimator android:propertyName="translationZ" android:duration="100" android:valueTo="0" android:valueType="floatType"/> </set> </item> </selector> ~~~ 還是我們熟悉的`selector`,不過它的item是一個`objectAnimator`, 這里我們指定了`translationZ`的變化,然后我們在布局中使用它, ~~~ <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:stateListAnimator="@drawable/view_state" android:text="@string/hello_world" /> ~~~ 這里我們引入了一個新的屬性`android:stateListAnimator`,我們通過這個屬性來設置我們剛才定義的`selector`, 來看看效果, ![](https://box.kancloud.cn/2016-02-18_56c55b3d88703.jpg "") 仔細觀察效果,我們在點擊的過程中Button的`translationZ`有一個動畫的效果。 說到這里,如果我們可以給它的背景一個動畫就更爽了, 當然這也是可以辦到的!首先還是定義一個drawablew文件,不過這里的文件是一個`AnimatedStateListDrawable`,我們在xml中使用`animated-selector`。 ~~~ <?xml version="1.0" encoding="utf-8"?> <animated-selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/press" android:state_pressed="true" android:drawable="@android:color/holo_blue_dark" /> <item android:id="@+id/focus" android:state_focused="true" android:drawable="@android:color/holo_purple" /> <item android:id="@+id/normal" android:drawable="@android:color/holo_red_dark" /> <transition android:fromId="@id/normal" android:toId="@id/press"> <animation-list> <item android:duration="200" android:drawable="@android:color/holo_red_dark" /> <item android:duration="200" android:drawable="@android:color/holo_blue_dark" /> </animation-list> </transition> </animated-selector> ~~~ 在這里,我們首先定義了三個item, 對應了三種狀態,并且都制定了id, 接下來是一個`transition`節點,這個節點下我們制定了`fromId`和`toId`,這里代表了動畫從哪個狀態到哪個狀態執行,這個節點下又是一個`animation-list`節點,我們指定了兩個`item`,這里要注意一下這兩個`item`的執行順序,如果是從`fromId`到`toId`,這里是從正常狀態到按下,則會正序執行,如果從`toId`到`fromId`,這里是從按下狀態到正常,則會反序執行。這里我們給每個item 200ms的停留時間。 ![](https://box.kancloud.cn/2016-02-18_56c55b3daeb8a.jpg "") 從效果中可能看不出我何時點擊何時松開的,這里每個顏色都會有一段停留時間的。 ### 六、 SVG矢量動畫 在新的sdk中, Google終于提供了原生的對SVG的支持,而這一切都是一個`VectorDrawable`的功勞, 當然, `VectorDrawable`也是一個`Drawable`, 所以我們還是可以在xml中定義它, ~~~ <?xml version="1.0" encoding="utf-8"?> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="64dp" android:height="64dp" android:viewportHeight="600" android:viewportWidth="600"> <group android:name="group" android:pivotX="300" android:pivotY="300" android:rotation="0"> <path android:name="path" android:fillColor="#FFFF0000" android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z"/> </group> </vector> ~~~ 這里我們定義了一個`drawable`文件,它的根節點是一個`vector`,代表著它是一個`VectorDrawable`,看看它的內容,又一個`group`和多個`path`組成,一個`group`可以包含多個`path`,當然這里我們僅僅寫了一個,值得注意的是`path`的`android:pathData`屬性,這里定義了我們圖形的形狀。怎么使用呢? 就像正常的圖片一樣,給`ImageView`的`src`屬性賦值就ok。 這是一個什么形狀呢? ![](https://box.kancloud.cn/2016-02-18_56c55b3dd00f0.jpg "") 當然,我們可以借助一些工具很輕松的實現一些`pathData`。 好了, 現在僅僅是一個簡單的圖形,并沒有動畫效果, 現在我們想讓這個圖形動起來,而且顏色也要不斷變化,該怎么做?這里又要引入一個新的東西-`animated-vector`。 利用它,我們可以根據上面書寫的name值指定不同的動畫了。 首先,我們定義兩個動畫,一個是旋轉的動畫,一個是顏色值變化的動畫。 ~~~ <?xml version="1.0" encoding="utf-8"?> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="5000" android:propertyName="rotation" android:valueFrom="0" android:valueTo="360" android:valueType="floatType"/> <?xml version="1.0" encoding="utf-8"?> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="5000" android:propertyName="fillColor" android:valueFrom="#FFFF0000" android:valueTo="#FF000000" android:valueType="intType"/> ~~~ 這里我們定義了兩個`Animator`,需要注意的是他的`android:propertyName`的值, 仔細觀察一下,他們分別就是上面我們定義的那個`vector`的`group` 和`path`標簽的其中一個屬性,這兩個動畫分別是一個旋轉和顏色變化的動畫, 那怎么用呢? 我們還需要一個`animated-vector`的`drawable`文件。 ~~~ <?xml version="1.0" encoding="utf-8"?> <animated-vector xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/svg"> <target android:animation="@animator/rotation" android:name="group" /> <target android:animation="@animator/color" android:name="path" /> </animated-vector> ~~~ 在這個文件中,我們指定了`drawable`為我們先前定義的那個`vector`文件, 并且寫了兩個`target`標簽,這里很簡單,只有兩個屬性,他們分別指定了所用的動畫和這個動畫該給誰(還記得我們之前給`group`和`path`指定的`name`屬性嗎)! ok, 現在將`ImageView`的`src`指定為這個`animated-vector`文件, 運行一下,你可能會感到沮喪,因為沒有任何動畫! 那怎么讓動畫跑起來呢? 很簡單。 ~~~ final ImageView iv = (ImageView) findViewById(R.id.iv); iv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Drawable d = iv.getDrawable(); if(d instanceof Animatable) ((Animatable) d).start(); } }); ~~~ 我們在點擊`ImageView`的時候,去獲取這個`ImageView`的圖片資源,然后判斷它是不是`Animatable`類型的,如果是,直接調用它的`start`方法! 最后,我們來看看這時候的效果。 ![](https://box.kancloud.cn/2016-02-18_56c55b3de0fcb.jpg "") 有一個旋轉的動畫, 在旋轉的過程中還伴隨著顏色的變化,棒棒噠。 ok, 到這里,Material Design動畫,我們就學習完了 最后是demo的代碼下載和參考資料。 [demo代碼下載,戳這里](http://download.csdn.net/detail/qibin0506/9172775) 參考資料:[https://developer.android.com/training/material/animations.html](https://developer.android.com/training/material/animations.html)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看