In a Multiplatform SwiftUI app I'm developing, I have a Text view embedded in a scroll view. I want to add a long press gesture to the Text view that lets the user copy the contents to the clipboard.
When I do that, the iOS version no longer scrolls the text when you press on the contents and drag. Below is the code in question. Is there a way to support both scrolling and a long press gesture recognizer?
(In UIKit you can make a gesture recognizer only fire when others fail. I suspect the long press gesture recognizer is intercepting the touch event and preventing the ScrollView from getting it.)
ScrollView() {
// MARK: Resuts word list
Text(anagramsState.wordList)
.lineLimit(nil)
.multilineTextAlignment(.leading)
.frame(minWidth: geometry.size.width - 2, minHeight: 20, alignment: .topLeading)
.onLongPressGesture {
if copyTextToClipboard(anagramsState.wordList) {
anagramsState.statusMessage = "Results copied to clipboard."
} else {
anagramsState.statusMessage = "Long press ignored."
}
}
}
SwiftUI currently has very few modifiers that allows you to fiddle with the built-in gesture recognisers of scroll views. The only one I can think of off the top of my head is presentationContentInteraction
, which is rather irrelevant here.
If your goal is to just allow the user to copy the entirety of the Text
, you can use textSelection
:
Text("some text")
.textSelection(.enabled)
Note that the behaviour on macOS is different from that on iOS:
On macOS, people use the mouse or trackpad to select a range of text, which they can quickly copy by choosing Edit > Copy, or with the standard keyboard shortcut.
On iOS, the person using the app touches and holds on a selectable
Text
view, which brings up a system menu with menu items appropriate for the current context. These menu items operate on the entire contents of theText
view; the person can’t select a range of text like they can on macOS.
If the ScrollView
contains only the Text
, consider using a TextEditor
instead. You can pass it a constant
binding to disable editing:
TextEditor(text: .constant("Some Text"))
This allows selecting specific ranges of text.