今天要來講的項目叫做Interpolator(插值器)
以前有次去一家公司面試時,我曾經被問到一個問題
面試官:你覺得當工程師,理論學科跟經驗豐富,哪邊比較重要?
我回答:我覺得經驗豐富可能只是做得久,遇到問題就可能很快就能有應對方法
但是如果理論學科好,才能夠在這條路上走得又長又遠
而今天要講的這一篇,就是我認為能夠應證我這個想法的一篇文章
這篇文章我會講述「如何在Android上完成呼吸燈動畫」
而要完成這一章節的內容,就得了解一些數學理論才能夠完成
麻...無論如何,先來看範例吧
這次的程式很短,所以沒有Github歐!
1. 呼吸燈與數學公式
各位,如果你還是學生的話,或者你有親戚小孩什麼的還在唸書
我這裡只想講一句非常、非常重要的話
數學...不是拿來考試用的,數學很重要....(嘆)
首先,關於呼吸燈的實踐,我們必須用積分曲線去完成它
看圖,這是我用desmos所繪製出來的呼吸曲線
這一整張圖代表的是一個呼吸週期,而我們要控制的就是y軸的變量...在本案中你可以理解為Alpha值,而X軸為時間
而在專案的控制方法中,我們要實現的就是讓這個曲線一直不斷地重複,大致就是如此
那麼,這個是怎麼實現的呢?
首先我們從上升曲線開始看(完整請點此)
上升曲線就是綠色(吸氣)的部分,公式為
其中,k=1/3,代表上升週期
t=總週期
n為一常數1
再來是下降(吐氣)的部分,公式如下
此外,k的部分則是可以調整吸與吐的斷點,下圖為1/3時吐氣
我改為1/5
可以發現,「呼吸」變得急促了!
OK,理解數學公式後,接下來就要來在程式上實現了
2. 漸變動畫實現
接下來就要來就要來把這個東西放到Android上實現
首先是專案結構
Breath.class就是今天專案要用的差值器類別
其他的都很基本,就不在多談
獻上介面
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/layout" android:layout_width="0dp" android:layout_height="0dp" android:layout_margin="40dp" android:background="#000" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
再來寫入呼吸燈動畫
Breath.java
public class Breath implements TimeInterpolator { @Override public float getInterpolation(float input) { float x = 6*input; float k = 1f/2; int t = 6; int n = 1; float PI = 3.1415926f; float output = 0; if (x >= ((n - 1) * t) && x < ((n - (1 - k)) * t)) { output = (float) (0.5 * Math.sin((PI / (k * t)) * ((x - k * t / 2) - (n - 1) * t)) + 0.5); } else if (x >= (n - (1 - k)) * t && x < n * t) { output = (float) Math.pow((0.5 * Math.sin((PI / ((1 - k) * t)) * ((x - (3 - k) * t / 2) - (n - 1) * t)) + 0.5), 2); } return output; } }
還記得我們上面的公式嗎?
綠色部分:
橘色部分
最後模組寫好,將模組套用到主畫面上
MainActivity.java
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ConstraintLayout show = findViewById(R.id.layout); ObjectAnimator animator = ObjectAnimator.ofFloat(show,"alpha",0.5f,1f); animator.setDuration(6000); animator.setInterpolator(new Breath()); animator.setRepeatCount(ValueAnimator.INFINITE); animator.start(); } }
OK,這時候按下操作就可以完成呼吸燈操作囉:D
那最後..