我有包装NSTextView
实例垂直堆叠,例如:
The quick brown fox
jumps over the lazy dog
Jackdaws love my big
sphinx of quartz
我需要用上下箭头在它们之间移动。例如,当光标位于l之后时在"lazy"当用户按下向下箭头时,光标应该跳转到y之后。在"my"-就像这些句子在同一个文本视图中一样。
默认情况下,当光标位于最后一个换行行时按下向下箭头时,文本视图将其移动到该行的末尾。虽然我可以在NSTextViewDelegate
中使用textView(_:doCommandBy:)
来检测"箭头向下";选择器和覆盖默认行为,有两个问题:
我可以确定光标是否在最后一行,通过
selectedRanges
属性获得其位置,然后检查该位置后的换行字符,但不可能知道它是否在最后包装的行,即在当前文本视图的边界附近。我需要知道光标的X坐标,以便将其放置在另一个文本视图中大致相同的X坐标上(字体不一定是固定宽度的,所以我不能依赖于字符数)。
我想这两个问题都可以通过NSLayoutManager
解决,但是我无法理解它所有可用的方法。
这是相对容易的,这是我所做的(示例是用c#编写的)。首先,boundingRect(forGlyphRange:in:)
获取光标在当前视图中的位置:
var cursorLocation = new NSRange(CurrentTextView.SelectedRange.Location, 0);
var cursorCoordinates = CurrentTextView.LayoutManager.BoundingRectForGlyphRange(cursorLocation, CurrentTextView.TextContainer).Location;
如果第二个文本视图在下面,则插入点将位于Y轴上的0处:
var insertionPoint = new CGPoint(cursorCoordinates.X, 0);
如果它在上面,那么应该使用另一个视图的高度(减少1,否则产生的字符索引将不正确,光标将被放置在行尾):
var insertionPoint = new CGPoint(cursorCoordinates.X, AnotherTextView.Bounds.Size.Height - 1);
获得插入点后,另一个视图需要成为第一响应者,然后characterIndexForInsertion(at:)
完成这项工作:
Window.MakeFirstResponder(AnotherTextView);
var index = AnotherTextView.CharacterIndex(insertionPoint);
AnotherTextView.SelectedRange = new NSRange(index, 0);