From 8b4336888b604499f1252d19d62260a2f88ebd95 Mon Sep 17 00:00:00 2001 From: Lisha Li Date: Wed, 13 Apr 2022 16:16:04 -0700 Subject: [PATCH] Added the slide toggle example code --- slide-toggle/SlideToggle.cs | 104 +++++++++++++++++++++++++++++ slide-toggle/SlideToggle.uss | 63 +++++++++++++++++ slide-toggle/SlideToggleUsage.uxml | 4 ++ 3 files changed, 171 insertions(+) create mode 100644 slide-toggle/SlideToggle.cs create mode 100644 slide-toggle/SlideToggle.uss create mode 100644 slide-toggle/SlideToggleUsage.uxml diff --git a/slide-toggle/SlideToggle.cs b/slide-toggle/SlideToggle.cs new file mode 100644 index 0000000..d6b9ddc --- /dev/null +++ b/slide-toggle/SlideToggle.cs @@ -0,0 +1,104 @@ +using UnityEngine; +using UnityEngine.UIElements; + +namespace MyUILibrary +{ + // Derives from BaseField base class. Represents a container for its input part. + public class SlideToggle : BaseField + { + public new class UxmlFactory : UxmlFactory { } + + public new class UxmlTraits : BaseFieldTraits { } + + // In the spirit of the BEM standard, the SlideToggle has its own block class and two element classes. It also + // has a class that represents the enabled state of the toggle. + public static readonly new string ussClassName = "slide-toggle"; + public static readonly new string inputUssClassName = "slide-toggle__input"; + public static readonly string inputKnobUssClassName = "slide-toggle__input-knob"; + public static readonly string inputCheckedUssClassName = "slide-toggle__input--checked"; + + VisualElement m_Input; + VisualElement m_Knob; + + // Custom controls need a default constructor. This default constructor calls the other constructor in this + // class. + public SlideToggle() : this(null) { } + + // This constructor allows users to set the contents of the label. + public SlideToggle(string label) : base(label, new()) + { + // Style the control overall. + AddToClassList(ussClassName); + + // Get the BaseField's visual input element and use it as the background of the slide. + m_Input = this.Q(className: BaseField.inputUssClassName); + m_Input.AddToClassList(inputUssClassName); + Add(m_Input); + + // Create a "knob" child element for the background to represent the actual slide of the toggle. + m_Knob = new(); + m_Knob.AddToClassList(inputKnobUssClassName); + m_Input.Add(m_Knob); + + // There are three main ways to activate or deactivate the SlideToggle. All three event handlers use the + // static function pattern described in the Custom control best practices. + + // ClickEvent fires when a sequence of pointer down and pointer up actions occurs. + RegisterCallback(evt => OnClick(evt)); + // KeydownEvent fires when the field has focus and a user presses a key. + RegisterCallback(evt => OnKeydownEvent(evt)); + // NavigationSubmitEvent detects input from keyboards, gamepads, or other devices at runtime. + RegisterCallback(evt => OnSubmit(evt)); + } + + static void OnClick(ClickEvent evt) + { + var slideToggle = evt.currentTarget as SlideToggle; + slideToggle.ToggleValue(); + + evt.StopPropagation(); + } + + static void OnSubmit(NavigationSubmitEvent evt) + { + var slideToggle = evt.currentTarget as SlideToggle; + slideToggle.ToggleValue(); + + evt.StopPropagation(); + } + + static void OnKeydownEvent(KeyDownEvent evt) + { + var slideToggle = evt.currentTarget as SlideToggle; + + // NavigationSubmitEvent event already covers keydown events at runtime, so this method shouldn't handle + // them. + if (slideToggle.panel?.contextType == ContextType.Player) + return; + + // Toggle the value only when the user presses Enter, Return, or Space. + if (evt.keyCode == KeyCode.KeypadEnter || evt.keyCode == KeyCode.Return || evt.keyCode == KeyCode.Space) + { + slideToggle.ToggleValue(); + evt.StopPropagation(); + } + } + + // All three callbacks call this method. + void ToggleValue() + { + value = !value; + } + + // Because ToggleValue() sets the value property, the BaseField class fires a ChangeEvent. This results in a + // call to SetValueWithoutNotify(). This example uses it to style the toggle based on whether it's currently + // enabled. + public override void SetValueWithoutNotify(bool newValue) + { + base.SetValueWithoutNotify(newValue); + + //This line of code styles the input element to look enabled or disabled. + m_Input.EnableInClassList(inputCheckedUssClassName, newValue); + } + } +} diff --git a/slide-toggle/SlideToggle.uss b/slide-toggle/SlideToggle.uss new file mode 100644 index 0000000..8d72d89 --- /dev/null +++ b/slide-toggle/SlideToggle.uss @@ -0,0 +1,63 @@ +.slide-toggle__input { + background-color: var(--unity-colors-slider_groove-background); + max-width: 25px; + border-top-left-radius: 8px; + border-bottom-left-radius: 8px; + border-top-right-radius: 8px; + border-bottom-right-radius: 8px; + overflow: visible; + border-left-width: 1px; + border-right-width: 1px; + border-top-width: 1px; + border-bottom-width: 1px; + border-right-color: var(--unity-colors-slider_thumb-border); + border-top-color: var(--unity-colors-slider_thumb-border); + border-bottom-color: var(--unity-colors-slider_thumb-border); + max-height: 16px; + margin-top: 10px; + border-left-color: var(--unity-colors-slider_thumb-border); + transition-property: background-color; + transition-duration: 0.5s; +} + +.slide-toggle__input-knob { + height: 16px; + width: 16px; + background-color: var(--unity-colors-slider_thumb-background); + position: absolute; + border-top-left-radius: 25px; + border-bottom-left-radius: 25px; + border-top-right-radius: 25px; + border-bottom-right-radius: 25px; + top: -1px; + transition-property: translate, background-color; + transition-duration: 0.5s, 0.5s; + translate: -1px 0; + border-left-width: 1px; + border-right-width: 1px; + border-top-width: 1px; + border-bottom-width: 1px; + border-left-color: var(--unity-colors-slider_thumb-border); + border-right-color: var(--unity-colors-slider_thumb-border); + border-top-color: var(--unity-colors-slider_thumb-border); + border-bottom-color: var(--unity-colors-slider_thumb-border); +} + +.slide-toggle__input--checked { + background-color: rgb(0, 156, 10); +} + +.slide-toggle__input--checked > .slide-toggle__input-knob { + translate: 8px 0; +} + +.slide-toggle:focus .slide-toggle__input-knob { + border-left-width: 1px; + border-right-width: 1px; + border-top-width: 1px; + border-bottom-width: 1px; + border-left-color: var(--unity-colors-input_field-border-focus); + border-right-color: var(--unity-colors-input_field-border-focus); + border-top-color: var(--unity-colors-input_field-border-focus); + border-bottom-color: var(--unity-colors-input_field-border-focus); +} \ No newline at end of file diff --git a/slide-toggle/SlideToggleUsage.uxml b/slide-toggle/SlideToggleUsage.uxml new file mode 100644 index 0000000..67d9c03 --- /dev/null +++ b/slide-toggle/SlideToggleUsage.uxml @@ -0,0 +1,4 @@ + +