使用SVG實現的一個Android播放/暫停按鈕

saka發表於2019-03-17

很久沒寫文章了,寫這篇文章的目的是騙幾個贊,結尾有說明。先上效果圖:

使用SVG實現的一個Android播放/暫停按鈕

非常簡單的一個按鈕,實現了從播放到暫停並且從暫停到播放的狀態。

這個主要是依賴Android內建的vector、objectAnimator和animated-vector組合實現的動畫效果。

1. Vector部分

vector主要功能室以svg語法的形式繪製靜態影像。它的主要優勢在於繪製簡單圖形時可以向量圖的形式展示,不會因為放大或縮小而失真。

首先建立icon-play.xml,並填寫如下內容:

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="48dp"
    android:height="48dp"
    android:viewportWidth="48"
    android:viewportHeight="48">
    <!--背景圓-->
    <path
        android:name="bg_circle"
        android:fillColor="#e91e63"
        android:pathData="M0,24
                          A24,24 0 1,1 48,24
                          A24,24 0 1,1, 0,24z" />
    <!--線-->
    <path
        android:name="line"
        android:fillColor="#ffffff"
        android:pathData="M15,33
                          L15,15
                          Q15,12 18,12
                          L18,12
                          Q21,12 21,15
                          L21,33
                          Q21,36 18,36
                          L18,36
                          Q15,36 15,33
                          
                          M27,33
                          L27,15
                          Q27,12 30,12
                          L30,12
                          Q33,12 33,15
                          L33,33
                          Q33,36 30,36
                          L30,36
                          Q27,36 27,33
                    " />
</vector>
複製程式碼

顯示效果如下:

使用SVG實現的一個Android播放/暫停按鈕

vector的畫布座標與view中的畫布座標一致,左上角是原點,向右是x正方向,向下是y正方向。vector節點下的width和height與常用xml佈局中的屬性是一致的,而viewportWidth和viewHeight是將畫布平分為對應的份數,也就是將width平均分成viewWidth份,從而可以自由定製座標系的單位長度。

path節點下的一系列屬性都與paint相似,可以設定顏色,strokeColor,strokeWidth,fillColor等。pathData即是svg的路徑。這裡分兩段繪製,其中圓角部分採用的一階貝塞爾曲線。

然後建立icon-puase.xml檔案,並填寫內容如下:

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="48dp"
    android:height="48dp"
    android:viewportWidth="48"
    android:viewportHeight="48">

    <!--背景圓-->
    <path
        android:name="bg_circle"
        android:fillColor="#e91e63"
        android:pathData="M0,24
                          A24,24 0 1,1 48,24
                          A24,24 0 1,1, 0,24z" />

    <path
        android:name="triangle"
        android:fillColor="#ffffff"
        android:pathData="M15,33
                          L15,15
                          Q15,11 18,12
                          L24,16
                          Q24,16 24,16
                          L24,32
                          Q24,32 24,32
                          L18,36
                          Q15,37 15,33
                          M24,32
                          L24,16
                          Q24,16 24,16
                          L33,22
                          Q35,23.3 35,24
                          L35,24
                          Q35,24.7 33,26
                          L24,32
                          Q24,32 24,32
                    " />
</vector>
複製程式碼

這裡的形式與icon-play.xml一致,不同的地方在於pathData部分。效果如下:

使用SVG實現的一個Android播放/暫停按鈕

為了要實現文章開頭的效果,最右側的圓角部分採用了一種曲折的方式實現,計算了方程的斜率來計算出貝塞爾曲線的控制點。

注意:前後兩個XML檔案的pathData形式一定要一致,否則將會丟擲異常

這樣就繪製好了開始和結束的狀態了。

2. objectAnimator部分

建立play_pause_anim.xml,實現從play狀態到pause狀態的過渡:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="sequentially">
    <objectAnimator
        android:duration="1000"
        android:propertyName="pathData"
        android:valueFrom="M15,33
                          L15,15
                          Q15,12 18,12
                          L18,12
                          Q21,12 21,15
                          L21,33
                          Q21,36 18,36
                          L18,36
                          Q15,36 15,33
                          M27,33
                          L27,15
                          Q27,12 30,12
                          L30,12
                          Q33,12 33,15
                          L33,33
                          Q33,36 30,36
                          L30,36
                          Q27,36 27,33"
        android:valueTo="M15,33
                          L15,15
                          Q15,11 18,12
                          L24,16
                          Q24,16 24,16
                          L24,32
                          Q24,32 24,32
                          L18,36
                          Q15,37 15,33
                          M24,32
                          L24,16
                          Q24,16 24,16
                          L33,22
                          Q35,23.3 35,24
                          L35,24
                          Q35,24.7 33,26
                          L24,32
                          Q24,32 24,32"
        android:valueType="pathType" />
</set>
複製程式碼

android:propertyName設定為pathData,android:valueType設定為pathType,這樣valueFrom和valueTo就會按照svg路徑來運動。

然後建立pause_play_anim.xml,實現從pause到play狀態的轉換:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="sequentially">
    <objectAnimator
        android:duration="1000"
        android:propertyName="pathData"
        android:valueFrom="M15,33
                          L15,15
                          Q15,11 18,12
                          L24,16
                          Q24,16 24,16
                          L24,32
                          Q24,32 24,32
                          L18,36
                          Q15,37 15,33
                          M24,32
                          L24,16
                          Q24,16 24,16
                          L33,22
                          Q35,23.3 35,24
                          L35,24
                          Q35,24.7 33,26
                          L24,32
                          Q24,32 24,32"
        android:valueTo=" M27,33
                          L27,15
                          Q27,12 30,12
                          L30,12
                          Q33,12 33,15
                          L33,33
                          Q33,36 30,36
                          L30,36
                          Q27,36 27,33
                          M15,33
                          L15,15
                          Q15,12 18,12
                          L18,12
                          Q21,12 21,15
                          L21,33
                          Q21,36 18,36
                          L18,36
                          Q15,36 15,33
                         "
        android:valueType="pathType" />
</set>
複製程式碼

3. animated-vector部分

這個是最終的粘合劑,將svg於objectAnimator結合起來。

建立icon_pause_anim.xml:

<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/icon_pause">
    <target
        android:name="triangle"
        android:animation="@animator/pause_play_anim" />
</animated-vector>
複製程式碼

建立icon_play_anim.xml:

<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/icon_play">
    <target
        android:name="line"
        android:animation="@animator/play_pause_anim" />
</animated-vector>
複製程式碼

然後我們就可以將動畫展示出來了。定義一個imageview:

<ImageView
        android:id="@+id/icon"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:onClick="start"
        app:srcCompat="@drawable/icon_play_anim" />
複製程式碼

java程式碼如下:

 public void start(View view) {
    isChecked = !isChecked;
    imageView.setImageResource(isChecked ? R.drawable.icon_play_anim : R.drawable.icon_pause_anim);
    Drawable drawable = imageView.getDrawable();
    if (drawable instanceof Animatable) {
        ((Animatable) drawable).start();
    }
}
複製程式碼

所有的都做好了。

5. 後記

最後推廣一下根據ssokit,這是一個用qml'重構的sokit的socket除錯軟體,目前提供了dmg檔案的下載,但是並未上架brew-cask,官方回覆原因是用的人太少,start不夠,所以希望覺得好用的朋友可以給個start

This app is a advanced qml project for sokit github.com/sinpolib/so…

The dmg download address:

github.com/rangaofei/S…

It can used be as a Tcp/Udp server,the user interface is just like this :

使用SVG實現的一個Android播放/暫停按鈕

使用SVG實現的一個Android播放/暫停按鈕
使用SVG實現的一個Android播放/暫停按鈕
使用SVG實現的一個Android播放/暫停按鈕

相關文章