Switch开关

效果如下:

原理上面,其实就是一个Toggle,选中时改变圆点的位置,并将背景色改为绿色;未选中时,圆点回到默认位置,并将背景色改为默认色。

层级结构如下:

面板参数如下:

要注意两个地方:

  1. Toggle图片有红框的位置,要一致。
  2. 小圆点也就是Checkmark,锚点需要是居中。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class SwitchToggle : MonoBehaviour
{
    //把手RectTransform
    [SerializeField] private RectTransform handleRectTransform;

    //把手开启颜色
    [SerializeField] private Color _handleActiveColor;

    //开关背景开启颜色
    [SerializeField] private Color _backgroundActiveColor;

    //动画时间
    [SerializeField] private float _duration = 0.5f;

    //开关背景与把手的图片
    private Image _handleImage, _backgroundImage;

    //开关背景与把手的默认颜色
    private Color _handleColor, _backgroundColor;

    //把手移动的位置
    private Vector2 _handlePosition;

    private Toggle _toggle;


    private void Awake()
    {

        _toggle = GetComponent<Toggle>();
        handleRectTransform = transform.Find("Background").Find("Checkmark").GetComponent<RectTransform>();
        _handleImage = handleRectTransform.GetComponent<Image>();
        _backgroundImage = handleRectTransform.parent.GetComponent<Image>();

        _handleColor = _handleImage.color;
        _backgroundColor = _backgroundImage.color;

        _handlePosition = handleRectTransform.anchoredPosition;

        _toggle.onValueChanged.AddListener(OnSwitch);

        //在游戏对象启动时检查 _toggle 组件的初始选中状态,依据选中状态来执行OnSwitch方法函数
        if (_toggle.isOn)
        {
            OnSwitch(true);
        }
    }

    //控制开关动画方法函数
    private void OnSwitch(bool on)
    {
    	//没有Dotween插件使用下面的代码
        if (on)
        {
            handleRectTransform.anchoredPosition = Vector2.MoveTowards(handleRectTransform.anchoredPosition, new Vector2(-_handlePosition.x, _handlePosition.y), _duration * 100);
        }
        else
            handleRectTransform.anchoredPosition = Vector2.MoveTowards(handleRectTransform.anchoredPosition, new Vector2(_handlePosition.x, _handlePosition.y), _duration * 100);
        
        if (on)
            _backgroundImage.color = _backgroundActiveColor;
        else
            _backgroundImage.color = _backgroundColor;
            
        if (on)
            _handleImage.color = _handleActiveColor;
        else
            _handleImage.color = _handleColor; ;

		

		//有Dotween插件时使用下面的代码

		/handleRectTransform.DOAnchorPos(on ? -_handlePosition : _handlePosition, _duration).SetEase(Ease.InOutBack);
        //_backgroundImage.DOColor(on ? _backgroundActiveColor : _backgroundColor, _duration).SetEase(Ease.InOutBack);
        //_handleImage.DOColor(on ? _handleActiveColor : _handleColor, _duration).SetEase(Ease.InOutBack);
    }

    //避免持续监听 _toggle 的 onValueChanged 事件,防止在对象已销毁的情况下继续调用 OnSwitch 方法,避免潜在的错误或资源浪费
    private void OnDestroy()
    {
        _toggle.onValueChanged.RemoveListener(OnSwitch);
    }
}