【问题标题】:Detect scroll event in NSScrollView检测 NSScrollView 中的滚动事件
【发布时间】:2013-07-13 13:43:46
【问题描述】:

我想使用 MonoMac 在 NSScrollView 中读取和写入滚动位置(水平和垂直)。我这样做是因为我想保存和加载几个不同的状态,其中包括滚动位置。我没有几个不同的 NSScrollView,而是只有一个,并且希望在状态发生变化时对其进行更改。

到目前为止,我发现我对 NSScrollView 的 Horizo​​ntalScroller 和 VerticalScroller 的 DoubleValue 感兴趣。但是我一生无法弄清楚如何检测这个值何时发生变化,以便我可以保存它。无论用户是单击滚动条、拖动它还是使用鼠标或触控板,我都需要检测更改。只要滚动条移动,我就想保存位置。

有什么建议吗?

【问题讨论】:

    标签: c# cocoa xamarin monomac


    【解决方案1】:

    我认为您以错误的方式处理此问题。我的理解是,直接与NSScroller 交互不是最佳做法(我认为这也行不通)。

    请参阅此question 的答案,我认为这与您的情况相似。最好的办法是设置滚动视图的ContentView 的原点。

    我将该问题的答案转换为 C#:

    public override void AwakeFromNib()
    {
        tableView.EnclosingScrollView.ContentView.PostsBoundsChangedNotifications = true;
        NSNotificationCenter.DefaultCenter.AddObserver(this, new Selector("boundsDidChangeNotification"), 
        NSView.BoundsChangedNotification, tableView.EnclosingScrollView.ContentView);
    
        base.AwakeFromNib();
    }
    
    [Export("boundsDidChangeNotification")]
    public void BoundsDidChangeNotification(NSObject o)
    {
        var notification = o as NSNotification;
        var view = notification.Object as NSView;
        var position = view.Bounds.Location;
        Console.WriteLine("Scroll position: " + position.ToString());
    } 
    

    您可以像这样滚动到特定点:

    PointF scrollTo = new PointF(19, 1571);
    tableView.EnclosingScrollView.ContentView.ScrollToPoint(scrollTo);
    tableView.EnclosingScrollView.ReflectScrolledClipView(tableView.EnclosingScrollView.ContentView);
    

    你可能会觉得这很有趣:Scroll View Programming Guide for Mac

    【讨论】:

    • 谢谢,这适用于读取值。但是当我尝试设置它时,什么也没有发生。
    • 不幸的是,自上次 Xamarin.Mac 更新 (1.12) 以来,boundsdidchangenotification 不再具有参数。如果你运行它,你会在 Main 中得到一个 System.AggregateException
    【解决方案2】:

    自 Xamarin.Mac 1.12 以来,@TheNextman 发布的解决方案需要一些调整。 BoundsDidChangeNotification 必须没有参数,否则将在 Main 中引发 System.AggregateException。如果您在选择器代码中不需要该参数,只需将其从方法签名中删除即可。但是如果你需要,你必须使用其他版本的 AddObserver 方法

    public override void AwakeFromNib()
    {
        tableView.EnclosingScrollView.ContentView.PostsBoundsChangedNotifications = true;
        NSNotificationCenter.DefaultCenter.AddObserver(NSView.BoundsChangedNotification, BoundsDidChangeNotification, tableView.EnclosingScrollView.ContentView);
    
        base.AwakeFromNib();
    }
    
    public void BoundsDidChangeNotification(NSNotification notification)
    {
        var view = notification.Object as NSView;
        var position = view.Bounds.Location;
        Console.WriteLine("Scroll position: " + position.ToString());
    } 
    

    注意,action 方法也可以使用 lambda 结构内联实现

    更新 在与支持人员交谈后,似乎某些组件变得更加挑剔。您仍然可以将基于选择器的解决方案与参数一起使用,但您必须在选择器名称的末尾添加分号

    [Export("boundsDidChangeNotification:")]
    public void BoundsDidChangeNotification(NSObject o)
    

    【讨论】:

      猜你喜欢
      • 2022-11-11
      • 1970-01-01
      • 1970-01-01
      • 2016-06-10
      • 2011-09-11
      • 2018-04-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多