在SwiftUI中更改TextEditor的背景颜色

时间:2020-07-11 10:57:23

标签: swift swiftui

TextEditor似乎具有默认的白色背景。因此,以下内容不起作用,并且显示为white而不是定义的red

var body: some View {
    TextEditor(text: .constant("Placeholder"))
        .background(Color.red)
}

是否可以将颜色更改为自定义颜色?

3 个答案:

答案 0 :(得分:26)

TextEditorUITextView支持。因此,您需要先摆脱UITextView的{​​{1}},然后才能将backgroundColor设置为View

background

答案 1 :(得分:3)

在 macOS 上使用 SwiftUI 自定义背景颜色

不幸的是,在 macOS 上,您必须回退到 AppKit 并包装 NSTextView。

你需要声明一个符合NSViewRepresentable

的视图

这应该为您提供与 SwiftUI 的 TextEditor-View 几乎相同的行为,并且由于包装的 NSTextView 不绘制其背景,您可以使用 .background-ViewModifier 更改背景

struct CustomizableTextEditor: View {
    @Binding var text: String
    
    var body: some View {
        GeometryReader { geometry in
            NSScrollableTextViewRepresentable(text: $text, size: geometry.size)
        }
    }
    
}

struct NSScrollableTextViewRepresentable: NSViewRepresentable {
    typealias Representable = Self
    
    // Hook this binding up with the parent View
    @Binding var text: String
    var size: CGSize
    
    // Get the UndoManager
    @Environment(\.undoManager) var undoManger
    
    // create an NSTextView
    func makeNSView(context: Context) -> NSScrollView {
        
        // create NSTextView inside NSScrollView
        let scrollView = NSTextView.scrollableTextView()
        let nsTextView = scrollView.documentView as! NSTextView
        
        // use SwiftUI Coordinator as the delegate
        nsTextView.delegate = context.coordinator
        
        // set drawsBackground to false (=> clear Background)
        // use .background-modifier later with SwiftUI-View
        nsTextView.drawsBackground = false
        
        // allow undo/redo
        nsTextView.allowsUndo = true
        
        return scrollView
    }
    
    func updateNSView(_ scrollView: NSScrollView, context: Context) {
        // get wrapped nsTextView
        guard let nsTextView = scrollView.documentView as? NSTextView else {
            return
        }
        
        // fill entire given size
        nsTextView.minSize = size
        
        // set NSTextView string from SwiftUI-Binding
        nsTextView.string = text
    }
    
    // Create Coordinator for this View
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    // Declare nested Coordinator class which conforms to NSTextViewDelegate
    class Coordinator: NSObject, NSTextViewDelegate {
        var parent: Representable // store reference to parent
        
        init(_ textEditor: Representable) {
            self.parent = textEditor
        }
        
        // delegate method to retrieve changed text
        func textDidChange(_ notification: Notification) {
            // check that Notification.name is of expected notification
            // cast Notification.object as NSTextView

            guard notification.name == NSText.didChangeNotification,
                let nsTextView = notification.object as? NSTextView else {
                return
            }
            // set SwiftUI-Binding
            parent.text = nsTextView.string
        }
        
        // Pass SwiftUI UndoManager to NSTextView
        func undoManager(for view: NSTextView) -> UndoManager? {
            parent.undoManger
        }

        // feel free to implement more delegate methods...
        
    }
    
}

用法

ContenView: View {
    @State private var text: String

    var body: some View {
        VStack {
            Text("Enter your text here:")
            CustomizableTextEditor(text: $text)
                .background(Color.red)
        }
            .frame(minWidth: 600, minHeight: 400)

    }
}

编辑:

  • 传递对 SwiftUI UndoManager 的引用,以便可以使用默认的撤消/重做操作。
  • 将 NSTextView 包裹在 NSScrollView 中,使其可滚动。将 NSTextView 的 minSize 属性设置为包含 SwiftUIView-Size,以便它填充整个允许的空间。

警告:只有此自定义文本编辑器的第一行可点击以启用文本编辑。

答案 2 :(得分:3)

iOS 和 macOS 上的纯 SwiftUI 解决方案

colorMultiply 是您的朋友。

struct ContentView: View {
    
    @State private var editingText: String = ""
    
    var body: some View {
        
        TextEditor(text: $editingText)
            .frame(width: 400, height: 100, alignment: .center)
            .cornerRadius(3.0)
            .colorMultiply(.gray)
    }
}