forked from unoplatform/uno
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathScrollViewExtensions.iOS.cs
More file actions
153 lines (129 loc) · 4.86 KB
/
Copy pathScrollViewExtensions.iOS.cs
File metadata and controls
153 lines (129 loc) · 4.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
using System;
using System.Drawing;
#if XAMARIN_IOS_UNIFIED
using UIKit;
using CoreGraphics;
#elif XAMARIN_IOS
using MonoTouch.UIKit;
using CGRect = System.Drawing.RectangleF;
using nfloat = System.Single;
using CGPoint = System.Drawing.PointF;
#endif
namespace Uno.UI.Extensions
{
public static class ScrollViewExtensions
{
public enum ScrollingMode
{
/// <summary>
/// Do not animate the scrolling.
/// </summary>
NotAnimated,
/// <summary>
/// Use standard animation
/// </summary>
Animated,
/// <summary>
/// Should use animation, but mainly force the target view port (bypasses platform validation). (Will animate on iOS 8 -if th keyboard is closed- but not on iOS 7, but works in all cases)
/// </summary>
Forced
}
/// <summary>
/// Make a view visible into a scroll view
/// </summary>
/// <param name="scrollView">The scroll view to scroll to get the item visible.</param>
/// <param name="view">View to make visible.</param>
/// <param name="mode">Specifies a mode to use to place the view into the view port.</param>
/// <param name="padding">
/// Add an extra margin to the view from the edge of the view port when mode is
/// <seealso cref="BringIntoViewMode.TopLeftOfViewPort"/> or <seealso cref="BringIntoViewMode.BottomRightOfViewPort"/>.
/// </param>
/// <param name="animationMode">Sepcifies animation mode to use to animate the scrolling (or not).</param>
public static void BringIntoView(
this UIScrollView scrollView,
UIView view,
BringIntoViewMode mode = BringIntoViewMode.ClosestEdge,
int padding = 0,
ScrollingMode animationMode = ScrollingMode.Forced)
{
var boundsOfViewInScrollViewCoordinatesSystem = scrollView.ConvertRectFromView(view.Bounds, view);
var bounds = scrollView.Bounds;
var inset = scrollView.ContentInset;
var viewPort = new CGRect
(
bounds.X + inset.Left,
bounds.Y + inset.Top,
bounds.Width - inset.Left - inset.Right,
bounds.Height - inset.Top - inset.Bottom
);
nfloat x, y;
switch (mode)
{
case BringIntoViewMode.ClosestEdge:
scrollView.ScrollRectToVisible(boundsOfViewInScrollViewCoordinatesSystem, animationMode != ScrollingMode.NotAnimated);
return;
case BringIntoViewMode.TopLeftOfViewPort:
x = boundsOfViewInScrollViewCoordinatesSystem.Left - padding;
y = boundsOfViewInScrollViewCoordinatesSystem.Top - padding;
break;
case BringIntoViewMode.CenterOfViewPort:
x = boundsOfViewInScrollViewCoordinatesSystem.Left - (viewPort.Width/2) + (boundsOfViewInScrollViewCoordinatesSystem.Width/2);
y = boundsOfViewInScrollViewCoordinatesSystem.Top - (viewPort.Height/2) + (boundsOfViewInScrollViewCoordinatesSystem.Height/2);
break;
case BringIntoViewMode.BottomRightOfViewPort:
x = boundsOfViewInScrollViewCoordinatesSystem.Right - viewPort.Width + padding;
y = boundsOfViewInScrollViewCoordinatesSystem.Bottom - viewPort.Height + padding;
break;
default:
throw new NotSupportedException("Unknown scroll into view behavior");
}
var maxX = scrollView.ContentSize.Width - viewPort.Width;
var maxY = scrollView.ContentSize.Height - viewPort.Height;
x = (nfloat)Math.Max(0, (nfloat)Math.Min(maxX, x));
y = (nfloat)Math.Max(0, (nfloat)Math.Min(maxY, y));
switch (animationMode)
{
case ScrollingMode.NotAnimated:
scrollView.SetContentOffset(new CGPoint(x, y), false);
break;
case ScrollingMode.Animated:
scrollView.SetContentOffset(new CGPoint(x, y), true);
break;
case ScrollingMode.Forced:
scrollView.ContentOffset = new CGPoint(x, y);
break;
default:
throw new NotSupportedException("Unknown animation mode");
}
}
/// <summary>
/// Reset the scrolling state to a valid location, i.e. ensure that the offset is not upper than the ContentSize.
/// </summary>
/// <param name="scrollView"></param>
/// <param name="animationMode">Sepcifies animation mode to use to animate the scrolling (or not).</param>
public static void ClearCustomScrollOffset(this UIScrollView scrollView, ScrollingMode animationMode = ScrollingMode.Forced)
{
var viewPort = scrollView.Bounds;
var x = scrollView.ContentOffset.X;
var y = scrollView.ContentOffset.Y;
var maxX = scrollView.ContentSize.Width - viewPort.Width;
var maxY = scrollView.ContentSize.Height - viewPort.Height;
x = (nfloat)Math.Max(0, (nfloat)Math.Min(maxX, x));
y = (nfloat)Math.Max(0, (nfloat)Math.Min(maxY, y));
switch (animationMode)
{
case ScrollingMode.NotAnimated:
scrollView.SetContentOffset(new CGPoint(x, y), false);
break;
case ScrollingMode.Animated:
scrollView.SetContentOffset(new CGPoint(x, y), true);
break;
case ScrollingMode.Forced:
scrollView.ContentOffset = new CGPoint(x, y);
break;
default:
throw new NotSupportedException("Unknown animation mode");
}
}
}
}