具有 Next/Previous 页面预览的 Xamarin iOS UIScrollView:缩放未按预期工作
Xamarin iOS UIScrollView With Next/Previous Page Preview: Zoom Not Working as Expected
我有一个分页的 UIScrollView,其中填充了一组 UIImageView。滚动视图显示上一页和下一页的预览。
我的目标是让滚动视图的每一页都可以缩放。这是我遇到的问题的 gif,其中其他页面似乎随着图像的缩放而改变了它们的坐标:
我相信缩放本身会导致滚动视图的 ContentSize 发生巨大变化,这会使其他所有内容都乱七八糟。
故事板层次结构
[控制器]
---- [UIView]
-------- [UIScrollView], 自定义 Class CapturedResultScrollView
我的 UIScrollView
对其父 UIView 有以下约束:
代码
这是 CapturedResultScrollView
实现以及委托:
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;
}
}
}
当包含控制器的ViewWillAppear
事件被触发时,CaptureResultScrollView
的Setup
方法被调用如下:
public override void ViewWillAppear(bool animated) {
base.ViewWillAppear(animated);
CapturedResultScrollView.Setup(CapturedResults);
}
我做错了什么?
原因:
我认为你的问题是你为方法 ViewForZoomingInScrollView
设置了 imageView
,当你缩放你选择的 imageview
时,只有 imageView
会缩放并且其他 imageView 将保持它们在其 superView 中的位置(这里是 ScrollerView
),因此其他页面似乎会随着图像缩放而改变它们的坐标。
public override UIView ViewForZoomingInScrollView(UIScrollView scrollView) {
var pageIndex = (int)Math.Round(scrollView.ContentOffset.X / scrollView.Frame.Size.Width);
return pageHandler.Pages[pageIndex];
}
解法:
我的建议是您可以添加一个与 ScrollView 具有相同框架的视图作为您的 imageView 的超级视图。并将此视图设置为方法 ViewForZoomingInScrollView
的 return 值而不是 imageView,因此当您缩放此视图时,imageViews 将正确缩放。
这是我的代码:
1.Add backView in you IHandlePaging
interface
public interface IHandlePaging
{
UIImageView[] Pages { get; set; }
UIView backView { get; set; }
}
2.Add 这个 backView
到 ScrovllView 并将 ImageView 添加到这个 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 backView
到方法 ViewForZoomingInScrollView
的 return 值
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最后,调用CaptureResultScrollView
的Setup
方法
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);
}
我有一个分页的 UIScrollView,其中填充了一组 UIImageView。滚动视图显示上一页和下一页的预览。
我的目标是让滚动视图的每一页都可以缩放。这是我遇到的问题的 gif,其中其他页面似乎随着图像的缩放而改变了它们的坐标:
我相信缩放本身会导致滚动视图的 ContentSize 发生巨大变化,这会使其他所有内容都乱七八糟。
故事板层次结构
[控制器]
---- [UIView]
-------- [UIScrollView], 自定义 Class CapturedResultScrollView
我的 UIScrollView
对其父 UIView 有以下约束:
代码
这是 CapturedResultScrollView
实现以及委托:
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;
}
}
}
当包含控制器的ViewWillAppear
事件被触发时,CaptureResultScrollView
的Setup
方法被调用如下:
public override void ViewWillAppear(bool animated) {
base.ViewWillAppear(animated);
CapturedResultScrollView.Setup(CapturedResults);
}
我做错了什么?
原因:
我认为你的问题是你为方法 ViewForZoomingInScrollView
设置了 imageView
,当你缩放你选择的 imageview
时,只有 imageView
会缩放并且其他 imageView 将保持它们在其 superView 中的位置(这里是 ScrollerView
),因此其他页面似乎会随着图像缩放而改变它们的坐标。
public override UIView ViewForZoomingInScrollView(UIScrollView scrollView) {
var pageIndex = (int)Math.Round(scrollView.ContentOffset.X / scrollView.Frame.Size.Width);
return pageHandler.Pages[pageIndex];
}
解法:
我的建议是您可以添加一个与 ScrollView 具有相同框架的视图作为您的 imageView 的超级视图。并将此视图设置为方法 ViewForZoomingInScrollView
的 return 值而不是 imageView,因此当您缩放此视图时,imageViews 将正确缩放。
这是我的代码:
1.Add backView in you IHandlePaging
interface
public interface IHandlePaging
{
UIImageView[] Pages { get; set; }
UIView backView { get; set; }
}
2.Add 这个 backView
到 ScrovllView 并将 ImageView 添加到这个 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 backView
到方法 ViewForZoomingInScrollView
的 return 值
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最后,调用CaptureResultScrollView
Setup
方法
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);
}