c# - 带有下一页/上一页预览的 Xamarin iOS UIScrollView : Zoom Not Working as Expected

标签 c# ios xamarin.ios uiscrollview zooming

我有一个分页的 UIScrollView,其中填充了一组 UIImageView。 ScrollView 显示上一页和下一页的预览。

我的目标是让 ScrollView 的每一页都可以缩放。这是我遇到的问题的 gif,其中其他页面似乎随着图像的缩放而改变了它们的坐标:

enter image description here

我相信缩放本身会导致 ScrollView 的 ContentSize 发生剧烈变化,这会使其他所有内容都乱七八糟。

Storyboard层次结构

[ Controller ]

---- [UIView]

-------- [UIScrollView], 自定义类 CapturedResultScrollView

我的 UIScrollView 对其父 UIView 有以下约束:

enter image description here

代码

这是 CapturedResultScrollView 实现,以及委托(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;
        }
    }
}

CaptureResultScrollViewSetup 方法在包含 Controller 的 ViewWillAppear 事件被触发时被调用,如下所示:

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 具有相同框架的 View 作为您的 imageView 的 super View 。并将此 View 设置为方法 ViewForZoomingInScrollView 的返回值而不是 imageView,因此当您缩放此 View 时,imageView 将正确缩放。

这是我的代码:

1.在IHandlePaging界面中添加一个backView

 public interface IHandlePaging
    {
        UIImageView[] Pages { get; set; }

        UIView backView { get; set; }

    }

2.将此backView添加到ScrovllView并将ImageViews添加到此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.将backView设置为方法ViewForZoomingInScrollView的返回值

  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.最后调用CaptureResultScrollViewSetup方法

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);
        }

关于c# - 带有下一页/上一页预览的 Xamarin iOS UIScrollView : Zoom Not Working as Expected,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52978363/

相关文章:

xamarin - 如何在 iOS 中为 TTTAttributedLabel LinkAttributes 添加 NSDictionary UIColor

c# - MonoTouch 中的按钮问题

ios - 如何将按钮添加到选项卡栏 Controller

ios - iTunes 资料库 "Distinguished Kind"

c# - 找不到 Entity Framework 4 注释

c# - 使用 Vector<T> 的 SIMD 向量化 C# 代码运行速度比经典循环慢

ios - WKWebView 白屏(Objective-C)

firebase - 为什么我的 Xamarin.iOS 应用程序没有收到来自 Google Firebase 的推送通知?

c# - 在不使用 Include 的情况下选择具有多个嵌套级别的实体

c# - 从文件中高效读取结构化二进制数据