sunagimoブログ

主にUnityに関する技術を取り上げます

【Unity】ドロップダウンのプレースホルダーの設定

選択式のUIコンポーネントです。

f:id:sunagimo_app:20190519181236p:plain:w400:h300

Dropdown、TMP_Dropdown(TextMeshPro)にはプレースホルダーを設定する機能はついていません。
今回はそれを独自に実装する方法を2つ紹介します。
(今回はTextMehPro向けに記載しています。)


リスト選択項目に追加する実装


f:id:sunagimo_app:20190519183231p:plain

ドロップダウンの1つ目の選択肢をプレースホルダーとして使います。
ただプレースホルダー自体も選択肢の一つになるので、
本来のプレースホルダーの機能とは異なっている気がします。

    /// <summary>
    /// ドロップダウン。
    /// </summary>
    [Header("ドロップダウン")]
    [SerializeField]
    TMP_Dropdown dropdown = default;

    void Start()
    {
        dropdown.options.Insert(0, new TMP_Dropdown.OptionData("Please select"));
        dropdown.value = 0;
    }




リスト選択項目に追加しない実装


f:id:sunagimo_app:20190519183438p:plain

リスト選択項目には追加せず、一度他の選択肢を選択すると
プレースホルダーを選択できなくなります。
本来のプレースホルダーの機能を果たしていると思います。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;

[RequireComponent(typeof(TMP_Dropdown))]
public class DropdownPlaceHolder : MonoBehaviour
{
    #region Inspector
    /// <summary>
    /// プレースホルダーラベルカラー。
    /// </summary>
    [SerializeField]
    [Header("プレースホルダーカラー")]
    Color32 placeHolderLblColor = new Color32(50, 50, 50, 255);

    /// <summary>
    /// 通常のラベルカラー。
    /// </summary>
    [Header("通常のラベルカラー")]
    [SerializeField]
    Color32 normalLblColor = new Color32(255, 255, 255, 255);
    #endregion

    #region Param

    /// <summary>
    /// 選択が終了しているか。
    /// </summary>
    public bool IsFinishSelected
    { 
        get { return IsEnabledPlaceHolder; }
    }

    /// <summary>
    /// ドロップダウン。
    /// </summary>
    TMP_Dropdown dropdown;

    /// <summary>
    /// プレースホルダーが有効か。
    /// </summary>
    public bool IsEnabledPlaceHolder { get; private set; } = false;

    /// <summary>
    /// プレースホルダーテキスト。
    /// </summary>
    string placeHolderText = string.Empty;
    #endregion

    /// <summary>
    /// ドロップダウンコンポーネントを取得。
    /// </summary>
    TMP_Dropdown GetDropdownComponent
    {
        get 
        { 
            if(dropdown == null)
            {
                return dropdown = GetComponent<TMP_Dropdown>();
            }
            return dropdown;
        }
    }

    /// <summary>
    /// プレースホルダのラベルを設定。
    /// </summary>
    /// <param name="placeHolderText">プレースホルダーテキスト。</param>
    public void SetPlaceHolderLbl(string placeHolderText)
    {
        this.placeHolderText = placeHolderText;
        IsEnabledPlaceHolder = true;
        GetDropdownComponent.captionText.text = placeHolderText;
        SetPlaceHolderLblStyle();
    }
    
    /// <summary>
    /// ドロップダウンアイテム押下処理。
    /// </summary>
    public void OnClickDropdownItem()
    {
        IsEnabledPlaceHolder = false;
        GetDropdownComponent.captionText.text = dropdown.options[dropdown.value].text;
        SetDefaultLblStyle();
    }

    /// <summary>
    /// プレースホルダーのラベルスタイルセット。
    /// </summary>
    void SetPlaceHolderLblStyle()
    {
        GetDropdownComponent.captionText.fontStyle = FontStyles.Italic;
        GetDropdownComponent.captionText.color = placeHolderLblColor;
    }

    /// <summary>
    /// 通常のラベルスタイルセット
    /// </summary>
    void SetDefaultLblStyle()
    {
        GetDropdownComponent.captionText.fontStyle = FontStyles.Normal;
        GetDropdownComponent.captionText.color = normalLblColor;
    }

    void Update()
    {
        // 画面をアクティブ・非アクティブ時に戻ってしまうためUpdateで更新する。
        if(IsEnabledPlaceHolder)
        {
            GetDropdownComponent.captionText.text = placeHolderText;
        }
    }
}





using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

[RequireComponent(typeof(Toggle))]
public class DropdownPlaceHolderItem : MonoBehaviour
{
    void Start()
    {
        var dropdownPlaceHolderComponent = GetComponentInParent<DropdownPlaceHolder>();
        var toggleComponent = GetComponent<Toggle>();

        toggleComponent.onValueChanged.AddListener(delegate(bool isOn)
        {
            if(isOn)
            {
                if(dropdownPlaceHolderComponent != null)
                {
                    dropdownPlaceHolderComponent.OnClickDropdownItem();
                }
            }
        });
    }
}


上記でやっていることは以下になります。

1.ドロップダウンで現在選択されているテキストをプレースホルダーのテキストで更新
2.ドロップダウンから選択されたら選択したアイテムの選択肢のテキストに更新


まとめ


dropdownのvalue自体は-1などにしても、自動で0に戻ってしまうため、
何も選択していない状態は作れません。
少々面倒くさい実装になりましたが、これで意図したプレースホルダーになっていると思います。


実装したサンプルコード


github.com