【问题标题】:Xamarin iOS UIScrollView With Next/Previous Page Preview: Zoom Not Working as ExpectedXamarin iOS UIScrollView 与下一个/上一个页面预览:缩放不按预期工作
【发布时间】:2019-03-29 10:07:39
【问题描述】:

我有一个分页的 UIScrollView,其中填充了 UIImageViews 的集合。滚动视图显示上一页和下一页的预览。

我的目标是让滚动视图的每一页都可以缩放。这是我遇到的问题的 gif 图像,其他页面似乎在图像缩放时改变了它们的坐标:

我相信缩放本身会导致滚动视图的 ContentSize 发生巨大变化,这会使其他所有内容都乱七八糟。

故事板层次结构

[控制器]

---- [UIView]

-------- [UIScrollView],自定义类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事件被触发时调用CaptureResultScrollViewSetup方法如下:

public override void ViewWillAppear(bool animated) {
    base.ViewWillAppear(animated);

    CapturedResultScrollView.Setup(CapturedResults);
}

我在这里做错了什么?

【问题讨论】:

    标签: c# ios xamarin.ios uiscrollview zooming


    【解决方案1】:

    原因:

    我认为您的问题是您将imageView 设置为ViewForZoomingInScrollView 方法,当您缩放您选择的imageview 时,只有imageView 会缩放,而其他imageViews 将保持它们在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方法的返回值而不是imageView,这样当你缩放这个视图时,imageViews会正确缩放。

    这是我的代码:

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

    【讨论】:

    • 是的,是的,是的!这绝对是正在发生的事情,并且完全有道理。当然,其他图像试图保持它们的坐标。我已经按照您的建议进行了工作,并且效果很好。谢谢 Jack Hua,欢迎来到 Stack Overflow!
    猜你喜欢
    • 2021-10-21
    • 1970-01-01
    • 1970-01-01
    • 2022-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-30
    相关资源
    最近更新 更多