Author Topic: Bug report with UIScrollView's ResetPosition() when "Cancel Drag If Fits" is set  (Read 4699 times)

DEngland

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 9
    • View Profile
Hello. I ran into this issue earlier today and I think I have a pretty good grasp of what's going wrong.

Situation:
- A typical ScrollView setup, except both the ScrollView and its single child are left-aligned.
- The Reset Position on the UIScrollView is set to 0, 0.

Bug: Calling ResetPosition() can place the contents slightly outside of the ScrollView such that the floating-point math in the shouldMove property will return true, even if the contents are smaller than the panel.

When combined with the "Cancel Drag If Fits" option, this can result in a situation where you can drag the contents but if you release it somewhere where it is fully contained within the panel then it becomes frozen in that position. I noticed that if I released the contents on the outside of the panel on the same side it was initially on, then it will be animated to its original position (as usual) and will not become frozen yet. This indicates that the animation itself does not return the contents to be fully-inside the panel, at least not within a safe range to negate floating-point errors.

My current workaround is to put the Reset Position at 0.001 to ensure that "shouldMove" evaluates correctly.

I think the simplest fix for this would be to update "shouldMove" to look at the "Cancel Drag If Fits" setting and do a safety check in that case.

Cheers

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Reset position is no longer something you set in the current version of NGUI. Please update.

Real World

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 0
  • Posts: 15
    • View Profile
I'm having the same problem in the latest version of NGUI. What should I be calling instead of ResetPosition()?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
This topic is from over 3 years ago, Real World. Please make a new post explaining what issue you're running into, or at least describe your issue more thoroughly. Also note the description of the two functions:
  1.         /// <summary>
  2.         /// Reset the scroll view's position to the top-left corner.
  3.         /// It's recommended to call this function before AND after you re-populate the scroll view's contents (ex: switching window tabs).
  4.         /// Another option is to populate the scroll view's contents, reset its position, then call this function to reposition the clipping.
  5.         /// </summary>
  6.  
  7.         [ContextMenu("Reset Clipping Position")]
  8.         public void ResetPosition()
  1.         /// <summary>
  2.         /// Call this function after you adjust the scroll view's bounds if you want it to maintain the current scrolled position
  3.         /// </summary>
  4.  
  5.         public void UpdatePosition ()

Real World

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 0
  • Posts: 15
    • View Profile
My issue is exactly as described in the original post despite the three-year gap.
I call ResetPosition() before and after repopulating my grid in my scroll view. The items correctly appear to snap to the top of the scroll view but the scroll view can still be scrolled. Debugging through the logic of the "can scroll" function I can see that the scroll view is fractionally (I mean 0.00001) too far in one direction which fails the test and allows scrolling. I can't be more specific at the moment as I don't have the NGUI code as I'm meant to be on holiday.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Sounds like a floating point precision issue. Try changing UIScrollView.shouldMove to this:
  1.         protected virtual bool shouldMove
  2.         {
  3.                 get
  4.                 {
  5.                         if (!disableDragIfFits) return true;
  6.  
  7.                         if (mPanel == null) mPanel = GetComponent<UIPanel>();
  8.                         Vector4 clip = mPanel.finalClipRegion;
  9.                         Bounds b = bounds;
  10.  
  11.                         float hx = (clip.z == 0f) ? Screen.width  : clip.z * 0.5f;
  12.                         float hy = (clip.w == 0f) ? Screen.height : clip.w * 0.5f;
  13.  
  14.                         if (canMoveHorizontally)
  15.                         {
  16.                                 if (b.min.x + 0.001f < clip.x - hx) return true;
  17.                                 if (b.max.x - 0.001f > clip.x + hx) return true;
  18.                         }
  19.  
  20.                         if (canMoveVertically)
  21.                         {
  22.                                 if (b.min.y + 0.001f < clip.y - hy) return true;
  23.                                 if (b.max.y - 0.001f > clip.y + hy) return true;
  24.                         }
  25.                         return false;
  26.                 }
  27.         }

Real World

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 0
  • Posts: 15
    • View Profile
Yes, that solves the problem. Thank you.