SwiftUI:如何删除 macOS 上的文本选择

问题描述 投票:0回答:1

我有两个简单的文本区域,其中包含文本:

import SwiftUI

struct ContentView: View 
{
    @State private var text1 = "Acing cipsusto dictumst ut nisim mincidunt bibendum nostra; tisi niscilit mauris integer. Praesent dolendrem sit tionsequi blandit, iliquamcon quamconsequi aliquam. Doloboreet niat diam facillum torquent, etiam potenti ationullaoret. Euisi ea adignit, modit iliquiscipis, sapien sectem, in quatums vitae sustrud consequipis. Henim faciduisi penatibus, modionsed velisim, consenisim do, lamconullaor sed adiat odionsequip lacinia."
    @State private var text2 = "Ipsustrud wis nostrud ullan. Dolorem nis tue facincil. Enis lor endre consenibh habitant enissim velestionse quatet nullut; niat ver facilisse acidunt sum hendipisim. Fames diamcom conulluptat facidunt landrem."
    
    var body: some View
    {
        VStack
        {
            TextEditor(text: $text1)
            TextEditor(text: $text2)
        }
    }
}

我的问题是在它们之间单击时保留文本选择。

选择 text2 时,text1 中的文本保持选中状态,尽管呈灰色(甚至失去焦点)。我本以为突出显示两个选择区域会是糟糕的 UI 设计?

我该如何阻止这种情况发生?

macos swiftui textarea
1个回答
0
投票

这是设计使然。这就是两个

TextEditor
的行为方式。这是底层
NSTextView
的默认行为。 应该可以同时在多个文本视图中选择内容。您可以看到这正是 Xcode 的行为方式。在这里,我在两个编辑器中选择一些文本,也在“快速帮助”面板中选择一些文本。

我强烈建议您接受这种默认行为。

如果你真的想做这样的事情,我建议在 AppKit 中做。这就像覆盖

becomeFirstResponder
来调用回调一样简单,并将另一个文本视图的选定范围设置为空。一个非常粗略的例子:

class ViewController: NSViewController {
    @IBOutlet var editor1: MyTextView!
    @IBOutlet var editor2: MyTextView!
    
    override func viewDidLoad() {
        editor1.onFocusChange = {
            print("Foo")
            self.editor2.setSelectedRange(NSRange(location: 0, length: 0))
        }
        editor2.onFocusChange = {
            self.editor1.setSelectedRange(NSRange(location: 0, length: 0))
        }
    }
}

class MyTextView: NSTextView {
    var onFocusChange: () -> Void = { }
    override func becomeFirstResponder() -> Bool {
         onFocusChange()
        return super.becomeFirstResponder()
    }
}

SwiftUI

TextEditor
相对来说是不可配置的。你无法改变他们的行为太多。据我所知,清除选择的唯一方法是通过更改其身份来强制重新绘制
TextEditor

@State private var editor1Id = UUID()
@State private var editor2Id = UUID()

@FocusState var focusedEditor: Int?

var body: some View
{
    VStack
    {
        TextEditor(text: $text1)
            .focused($focusedEditor, equals: 0)
            .id(editor1Id)
        TextEditor(text: $text2)
            .focused($focusedEditor, equals: 1)
            .id(editor2Id)
    }
    .onChange(of: focusedEditor) { oldValue, _ in
        if oldValue == 0 { // focus was on the first editor
            editor1Id = UUID() // redraw the first editor
        } else if oldValue == 1 { // focus was on the second editor
            editor2Id = UUID() // redraw the second editor
        }
    }
}

这不仅会产生很多不必要的

NSTextView
,重新绘制
NSTextView
还会产生副作用,例如弄乱滚动位置等。

© www.soinside.com 2019 - 2024. All rights reserved.