Search Unity

  1. Unity 2019.2 is now released.
    Dismiss Notice

New UI Widgets

Discussion in 'Assets and Asset Store' started by ilih, Feb 11, 2015.

  1. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    898
    Thank you very much :D
     
  2. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    898
  3. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    705
    jGate99 likes this.
  4. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    898
    @ilih
    Getting following error in Unity 2020.1a3 if i set a null dataSource.
    please advise Capture.PNG
     
  5. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    705
    Null not supported, please use an empty list instead of the null.
     
    jGate99 likes this.
  6. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    705
    I added new ListViewEllipse type, please check v1.11.0f1, examples at Examples/ListView/ListViewEllipse scene.

    EasyLayout settings for the ListViewEllipse type:
    • RectTransform pivot defines on which side or corner will be the center point
    • EasyLayout.Ellipse Settings: width and height usually should be specified
    • Angle Start is a base rotation for the first item
    • Angle Step Auto should be disabled
    • Angle Step is an angular distance between items
    • Fill should be Arc
    • Arc Length should be 180 if center at the side and 90 if center at the corner
     
    jGate99 likes this.
  7. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    898
    Thank you very much :)
     
  8. ossang

    ossang

    Joined:
    Aug 2, 2018
    Posts:
    5
    Hi.
    It looks like basic question, I tried to add draggble and resizable to my object as components and It worked well.
    But I would like to get callback OnDrag during resize and process something I want in my script without editing your code(resizable.cs).
    Please help me to how to get events.
    Thank you.
     
  9. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    705
    I added OnResize event to Resizable component in v1.11.1b1.
    You can update to this version or use the following script:
    Code (CSharp):
    1. namespace UIWidgets.Examples
    2. {
    3.     using UIWidgets;
    4.     using UnityEngine;
    5.     using UnityEngine.Events;
    6.     using UnityEngine.EventSystems;
    7.  
    8.     [RequireComponent(typeof(Resizable))]
    9.     public class ResizableDragEvent : MonoBehaviour, IDragHandler
    10.     {
    11.         public UnityEvent OnResize = new UnityEvent();
    12.  
    13.         bool isResize;
    14.  
    15.         public void OnDrag(PointerEventData eventData)
    16.         {
    17.             if (isResize)
    18.             {
    19.                 OnResize.Invoke();
    20.             }
    21.         }
    22.  
    23.         protected void Start()
    24.         {
    25.             var resizable = GetComponent<Resizable>();
    26.             if (resizable != null)
    27.             {
    28.                 resizable.OnStartResize.AddListener(StartResize);
    29.                 resizable.OnEndResize.AddListener(EndResize);
    30.             }
    31.         }
    32.  
    33.         protected void OnDestroy()
    34.         {
    35.             var resizable = GetComponent<Resizable>();
    36.             if (resizable != null)
    37.             {
    38.                 resizable.OnStartResize.RemoveListener(StartResize);
    39.                 resizable.OnEndResize.RemoveListener(EndResize);
    40.             }
    41.         }
    42.  
    43.         void StartResize(Resizable r)
    44.         {
    45.             isResize = true;
    46.         }
    47.  
    48.         void EndResize(Resizable r)
    49.         {
    50.             isResize = false;
    51.         }
    52.     }
    53. }
     
  10. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    705
    Released version 1.11.0

    Changelog:
    • added ScrollRectHeader (example of usage in Examples/ListView/ListViewHeader scene)
    • added EasyLayoutEllipseScroll
    • Combobox: added OnShowListView and OnHideListView events
    • EasyLayout: added new layout type Ellipse
    • EasyLayout: added new option ResetRotation
    • ListView: added DestroyDefaultItemsCache, if enabled instances of the previous DefaultItem will be destroyed when replacing DefaultItem
    • ListView: added new ListViewEllipse list type
    • Scroller: renamed to ScrollBlock
     
    hopeful and jGate99 like this.
  11. smada-luap

    smada-luap

    Joined:
    Aug 22, 2013
    Posts:
    945
    I'm liking a lot of what I find in this asset.

    One question regarding the Notification containers - is there a way to slide the notification off screen horizontally?
     
  12. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    705
    You need to specify custom
    hideAnimation
    .
    Here is an example script with four different horizontal animations:
    • resize (HorizontalCollapse)
    • rotate (HorizontalRotate)
    • slide to left (HorizontalSlideLeft)
    • slide to right (HorizontalSlideRight)
    Those animations will be included in the next update.
    Code (CSharp):
    1. namespace UIWidgets.Examples
    2. {
    3.     using System.Collections;
    4.     using System.Collections.Generic;
    5.     using EasyLayoutNS;
    6.     using UIWidgets;
    7.     using UnityEngine;
    8.     using UnityEngine.UI;
    9.  
    10.     public class TestNotification : MonoBehaviour
    11.     {
    12.         [SerializeField]
    13.         protected Notify NotifyTemplate;
    14.  
    15.         /// <summary>
    16.         /// Notification with horizontal collapse animation.
    17.         /// </summary>
    18.         public void HorizontalCollapse()
    19.         {
    20.             NotifyTemplate.Clone().Show("Notification message.", customHideDelay: 3f, hideAnimation: x => AnimationCollapseHorizontal(x, 200f), slideUpOnHide: false);
    21.         }
    22.  
    23.         /// <summary>
    24.         /// Notification with horizontal rotate animation.
    25.         /// </summary>
    26.         public void HorizontalRotate()
    27.         {
    28.             NotifyTemplate.Clone().Show("Notification message.", customHideDelay: 3f, hideAnimation: x => AnimationRotateHorizontal(x, 0.5f), slideUpOnHide: false);
    29.         }
    30.  
    31.         /// <summary>
    32.         /// Notification with slide animation to left.
    33.         /// </summary>
    34.         public void HorizontalSlideLeft()
    35.         {
    36.             NotifyTemplate.Clone().Show("Notification message.", customHideDelay: 3f, hideAnimation: x => AnimationSlideBase(x, true, -1f, 200f), slideUpOnHide: false);
    37.         }
    38.  
    39.         /// <summary>
    40.         /// Notification with slide animation to right.
    41.         /// </summary>
    42.         public void HorizontalSlideRight()
    43.         {
    44.             NotifyTemplate.Clone().Show("Notification message.", customHideDelay: 3f, hideAnimation: x => AnimationSlideBase(x, true, +1f, 200f), slideUpOnHide: false);
    45.         }
    46.  
    47.         static Stack<RectTransform> replacements = new Stack<RectTransform>();
    48.  
    49.         static RectTransform GetReplacement()
    50.         {
    51.             RectTransform replacement;
    52.  
    53.             if (replacements.Count == 0)
    54.             {
    55.                 var obj = new GameObject("NotifyReplacement");
    56.                 obj.SetActive(false);
    57.                 replacement = obj.AddComponent<RectTransform>();
    58.  
    59.                 var image = obj.AddComponent<Image>();
    60.                 image.color = Color.clear;
    61.             }
    62.             else
    63.             {
    64.                 do
    65.                 {
    66.                     replacement = (replacements.Count > 0) ? replacements.Pop() : GetReplacement();
    67.                 }
    68.                 while (replacement == null);
    69.             }
    70.  
    71.             return replacement;
    72.         }
    73.  
    74.         static RectTransform GetReplacement(Notify notify)
    75.         {
    76.             var replacement = GetReplacement();
    77.  
    78.             var source_rect = notify.transform as RectTransform;
    79.  
    80.             replacement.localRotation = source_rect.localRotation;
    81.             replacement.localPosition = source_rect.localPosition;
    82.             replacement.localScale = source_rect.localScale;
    83.             replacement.anchorMin = source_rect.anchorMin;
    84.             replacement.anchorMax = source_rect.anchorMax;
    85.             replacement.anchoredPosition = source_rect.anchoredPosition;
    86.             replacement.anchoredPosition3D = source_rect.anchoredPosition3D;
    87.             replacement.sizeDelta = source_rect.sizeDelta;
    88.             replacement.pivot = source_rect.pivot;
    89.  
    90.             replacement.transform.SetParent(source_rect.parent, false);
    91.             replacement.transform.SetSiblingIndex(source_rect.GetSiblingIndex());
    92.  
    93.             replacement.gameObject.SetActive(true);
    94.  
    95.             return replacement;
    96.         }
    97.  
    98.         /// <summary>
    99.         /// Base slide animation.
    100.         /// </summary>
    101.         /// <param name="notify">Notify.</param>
    102.         /// <param name="isHorizontal">Is horizontal slide?</param>
    103.         /// <param name="direction">Slide direction.</param>
    104.         /// <param name="speed">Speed.</param>
    105.         /// <returns>Animation.</returns>
    106.         public static IEnumerator AnimationSlideBase(Notify notify, bool isHorizontal, float direction, float speed = 200f)
    107.         {
    108.             var replacement = GetReplacement(notify);
    109.  
    110.             var layout_element = Utilites.GetOrAddComponent<LayoutElement>(notify);
    111.             layout_element.ignoreLayout = true;
    112.  
    113.             var rect = notify.transform as RectTransform;
    114.             var base_size = isHorizontal ? rect.rect.width : rect.rect.height;
    115.             var base_pos = rect.anchoredPosition;
    116.  
    117.             var time = base_size / speed;
    118.             var end_time = Time.unscaledTime + time;
    119.  
    120.             while (Time.unscaledTime <= end_time)
    121.             {
    122.                 var t = 1 - ((end_time - Time.unscaledTime) / time);
    123.                 var size = Mathf.Lerp(0, base_size, t);
    124.                 rect.anchoredPosition = isHorizontal
    125.                     ? new Vector2(base_pos.x + (size * direction), base_pos.y)
    126.                     : new Vector2(base_pos.x, base_pos.y + (size * direction));
    127.  
    128.                 yield return null;
    129.             }
    130.  
    131.             layout_element.ignoreLayout = false;
    132.  
    133.             replacements.Push(replacement);
    134.             replacement.gameObject.SetActive(false);
    135.         }
    136.  
    137.         /// <summary>
    138.         /// Horizontal collapse animation.
    139.         /// </summary>
    140.         /// <param name="notify">Notify.</param>
    141.         /// <param name="speed">Speed.</param>
    142.         /// <returns>Animation.</returns>
    143.         public static IEnumerator AnimationCollapseHorizontal(Notify notify, float speed = 200f)
    144.         {
    145.             var rect = notify.transform as RectTransform;
    146.             var layout = notify.GetComponentInParent<EasyLayout>();
    147.             var base_width = rect.rect.width;
    148.  
    149.             var time = base_width / speed;
    150.             var end_time = Time.unscaledTime + time;
    151.  
    152.             while (Time.unscaledTime <= end_time)
    153.             {
    154.                 var t = 1 - ((end_time - Time.unscaledTime) / time);
    155.                 var width = Mathf.Lerp(base_width, 0, t);
    156.                 rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, width);
    157.                 if (layout != null)
    158.                 {
    159.                     layout.NeedUpdateLayout();
    160.                 }
    161.  
    162.                 yield return null;
    163.             }
    164.  
    165.             // return width back for future use
    166.             rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, base_width);
    167.         }
    168.  
    169.         /// <summary>
    170.         /// Horizontal rotate animation.
    171.         /// </summary>
    172.         /// <param name="notify">Notify.</param>
    173.         /// <param name="timeLength">Time length.</param>
    174.         /// <returns>Returns animations.</returns>
    175.         public static IEnumerator AnimationRotateHorizontal(Notify notify, float timeLength = 0.5f)
    176.         {
    177.             var rect = notify.transform as RectTransform;
    178.             var start_rotarion = rect.localRotation.eulerAngles;
    179.  
    180.             var end_time = Time.unscaledTime + timeLength;
    181.  
    182.             while (Time.unscaledTime <= end_time)
    183.             {
    184.                 var t = 1 - ((end_time - Time.unscaledTime) / timeLength);
    185.                 var rotation_y = Mathf.Lerp(0, 90, t);
    186.  
    187.                 rect.localRotation = Quaternion.Euler(start_rotarion.x, rotation_y, start_rotarion.z);
    188.                 yield return null;
    189.             }
    190.  
    191.             // return rotation back for future use
    192.             rect.localRotation = Quaternion.Euler(start_rotarion);
    193.         }
    194.     }
    195. }
     
    Last edited: Sep 25, 2019
    smada-luap likes this.
  13. ossang

    ossang

    Joined:
    Aug 2, 2018
    Posts:
    5
    Hi,
    I would like to get an event when tab changed. Please let me know both select and deselect.
    Thank you so much for giving example code.

    Thank you.
     
  14. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    705
    You should use the OnTabSelect event.
    Save the currently selected tab index (this will be the index of deselected tab) on start and get a newly selected index from the event.

    Code (CSharp):
    1.     using System;
    2.     using UIWidgets;
    3.     using UnityEngine;
    4.  
    5.     public class TestTabsEvents : MonoBehaviour
    6.     {
    7.         [SerializeField]
    8.         protected TabsIcons Tabs;
    9.  
    10.         int current_tab_index;
    11.  
    12.         protected void Start()
    13.         {
    14.             current_tab_index = Array.IndexOf(Tabs.TabObjects, Tabs.SelectedTab);
    15.  
    16.             Tabs.OnTabSelect.AddListener(TabChanged);
    17.         }
    18.  
    19.         void TabChanged(int new_tab_index)
    20.         {
    21.             Debug.Log("deselected tab: " + GetTabName(current_tab_index) + "; index " + current_tab_index);
    22.             Debug.Log("selected tab: " + GetTabName(new_tab_index) + "; index " + new_tab_index);
    23.            
    24.             current_tab_index = new_tab_index;
    25.         }
    26.  
    27.         string GetTabName(int index)
    28.         {
    29.             if (index < 0 || index >= Tabs.TabObjects.Length)
    30.             {
    31.                 return "none"; // tab was not selected at start or tabs were changed
    32.             }
    33.  
    34.             return Tabs.TabObjects[index].Name;
    35.         }
    36.  
    37.         protected void OnDestroy()
    38.         {
    39.             Tabs.OnTabSelect.RemoveListener(TabChanged);
    40.         }
    41.     }
     
    hopeful likes this.
  15. Petskus

    Petskus

    Joined:
    Jan 29, 2019
    Posts:
    1
    How is ListView.DataSource can be inited automaticaly from hierarchy ScrollRect.Viewport.List childs?
     
  16. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    705
    No, ListView instantiates ScrollRect.Viewport.List children based on DataSource, so an automatical reverse process not possible.
    But you can use a script to convert ScrollRect.Viewport.List children to DataSource and destroy them, then ListView instantiates new children based on DataSource.

    Code example:
    Code (CSharp):
    1.  
    2.     using UIWidgets;
    3.     using UnityEngine;
    4.  
    5.     /// <summary>
    6.     /// Create ListView data from hierarchy.
    7.     /// </summary>
    8.     public class ListViewDataFromHierarchy
    9.     {
    10.         /// <summary>
    11.         /// ListView.
    12.         /// </summary>
    13.         public ListViewIcons ListView;
    14.  
    15.         /// <summary>
    16.         /// Test.
    17.         /// </summary>
    18.         public void Test()
    19.         {
    20.             ListView.DataSource = Hierarchy2Data(ListView.Container);
    21.         }
    22.  
    23.         ObservableList<ListViewIconsItemDescription> Hierarchy2Data(Transform source)
    24.         {
    25.             var data = new ObservableList<ListViewIconsItemDescription>();
    26.  
    27.             foreach (Transform child in source)
    28.             {
    29.                 var is_default_item = child.gameObject.GetInstanceID() == ListView.DefaultItem.gameObject.GetInstanceID();
    30.                 if (is_default_item)
    31.                 {
    32.                     // ignore DefaultItem
    33.                     continue;
    34.                 }
    35.  
    36.                 // convert gameobject to data, the actual conversion should be more complex
    37.                 data.Add(new ListViewIconsItemDescription() {
    38.                     Name = child.name,
    39.                 });
    40.  
    41.                 // destroy gameobject
    42.                 Object.Destroy(child.gameObject);
    43.             }
    44.  
    45.             return data;
    46.         }
    47.     }
    48.  
     
    Petskus likes this.
  17. gregdetre

    gregdetre

    Joined:
    Sep 9, 2019
    Posts:
    2
    Hello, I'm excited to use the Combobox, but it doesn't work the way I'd hoped. I would like the user to be able to select from a fixed list without being able to add new items, kind of like a searchable drop-down.

    For example, let's say I have these 3 items in the ComboboxListView.DataSource:
    - Hello world
    - Hello foo
    - Blahblah

    If I type 'hello' into the inputfield, I would like just the matching items ('Hello world' and 'Hello foo') to be shown for me to choose from. The user shouldn't be able to add new items.

    I think it is relatively common for the term 'combobox' to refer to a searchable dropdown, and this was the sole reason I bought this asset. Is this possible to do, without having to extensively recode things myself? If not, would you be willing to add this functionality?

    Many thanks for a beautifully designed and documented set of assets!
     
    Last edited: Nov 1, 2019
  18. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    705
    Please check Autocomplete with InputType = AllInput, Result = Replace and following script.
    With such settings, Autocomplete can be used as Combobox with the fixed list.
    Code (CSharp):
    1.  
    2.     using UIWidgets;
    3.     using UnityEngine;
    4.     using UnityEngine.UI;
    5.  
    6.     public class AutocompleteValidation : MonoBehaviour
    7.     {
    8.         [SerializeField]
    9.         public Autocomplete Autocomplete;
    10.  
    11.         [SerializeField]
    12.         public InputField Input;
    13.  
    14.         [SerializeField]
    15.         public int Index = -1;
    16.  
    17.         protected void Start()
    18.         {
    19.             Input.onEndEdit.AddListener(Validate);
    20.         }
    21.  
    22.         protected void OnDestroy()
    23.         {
    24.             Input.onEndEdit.RemoveListener(Validate);
    25.         }
    26.  
    27.         protected void Validate(string value)
    28.         {
    29.             Index = Autocomplete.DataSource.IndexOf(value);
    30.  
    31.             if (Index == -1)
    32.             {
    33.                 // reset value
    34.                 Input.text = string.Empty;
    35.  
    36.                 // or return focus
    37.                 //Input.ActivateInputField();
    38.                 //Input.Select();
    39.             }
    40.         }
    41.  
    42.         // use this function with a button to show ListView with all values
    43.         public void ShowOptions()
    44.         {
    45.             Input.ActivateInputField();
    46.             Input.Select();
    47.             Input.onValueChange.Invoke(string.Empty);
    48.         }
    49.     }
    50.  
     
  19. gregdetre

    gregdetre

    Joined:
    Sep 9, 2019
    Posts:
    2
    Brilliant! Thank you very much indeed.

     
  20. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    898
    Hi @ilih
    Drag Drop components uses fixed offset, but there are different mobile devices with different ppis/dpis and screen sizes. So how can i provide an offset so dragable item always appear above finger.
    Thanks
     
  21. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    705
    You can modify DragInfo gameobject moving content objects (Icon, Text) into a new gameobject (Background on the screenshot) and then use a separate script to set its position like offset.
    Drag components offset can be set to 0 to simplify calculations.

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class CustomDragInfoOffset : MonoBehaviour
    4. {
    5.     public RectTransform ActualDragInfo;
    6.  
    7.     protected void Start()
    8.     {
    9.         // offset should be calculated based on screen size and/or dpi
    10.         var offset = new Vector2(
    11.             0f,
    12.             Screen.dpi / 2f // half-inch offset to the top
    13.         );
    14.         ActualDragInfo.anchoredPosition = offset;
    15.     }
    16. }
    Another way is the script to modify Drag component offset, but you will need to create the script for each Drag script instead of the single script.
     
    Last edited: Nov 5, 2019
    jGate99 likes this.
  22. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    898
    Thanks for your detailed reply, i have more question regarding code
    Can you please explain how Screen.dpi/2f represents half inch?
    Does it mean Screen.dpi/1 will always be 1 inch?
    Thanks
     
  23. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    705
    DPI is dots per inch (pixels per inch), so divide on 2 it will be the half inch. For example, if dpi is 96 and 48 will be half-inch of physical screen size.
    It's applied only if you use CanvasScaler with Constant Pixel Size.

    And another way: you can use CanvasScaler with Constant Physical Size, so UI elements size and positions specified in physical units instead of the pixels.
     
    jGate99 likes this.
  24. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    898
    Now i understand, sorry for my stupid question
    thank you very much