UnityでiOS風のトグルを実装してみました。
iOSのネイティブコードはもちろん使用していません。
アニメーションにはDOTweenを使用しました。
画像素材
必要な画像素材は背景のカプセル型画像とハンドルの円形画像の2つだけです。
透過画像で用意したので、よければ保存して使ってください。
色はどちらも真っ白です。
ハンドル画像に薄くドロップシャドウをかけておくのがクオリティアップのポイントです。
Unityで配置
Canvas以下にToggleオブジェクトを作成し、その子オブジェクトにBackgroundとHandleを作成します。
ToggleはButton、BackgroundとHandleはImageとして作成します。
Toggle
大きさはBackgroundと同じ大きさにしておきます。
ImageはButtonを動作させるためだけのものなので、Spriteは設定せず、Colorのアルファ値を0にして見えないようにしておきます。
Background
BackgroundのImageにはカプセル型画像を設定します。
色はスクリプトから設定するのですが、実行中以外でも見やすいように明るめのグレーを設定しておきます。
Handle
HandleのImageにはドロップシャドウ付きの円形画像を設定します。
大きさはBackgroundの高さよりも若干小さくなるようにします。
位置はどちらかの端に寄せておきます。
挙動の実装
ソースコード
Toggle.csを作成します。
using System;
using DG.Tweening;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// トグル
/// </summary>
public class Toggle : MonoBehaviour
{
[SerializeField] private Image backgroundImage;
[SerializeField] private RectTransform handle;
[SerializeField] private bool onAwake;
/// <summary>
/// トグルの値
/// </summary>
[NonSerialized] public bool Value;
private float handlePosX;
private Sequence sequence;
private static readonly Color OFF_BG_COLOR = new Color(0.92f, 0.92f, 0.92f);
private static readonly Color ON_BG_COLOR = new Color(0.2f, 0.84f, 0.3f);
private const float SWITCH_DURATION = 0.36f;
private void Start()
{
handlePosX = Mathf.Abs(handle.anchoredPosition.x);
Value = onAwake;
UpdateToggle(0);
}
/// <summary>
/// トグルのボタンアクションに設定しておく
/// </summary>
public void SwitchToggle()
{
Value = !Value;
UpdateToggle(SWITCH_DURATION);
}
/// <summary>
/// 状態を反映させる
/// </summary>
private void UpdateToggle(float duration)
{
var bgColor = Value ? ON_BG_COLOR : OFF_BG_COLOR;
var handleDestX = Value ? handlePosX : -handlePosX;
sequence?.Complete();
sequence = DOTween.Sequence();
sequence.Append(backgroundImage.DOColor(bgColor, duration))
.Join(handle.DOAnchorPosX(handleDestX, duration / 2));
}
}
Unityエディタでの設定
ToggleオブジェクトにToggle.csをアタッチします。
インスペクタのBackgroundImageとHandleに、それぞれBackgroundとHandleをドラッグ&ドロップして指定します。
そして、ToggleのボタンのOnClickにSwitchToggle()を指定します。
ちょっとしたポイント
クオリティアップ&UX向上のためのちょっとしたポイント。
Buttonの大きさ
まず、ButtonコンポーネントはHandleではなく親のToggle(Backgroundの大きさ)にアタッチしている点。
ハンドルを動かすイメージなのでハンドルにButtonを付けがちですが、ハンドルは結構小さいのでクリックしづらいという難点があります。
特にスマホで使う場合はかなりタップしづらくなります。
そこで、トグル全体をクリックに反応させることでクリックのしづらさを緩和しています。
iOS機器を持っている方は実際に試してみてほしいのですが、iOSのトグルもBackground部分をタップしても反応するようになっています。
ハンドルの移動と背景の色変化をずらす
今回、ハンドルが移動する時間を背景の色変化の時間の半分に設定しました。
これは個人的な好みかもしれませんが、ハンドルの移動は素早くフィードバックしてほしいのに対し、背景の色変化は少しゆっくりめに変化した方が綺麗に見える気がします。
是非55行目のduration / 2
の部分をduration
に変更して、違いを確かめてみてください。
どちらを採用するかはお好みで。
使い方
ToggleコンポーネントのOnAwakeでは初期状態を指定します。
OnAwakeにチェックを入れておくと初期状態でONに、入れないとOFFになります。
エディタ実行してトグルをクリックすると、状態が切り替えが実現できているとか思います。
他のスクリプトからトグルの状態を取得したいときは、ToggleコンポーネントのValueの値を取得してください。
まとめ
UnityでiOSのトグルを再現してみました。
再現度高く、細かなこだわりも含めて実現できました。
- UnityでiOS風トグルが簡単に作れる
- ボタンの大きさをトグル全体にすることでUX向上
- ハンドルの移動と背景の色変化をずらすことで綺麗なアニメーションに
コメント