Author Topic: Forcing a UIScrollView contents to "spring" to the top when not full  (Read 7946 times)

Prodigga

  • Newbie
  • *
  • Thank You
  • -Given: 1
  • -Receive: 2
  • Posts: 17
    • View Profile
Hey guys. I am trying to make my scroll view 'spring' back to the top of the grid of items it contains (Back to the default resting position) when the scroll view is not full. When the scroll view is not full, you can scroll the objects in the scroll view around freely and they will just hover around wherever you stop dragging them. I want it so that if the player pulls the content down/away from the top, they spring back up there (You can observe this behaviour in the ScrollView if the scroll view is full).

I am trying to create a 'pull to refresh' type feature with my scrollview so for this reason I need the content to 'spring' back up to the top even if the scrollview is not full.

Any ideas?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Forcing a UIScrollView contents to "spring" to the top when not full
« Reply #1 on: June 26, 2014, 11:10:09 AM »
Call ResetPosition() on the scroll view, assuming you set its content origin.

Prodigga

  • Newbie
  • *
  • Thank You
  • -Given: 1
  • -Receive: 2
  • Posts: 17
    • View Profile
Re: Forcing a UIScrollView contents to "spring" to the top when not full
« Reply #2 on: June 26, 2014, 11:26:59 AM »
ResetPosition just snaps it back to the top. I don't want that.


ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Forcing a UIScrollView contents to "spring" to the top when not full
« Reply #3 on: June 26, 2014, 11:37:32 AM »
Have a look inside the RestrictWithinBounds function. It calculates the offset then uses SpringPanel.Begin to move the scroll view into place smoothly. In your case you'd do something similar, based on the distance from the content's top to the scroll view's top instead of CalculateConstrainOffset.

Prodigga

  • Newbie
  • *
  • Thank You
  • -Given: 1
  • -Receive: 2
  • Posts: 17
    • View Profile
Re: Forcing a UIScrollView contents to "spring" to the top when not full
« Reply #4 on: June 26, 2014, 11:57:51 AM »
thanks ill have a look tomorrow at work and get back to you!

Prodigga

  • Newbie
  • *
  • Thank You
  • -Given: 1
  • -Receive: 2
  • Posts: 17
    • View Profile
Re: Forcing a UIScrollView contents to "spring" to the top when not full
« Reply #5 on: June 26, 2014, 08:56:01 PM »
I got it working. For anyone with the same problem, here is what I did:

In UIPanel, replace CalculateConstrainOffset with

  1. public virtual Vector3 CalculateConstrainOffset (Vector2 min, Vector2 max, bool SnapToTopOfGrid = false)
  2.         {
  3.                 Vector4 cr = finalClipRegion;
  4.  
  5.                 float offsetX = cr.z * 0.5f;
  6.                 float offsetY = cr.w * 0.5f;
  7.  
  8.                 Vector2 minRect = new Vector2(min.x, min.y);
  9.                 Vector2 maxRect = new Vector2(max.x, max.y);
  10.  
  11.                 Vector2 minArea = new Vector2(cr.x - offsetX, cr.y - offsetY);
  12.                 Vector2 maxArea = new Vector2(cr.x + offsetX, cr.y + offsetY);
  13.                
  14.  
  15.                 if(SnapToTopOfGrid)
  16.                 {
  17.                         UIGrid ChildGrid = GetComponentInChildren<UIGrid>();
  18.                         if(ChildGrid != null)
  19.                         {
  20.                                 BetterList<Transform> childs = ChildGrid.GetChildList();
  21.                                 UIWidget lastChildWidget = childs[childs.size-1].GetComponent<UIWidget>();
  22.                                 float childHeight = lastChildWidget.CalculateBounds().extents.y;
  23.                                 float newExtentY = -cr.w;
  24.                                 newExtentY+=childHeight;
  25.                                 if(newExtentY < minRect.y)
  26.                                 {
  27.                                         minRect.y = newExtentY;
  28.                                 }
  29.                                
  30.                         }
  31.                 }
  32.  
  33.                 if (clipping == UIDrawCall.Clipping.SoftClip)
  34.                 {
  35.                         minArea.x += clipSoftness.x;
  36.                         minArea.y += clipSoftness.y;
  37.                         maxArea.x -= clipSoftness.x;
  38.                         maxArea.y -= clipSoftness.y;
  39.                 }
  40.  
  41.  
  42.                 return NGUIMath.ConstrainRect(minRect, maxRect, minArea, maxArea);
  43.         }
  44.  

then in UIScrollView, add "true" as a paramater to both the "CalculateConstrainOffset" method calls, ie:

  1. Vector3 constraint = mPanel.CalculateConstrainOffset(bounds.min, bounds.max);
  2. //becomes
  3. Vector3 constraint = mPanel.CalculateConstrainOffset(bounds.min, bounds.max, true);

Things to be aware of:

Only tested to on UIScrollView that scroll vertically and snap to the top.
Expects a UIGrid child which contains a vertical grid of items of the same height.

e-tip

  • Newbie
  • *
  • Thank You
  • -Given: 1
  • -Receive: 0
  • Posts: 10
    • View Profile
Wow, that's should be part of official NGUI sources thanks

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
I would recommend you make this function a part of your own class rather than modifying NGUI. This way when you update your changes won't be lost.

mucylulu

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 1
    • View Profile
Re: Forcing a UIScrollView contents to "spring" to the top when not full
« Reply #8 on: January 27, 2016, 01:02:39 AM »
I got the same problem too,my solution is below:
  1. private UIScrollView scrollView;
  2.     private Vector3 startPos = Vector3.zero;
  3.     private void dragFinished()
  4.     {
  5.         if (scrollView != null)
  6.         {
  7.             if (!scrollView.shouldMoveVertically)
  8.             {
  9.  
  10.                 if (scrollView.dragEffect == UIScrollView.DragEffect.MomentumAndSpring)
  11.                 {
  12.                     // Spring back into place
  13.                     SpringPanel.Begin(scrollView.GetComponent<UIPanel>().gameObject, startPos, 13f).strength = 8f;
  14.                 }
  15.  
  16.             }
  17.         }
  18.         else
  19.         {
  20.             Debug.Log("grid or scroll view is null FUNC:dragFinished POS:PackageTypeClick.cs");
  21.         }
  22.     }
  23.  
  24.     private void dragStart()
  25.     {
  26.         scrollView = CurrentScrollView.GetComponent<UIScrollView>();
  27.         startPos = scrollView.gameObject.transform.localPosition;
  28.        
  29.     }
  30.  

 ;D ;D ;Dit's works well