📳振動機能の利用に関する注意点
アプリに振動機能を実装する方法を学ぶ前に、まずは『振動機能を利用する際に注意すべきポイント』を確認しておきましょう。
振動機能を利用する際は細心の注意を払い、ユーザー体験を損なわないように気をつける必要があります。少なくとも、目的もなしに無闇矢鱈に振動機能を利用することは推奨されません。
悪い例として、『画面が切り替わる度に振動するアプリ』を想像してみてください。おそらく、かなり鬱陶しいと感じるのではないかと思います。
画面が切り替わる頻度や目的にもよりますが、一般的には、画面の切り替わりを振動でユーザーに知らせる必要性は低いと言えるでしょう。
振動効果の乱用は避け、ここぞという時に限って利用することをオススメします。
具体的には次のような状況での利用が効果的であると考えられます。
1) 重要な通知があることを伝える
電話やテキストメッセージの送受信機能を有するアプリの場合、電話やメッセージの着信は極めて重要な意味を持ちます。
テキストメッセージの受信通知はやや控えめに設定しておいても良いかもしれませんが、『電話の着信に気づくのが難しいアプリ』ではさすがに困りますよね。
着信通知のように、ユーザーに確実に通知に気づいてもらう必要がある場合は、振動機能の利用が効果的です。
2) 重要なボタンやスイッチがタップされたことを知らせる
たとえば、データの自動保存と手動保存の切り替えなど、アプリの利用において重要度の高い設定の変更を行うスイッチがタップされた時、その事実(アクション)は確実にユーザーに知らせる必要があると言えます。もしかしたら、ユーザーが意図的にタップしたわけではなく、誤って指が触れてしまったかもしれないからです。
このようなケースも、振動機能を利用してユーザーにフィードバックを送ることが効果的であると言えます。
一般的なアプリの場合、主に上記の2つのケースのいずれかに該当する場合に、振動機能が利用されることが多いです。ただし、上記の2つに利用シーンが限られるというわけではありません。ゲームアプリであれば、ユーザーがステージをクリアした時に演出として振動機能を利用するのも効果的であると言えるでしょう。
また、『どのようなシーンで振動機能を利用するか』だけでなく、『どの程度の振動を与えるか』という点にも注意が必要です。
電話の着信を知らせるための振動である場合、ほんの一瞬振動させるだけではユーザーに気づいてもらえないでしょう。この場合、やや強めの振動をある程度長い時間与えた方が良いと言えます。
一方、ボタンやスイッチがタップされた時に振動効果を利用する場合は、瞬間的に弱めの振動を与えるだけで十分です。強すぎる刺激はユーザーに鬱陶しく感じられ、逆効果となり得ます。
振動機能は、適切な状況で且つ適切な強度で設定することが重要です。
振動機能を利用する上で気をつけたいポイントは、Googleが提供しているAndroid Developers公式サイトにも掲載されているので、一度は目を通しておくことをおすすめします。
・Haptics design principles | Android Developers
https://developer.android.com/develop/ui/views/haptics/haptics-principles
POINT!
- ・振動機能は、ユーザーエクスペリエンスを悪化させないように慎重に利用しよう!
- ・重要なイベントをユーザーに知らせる必要がある場合などが効果的!
- ・振動の強度や時間にも注意が必要!
VibrationEffectを利用する準備
Androidアプリで振動機能を設定する方法は色々ありますが、この記事では『VibrationEffect』を利用する方法をご紹介します。
VibrationEffectを利用するには、まず AndroidManifest.xml ファイルに振動機能のパーミッションを追加する必要があります。
<!-- AndroidManifest.xml file: -->
<uses-permission android:name="android.permission.VIBRATE"/>
振動機能はAndroid端末に標準で搭載されている機能であり、外部のライブラリを利用するわけではありません。そのため、build.gradke.kts
ファイルに依存関係を追加する必要はなく、事前準備としてはこれだけでOKです。
…と言いたいところですが、VibrationEffectの利用にはAPIレベル26以上を必要とし、この記事では更に上位のAPIレベル(29)を使用するため、minSdk
の設定変更が必要になる場合があります。
なお、minSdk
の設定値を変更するのではなく、コード内で条件分岐を行うことでもAPIレベルの問題を解決できますが、その場合はコードが複雑になってしまいます。なのでここでは minSdk
の設定値を変更することで対応することとします。
モジュールレベルの build.gradle.kts
ファイルを開き、minSdk
を次のように設定します。
defaultConfig {
applicationId = "com.example.myapp"
minSdk = 29
// ...other settings
}
ちなみに、Android Developers公式サイトのドキュメント(VIEWSの項目)では、振動機能を利用する際、Viewを利用する方法を推奨として一番目に掲載しています。
・Add haptic feedback to events | Android Developers
https://developer.android.com/develop/ui/views/haptics/haptic-feedback
Viewを利用する場合、パーミッションを設定する必要がないなどのメリットが得られる一方、Jetpack Composeとの相性はあまり良くありません。(開発者の思考や好みにもよると思いますが)
Jetpack Composeを利用する場合は、基本的に VibrationEffect を利用した方がコードがスッキリ書けるのでオススメです。
POINT!
- ・振動機能を利用する方法の一つに、VibrationEffectを使う方法がある!
- ・VibrationEffectを利用するには、パーミッションの追加設定が必要!
- ・その他、Viewを利用する方法もあるが、Jetpack Composeとはやや相性が良くない!
🔧UIの構築
パーミッション追加などの事前準備が完了したら、次はサンプルアプリのUIを構築していきましょう。
デバイスを振動させたいタイミングや状況は様々ですが、振動機能のテストを行うためだけにメッセージの送受信といった複雑な機能を搭載するのは大変です。なので、今回は『ボタンのタップ』を振動発生のトリガーとして利用します。
ボタンを5つ用意し、画面の中央に配置されるようにレイアウトします。タップしやすいように、 padding
を設定してボタンの間隔を少し開けておくと良いでしょう。適用する振動効果に合わせて、ボタンの見た目も変えています。(各ボタンにそれぞれどのような振動効果を適用するのかは、この後順番に紹介します)
コード例と画面のイメージは次のようになります。
@Composable
fun VibrationEx() {
Column(
modifier = Modifier
.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
OutlinedButton(
onClick = { /*TODO*/ }
) {
Text(text = "Vibration")
}
var isActive by remember {
mutableStateOf(false)
}
FilledIconToggleButton(
checked = isActive,
onCheckedChange = {
isActive = !isActive
},
modifier = Modifier
.padding(top = 32.dp)
) {
Icon(
imageVector = Icons.Default.Notifications,
contentDescription = null
)
}
Button(
onClick = { /*TODO*/ },
modifier = Modifier
.padding(top = 64.dp)
) {
Text(text = "Click Effect")
}
Button(
onClick = { /*TODO*/ },
modifier = Modifier
.padding(vertical = 32.dp)
) {
Text(text = "Heavy Click Effect")
}
Button(
onClick = { /*TODO*/ }
) {
Text(text = "Double Click Effect")
}
}
}
非常にシンプルな画面ですが、振動機能の実装を試すだけならこれで十分です。
次のステップでは、『Vibration』と書かれた一番上のボタンにシンプルな振動を設定していきます。
POINT!
- ・振動機能のテストを行う際は、ボタンタップをトリガーにするとやりやすい!
- ・設定する振動の種類別に、ボタンの見た目を変えておこう!
- ・誤って別のボタンをタップしてしまわないよう、ボタンの間隔をある程度開けておこう!
①シンプルな振動(繰り返しなし)
振動機能を利用するには、Vibratorクラスのインスタンスが必要であり、そのインスタンスを作成するためには現在のコンテキストが必要です。なので、まずは VibrationEx
コンポーザブルに次のコードを追加する必要があります。(import文は省略)
val context = LocalContext.current
val vibrator = context.getSystemService(Vibrator::class.java)
これにより、VibrationEffectを利用した振動機能を実装する準備が整いました。
では、一番上のボタンがタップされた時、『500ミリ秒の長さ&デフォルトの強度で振動する(一回きり)』ようにコードを編集してみましょう。このように、振動の長さと強度をある程度自由に調整したい場合で、かつ振動を繰り返す必要がない場合は createOneShot()
を使用します。
createOneShot()
の第一引数は振動時間(ミリ秒)をLong型で指定し、第二引数は振動強度を1〜255までのInt型で指定します。ただし、振動強度の指定には注意が必要です。Android端末は色々なメーカーが開発しているため、振動の強さもデバイスによって異なる場合があるからです。
例えば、振動強度を100と指定した時、あるデバイスでは振動が強く感じられ、あるデバイスでは弱く感じられる…といった差異が生じる可能性があります。そういった差異の発生をできるだけ回避し、適切な強度に設定するために、VibrationEffect にはデフォルトの振動強度が用意されています。それが、DEFAULT_AMPLITUDE
です。(内部的な数値は-1)
振動の強度を細かく調整する必要がない場合は DEFAULT_AMPLITUDE
を指定し、デフォルトの強度に設定しておくことをオススメします。
コード例は次のようになります。
OutlinedButton(
onClick = {
vibrator.vibrate(
VibrationEffect.createOneShot(
500L,
VibrationEffect.DEFAULT_AMPLITUDE
)
)
}
) {
Text(text = "Vibration")
}
この状態で一旦アプリをビルドし、実機で振動効果を確認したものが下の動画になります。端末が振動していることがわかるように、机に置いた状態でボタンをタップして振動音を発生させています。(なので動画は音声をONにして再生してください)
特定のタイミングで1回だけ振動させれば良い場合は、この方法で十分でしょう。コードもシンプルで分かりやすいですね。しかし、電話の着信やアラームなどユーザーが気づいてくれるまで(あるいは一定時間ずっと)振動を繰り返したい場合は、この方法は使えません。
次のステップでは、繰り返し振動させる方法を確認していきましょう。
POINT!
- ・Vibratorクラスのインスタンスを作成するには現在のコンテキストが必要!
- ・指定の時間、一度だけ振動させるには、createOneShot()を利用する!
- ・特別な調整を必要としない場合の振動強度は、DEFAULT_AMPLITUDEに指定するのがオススメ!
②繰り返しの振動
振動を一定の周期で繰り返すには、createWaveform()
を使用します。
createWaveform()
の第一引数はLongArrayで、これは振動周期のタイミングを指定するものです。
例えば、longArrayOf(0,500,300)
と指定した場合、振動を設定したイベントが発火したらすぐに振動が始まり(0)、500ミリ秒間振動し(500)、その後、300ミリ秒間振動がオフ(300)になります。通常、イベント発火と同時に振動させたい場合が多いので、LongArrayの最初の要素(LongArray[0])の値は0になることが多いです。
そして第二引数には、第一引数で指定したタイミングのうち、振動パターンを繰り返すインデックスをInt型(整数)で指定します。例として、第一引数に longArrayOf(0,500,300)
と指定した場合で、第二引数に 1 と指定した場合、500ミリ秒の振動から繰り返されることになり、500ミリ秒の振動と300ミリ秒の停止を繰り返すことになります。永遠に繰り返したくない場合は -1 を指定します。
振動が永続的に繰り返されるように設定する場合は、振動をキャンセルできるようにしておく必要があります。この記事では Vibrationクラスのインスタンスを不変変数 vibrator
として宣言しているので、vibrator.cancel()
でキャンセルすることができます。
それでは、トグルアイコンボタンに繰り返しの振動を設定してみましょう。ボタンがアクティブな状態と非アクティブな状態で条件分岐を行い、アクティブな状態になっている間は繰り返し振動を発生させ、非アクティブな状態になったら振動をキャンセルするようにします。
コード例は次のようになります。
FilledIconToggleButton(
checked = isActive,
onCheckedChange = {
isActive = !isActive
if (isActive) {
vibrator.vibrate(
VibrationEffect.createWaveform(
longArrayOf(0,500,300), // timings
1 // repeat
)
)
} else {
vibrator.cancel()
}
}
) {
Icon(
imageVector = Icons.Default.Notifications,
contentDescription = null
)
}
下の動画は、繰り返される振動の様子を撮影したものです。
トグルボタンがアクティブな状態の時は、指定した振動周期(500ミリ秒の振動 ↔️ 300ミリ秒のオフ)が繰り返され、非アクティブになった時は振動がキャンセル処理されて完全に停止することが確認できます。
さて、これまで紹介してきた振動の設定は、ある程度長い時間端末を振動させたい場合に有効なものです。着信通知などの振動として適している一方、ボタンのクリックなどを表現するための振動にはあまり向きません。
そこで最後のステップでは、ボタンがタップされた時に『カチッ』というような感触が得られる振動効果を設定する方法を学んでいきたいと思います。
POINT!
- ・振動を繰り返したい場合は、createWaveform()を使う!
- ・第1引数は繰り返しの周期(タイミング)、第2引数は振動パターンを繰り返すインデックスを指定する!
- ・永続的に振動を繰り返すように設定する場合は、振動をキャンセルするロジックも用意しておこう!
③クリックエフェクトとしての振動
Android端末の機種や設定にもよりますが、端末の『ホーム』ボタンや『戻る』ボタンをクリック(タップ)した時、端末が振動するというよりは「カチッ」というふうに一瞬だけ端末が反応する場合があります。パソコンのマウスでクリック動作を行ったような触覚が得られ、ユーザーは『間違いなくボタンが押された』という事実を認識することができます。
このような振動(クリックエフェクト)は、createPredefined()
を使うことで、Androidアプリでも簡単に利用することができます。(APIレベル29以上)
createPredefined()
は引数を一つだけとり、型としては Int
です。ただ、整数値をそのまま指定するのではなく、キーワードを用いて指定します。たとえばノーマルなクリックエフェクトを設定したい場合、EFFECT_CLICK
を用いて次のように指定できます。
Button(
onClick = {
vibrator.vibrate(
VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK)
)
}
) {
Text(text = "Click Effect")
}
通常のクリックエフェクトよりも強いバージョン(EFFECT_HEAVY_CLICK)も用意されています。
Button(
onClick = {
vibrator.vibrate(
VibrationEffect.createPredefined(VibrationEffect.EFFECT_HEAVY_CLICK)
)
}
) {
Text(text = "Heavy Click Effect")
}
より注意を引くことができる、ダブルクリックエフェクト(EFFECT_DOUBLE_CLICK)もあります。その名の通り、短い間隔で2回振動します。
Button(
onClick = {
vibrator.vibrate(
VibrationEffect.createPredefined(VibrationEffect.EFFECT_DOUBLE_CLICK)
)
}
) {
Text(text = "Double Click Effect")
}
下の動画は、それぞれのボタンを2回ずつタップした様子を録画したものです。これまでの振動と比べると振動音が発生するのが一瞬かつ音も小さめなので、少し分かりづらいかもしれませんがご容赦ください!
また、この記事で紹介したサンプルコードはプロジェクトごとGithubで公開しています。なので、まるっとコピーしてお持ちのデバイスにビルドして、ぜひ実際の振動を体感してみてください。
・Android-vibration-sample(GitHub)
https://github.com/roydo/Android-vibration-sample
POINT!
- ・クリックエフェクトを利用したい場合は、createPredefined()を使う!
- ・クリックエフェクトは、通常のクリックからダブルクリックまで数種類用意されている!
- ・APIレベル29以上が必要となるので、その点に注意が必要!