Android 裝置上最常見的震動致動器是線性共振致動器 (LRA)。LRA 會模擬按鈕點擊的感覺,讓原本沒有反應的玻璃表面產生觸覺回饋。清晰明確的按鈕回饋訊號通常會持續 10 到 20 毫秒。這種感覺可讓使用者互動更自然。如果是虛擬鍵盤,這項點擊回饋可提高打字速度並減少錯誤。
LRA 有幾種常見的共振頻率:
- 部分 LRA 的共振頻率介於 200 至 300 Hz 之間,這與人體皮膚對震動最敏感的頻率一致。這個頻率範圍的震動通常會帶來平滑、尖銳和穿透的感覺。
- 其他 LRA 型號的共振頻率較低,約為 150 Hz,可提供更柔和、更飽滿的觸覺回饋。
在兩種不同頻率下,即使輸入電壓相同,震動輸出振幅也可能不同。頻率與 LRA 共振頻率的差距越大,震動幅度就越小。
特定裝置的觸覺效果會同時使用震動致動器和驅動程式。 包含過驅動和主動煞車功能的觸覺驅動程式可縮短 LRA 的上升時間和鈴聲,進而產生更靈敏清晰的震動。
震動器輸出加速
頻率至輸出加速對應 (FOAM) 說明在特定振動頻率 (以赫茲為單位) 下,可達到的最大輸出加速 (以 G 峰值為單位)。從 Android 16 (API 級別 36) 開始,平台會透過 VibratorFrequencyProfile 內建支援這項對應。您可以搭配使用這個類別與基本和進階信封 API,建立觸覺效果。
大多數 LRA 馬達的 FOAM 只有一個尖峰,通常接近共振頻率。一般來說,當頻率偏離這個範圍時,加速度會呈指數下降。曲線可能不對稱,且共振頻率附近可能出現平緩區,以保護馬達免於損壞。
鄰近的圖表顯示 LRA 馬達的 FOAM 範例。
人類感知偵測門檻
人類感知偵測門檻是指人體可穩定偵測到的最低震動加速度。震動強度會因震動頻率而異。
相鄰的圖表顯示人類觸覺感知偵測閾值 (以加速度表示),是時間頻率的函數。門檻資料是根據 Bolanowski Jr. 論文圖 1 的位移門檻轉換而來,S. J. 等人於 1988 年發表的文章「Four channels mediate the mechanical aspects of touch.」(四個管道調解觸覺的機械層面)。
Android 會在 BasicEnvelopeBuilder 中自動處理這個門檻,確認所有效果使用的頻率範圍產生的震動幅度,至少要比人類感知偵測門檻高出 10 分貝。
線上教學課程會進一步說明加速度振幅和位移振幅之間的轉換。
震動加速度等級
人類對震動強度的感知 (感知測量) 並不會隨著震動幅度 (物理參數) 呈線性成長。感知強度的特徵是感覺等級 (SL),定義為相同頻率下高於偵測閾值的 dB 值。
對應的振動加速度振幅 (以 G 峰值為單位) 計算方式如下:
...其中,振幅 dB 是 SL 和偵測閾值的總和,也就是相鄰圖中特定頻率的縱軸值。
旁邊的圖表顯示 10、20、30、40 和 50 dB SL 的震動加速度,以及人類觸覺感知偵測閾值 (0 dB SL),以時間頻率為函數。這項資料是根據 Verrillo, R. 論文中的圖 8 估算而得。T. 等人於 1969 年發表的文章「Sensation magnitude of vibrotactile stimuli.」(震動觸覺刺激的感覺強度)。
Android 會在 BasicEnvelopeBuilder 中自動處理這項轉換,該函式會將值視為感覺層級空間 (dB SL) 中的標準化強度,並將其轉換為輸出加速度。另一方面,WaveformEnvelopeBuilder 不會套用這項轉換,而是以加速度空間 (Gs) 中經過正規化的輸出加速度幅度做為值。封包 API 假設設計人員或開發人員在考慮震動強度變化時,會預期感知強度遵循分段線性封包。
裝置預設波形平滑度
以一般裝置上的自訂波形模式為例:
Kotlin
val timings: LongArray = longArrayOf(50, 50, 50, 50, 50, 100, 350, 250)
val amplitudes: IntArray = intArrayOf(77, 79, 84, 99, 143, 255, 0, 255)
val repeatIndex = -1 // Don't repeat.
vibrator.vibrate(VibrationEffect.createWaveform(timings, amplitudes, repeatIndex))
Java
long[] timings = new long[] { 50, 50, 50, 50, 50, 100, 350, 250 };
int[] amplitudes = new int[] { 77, 79, 84, 99, 143, 255, 0, 255 };
int repeatIndex = -1 // Don't repeat.
vibrator.vibrate(VibrationEffect.createWaveform(timings, amplitudes, repeatIndex));
下圖顯示輸入波形和輸出加速度,與先前的程式碼片段相符。請注意,模式中的振幅出現階梯式變化時 (也就是在 0 毫秒、150 毫秒、200 毫秒、250 毫秒和 700 毫秒時),加速度會逐漸增加,而不是突然增加。此外,在每個振幅變化步驟中,都會出現過衝,且當輸入振幅突然降至 0 時,可見的鈴聲至少會持續 50 毫秒。
改良的觸覺回饋模式
為避免過衝並縮短鈴聲時間,請更緩慢地變更振幅。以下顯示修訂版的波形和加速度圖:
Kotlin
val timings: LongArray = longArrayOf(
25, 25, 50, 25, 25, 25, 25, 25, 25, 25, 75, 25, 25,
300, 25, 25, 150, 25, 25, 25
)
val amplitudes: IntArray = intArrayOf(
38, 77, 79, 84, 92, 99, 121, 143, 180, 217, 255, 170, 85,
0, 85, 170, 255, 170, 85, 0
)
val repeatIndex = -1 // Do not repeat.
vibrator.vibrate(VibrationEffect.createWaveform(timings, amplitudes, repeatIndex))
Java
long[] timings = new long[] {
25, 25, 50, 25, 25, 25, 25, 25, 25, 25, 75, 25, 25,
300, 25, 25, 150, 25, 25, 25
};
int[] amplitudes = new int[] {
38, 77, 79, 84, 92, 99, 121, 143, 180, 217, 255, 170, 85,
0, 85, 170, 255, 170, 85, 0
};
int repeatIndex = -1; // Do not repeat.
vibrator.vibrate(VibrationEffect.createWaveform(timings, amplitudes, repeatIndex));
建立更複雜的觸覺效果
令人滿意的點擊回應中的其他元素較為複雜,需要具備裝置中使用的 LRA 相關知識。為獲得最佳結果,請使用裝置預先製作的波形和平台提供的常數,以便執行下列操作:
- 執行清除效果和基本體。
- 將這些效果串連起來,即可組成新的觸覺效果。
這些預先定義的觸覺常數和基本型別可大幅加快工作速度,同時建立高品質的觸覺效果。