Reputation: 5866
I have a paged UIScrollView that's populated with a collection of UIImageViews. The scroll view shows a preview of the previous and next page.
My goal is to make each page of the scroll view zoomable. Here's a gif of the problem I'm experiencing, where the other pages appear to change their coordinates as the image is zoomed:
I believe the zoom itself is causing the ContentSize of the scroll view to change drastically, which throws everything else out of sorts.
StoryBoard Hierarchy
[Controller]
---- [UIView]
-------- [UIScrollView], Custom Class CapturedResultScrollView
My UIScrollView
has the following constraints to its parent UIView:
Code
Here's the CapturedResultScrollView
implementation, as well as the delegate:
public class CaptureResultScrollViewDelegate : UIScrollViewDelegate {
public CaptureResultScrollViewDelegate(IHandlePaging pageHandler) {
this.pageHandler = pageHandler ?? throw new ArgumentNullException(nameof(pageHandler));
}
private readonly IHandlePaging pageHandler;
public override UIView ViewForZoomingInScrollView(UIScrollView scrollView) {
var pageIndex = (int)Math.Round(scrollView.ContentOffset.X / scrollView.Frame.Size.Width);
return pageHandler.Pages[pageIndex];
}
}
public interface IHandlePaging {
UIImageView[] Pages { get; set; }
}
public partial class CaptureResultScrollView : UIScrollView, IHandlePaging {
public CaptureResultScrollView(IntPtr handle) : base(handle) {
MinimumZoomScale = 1.0f;
MaximumZoomScale = 3.0f;
ZoomScale = 1.0f;
PagingEnabled = true;
ClipsToBounds = false;
ShowsHorizontalScrollIndicator = false;
ShowsVerticalScrollIndicator = false;
Delegate = new CaptureResultScrollViewDelegate(this);
}
public UIImageView[] Pages { get; set; }
public void Setup(IList<CapturedResultModel> capturedResults) {
// setup called from another controller during segue
Pages = new UIImageView[capturedResults.Count];
var pageSize = Frame.Size;
ContentSize = new CGSize(pageSize.Width * Pages.Length, pageSize.Height);
for (int page = 0; page < capturedResults.Count; page++) {
var imageView = new UIImageView() {
// hardcoded value allow for preview of previous/next pages.
Frame = new CGRect(pageSize.Width * page, 0, pageSize.Width - 30, pageSize.Height),
ContentMode = UIViewContentMode.ScaleAspectFill,
Image = UIImage.FromFile(capturedResults[page].ResultImagePath),
ClipsToBounds = true
};
AddSubview(imageView);
Pages[page] = imageView;
}
}
}
The Setup
method of CaptureResultScrollView
is called when the containing controller's ViewWillAppear
event is triggered as follows:
public override void ViewWillAppear(bool animated) {
base.ViewWillAppear(animated);
CapturedResultScrollView.Setup(CapturedResults);
}
What am I doing wrong here?
Upvotes: 0
Views: 176
Reputation: 15806
Cause:
I think your problem is that you set your imageView
for the method ViewForZoomingInScrollView
, when you zoom the imageview
you selected, only that imageView
will zoom and the other imageViews will keep their positions in their superView(here is ScrollerView
),so the other pages appear to change their coordinates as the image is zoomed.
public override UIView ViewForZoomingInScrollView(UIScrollView scrollView) {
var pageIndex = (int)Math.Round(scrollView.ContentOffset.X / scrollView.Frame.Size.Width);
return pageHandler.Pages[pageIndex];
}
Solution:
My advice is that you can add a view who has the same frame with the ScrollView as your imageView's superview. And set this view to the method ViewForZoomingInScrollView
's return value instead of the imageView,so when you zoom this view, imageViews will zoom correctly.
Here is my code:
1.Add a backView in you IHandlePaging
interface
public interface IHandlePaging
{
UIImageView[] Pages { get; set; }
UIView backView { get; set; }
}
2.Add this backView
to the ScrovllView and Add the ImageViews to this backView
public void Setup(IList<CapturedResultModel> capturedResults)
{
Pages = new UIImageView[capturedResults.Count];
var pageSize = Frame.Size;
ContentSize = new CGSize(pageSize.Width * Pages.Length, pageSize.Height);
backView = new UIView()
{
//set the backView's size same as scrollview's contentSize
Frame = new CGRect(15,40,pageSize.Width * capturedResults.Count, pageSize.Height),
BackgroundColor = UIColor.Blue,
ClipsToBounds = true
};
Add(backView);
for (int page = 0; page < capturedResults.Count; page++)
{
var imageView = new UIImageView()
{
Frame = new CGRect( pageSize.Width * page, 0,pageSize.Width - 30, pageSize.Height),
Image = UIImage.FromBundle(capturedResults[page].ResultImagePath),
BackgroundColor = UIColor.Blue,
ClipsToBounds = true
};
backView.AddSubview(imageView);
Pages[page] = imageView;
}
}
3.Set the backView
to the method ViewForZoomingInScrollView
's return Value
public class CaptureResultScrollViewDelegate : UIScrollViewDelegate
{
public CaptureResultScrollViewDelegate(IHandlePaging pageHandler)
{
this.pageHandler = pageHandler ?? throw new ArgumentNullException(nameof(pageHandler));
}
private readonly IHandlePaging pageHandler;
public override UIView ViewForZoomingInScrollView(UIScrollView scrollView)
{
var pageIndex = (int)Math.Round(scrollView.ContentOffset.X / scrollView.Frame.Size.Width);
return pageHandler.backView;
}
}
4.At last, call the Setup
method of CaptureResultScrollView
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
IList<CapturedResultModel> CapturedResults = new List< CapturedResultModel >{ new CapturedResultModel { ResultImagePath = "Images1" },
new CapturedResultModel { ResultImagePath = "Images2"},
new CapturedResultModel { ResultImagePath = "Images1" }
};
CaptureResultScrollView CapturedResultScrollView = new CaptureResultScrollView();
CapturedResultScrollView.Frame = new CGRect(15, 40, View.Frame.Size.Width - 30, View.Frame.Size.Height-80);
CapturedResultScrollView.Setup(CapturedResults);
Add(CapturedResultScrollView);
}
Upvotes: 1