Search Unity

  1. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    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:
    1,048
    @ilih
    Getting following error in Unity 2020.1a3 if i set a null dataSource.
    please advise Capture.PNG
     
  2. ilih

    ilih

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

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    808
    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.
  4. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,048
    Thank you very much :)
     
  5. ossang

    ossang

    Joined:
    Aug 2, 2018
    Posts:
    6
    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.
     
  6. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    808
    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. }
     
  7. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    808
    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.
  8. 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?
     
  9. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    808
    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.
  10. ossang

    ossang

    Joined:
    Aug 2, 2018
    Posts:
    6
    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.
     
  11. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    808
    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.
  12. Petskus

    Petskus

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

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    808
    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.
  14. 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
  15. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    808
    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.  
     
  16. gregdetre

    gregdetre

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

     
  17. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,048
    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
     
  18. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    808
    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.
  19. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,048
    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
     
  20. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    808
    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.
  21. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,048
    Now i understand, sorry for my stupid question
    thank you very much
     
  22. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    808
    v1.11.1 released

    Changelog:
    • added AutocompleteCombobox
    • ListView: fixed scrolling bug with variable size list types
    • Notify: renamed AnimationRotate to AnimationRotateVertical, AnimationCollapse to AnimationCollapseVertical
    • Notify: added animations AnimationRotateHorizontal, AnimationCollapseHorizontal, AnimationSlideRight, AnimationSlideLeft, AnimationSlideUp, AnimationSlideDown
    • Notify: added configurable animations AnimationRotateBase, AnimationCollapseBase, AnimationSlideBase
    • Resizable: added OnResize event
    • Splitter: added OnResize event
    • Tabs: added SelectedTabIndex property
     
    hopeful and jGate99 like this.
  23. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,048
    Just noticed UI Widgets now have Top Rated Tag, Congrats, its well deserved.
     
  24. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    808
    Thanks.
    It takes a time to figure where is this badge: "Top Rated " badge displayed randomly on some visits (I think this is A/B testing by Assetstore team, tried open page in incognito mode until badge displayed), so it is not a permanent feature for now.
     
    jGate99 likes this.
  25. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,048
    for me its appearing in search
    Capture.PNG
     
    ilih likes this.
  26. Maggi1417

    Maggi1417

    Joined:
    Jul 8, 2017
    Posts:
    1
    I just updated my UI Widget Asset to fix the ListView Scrolling Bug and now I have 84 errors saying "The type or namespace name 'TMPro' could not be found". TextmeshPro 1.3.0 is in the packages. How do I fix this?
     
  27. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    808
    Please open then menu "Project Settings... / New UI Widgets", disable TextMesh Pro support and then enable it back.

    New UI Widgets use Assembly Definitions and TextMesh Pro support requires TMPro reference in .asmdef files but the update overwrites .asmdef files so reference should be added again.
    I'll try to find a way to automatically add TMPro reference after update without manual disable/enable.
     
  28. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,048
    @ilih,
    im using a generic class for all uGUI controls and use where TControl:selectable
    because it has interactable property and all ugui controls are selectable.

    However Your components (especially ComboBox, ListView) etc even though has all the properties of selectable but doesnt use Selectable, is there any reason?

    Please advise

    ------

    Update 2:
    Never mind, i seen that Selectable has a lot of extra code unnecessary for UIWidgets
     
    Last edited: Nov 24, 2019
  29. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    808
    Because of the navigation.
    Users can use not only a mouse or touch but also a keyboard and gamepad which use the navigation to toggle between widgets/controls, and any gameobject with the Selectable component are possible to select.
    But selectable object does not have much meaning if it does not have any interaction (ListView items can be selected/deselected/highlighted, but ListView self does not any interaction) and difficult to create default good navigation between nested selectable components.

    It is always possible to add the Selectable component to the widget if it really needed, but hard to do disable if its a base class.

    You can check the navigation scheme if navigation visualize is enabled on any selectable component in the Inspector window.
     
    jGate99 likes this.
  30. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,048
    @ilih

    I have one feature request which can improve performance a lot.

    I'm building a game where there are lot of comboboxes that show same data (So same typed classes).
    Now problem is each combobox has its own listview which is fine if you are using one combobox or unique comboboxes.

    But'it'd be really great if we can point a single listview for multiple same typed comoboxes because at the same time only one will open. This is partially possible but positioning is not automated. This way we can improve performance a lot.

    Thanks
     
  31. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    808
    I'll think about it, but this work only if same type and same data with the same selected items.
     
    jGate99 likes this.
  32. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,048
    DataProviders will be different however everything else will be same

    For example, lets suppose i have a ItemClass{
    id,
    Title
    }

    and i have 3 dropdowns, all 3 are based on it.
    User will open one at a time so seee one listview at a time but that list view will show data provider and selection based on that clicked combobox.

    Its just like recycled virtualized items in a list view, BUT this time whole listview is reused between same comboboxes (with their own data providers)
     
  33. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,048
    @ilih,

    I have a list control and listening to OnSelect and OnDesect.
    I select first item, i get OnSelectEvent
    Then i set a new DataProvider, so no items are selected anymore
    But i dont get OnDeselct Event.

    Please advise
     
  34. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    808
    OnDeselect event not raised because data are replaced and the index of the deselected item will not match with actual item data or does not have any data at all.
    Correct way is deselecting all items before replacing data:
    Code (CSharp):
    1. ListView.SelectedIndices.ForEach(ListView.Deselect);
    2. ListView.DataSource = new_data;
     
    jGate99 likes this.
  35. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,048
    @ilih,
    How can i know if there are any dialogs currently open?
    Ideally a static field like Dialgs.OppenedDialogsCount
     
    Last edited: Nov 30, 2019
  36. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    808
    Code (CSharp):
    1. var opened_dialogs = FindObjectsOfType<Dialog>().Length;
    Warning: this is very slow and not recommended to use every frame.

    Probably add this in the next update.
     
    jGate99 likes this.
  37. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,048
    Hi @ilih,
    How can i disable highlight on group list group component.
    Thanks
     
  38. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    808
    You need to override HighlightColoring method in your ListView class:
    Code (CSharp):
    1.         protected override void HighlightColoring(GroupedListViewComponent component)
    2.         {
    3.             var is_group = (component != null) && (DataSource[component.Index] is GroupedListGroup);
    4.             if (is_group) // skip highlight if group item
    5.             {
    6.                 return;
    7.             }
    8.  
    9.             base.HighlightColoring(component);
    10.         }
    GroupedListViewComponent and GroupedListGroup should be replaced with your classes.
     
    jGate99 likes this.
  39. Straafe

    Straafe

    Joined:
    Oct 15, 2012
    Posts:
    64
    I have a custom simple data class that only contains some public string fields. If I then make a list of this class, what's the quickest/easiest way to display that data as a table using this asset?
     
  40. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    808
    Widgets generation: right-click on the file with data class to open the context menu then Create / New UI Widgets / Generate Widgets.
    After this you can create the widgets from asset menu or context menu in a hierarchy window: UI / New UI Widgets - DataClassName / Table
     
  41. Straafe

    Straafe

    Joined:
    Oct 15, 2012
    Posts:
    64

    The "Generate Widgets" is greyed out for me. I created a new data class by itself in its own file, and even on that it is greyed out. The class only contains a few public string fields. Tried one that inherits from monobehavior, and one that does not. Do I need to do anything special when creating the data class?

    Using 2019.1.8f1

    https://i.imgur.com/aATcuDQ.png



     
  42. Straafe

    Straafe

    Joined:
    Oct 15, 2012
    Posts:
    64
    Hey @ilih - not sure what I did wrong the first time. I made a new file with another test class and it worked this time. My original file which contains a nearly identical data class still has that option greyed out, but if I copy paste it into a brand new file it will allow me to create the widget which should work fine for me.
     
  43. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    808
    Because of this:
    Widgets generation does not work with classes derived from
    UnityEngine.Object
    with exception of classes derived from
    ScriptableObject
    .
    Since classes derived from UnityEngine.Object cannot be created directly (like
    var a = new SomeClass();
    ), only with
    gameobject.AddComponent<SomeClass>()
    , so this a bad choice to use them as data class and I decide to disable generation for such classes.

    I'll replace the disabled option with an additional confirmation window for such cases in the next update.
     
    Last edited: Dec 9, 2019
  44. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,048
    Hi @ilih,
    I'm creating DefaultItem on runtime based on data which works fine without any issues.

    However i today added support for drag drop and now listview doesnt show items even though it creates them as inactive. I disabled first DropSupport and then DragSupport and found out issue is due to DragSupport.

    One reason in my mind is that DragSupport take current listview as input, and because on runtime when i instantiate a copy of DefaultItem which dont have a listview instance is somehow causing this issue.

    please advise
     
  45. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    808
    Probably you use DefautItem as DragSupport.DragInfo field, like this:
    Code (CSharp):
    1. ListView.DefaultItem = runtime_created_item;
    2. var drag_support = ListView.DefaultItem.gameobject.AddComponent<YourDragSupport>();
    3. drag_support.DragInfo = runtime_created_item; // here is problem
    4. // or
    5. drag_support.DragInfo = ListView.DefaultItem; // same problem
    DragInfo is gameobject used to display data of the dragged item and it's cannot be the same instance as DefaultItem.
    Вuring instantiation DragInfo of the created item reference to DefaultItem will be replaced with reference to the item itself, and then gameobject will be automatically disabled because dragged data should be displayed only during the drag.

    You need to create the copy of the DefaultItem and use it:
    Code (CSharp):
    1. drag_support.DragInfo = Instantiate(runtime_created_item, rootCanvas.transform);
     
    jGate99 likes this.
  46. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,048
    This solved the problem thanks.

    However now i have a different problem, my listview has quite big defaultitems typically 1.5 items appear in listview which means drag drop doesnt work as expected. I increased the size on provided sample and was able to reporduce the same issue. For example if you drag first item and try to replace its position with 2nd it wont work
    Please advise

    Capture.PNG
     
  47. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    808
    ListView does not support items reordering if enabled ListView.Sort, you need to disable it for reordering.
    Because when items order changed, it will be restored with sorting.

    So maybe you set DataSource.Comparison or enabled ListView.Sort with specified ListView.SortFunc.
     
    jGate99 likes this.
  48. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,048
    Actually this problem can be seen in even "ListViewIcons" if you increase defaultitem height so only 1 and another half item is visible, then dragging 1st item to 2nd item to replace position will not work.
     
  49. ilih

    ilih

    Joined:
    Aug 6, 2013
    Posts:
    808
    Index (position) of the dropped item is determined by a cursor/pointer: if the cursor is over the top half of the item, then dragged item will be added before if; if over cursor over the bottom half of the item then dragged item will be added after it.

    You can change this overriding
    GetNearestIndex(Vector2 point)
    function in your ListView class:
    Code (CSharp):
    1.         public override int GetNearestIndex(Vector2 point)
    2.         {
    3.                 if (IsSortEnabled())
    4.                 {
    5.                     return -1;
    6.                 }
    7.  
    8.                 var pos = IsHorizontal() ? point.x : -point.y;
    9.                 var size = (IsHorizontal() ? ItemSize.x : ItemSize.y) + LayoutBridge.GetSpacing();
    10.                 // CeilToInt to add after item under cursor
    11.                 // FloorToInt to add before item under cursor
    12.                 // RoundToInt to add by top/bottom item half under cursor;
    13.                 var index = Mathf.CeilToInt(pos / size);
    14.  
    15.                 return Mathf.Min(index, DataSource.Count);
    16.         }
     
    Last edited: Dec 20, 2019
    jGate99 likes this.
  50. jGate99

    jGate99

    Joined:
    Oct 22, 2013
    Posts:
    1,048
    Hi @ilih
    Currently drag and drop works over whole iteam which means now if we want to scroll the list, we are forced to use scroll bar. In ionic you can actually define a area which becomes dragable and rest of the item remains as usual.
    https://ionicframework.com/docs/api/reorder

    Can you please add a feature like this? So we can only drag items from a handle .
     
unityunity