4

首先,我想说我已经查看了很多其他资源来尝试实现这一点,但我所查看的似乎没有任何帮助。

例如:使用自动布局自动增长 NSScrollView 的文档视图?

我有一个在 Interface Builder 中创建的 NSScrollView 并设置约束以填充它所在的窗口:滚动视图的顶部、左侧、右侧和底部设置为等于超级视图的顶部、左侧、右侧和底部(其中是 Xamarin 中的 viewcontroller 使用的 xib 视图)。

我想要的文档视图是一个简单的 NSView,它在我的 viewcontroller 的 ViewDidLoad 中动态填充了 NSImageViews:

EventListScrollView.TranslatesAutoresizingMaskIntoConstraints = false;

var documentView = new NSView(EventListScrollView.Bounds);
//documentView.AutoresizingMask = NSViewResizingMask.WidthSizable | NSViewResizingMask.HeightSizable;
//documentView.TranslatesAutoresizingMaskIntoConstraints = false;

NSView lastHeader = null;
foreach(var project in _projects)
{
    var imageView = new NSImageView();
    imageView.TranslatesAutoresizingMaskIntoConstraints = false;
    imageView.SetContentCompressionResistancePriority(1, NSLayoutConstraintOrientation.Horizontal);
    imageView.SetContentCompressionResistancePriority(1, NSLayoutConstraintOrientation.Vertical);
    imageView.ImageScaling = NSImageScale.ProportionallyUpOrDown;

    var xPosConstraint = NSLayoutConstraint.Create(imageView, NSLayoutAttribute.Left, NSLayoutRelation.Equal, documentView, NSLayoutAttribute.Left, 1, 0);
    NSLayoutConstraint yPosConstraint = null;
    if(lastHeader!=null)
    {
        yPosConstraint = NSLayoutConstraint.Create(imageView, NSLayoutAttribute.Top, NSLayoutRelation.Equal, lastHeader, NSLayoutAttribute.Bottom, 1, 0);
    }
    else
    {
        yPosConstraint = NSLayoutConstraint.Create(imageView, NSLayoutAttribute.Top, NSLayoutRelation.Equal, documentView, NSLayoutAttribute.Top, 1, 0);
    }

    var widthConstraint = NSLayoutConstraint.Create(imageView, NSLayoutAttribute.Width, NSLayoutRelation.Equal, documentView, NSLayoutAttribute.Width, 1, 0);
    var heightConstraint = NSLayoutConstraint.Create(imageView, NSLayoutAttribute.Height, NSLayoutRelation.Equal, imageView, NSLayoutAttribute.Width, (nfloat)0.325, 0);

    documentView.AddSubview(imageView);
    documentView.AddConstraints(new[] { xPosConstraint, yPosConstraint, widthConstraint, heightConstraint });

    lastHeader = imageView;
    ImageService.Instance.LoadUrl($"https:{project.ProjectLogo}").Into(imageView);
}

EventListScrollView.DocumentView = documentView;

因为我不一定知道有多少项目,_projects也不知道将加载到每个项目中的图像的高度imageView,虽然我知道预期的比例,但直到运行时我才知道我的 documentView 的高度.

我希望将documentView' 的宽度调整为与NSClipView每次调整滚动视图所在的封闭窗口(因此也调整滚动视图)的大小时相同。至于 的高度,我希望它由我在 中填充documentView的 s 的大小来确定,这就是高度约束与宽度相关的原因。imageViewdocumentView

我玩过AutoresizingMask, documentView,NSClipView滚动视图等。我尝试为所有内容设置TranslatesAutoresizingMaskIntoConstraintstofalse并添加约束以将左侧、右侧和顶部设置为documentView等于NSClipView. 当我这样做时,视图似乎甚至没有出现。我似乎无法弄清楚这一点。

我也试过在不使用 NSImageViews 的情况下这样做:

public override void ViewDidLoad()
{
    base.ViewDidLoad();

    EventListScrollView.TranslatesAutoresizingMaskIntoConstraints = false;
    var clipView = new NSClipView
    {
        TranslatesAutoresizingMaskIntoConstraints = false
    };

    EventListScrollView.ContentView = clipView;
    EventListScrollView.AddConstraint(NSLayoutConstraint.Create(clipView, NSLayoutAttribute.Left, NSLayoutRelation.Equal, EventListScrollView, NSLayoutAttribute.Left, 1, 0));
    EventListScrollView.AddConstraint(NSLayoutConstraint.Create(clipView, NSLayoutAttribute.Right, NSLayoutRelation.Equal, EventListScrollView, NSLayoutAttribute.Right, 1, 0));
    EventListScrollView.AddConstraint(NSLayoutConstraint.Create(clipView, NSLayoutAttribute.Top, NSLayoutRelation.Equal, EventListScrollView, NSLayoutAttribute.Top, 1, 0));
    EventListScrollView.AddConstraint(NSLayoutConstraint.Create(clipView, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal, EventListScrollView, NSLayoutAttribute.Bottom, 1, 0));

    var documentView = new NSView();
    documentView.WantsLayer = true;
    documentView.Layer.BackgroundColor = NSColor.Black.CGColor;
    documentView.TranslatesAutoresizingMaskIntoConstraints = false;
    EventListScrollView.DocumentView = documentView;
    clipView.AddConstraint(NSLayoutConstraint.Create(documentView, NSLayoutAttribute.Left, NSLayoutRelation.Equal, clipView, NSLayoutAttribute.Left, 1, 0));
    clipView.AddConstraint(NSLayoutConstraint.Create(documentView, NSLayoutAttribute.Right, NSLayoutRelation.Equal, clipView, NSLayoutAttribute.Right, 1, 0));
    clipView.AddConstraint(NSLayoutConstraint.Create(documentView, NSLayoutAttribute.Top, NSLayoutRelation.Equal, clipView, NSLayoutAttribute.Top, 1, 0));

    NSView lastHeader = null;
    foreach(var project in _projects)
    {
        var random = new Random();

        var imageView = new NSView();
        imageView.TranslatesAutoresizingMaskIntoConstraints = false;
        imageView.WantsLayer = true;
        imageView.Layer.BackgroundColor = NSColor.FromRgb(random.Next(0, 255), random.Next(0, 255), random.Next(0, 255)).CGColor;

        var xPosConstraint = NSLayoutConstraint.Create(imageView, NSLayoutAttribute.Left, NSLayoutRelation.Equal, documentView, NSLayoutAttribute.Left, 1, 0);
        NSLayoutConstraint yPosConstraint = null;
        if(lastHeader!=null)
        {
            yPosConstraint = NSLayoutConstraint.Create(imageView, NSLayoutAttribute.Top, NSLayoutRelation.Equal, lastHeader, NSLayoutAttribute.Bottom, 1, 0);
        }
        else
        {
            yPosConstraint = NSLayoutConstraint.Create(imageView, NSLayoutAttribute.Top, NSLayoutRelation.Equal, documentView, NSLayoutAttribute.Top, 1, 0);
        }

        var widthConstraint = NSLayoutConstraint.Create(imageView, NSLayoutAttribute.Width, NSLayoutRelation.Equal, documentView, NSLayoutAttribute.Width, 1, 0);
        var heightConstraint = NSLayoutConstraint.Create(imageView, NSLayoutAttribute.Height, NSLayoutRelation.Equal, imageView, NSLayoutAttribute.Width, (nfloat)0.325, 0);

        documentView.AddSubview(imageView);
        documentView.AddConstraints(new[] { xPosConstraint, yPosConstraint, widthConstraint, heightConstraint });

        lastHeader = imageView;
    }
}
4

3 回答 3

2

我想到了。所以,这样做的诀窍是 documentView 不知道自己有多大,除非你把它的底部固定在你的最后一个子视图上。您可以使用视觉格式来做到这一点,但如果您直到运行时才真正知道您的视图是什么,那就有点过头了。这是对我有用的代码:

public override void ViewDidLoad()
{
    base.ViewDidLoad();

    var clipView = EventListScrollView.ContentView;

    var documentView = new FlippedView();
    documentView.TranslatesAutoresizingMaskIntoConstraints = false;
    EventListScrollView.DocumentView = documentView;
    clipView.AddConstraint(NSLayoutConstraint.Create(documentView, NSLayoutAttribute.Left, NSLayoutRelation.Equal, clipView, NSLayoutAttribute.Left, 1, 0));
    clipView.AddConstraint(NSLayoutConstraint.Create(documentView, NSLayoutAttribute.Right, NSLayoutRelation.Equal, clipView, NSLayoutAttribute.Right, 1, 0));
    clipView.AddConstraint(NSLayoutConstraint.Create(documentView, NSLayoutAttribute.Top, NSLayoutRelation.Equal, clipView, NSLayoutAttribute.Top, 1, 0));

    NSView lastHeader = null;
    foreach (var project in _projects)
    {
        var imageView = new NSImageView();
        imageView.TranslatesAutoresizingMaskIntoConstraints = false;
        imageView.SetContentCompressionResistancePriority(1, NSLayoutConstraintOrientation.Horizontal);
        imageView.SetContentCompressionResistancePriority(1, NSLayoutConstraintOrientation.Vertical);
        imageView.ImageScaling = NSImageScale.ProportionallyUpOrDown;

        var xPosConstraint = NSLayoutConstraint.Create(imageView, NSLayoutAttribute.Left, NSLayoutRelation.Equal, documentView, NSLayoutAttribute.Left, 1, 0);
        NSLayoutConstraint yPosConstraint = null;
        if (lastHeader != null)
        {
            yPosConstraint = NSLayoutConstraint.Create(imageView, NSLayoutAttribute.Top, NSLayoutRelation.Equal, lastHeader, NSLayoutAttribute.Bottom, 1, 0);
        }
        else
        {
            yPosConstraint = NSLayoutConstraint.Create(imageView, NSLayoutAttribute.Top, NSLayoutRelation.Equal, documentView, NSLayoutAttribute.Top, 1, 0);
        }

        var widthConstraint = NSLayoutConstraint.Create(imageView, NSLayoutAttribute.Width, NSLayoutRelation.Equal, documentView, NSLayoutAttribute.Width, 1, 0);
        var heightConstraint = NSLayoutConstraint.Create(imageView, NSLayoutAttribute.Height, NSLayoutRelation.LessThanOrEqual, imageView, NSLayoutAttribute.Width, (nfloat)0.360, 0);

        documentView.AddSubview(imageView);
        documentView.AddConstraint(xPosConstraint);
        documentView.AddConstraint(yPosConstraint);
        documentView.AddConstraint(widthConstraint);
        documentView.AddConstraint(heightConstraint);

        lastHeader = imageView;
        ImageService.Instance.LoadUrl($"https:{project.ProjectLogo}").Into(imageView);
    }

    if(lastHeader!=null)
    {
        var bottomPinConstraint = NSLayoutConstraint.Create(documentView, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal, lastHeader, NSLayoutAttribute.Bottom, 1, 0);
        documentView.AddConstraint(bottomPinConstraint);
    }
}

关键是最后一个约束—— bottomPinConstraint. 这允许documentView扩展其高度以适应所有子视图。

IsFlipped = true;此外,即使我手动设置了NSClipView和 my之间的约束,我仍然需要使用视图documentView,否则它将忽略约束并将我的视图固定到NSClipView. 我的 EventListScrollView 是在 Interface Builder 中创建的,并设置了约束以使其填充它所在的整个窗口。

最终结果是一个带有 DocumentView 的 NSScrollView,它填充了 ScrollView 的宽度,但也垂直扩展以适应我以编程方式添加到其中的子视图。

于 2018-06-21T22:37:18.570 回答
0

我这样做是为了让我的自定义视图按滚动视图宽度调整大小。

    scrollView.documentView = customView
    customView.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
        customView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
        customView.widthAnchor.constraint(greaterThanOrEqualTo: scrollView.widthAnchor),
    ])

自定义视图intrinsicContentSize在 X 轴上提供。

于 2019-09-06T13:00:11.643 回答
0

eonil 的答案几乎是完美的,但是如果系统设置为始终显示滚动条,则偏移量会不正确。水平滚动条以一个小的偏移结束。要解决此问题,请改用剪辑视图的锚点:

  NSLayoutConstraint.activate([
     view.leadingAnchor.constraint(equalTo: scrollView.contentView.leadingAnchor),
     view.widthAnchor.constraint(equalTo: scrollView.contentView.widthAnchor),
    ])
于 2021-11-23T21:54:36.053 回答