Perfect Toggle effect
##目标
本文将从 0 教你如何打造一个 Unity 的组件,来创建属于你的 UGUI~
效果图在这里:

所有的 UI 空间都需要在 Canvas 下进行布局,当然这是废话。

对这里创建一个 Panel,来放下我们所有的组件,毕竟要手写一个 Toggle。这里起名叫做 NiceToggle。
大小设置为 200*70 。按照你的需求来。


我们这里使用 Button 来响应用户的点击,当然你也可以用别的相应点击效果。
- 背景是 Image 组件,起名为 ToggleBg。
- 滑块是 Image 组件,起名为 Handle。
- ON 是 Text 组件,起名 ON。
- OFF 是 Text 组件,起名 OFF。
- Button 是 Button 组件,起名 ToggleButton。
要把所有的组件组合起来,所以需要一些资源文件,在项目中你都可以得到这些资源文件,首先是背景,我这里叫 Toggle_bg,大概是这个样子。





ToggleBg 参数如下图:






给 NiceToggle 添加脚本,取名 ToggleController。

using System.Collections;
using System.Collections.Generic;
using DG.Tweening;
using UnityEngine;
using UnityEngine.UI;
public class ToggleController : MonoBehaviour
{
public bool isOn;
public bool isEnable = true;
public Color onColorBg;
public Color offColorBg;
public Color NoEnableBg;
public Image toggleBgImage;
public RectTransform toggle;
public GameObject handle;
private RectTransform handleTransform;
public Button SwitchButton;
private float handleSize;
private float onPosX;
private float offPosX;
public float handleOffset;
public GameObject onIcon;
public GameObject offIcon;
public float speed;
static float t = 0.0f;
private bool switching = false;
void Awake()
{
handleTransform = handle.GetComponent<RectTransform>();
RectTransform handleRect = handle.GetComponent<RectTransform>();
handleSize = handleRect.sizeDelta.x;
float toggleSizeX = toggle.sizeDelta.x;
onPosX = (toggleSizeX / 2) - (handleSize / 2) - handleOffset;
offPosX = onPosX * -1;
}
void Start()
{
if (isOn)
{
toggleBgImage.color = onColorBg;
handleTransform.localPosition = new Vector3(onPosX, 0f, 0f);
onIcon.gameObject.SetActive(true);
offIcon.gameObject.SetActive(false);
DOTweenTransparency(onIcon, 0f, 1f);
DOTweenTransparency(offIcon, 1f, 0f);
}
else
{
toggleBgImage.color = offColorBg;
handleTransform.localPosition = new Vector3(offPosX, 0f, 0f);
onIcon.gameObject.SetActive(false);
offIcon.gameObject.SetActive(true);
DOTweenTransparency(onIcon, 1f, 0f);
DOTweenTransparency(offIcon, 0f, 1f);
}
}
void Update()
{
if (isEnable)
{
if (switching)
{
Toggle(isOn);
}
}
else
{
toggleBgImage.color = NoEnableBg;
onIcon.gameObject.SetActive(false);
offIcon.gameObject.SetActive(true);
}
}
public void DoYourStaff()
{
Debug.Log(isOn);
}
public void Switching()
{
if (isEnable)
{
switching = true;
}
}
public void Toggle(bool toggleStatus)
{
if ((offIcon != null) && ((onIcon != null) && (!onIcon.active || !offIcon.active)))
{
onIcon.SetActive(true);
offIcon.SetActive(true);
}
if (toggleStatus)
{
StopDOTweenSwitching();
DOTweenSmoothColor(offColorBg);
DOTweenTransparency(onIcon, 1f, 0f);
DOTweenTransparency(offIcon, 0f, 1f);
DOTweenSmoothMove(onPosX, offPosX);
}
else
{
StopDOTweenSwitching();
DOTweenSmoothColor(onColorBg);
DOTweenTransparency(onIcon, 0f, 1f);
DOTweenTransparency(offIcon, 1f, 0f);
DOTweenSmoothMove(offPosX, onPosX);
}
}
void DOTweenSmoothMove(float startPosX, float endPosX)
{
DOTween.To(
() => handleTransform.localPosition,
x => handleTransform.localPosition = x,
new Vector3((endPosX - startPosX) / 2, 0f, 0f),
0.4f
).SetEase(Ease.OutQuad);
}
void DOTweenSmoothColor(Color endCol)
{
DOTween.To(
() => toggleBgImage.color,
x => toggleBgImage.color = x,
endCol,
0.4f
).SetEase(Ease.OutQuad);
}
void DOTweenTransparency(GameObject alphaObj, float startAlpha, float endAlpha)
{
CanvasGroup alphaVal;
alphaVal = alphaObj.gameObject.GetComponent<CanvasGroup>();
DOTween.To(() => alphaVal.alpha, x => alphaVal.alpha = x, endAlpha, 0.4f);
}
void StopDOTweenSwitching()
{
switching = false;
switch (isOn)
{
case true:
isOn = false;
DoYourStaff();
break;
case false:
isOn = true;
DoYourStaff();
break;
}
}
}请在 DoYourStaff() 中填写你的业务逻辑,这里使用的 DOTween 的数值线性变化,DOTween 的文档 下一篇文章会单独介绍这个的使用。再把所有的控件挂在到 Controller 上就可以达到文章开头的效果啦,试一下吧。

