- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
找不到任何线索如何管理它。
默认情况下,NSTextView 选择突出显示其文本容器的整个大小。它忽略行间距、头部或尾部缩进等。但在 Pages 应用程序选择中不会突出显示那些辅助部分,它仅突出显示字符。即使文本容器的高度较小(前后段落间距),它也会突出显示行的所有高度。
我想实现该行为,但不知道从哪里开始。我在这里搜索过,我搜索过 Apple 文档,我尝试过示例项目。什么都没有。
也许有人可以指导我正确的方向?谢谢!
最佳答案
我发现 hamstergene 的回答不正确。事实上,NSTextView 逐行突出显示其文本容器边界。
因此,如果您使用段落的头部缩进,那么段落前导的空白区域将突出显示。如果您选择 EOL 字符,那么段落的结尾空格也会突出显示。
我的解决方案是取消段落样式的头部和尾部缩进(我将它们缓存在私有(private)变量中,并在访问我的文本存储以进行打印时将它们放回原处)并通过覆盖 lineFragmentRectForProposedRect: atIndex: writingDirection: remainingRect 我的 NSTextContainer 子类的方法。
但后来我发现了很多合适的方法。只需覆盖 func fillBackgroundRectArray(_ rectArray: UnsafePointer<NSRect>, count rectCount: Int, forCharacterRange charRange: NSRange, color: NSColor)
在 NSLayoutManager 中,计算你的 rects 并用这些 rects 调用 super。如果您正确计算选择矩形,您将获得与 Apple Pages 或 MS Word 中一样的精确选择行为。
简单易行!
更新这是我计算选择矩形的代码:
public override func fillBackgroundRectArray(_ rectArray: UnsafePointer<CGRect>, count rectCount: Int, forCharacterRange charRange: NSRange, color: OSColor) {
// if characters are selected, make sure that we draw selection of those characters only, not the whole text container bounds
guard let textView = textContainer(forCharacterIndex: charRange.location)?.textView,
NSIntersectionRange(textView.selectedRange(), charRange).length > 0,
let textStorage = self.textStorage as? ParagraphTextStorage else {
super.fillBackgroundRectArray(rectArray, count: rectCount, forCharacterRange: charRange, color: color)
return
}
let selectedGlyphRange = self.glyphRange(forCharacterRange: charRange, actualCharacterRange: nil)
var selectionRectArray: [CGRect] = []
enumerateLineFragments(forGlyphRange: selectedGlyphRange) { (rect, usedRect, textContainer, glyphRange, stop) in
let lineCharRange = self.characterRange(forGlyphRange: glyphRange, actualGlyphRange: nil)
let intersection = NSIntersectionRange(charRange, lineCharRange)
// if selected all characters of the line, then we already have teir layout rects
if intersection == lineCharRange {
let paragraphIndex = textStorage.paragraphIndex(at: intersection.location)
let paragraphRange = textStorage.paragraphRanges[paragraphIndex]
let hasNewLineChar = lineCharRange.max == paragraphRange.max && paragraphRange.max < textStorage.length ||
paragraphRange.max == lineCharRange.max && intersection.max == textStorage.length && paragraphIndex < textStorage.paragraphRanges.count - 1
let newLineCharSize = hasNewLineChar ? self.newLineCharSize : .zero
let lineRect = CGRect(x: usedRect.origin.x + textView.textContainerInset.width + textContainer.lineFragmentPadding,
y: usedRect.origin.y + textView.textContainerInset.height - (rect.height - usedRect.height),
width: usedRect.width + newLineCharSize.width - textContainer.lineFragmentPadding * 2,
height: rect.height)
selectionRectArray.append(lineRect)
} else {
// calculate rect for partially selected characters of the line
let partialRect = self.usedLineRect(forCharacterRange: intersection, in: textContainer)
selectionRectArray.append(partialRect)
}
}
super.fillBackgroundRectArray(selectionRectArray, count: selectionRectArray.count, forCharacterRange: charRange, color: color)
}
public func usedLineRect(forCharacterRange charRange: NSRange, in textContainer: NSTextContainer) -> CGRect {
guard let textView = textContainer.textView, let textStorage = textStorage as? ParagraphTextStorage else { return .zero }
let glyphRange = self.glyphRange(forCharacterRange: charRange, actualCharacterRange: nil)
let textContainer = self.textContainer(forGlyphAt: glyphRange.location, effectiveRange: nil) as! ModernTextContainer
let paragraphIndex = textStorage.paragraphIndex(at: charRange.location)
let paragraphRange = textStorage.paragraphRanges[paragraphIndex]
let hasNewLine = paragraphRange.max == charRange.max && charRange.max < textStorage.length ||
paragraphRange.max == charRange.max && charRange.max == textStorage.length && paragraphIndex < textStorage.paragraphRanges.count - 1
let newLineCharSize = hasNewLine ? self.newLineCharSize : .zero
// if new line is in range, boundingRect will return the whole width of the text container, fix that
let noNewLineGlyphRange = hasNewLine ? NSRange(location: glyphRange.location, length: glyphRange.length - 1) : glyphRange
let charRect = boundingRect(forGlyphRange: noNewLineGlyphRange, in: textContainer)
let lineRect = lineFragmentRect(forGlyphAt: noNewLineGlyphRange.location, effectiveRange: nil, withoutAdditionalLayout: true)
#if os(macOS)
// respect the flipped coordinate system with abs function
let rect = CGRect(x: charRect.origin.x + textView.textContainerInset.width,
y: abs(charRect.origin.y + textView.textContainerInset.height - (lineRect.height - charRect.height)),
width: charRect.width + newLineCharSize.width,
height: lineRect.height)
#else
let rect = CGRect(x: charRect.origin.x + textView.textContainerInset.left,
y: abs(charRect.origin.y + textView.textContainerInset.top - (lineRect.height - charRect.height)),
width: charRect.width + newLineCharSize.width,
height: lineRect.height)
#endif
return rect
}
这个执行速度极快的计算的重要部分是我正在使用我自己的 ParagraphTextStorage 实现。其目的是在编辑文本存储时实时计算段落范围。了解正确的段落范围后,我可以在计算所选矩形时使用简单的整数(如 NSRange 的整数)。否则我不得不做一堆子字符串来了解是否选择了换行符。而且这些操作真的很慢。
我的 ParagraphTextStorage 的实现在这里:https://github.com/CineDev/ParagraphTextKit
关于objective-c - NSTextView 选择突出显示所有字符甚至段落缩进,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24407203/
如何调整 NSTextView 的文本以适合框的内容,而无需滚动?例如,如果用户输入一个长字符串,并且如果我稍后将该字符串显示为 NSTextView,我该如何使字体减小到足够小以适合该框? 最佳答案
我有一个包含格式化文本和嵌入图像的 NSTextView,如下所示。 我想将上面转换为纯文本,如下所示: Hi this is test data (...picture...)This is col
我对 Cocoa 很陌生,这可能是一个全新的问题。然而,我很沮丧。 我有一个非常简单的 Cocoa 应用程序(称为“行”)来测试将 1000 行文本发送到 TextView 。 我在 Xcode 4
我正在使用Markdown语法的Mac应用程序中的富文本编辑器上工作。我使用NSTextStorage监视Markdown语法中的匹配项,然后将样式实时应用于NSAttributedString,如下
当用户将数据粘贴到 NSTextView 中时,我需要收到通知,以便删除任何不允许的数据类型(url 链接等)。我不想使用 NSTextStorageDelegate 的 textStorageDid
我有一个继承自 NSTextView 的类,该类在初始化时使用 setContinouslySpellCheckingEnabled(true) 设置自动拼写检查,并且在聚焦时将自身设置为第一响应者。
如果您在 Mac 上安装 Microsoft Word 并打开文档,则可以通过按 Command + 2 将行距增加到 2。现在我的 cocoa 应用程序使用 NSTextView。我的用户希望应用程
NSTextView从哪里来? 在我的 OSX 应用程序中,我有一个 NSSearchField,我实现了 controlTextDidChange:,其中在键 NSFieldEditor 中包含一个
使用什么技术来创建一个包含电子邮件文本气泡的 TextView,与电子邮件中类似 最佳答案 这是一个 NSTokenField。看看它和 NSTokenFieldCell 类。如果您需要做的事情是高度
我想创建一个 TextView ,它将支持突出显示基本内容,例如链接和主题标签。类似的功能可以在 Twitter.app 中找到: 不需要支持点击这些链接,只需要在用户编辑 TextView 内容时正
我正在尝试更改 NSTextView 中的预设制表位。我发现了一个旧的帖子表单 2002,它说可以通过显示 NSTextView 的标尺然后编辑其上的选项卡来从 Interface Builder 中
我在 NSTextView 上打字时遇到挂起。 NSTextView 位于我以模态方式运行的窗口上。 [NSApp runModalForWindow:[自身窗口]]; 我不太确定是怎么回事,但我认为
我已经下载:NSTextView 突出显示:enter link description here 它按预期工作,如果您打开应用程序并输入符号“-”,它会变成红色,但后来我遇到了问题。我在.h文件中写
我正在尝试创建一个 NSTextView,其行为有点像一系列打字机页面 - 每个页面都有固定数量的可用行和列。 底层表示与显示完美匹配,而显示又与文件格式匹配。页面以换页符 '\f' 结尾。例如,两个
如何获取 NSTextView 插入符位置更改的回调? 我尝试过 KVO [textView addObserver:self forKeyPath:@"selectedRange" options:
我在 NSScrollView 中有一个 NSTextView,并且我以编程方式插入 NSView 子类作为 NSTextView 有什么方法可以让 NSTextView 接收其所有事件,即使我的 N
我的窗口上有一个 NSTextView 对象。我将 NSStrings 传递给它并显示出来。我想更改显示的文字大小。我怎么做?我是在检查器中执行此操作还是有办法在代码中执行此操作?请举个例子。谢谢!
我有一个带有 TextView 的 ScrollView 。如何找到当前选择的 TextView ? NSTextDelegate 中的委托(delegate)方法仅在您开始编辑时才起作用,而不是在首
我一定是做错了什么: 我的 Cocoa 应用程序有一个围绕自定义 View 的 ScrollView ,而自定义 View 又具有一个 TextView 。我只希望看到一个“这是一个”字符串,但角落里
我在使用 NSTextview 时遇到问题,它应该不断更新日志文件的内容。该应用程序是一个主从 UI,主视图包含一组“备份”对象,而详细 View 包含一个 NSTabView,其中一个选项卡包含 N
我是一名优秀的程序员,十分优秀!