Search Unity

Optimized ScrollView Adapter + Playmaker support

Discussion in 'Assets and Asset Store' started by xucian, Apr 1, 2016.

  1. xucian

    xucian

    Joined:
    Mar 7, 2016
    Posts:
    846
    Hey,

    As you'll see in the GridExample, you can store the data inside your main class implementation, not only in parameters.
    And in case of grids, it's easier to do it this way.
    Take a look there. Most of that code is pretty general and will apply to most cases. Just use SimpleDataHelper, if you have less than 10k items, as it's more straightforward.
     
    justtime likes this.
  2. xucian

    xucian

    Joined:
    Mar 7, 2016
    Posts:
    846
    Version 4.3 has just been released!
    It includes several improvements and 4 more demo scenes.
    Check the release notes! :D
     
    justtime likes this.
  3. justtime

    justtime

    Joined:
    Oct 6, 2013
    Posts:
    424
    Hi! My grid prefab uses a lot of vertical and hor. groups, and due to performance goals, i want to disable them after creating VH's. Now i'am just disable them in UpdateViews, may be there is more suitable place for this kind of operations?


    Also, my prefab has a lot of text and image components, and while scrolling via sria grid it produces a lot of prefomance spikes
     
    Last edited: Mar 26, 2019
  4. xucian

    xucian

    Joined:
    Mar 7, 2016
    Posts:
    846
    Hi,
    In case of a grid, you can do any changes you want inside your cell prefab. Since the disabling is done only once, do it in CreateViewsHolder (in pre v4.3) by iterating through all the cells in the newly created group or in OnCellViewsHolderCreated (in v4.3+)

    If you're referring to the cell group prefab's LayoutGroup (that is created internally by OSA), that one is certainly needed and can't be disabled.

    Regarding the performance spikes, I don't see any in your screenshot that are caused by OSA. EditorOverhead is something else.

    Lucian
     
    justtime likes this.
  5. justtime

    justtime

    Joined:
    Oct 6, 2013
    Posts:
    424
    Hi! Does it possible to add OSAHierarchyStickyHeader possibilities without rewriting base Adapter? It need a lot of rewriting my base model to IHierarchyNodeModel and other.
     
  6. xucian

    xucian

    Joined:
    Mar 7, 2016
    Posts:
    846
    IHierarchyNodeModel and related were needed so that the sticky header script could communicate with the hierarchy adapter, but they may be expanded in the future to be used for other purposes.

    This I don't know, since I don't know your exact implementation. You'll need to compare your code with the one in the provided example scene. Also see the objects in scene to know where to put the sticky header script
     
  7. justtime

    justtime

    Joined:
    Oct 6, 2013
    Posts:
    424
    Can i dynamically change grid cell size with instantly grid layout rebuilding?
     
  8. marcosocram

    marcosocram

    Joined:
    Jan 14, 2017
    Posts:
    3
    Hello, Im trying to implement Expand Collapse On Click, dont know what Im doing wrong. Im using "SimpleItemPrefab". Here is my Class:


    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. using UnityEngine.UI;
    6. using frame8.Logic.Misc.Other.Extensions;
    7. using Com.TheFallenGames.OSA.Core;
    8. using Com.TheFallenGames.OSA.CustomParams;
    9. using Com.TheFallenGames.OSA.DataHelpers;
    10. using Com.TheFallenGames.OSA.Util;
    11.  
    12.     public class BasicListAdapter : OSA<BaseParamsWithPrefab, MyListItemViewsHolder>, ExpandCollapseOnClick.ISizeChangesHandler
    13.     {
    14.  
    15.         public SimpleDataHelper<RoomID> Data { get; private set; }
    16.  
    17.         private DBManager dbManager;
    18.  
    19.         #region OSA implementation
    20.  
    21.         protected override void Awake()
    22.          {
    23.              dbManager = FindObjectOfType<DBManager>();
    24.          }
    25.  
    26.         protected override void Start()
    27.         {
    28.             Data = new SimpleDataHelper<RoomID>(this);
    29.  
    30.             // Calling this initializes internal data and prepares the adapter to handle item count changes
    31.             base.Start();
    32.  
    33.             // Retrieve the models from your data source and set the items count
    34.             RetrieveDataAndUpdate();  
    35.         }
    36.  
    37.         protected override MyListItemViewsHolder CreateViewsHolder(int itemIndex)
    38.         {
    39.             var instance = new MyListItemViewsHolder();
    40.  
    41.             instance.Init(_Params.itemPrefab, itemIndex);
    42.             instance.expandOnCollapseComponent.nonExpandedSize = 2f;
    43.  
    44.             return instance;
    45.         }
    46.  
    47.         protected override void UpdateViewsHolder(MyListItemViewsHolder newOrRecycled)
    48.         {      
    49.             RoomID model = Data[newOrRecycled.ItemIndex];
    50.             newOrRecycled.titleText.text = model.RoomName;
    51.  
    52.             if (newOrRecycled.expandOnCollapseComponent)
    53.             {
    54.                 newOrRecycled.expandOnCollapseComponent.expanded = model.expanded;
    55.                 newOrRecycled.expandOnCollapseComponent.nonExpandedSize = model.nonExpandedSize;
    56.             }
    57.         }
    58.  
    59.         // This is the best place to clear an item's views in order to prepare it from being recycled, but this is not always needed,
    60.         // especially if the views' values are being overwritten anyway. Instead, this can be used to, for example, cancel an image
    61.         // download request, if it's still in progress when the item goes out of the viewport.
    62.         // <newItemIndex> will be non-negative if this item will be recycled as opposed to just being disabled
    63.         // *For the method's full description check the base implementation
    64.         protected override void OnBeforeRecycleOrDisableViewsHolder(MyListItemViewsHolder inRecycleBinOrVisible, int newItemIndex)
    65.         {
    66.             base.OnBeforeRecycleOrDisableViewsHolder(inRecycleBinOrVisible, newItemIndex);
    67.         }
    68.        
    69.         #endregion
    70.  
    71.         // These are common data manipulation methods
    72.         // The list containing the models is managed by you. The adapter only manages the items' sizes and the count
    73.         // The adapter needs to be notified of any change that occurs in the data list. Methods for each
    74.         // case are provided: Refresh, ResetItems, InsertItems, RemoveItems
    75.         #region data manipulation
    76.         public void AddItemsAt(int index, IList<RoomID> items)
    77.         {
    78.             // Commented: the below 2 lines exemplify how you can use a plain list to manage the data, instead of a DataHelper, in case you need full control
    79.             //YourList.InsertRange(index, items);
    80.             //InsertItems(index, items.Length);
    81.  
    82.             Data.InsertItems(index, items);
    83.         }
    84.  
    85.         public void RemoveItemsFrom(int index, int count)
    86.         {
    87.             // Commented: the below 2 lines exemplify how you can use a plain list to manage the data, instead of a DataHelper, in case you need full control
    88.             //YourList.RemoveRange(index, count);
    89.             //RemoveItems(index, count);
    90.  
    91.             Data.RemoveItems(index, count);
    92.         }
    93.  
    94.         public void SetItems(IList<RoomID> items)
    95.         {
    96.             // Commented: the below 3 lines exemplify how you can use a plain list to manage the data, instead of a DataHelper, in case you need full control
    97.             //YourList.Clear();
    98.             //YourList.AddRange(items);
    99.             //ResetItems(YourList.Count);
    100.  
    101.             Data.ResetItems(items);
    102.         }
    103.         #endregion
    104.  
    105.  
    106.         void RetrieveDataAndUpdate()
    107.         {
    108.             StartCoroutine(FetchMoreItemsFromDataSourceAndUpdate());
    109.         }
    110.  
    111.         IEnumerator FetchMoreItemsFromDataSourceAndUpdate()
    112.         {
    113.             List<RoomID> roomsInfo = new List<RoomID>();
    114.  
    115.             roomsInfo = dbManager.GetRoomsDB(roomsInfo);
    116.             yield return new WaitUntil(dbManager.DBBussy);
    117.            
    118.             Debug.Log("newItems.Count: " + roomsInfo.Count);
    119.             OnDataRetrieved(roomsInfo);
    120.         }
    121.  
    122.         void OnDataRetrieved(List<RoomID> roomsInfo)
    123.         {
    124.             Data.InsertItemsAtEnd(roomsInfo);
    125.         }
    126.  
    127.         #region ExpandCollapseOnClick.ISizeChangesHandler implementation
    128.         bool ExpandCollapseOnClick.ISizeChangesHandler.HandleSizeChangeRequest(RectTransform rt, float newSize)
    129.         {
    130.             var vh = GetItemViewsHolderIfVisible(rt);
    131.  
    132.             // If the vh is visible, we update our list of sizes
    133.             if (vh == null)
    134.                 return false;
    135.  
    136.             RequestChangeItemSizeAndUpdateLayout(vh, newSize, true);//_Params.freezeItemEndEdgeWhenResizing
    137.  
    138.             return true;
    139.         }
    140.  
    141.         public void OnExpandedStateChanged(RectTransform rt, bool expanded)
    142.         {
    143.             var vh = GetItemViewsHolderIfVisible(rt);
    144.  
    145.             // If the vh is visible and the request is accepted, we update the model's "expanded" field
    146.             if (vh != null)
    147.                 Data.List[vh.ItemIndex].expanded = expanded;
    148.         }
    149.         #endregion
    150.     }
    151.  
    152.     public class RoomID
    153.     {
    154.         public string RoomName { get; set; }
    155.         public string RoomDBName { get; set; }
    156.         public int DBRowIDNumber { get; set; }
    157.         public bool expanded { get; set; }
    158.         public float nonExpandedSize { get; set; }
    159.     }
    160.  
    161.  
    162.     public class MyListItemViewsHolder : BaseItemViewsHolder
    163.     {
    164.         public Text titleText;
    165.         internal ExpandCollapseOnClick expandOnCollapseComponent;
    166.  
    167.         public override void CollectViews()
    168.         {
    169.             base.CollectViews();
    170.  
    171.             // GetComponentAtPath is a handy extension method from frame8.Logic.Misc.Other.Extensions
    172.             // which infers the variable's component from its type, so you won't need to specify it yourself
    173.             root.GetComponentAtPath("TitleText", out titleText);
    174.             expandOnCollapseComponent = root.GetComponent<ExpandCollapseOnClick>();
    175.         }
    176.     }
    177.  
     
  9. xucian

    xucian

    Joined:
    Mar 7, 2016
    Posts:
    846
    Generally, yes. The solution depends on:
    0. how many cells do you change at once
    1. what size do you change (width, height, ratio based on width, ratio based on height etc.)
    2. based on what do you choose the respective size
    3. when or how often should it happen

    Hey,

    What behavior do you get? Can you show me a gif/video? Or maybe just describe it in words.
    I'll respond tomorrow, but in the meanwhile make sure you're doing exactly the same as in the "example.unity" scene, regarding the expand/collapse behavior, if you're using a version older than 4.3.
    If you're using OSA v4.3, ignore the ExpandCollapseOnClick and go straight to look at the "expand_item_to_variable_size.unity" scene and its associated scripts, as most of the time users want to expand to an unknown and/or variable size, and that example does exactly that. It also handles the expand/collapse animation more elegantly.

    See you soon
    --Lucian
     
  10. justtime

    justtime

    Joined:
    Oct 6, 2013
    Posts:
    424
    0. 4 - 16 depends on screen size
    1.width and height
    2.Based on viewport size. Like 2 middle or 1 big in row, or 4 middle or 2 big and so on
    3.when player selects which size is more suitable, so it's rare

    BTW, does it possible to make Cell prefab without "Views" inner parent?
     
    Last edited: Mar 28, 2019
  11. marcosocram

    marcosocram

    Joined:
    Jan 14, 2017
    Posts:
    3

    Thanks, Lucian, problem solved: I updated the asset and implemented "example.unity" :D I didn't have all the examples until I opened the Demos scene and all of them downloaded.
     
    xucian likes this.
  12. justtime

    justtime

    Joined:
    Oct 6, 2013
    Posts:
    424
    Just faced another problem:
    I need to scroll to 1 element after grid data update
    This is before

    And after a little bit scrolled down


    Code (CSharp):
    1.  SmoothScrollToGroup(0, 0);
     
  13. xucian

    xucian

    Joined:
    Mar 7, 2016
    Posts:
    846
    Alright, so the user initiates the resizing of the viewport, which should lead to resizing of cells. The behavior at #2 is actually the maximum "responsiveness" possible: seeing as much data as possible in the given space, i.e no additional left-right padding should be seen. In this case, if 3 cells of the minimum size fit in the row, they'll be added; if not, then we'll have 2 cells per row which will be slightly sized up so no left and right padding will be seen.
    See an example here and let me know if this is exactly what you meant.
    If yes, then we'll continue on email, where I'll also need your code and the scene.
    If you just want to set a cell size to scale with the viewport, just play with the cell prefab's anchors, and see which is the best setup for your needs. You can just resize the viewport manually in edit mode and see how the prefab scales. That'll be the default size used by the adapter (and it automatically detects the prefab's size changes at runtime, any time the viewport size changes). You can set the prefab's anchors exactly in its corners and it'll scale identically with the viewport. Or you can set them half way (so the rectangle formed by the anchors will be half the prefab's size) and obtain a less sensitive reaction to viewport resizing. :)

    And nope, we need the Views intermediary game object.

    Perfect. Meet me here for more questions :)

    SmoothScrollToGroup isn't that useful for the average case. The "items" internally (from the OSA's perspective) are groups of cells. From the user's (and GridAdapter's) standpoint, the items are the cells inside the groups.
    Use SmoothScrollTo(), which takes the cell's index instead, in case of grid adapters.

    But I don't think you'll get a different result, as a group is just a row in the default configuration, and scrolling to it should be approximately the same as scrolling to any item at it.
    Do you actually want to ask why the last cell in the image is in the middle? You can control the group's gravity in the GridAdapter's inspector, as well as spacing & such.


    --Lucian
     
    justtime likes this.
  14. justtime

    justtime

    Joined:
    Oct 6, 2013
    Posts:
    424
    Hi there! Could you help me to achieve this effect via "gallery effect" ? I mean when prev and next are middle aligned.
    Also, should i use PercentageContentPadding when looping ? Thanks
     
    Last edited: Apr 6, 2019
  15. xucian

    xucian

    Joined:
    Mar 7, 2016
    Posts:
    846
    Hey,

    Yes, you need to set the gallery effect pivots to .5 and.5 in inspector. Also gravity to center.

    An no, it'll probably lead to problems if you use that script when looping, because in that case there's no concept of start\end (right\left, in your case) padding, because there's always an item before and after every item.
    If however you can have fewer items than what's needed to fill the viewport, you have 2 options:
    1. Enable\disable looping on count change, based on the content-to-viewport ratio. Let's say if content is less than 1.3x the viewport's size, you disable looping.
    You can retrieve this ratio using the extensions in IScrollRectProxy.cs.
    You should choose a threshold ratio in a way that will always keep at least 1 item out of view.
    2. Duplicate your models. For example, if you'll always (on all screens) have a max number of 10 items visible, then just duplicate your models whenever the count changes to something smaller than that: if resetting to count 8, reset it to 16 instead (but also have 16 models in your backing list). If using DatalHeper, this translates to adding 16 models at once - create an intermediary list which contains 8 models, then another 8, their duplicates. then DataHelper.ResetItems(thatList).

    Find additional info at #4 in the Manual's FAQ.

    Hope this helps

    --Lucian
     
    justtime likes this.
  16. LordBelasco

    LordBelasco

    Joined:
    May 1, 2017
    Posts:
    29
    Hi,

    Why don't you make the data migration for MaxCellsPerGroup breaking change ? So I need to reopen and modify all my grids
    The data were stored two times in the scene files, you removed one, it's good, but now I don't which data is good
    exemple :
    grid:
    _MaxCellsPerGroup: -1
    _UseDefaulfItemSizeForCellGroupSize: 0
    cellPrefab: {fileID: 224863401805302290, guid: 3e5e446716d16d24eb0ccf839c7de65d,
    type: 3}
    alignmentOfCellsInGroup: 4
    spacingInGroup: 0
    groupPadding:
    m_Left: 0
    m_Right: 0
    m_Top: 0
    m_Bottom: 0
    cellWidthForceExpandInGroup: 1
    cellHeightForceExpandInGroup: 1
    _MaxCellsPerGroup: 2
    _CellPrefab: {fileID: 0}
    _AlignmentOfCellsInGroup: 0
    _SpacingInGroup: -1
    _GroupPadding:
    m_Left: 0
    m_Right: 0
    m_Top: 0
    m_Bottom: 0
    _CellWidthForceExpandInGroup: 0
    _CellHeightForceExpandInGroup: 0

    For _CellWidthForceExpandInGroup: 0 and cellWidthForceExpandInGroup, I get 2 data, and one was removed, the good or not ??
     
  17. xucian

    xucian

    Joined:
    Mar 7, 2016
    Posts:
    846
    The GridParams._MaxCellsPerGroup was a leftover from the previous migration code (from v3.2 to v4.1).
    v3.2 to v4.1 was a major migration. Now the top-level _MaxCellsPerGroup would have no use and it'd even be confusing, that's why it was removed. Better sooner or later.

    Do a backup first. Then see the 2 solutions:

    1.
    Before upgrading, add this code, open each scene and execute the menu item, then remove the code:

    Code (CSharp):
    1.         [UnityEditor.MenuItem("Tools/OSA/Migrate all _MaxCellsPerGroup in scene")]
    2.         static void MigrateMaxCellsPerGroup()
    3.         {
    4.             var objs = Resources.FindObjectsOfTypeAll(typeof(UnityEngine.GameObject));
    5.             string migrationResult = "Migrated: ";
    6.             foreach (var ob in objs)
    7.             {
    8.                 var go = ob as GameObject;
    9.                 var osa = go.GetComponent(typeof(IOSA)) as IOSA;
    10.                 if (osa == null)
    11.                     continue;
    12.  
    13.                 var p = osa.BaseParameters as GridParams;
    14.                 if (p == null)
    15.                     continue;
    16.  
    17.                 if (p.grid == null)
    18.                     p.grid = new GridConfig();
    19.                 p.grid.MaxCellsPerGroup = p._MaxCellsPerGroup;
    20.  
    21.                 migrationResult += go.name + ", ";
    22.             }
    23.             Debug.Log(migrationResult);
    24.         }
    2.
    The other way is to just do it at runtime. Open an empty scene, import the new package and:
    - add back the "[SerializeField] int _MaxCellsPerGroup" in GridParams
    - inside GridParams.InitIfNeeded, set grid.MaxCellsPerGroup = _MaxCellsPerGroup
    This way you don't need to open all of the scenes, but it just delays the trouble, it doesn't resolve it.

    I understand it's not convenient, but migrations can't always be seamless. There are always trade-offs.

    Let me know if you solved it

    --Lucian
     
  18. LordBelasco

    LordBelasco

    Joined:
    May 1, 2017
    Posts:
    29
    First I need to search in VS the string _MaxCellsPerGroup to find my grids in .unity files
    In this case I think that I will do the change manually in VS

    For all others property, like cellWidthForceExpandInGroup and _CellHeightForceExpandInGroup, spacingInGroup, m_Left...
    they were stored twice, a part is deleted after migration. The deleted values was unused ? No data will be lost, no migration required ?
     
  19. xucian

    xucian

    Joined:
    Mar 7, 2016
    Posts:
    846
    I don't think I understand what you mean exactly. _MaxCellsPerGroup is private, so you'll only find it in GridParams.cs. I think you meant the property MaxCellsPerGroup, right?
    This property was removed specifically so it'll give you a compile-time error when you upgrade from 4.2, so you could have a chance to modify any programmatic accesses to it before the first compilation happens with v4.3

    Those ones (except one, see below) weren't used at all. They were only serialized, but hidden in inspector to allow the 3.2 to 4.2 migration.
    The exception is _CellPrefab, but this was a bug, because it shouldn't have been used either. However, it was used only if you didn't set neither of the cells' preferred or min size, but set the flexible size (which is rarely the case, as users usually need a preferred or min size set), and even then, it should've caused a NPE in your v4.2 code. If it didn't, then you won't be affected

    --Lucian
     
  20. LordBelasco

    LordBelasco

    Joined:
    May 1, 2017
    Posts:
    29
    After installing the the release 4.3, Git shows me that some scene files has changed, so I have compared before/after.
    The properties changed that I copied above, are the serialization in the .unity files
    So I can change the properties directly in the scene files opened in VS, it's simple text files. So I can copy the serialized value from a property to another.
    In the scene file opened as text, I see cellWidthForceExpandInGroup and _CellHeightForceExpandInGroup, spacingInGroup, m_Left... and a part is deleted when the scene is opened in Untiy, so I see it by Git in VS. And I'd to be sure that the removed serialized properties was unused
    I prefer to modify scene files opened as text file in VS, to compare exactly what have changed ;)
     
  21. xucian

    xucian

    Joined:
    Mar 7, 2016
    Posts:
    846
    I see.

    I'm doing the same with my projects.

    --Lucian
     
  22. LordBelasco

    LordBelasco

    Joined:
    May 1, 2017
    Posts:
    29
    So, except the for _MaxCellsPerGroup, can you confirm that all others serialized properties removed in the scene by this release was unused ?
    so this properties :
    _CellPrefab: {fileID: 0}
    _AlignmentOfCellsInGroup: 0
    _SpacingInGroup: -1
    _GroupPadding:
    _CellWidthForceExpandInGroup: 0
    _CellHeightForceExpandInGroup: 0
    could be deleted without migration ?
     
  23. xucian

    xucian

    Joined:
    Mar 7, 2016
    Posts:
    846
    Confirmed. I described the situation here.
    You can also check this directly in v4.2 by just using VS's 'Find All References' for each of them and you'll see they're not referenced anywhere.

    -- Lucian
     
  24. justtime

    justtime

    Joined:
    Oct 6, 2013
    Posts:
    424
    Hi! Is it possible to make items in horizontal view with certain height, not to container height?
     
  25. xucian

    xucian

    Joined:
    Mar 7, 2016
    Posts:
    846
    Hi,

    I'm assuming we're talking about a horizontal list (for grids it's different). So speaking in the context of what happens across different screen sizes:
    a) If you want a constant top/bottom space, use the top/bottom padding setting in the inspector.
    Done.

    b) If you want a constant item height, it's not available out of the box - for example, it should be exposed as a property in inspector. Even though it's something basic, I always forgot to do it. Will be there in the next minor update.
    Until then, do the following:
    1. Create this, which sets _Params.padding.top and bottom to half the available space:
    Code (CSharp):
    1.      
    2. void UpdateTransversalPadding()
    3. {
    4.    // For horizontal lists, height is the transversal size
    5.    float itemTransversalSize = _Params.itemPrefab.rect.height;
    6.    float viewportTransfersalSize = _Params.Viewport.rect.height;
    7.    float availableSpace = Mathf.Max(0f, viewportTransfersalSize - itemTransversalSize);
    8.    var padding = _Params.ContentPadding;
    9.    padding.bottom = padding.top = (int)(availableSpace / 2f);
    10. }
    11.  
    2. Override Start() and call it before base.Start()
    Code (CSharp):
    1.      
    2. protected override void Start()
    3. {
    4.    UpdateTransversalPadding();
    5.  
    6.    base.Start();
    7. }
    8.  
    If you initialize your adapter manually via Init(), just call UpdateTransversalPadding() before that instead.

    3. Override RebuildLayoutDueToScrollViewSizeChange() and do the same, so the padding will remain responsive should the viewport's size change at runtime:
    Code (CSharp):
    1.  
    2. protected override void RebuildLayoutDueToScrollViewSizeChange()
    3. {
    4.    UpdateTransversalPadding();
    5.  
    6.    base.RebuildLayoutDueToScrollViewSizeChange();
    7. }
    8.  

    --Lucian
     
    justtime likes this.
  26. anil_unity385

    anil_unity385

    Joined:
    Feb 7, 2019
    Posts:
    18
    Hi there, I've been using the plugins and am very happy with it, great work!

    Very simple question. With my scroll view, After I start scrolling my items if the user taps on the screen, it doesn't stop the rect from scrolling unless they also drag up. Is there a setting I can change to make it do this, or do I have to add my own custom code?
     
  27. xucian

    xucian

    Joined:
    Mar 7, 2016
    Posts:
    846
    Hey,

    I'll add this in the next version as a property in inspector.
    Until then, override OSA's OnPointerDown, set Velocity to zero (or call StopMovement()) and then call base.OnPointerDown.
    I didn't test this, so please let me know if it worked and if it affected the normal dragging functionality.

    --Lucian
     
  28. anil_unity385

    anil_unity385

    Joined:
    Feb 7, 2019
    Posts:
    18
    Thanks you for the prompt response! In the OSA.cs class, I can't see an OnPointerDown method to override. Is it kept somewhere else?

    There is a OnInitializePotentialDrag() method, so will try there.

    EDIT: And adding it here works. I just overrode the method and then called StopMovement(), and then base.OnInitializePotentialDrag().

    Thanks!
     
    Last edited: Apr 11, 2019
  29. xucian

    xucian

    Joined:
    Mar 7, 2016
    Posts:
    846
    Right, IPointerDownHandler was long gone, because we needed IInitializePotentialDragHandler instead and unity doesn't call IPointerDownHandler.OnPointerDown correctly if both interfaces implemented (at least in 2018.3).
    Sorry for the mistake.
    I was just about to reply about this, but you were faster. :D
    Thanks!

    Edit: It may be of interest: the reason the velocity isn't cut off when you just press and don't drag is to allow it to accelerate with each subsequent drag. With the above change, you won't be able to do so. There are some ways to achieve both - I'll think about them for the next version.

    --Lucian
     
  30. anil_unity385

    anil_unity385

    Joined:
    Feb 7, 2019
    Posts:
    18
    Thanks again, really appreciate it. The whole thing is very nicely done. Though I am going to warn you that I will be asking you some more questions about some of the example scenes and code in the future :) !
     
  31. justtime

    justtime

    Joined:
    Oct 6, 2013
    Posts:
    424
    Hi! Just catched some bug
    1)Open panel with OSA and looped horizontal list + snapper
    2)Drag list left/right
    3)Close panel via hide and disable GO
    4)Repeat steps 1-3 few times
    5)Open again. Everything is ok, but snapping doesn't work
     
  32. xucian

    xucian

    Joined:
    Mar 7, 2016
    Posts:
    846
    Sure. No problem. :D

    Thanks for finding this!

    I fixed it this way:
    1. Add the OnDisable method to OSA.cs:
    Code (CSharp):
    1.  
    2.         #region Unity methods
    3.         protected virtual void Awake() { }
    4.         protected virtual void OnEnable() { }
    5.         protected virtual void Start() { if (!IsInitialized) Init(); }
    6.         protected virtual void Update() { if (IsInitialized) MyUpdate(); }
    7.         protected virtual void LateUpdate() { if (IsInitialized) MyLateUpdate(); }
    8.         protected virtual void OnDisable() { if (IsInitialized) MyOnDisable(); }
    9.         protected virtual void OnDestroy() { Dispose(); }
    10.         #endregion
    11.  
    2. Add the MyOnDisable somewhere. I'll add it to OSAInternal.cs, below MyLateUpdate:
    Code (CSharp):
    1.  
    2.         void MyOnDisable()
    3.         {
    4.             // Disabling the GameObject or the script should clear the animation coroutines and related
    5.             CancelAnimationsIfAny();
    6.  
    7.             // Bugfix: if the routine is stopped, this is not restored back. Setting it to false is the best thing we can do
    8.             _SkipComputeVisibilityInUpdateOrOnScroll = false;
    9.         }
    10.  

    Edit: If you're using OnDisable/OnEnable in your OSA-derived classes, make sure you're now overriding the OSA's OnDisable/OnEnable (and calling the base methods, of course).
    I'll add a note about this in the next version's release notes.

    --Lucian
     
    Last edited: Apr 11, 2019
    justtime likes this.
  33. anil_unity385

    anil_unity385

    Joined:
    Feb 7, 2019
    Posts:
    18
    Is there a way to snap to a specific element in a grid view? There is a ScrollTo() method, but what is the usage for a grid? If I specify the ID of the element I want to snap to it doesn't always bring the element to view in a consistent manner.
     
  34. xucian

    xucian

    Joined:
    Mar 7, 2016
    Posts:
    846
    Hey,

    1. Are you using v4.3?
    2. What does your grid look like?
    3. Can you describe the inconsistent behaviour you see?

    --Lucian
     
  35. anil_unity385

    anil_unity385

    Joined:
    Feb 7, 2019
    Posts:
    18
    Hey Lucian,

    Yes I am using the latest version. I have a list of 77 items displayed in groups of 3. Let's say for example that I want to scroll to the 24th element in my data set, I assume that I call ScrollTo(23) . However, when I do this, the element I want to display is quite far off screen - it's not even close.

    When I look at my hierarchy I can see that on screen I have 3 OSA_CellGroupPrefab(Clone) objects and each of those have 3 of my custom prefabs in them. So far so good. But I wonder if I have to manually parse through this list of 9 prefabs on screen to call the correct item to scroll to?

    I have used ScrollTo() on a regular ListAdapter class and it works fine, so I imagine I am just not understanding how GridAdapter works?

    I also tried scrolling to (23 / 3) (dividing by number of cells per group) but this did not work either.
     
  36. xucian

    xucian

    Joined:
    Mar 7, 2016
    Posts:
    846
    Thanks for the details.
    Hm, can you see if the example scenes also have this problem?
    Also, do you get the same result with SmoothScrollTo?
    You're doing it right, BTW. You shouldn't worry about the group indices and such.

    --Lucian
     
  37. anil_unity385

    anil_unity385

    Joined:
    Feb 7, 2019
    Posts:
    18
    Ah that's interesting! If I use SmoothScrollTo(element, 0f, 0f, 0f), it actually works. So I will use this for now.
     
  38. Y76_Unity

    Y76_Unity

    Joined:
    Jan 29, 2018
    Posts:
    28
    Hey There :
    i am developing an AR Application with the ability of taking pictures with augmented objects

    and i want to make it fast smooth scroll image gallery that acts like the native device image gallery,

    note : each picture has 150kb size, and i have a huge number of taken pictures and so with captured videos,


    i used another asset called UGUI but it doesn't help
    https://assetstore.unity.com/packages/tools/gui/ugui-super-scrollview-86572
    the scroll gridview still load slow and not as smooth as the native image gallery .
    Please i want some one to confirm if this asset will help,

    my question is :
    Does this asset will solve the problem of loading images with huge size images, and whats the perfect image size that makes it working in perfect way ?

    Thanks in advance
     
  39. xucian

    xucian

    Joined:
    Mar 7, 2016
    Posts:
    846
    Hey,

    ScrollTo and SmoothScrollTo are supposed to work identically, the latter would just do it gradually.
    Can you confirm that if using the same paremeters, ScrollTo and SmoothScrollTo don't jump to the same item?
    Because if so, this is a bug and it'll help me solve it. Problem is I don't get this in the example scenes, so maybe there's something particular to your use case that leads to this. Thanks!

    Hey,
    Loading an individual image from the disk shouldn't differ, because that's Unity's (and Android's/iOS's) part.
    Different device manufacturers have their own image gallery implementation which they've developed in several days I'd assume.
    I think they're using something like first loading a low-q version of the images (and not all at once, they do it in chunks, based on where your scroll position is and possibly in which direction you're currently scrolling) and only after you stare 1-2 seconds at some (i.e. the scroll speed is near zero), only then it actually loads the full size images. This is one way of doing it.
    Another way is to still load images in chunks, but the full images. The chunk size is determined by trial and error to make sure the actual loading of the chunks doesn't block the main thread for too much.
    Another way is to just load the images individually on demand, but whether this would lead to significant FPS drop or not, you can only find this manually - knowing that the images are 150kb, you might have a chance to get away with this solution alone, which is the easiest to implement.
    In any case, you surely need to load images on demand (lazy-initialization) instead of all of them at once. And you'll need a pool where you're storing the most recent ones.

    This is my 2c for loading a lot of images, but it doesn't have anything to do with the ScrollView solution you use, as long as it uses recycling of views.

    -- Lucian
     
  40. justtime

    justtime

    Joined:
    Oct 6, 2013
    Posts:
    424
    Hi Lucian! Is it possible to make some vertical list, which has a visual current active element at the top, and can drug most bottom element to the top. It's like limited looping list, which ends when last element in list is reached.
    For example two images. Look at 3 column, first element at the top, and you can't scroll down anymore.

    This is last element in list, so list moved up until reaches this one.
     
  41. xucian

    xucian

    Joined:
    Mar 7, 2016
    Posts:
    846
    Hey,

    Not something that's implemented in OSA, as it's too specific.
    All of the 3 columns are OSA list views? If so, I don't see any problem with simply removing the item and then adding it back when the "active" item changes.

    If order is important, then just sort the list after each modification before notifying the adapter.
    If using SimpleDataHelper, do the operations on its List property directly, and call NotifyListChangedExternally() on it after, since you only want to update the views after the final step.
    The flow would be:
    0. Have an xSelected variable storing your selected model
    1. Item xNew was clicked
    2. If xSelected is not null, i.e. an item is already selected, add xSelected to the SimpleDataHelper.List
    3. Remove xNew from the SimpleDataHelper.List, set xSelected=xNew and update your header
    4. Sort the list
    5. Call SimpleDataHelper.NotifyListChangedExternally()

    Hope this helped

    --Lucian
     
    justtime likes this.
  42. justtime

    justtime

    Joined:
    Oct 6, 2013
    Posts:
    424
    Thanks, but it should work like a regular scroll, not only change items order on click something.
    Btw here is desirable behavior.
     
    Last edited: Apr 16, 2019
  43. xucian

    xucian

    Joined:
    Mar 7, 2016
    Posts:
    846
    Oh, got it.
    You can use Snapper script with 0 for both ViewportSnapPivot and ItemSnapPivot.

    Snapper has a private method GetMiddleVH() which can give you the viewsHolder that it's snapping to. It's called Middle because initially the snapping could only be done in the middle. I'll need to change that name. You can use this to color the VH accordingly, but you need to keep track of those that are snapped and those that aren't (coloring/un-coloring them).

    As for allowing that space at the end of the list, you can set a bottom padding if the viewport size is constant among screens.
    If not you can use the OSAPercentageContentPaddingSetter script to set the end padding to be a percent of the viewport's height.
    If the itemSize/viewportSize ratio is always the same, you're done: use (1 - itemSize/ViewportSize) for PaddingEndPercent and 0 for PaddingStartPercent.
    If the itemSize/viewportSize ratio is variable (for ex. viewport increases in size, but the item's size doesn't), then this is just a partial solution and I'll think about a better one. Let me know.

    --Lucian
     
  44. justtime

    justtime

    Joined:
    Oct 6, 2013
    Posts:
    424
    I did all of this with datetimepicker and nothing changes (
     
  45. xucian

    xucian

    Joined:
    Mar 7, 2016
    Posts:
    846
    Did you disable the looping? There's no concept of start/end padding on a looping list, so the padding is always set to the spacing automatically if looping is active
     
    justtime likes this.
  46. justtime

    justtime

    Joined:
    Oct 6, 2013
    Posts:
    424
    Yes, i tried different cases
     
  47. justtime

    justtime

    Joined:
    Oct 6, 2013
    Posts:
    424
    Hi! I've played with this a little more, and found a way to get it working =) What i should do in case of the itemSize/viewportSize ratio is variable ?

    Also, what are you thinking about next solution:
    1)I made two additional vars in BaseParams.cs
    Code (CSharp):
    1. [SerializeField]
    2.        bool _DragUpPossible = true;
    3.         public bool DragUpPossible
    4.         {
    5.             get { return _DragUpPossible; }
    6.             set { _DragUpPossible = value; }
    7.         }
    8.  
    9.         [SerializeField] bool _DragDownPossible = true;
    10.  
    11.         public bool DragDownPossible
    12.         {
    13.             get { return _DragDownPossible; }
    14.             set { _DragDownPossible = value; }
    15.         }
    2)Then in OSA.cs in OnDrag method i added
    Code (CSharp):
    1.     if (abstrDeltaInCTSpace > 0d && !_Params.DragUpPossible) // going to start
    2.                 return;
    3.  
    4.             if (abstrDeltaInCTSpace < 0d && !_Params.DragDownPossible) // going to end
    5.                 return;
    6.            
    3)Then in UpdateViewsHolder
    Code (CSharp):
    1. _Params.DragUpPossible = newOrRecycled.ItemIndex != _Params.Data.Count - 1;
    I dont know how to properly handle with DragDownPossible in this place. And there is another issue: if user scroll list too fast, first/last elements flies through, so my new vars doesn't have time to uprgade.
     
    Last edited: Apr 21, 2019
  48. xucian

    xucian

    Joined:
    Mar 7, 2016
    Posts:
    846
    Hi,
    This is similar with the above solution for transversal padding. It's the same concept:
    Code (CSharp):
    1.  
    2.         void UpdateCustomBottomPadding()
    3.         {
    4.             float itemSize = _Params.itemPrefab.rect.height;
    5.             float viewportSize = _Params.viewport.rect.height;
    6.  
    7.             _Params.ContentPadding.bottom = Mathf.RoundToInt(viewportSize - itemSize - _Params.ContentSpacing);
    8.         }
    9.  
    10.         protected override void RebuildLayoutDueToScrollViewSizeChange()
    11.         {
    12.             UpdateCustomBottomPadding();
    13.  
    14.             base.RebuildLayoutDueToScrollViewSizeChange();
    15.         }
    And also call it before initializing the adapter:
    Code (CSharp):
    1.         protected override void Start()
    2.         {
    3.             ...
    4.             UpdateCustomBottomPadding();
    5.  
    6.             base.Start();
    7.         }
    --Lucian
     
  49. justtime

    justtime

    Joined:
    Oct 6, 2013
    Posts:
    424
    Thanks. Will try it, but what do you think about my solution, that i posted above ? It would be more multipurpose without any component settings (i found that it tricky to get it worked, cause it's depending on the settings of viewport and his parents rect transforms). But it seems that check first/last element reached first viewholder in UpdateViewsHolder - wrong idea. May be there is better place for this operation?
     
  50. xucian

    xucian

    Joined:
    Mar 7, 2016
    Posts:
    846
    I now saw you edited your post.
    I don't really see why would you need the OnDrag stuff. And, as you've well noticed, it's not a reliable approach to store an information from UpdateViewsHolder (vhs are recycled constantly).
    Doesn't my solution do what you needed? If you want to prevent the pull/drag to be "elastic", just untick "Elastic Movement" in inspector. Maybe also untick Inertia, if you want an even more rigid dragging

    -- Lucian