Author Topic: Bug: UIScrollView with UICenterOnChild and IOSDragEmulation  (Read 3917 times)

snlehton

  • Newbie
  • *
  • Thank You
  • -Given: 1
  • -Receive: 1
  • Posts: 6
    • View Profile
Bug: UIScrollView with UICenterOnChild and IOSDragEmulation
« on: January 22, 2014, 03:54:27 AM »
Hi,

I recently discovered an issue with UIScrollView regarding UICenterOnChild and IOSDragEmulation.

A quick repro:
  • Open Example 7 - Scroll View (Panel)
  • Start playing, and activate Center on Items
  • Go to and center to the first item
  • Drag the first item towards right -> iOSDragEmulation does it job and slows down the drag
  • Go to and center to the first item again
  • Now drag the first item towards left -> iOSDragEmulation is slowing down the drag even it shouldn't. When the first item reaches the left side edge of the scroll view bounds, drag returns to normal speed.

The reason for this behavior is because the iOSDragEmulation is applied when the scroll view contents are considered out of bounds (and this is due to the UICenterOnChild). If you disable UICenterOnChild, it works as the first item now sticks to the left side of the scroll view boundaries if you scroll to the first item.

I don't have any easy fix for this. What I've done in one project is to set the scroll view bounds to exact size of the one scrollable item, and then set the clipping mode to ConstrainButDontClip. However, after that the dragging from outside the bounds didn't work, and I needed to fix UIPanel.IsVisible(Vector3 worldPos) like this:

  1. public bool IsVisible (Vector3 worldPos)
  2.         {
  3.                 if (mAlpha < 0.001f) return false;
  4.                 if (mClipping == UIDrawCall.Clipping.None) return true;        
  5.                 // BEGIN FIX
  6.                 if (mClipping == UIDrawCall.Clipping.ConstrainButDontClip) return true;
  7.                 // END FIX
  8.                 UpdateTransformMatrix();
  9.  
  10.                 Vector3 pos = worldToLocal.MultiplyPoint3x4(worldPos);
  11.                 if (pos.x < mMin.x) return false;
  12.                 if (pos.y < mMin.y) return false;
  13.                 if (pos.x > mMax.x) return false;
  14.                 if (pos.y > mMax.y) return false;
  15.                 return true;
  16.         }

I'm not sure if IsVisible should work differently with ConstrainButDontClip, but as it has no clipping, and Clipping.None always returns true, it seemed reasonable. However, this doesn't fix the iOSDragEmulation issue, it's just a workaround. ConstainButDontClip doesn't allow you to use nice alpha clipping.

I think the fundamental issue is that clipping bounds and constraint bounds should really be different ones... but that would require a fundamental change to the UIPanel logic.

What do you guys think?

Cheers,
Sampsa Lehtonen / Draconus Entertainment

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Bug: UIScrollView with UICenterOnChild and IOSDragEmulation
« Reply #1 on: January 22, 2014, 05:00:10 AM »
That seems like a valid change to me. Constrain but don't clip should constrain the content, but it should not prevent events. Your change addresses that.

snlehton

  • Newbie
  • *
  • Thank You
  • -Given: 1
  • -Receive: 1
  • Posts: 6
    • View Profile
Re: Bug: UIScrollView with UICenterOnChild and IOSDragEmulation
« Reply #2 on: January 22, 2014, 09:49:05 AM »
Yeah, that's what I thought. However, as I said, this is not a solve to the original problem because with ConstrainButDontClip you don't get alpha clipping. So this means that example scene 7 cannot be fixed with this.

If you're not sure what the problem is, I challenge you to change the iOSDragEmulation feature a bit for testing purposes by using 0.1f multiplier instead of 0.5f:

  1. Vector3 constraint = mPanel.CalculateConstrainOffset(bounds.min, bounds.max);
  2.  
  3.                                         if (constraint.magnitude > 1f)
  4.                                         {
  5.                                                 MoveAbsolute(offset * 0.1f);
  6.                                                 mMomentum *= 0.1f;
  7.                                         }
  8.                                         else
  9.                                         {
  10.                                                 MoveAbsolute(offset);
  11.                                         }
  12.  

Then try the Example 7 with Center on Items enabled and try moving to the first item and then to the second item...

Hope this makes it clear.