Вот кусок кода, половина закомментирована. В первой части текстовые элементы из массива находятся в VStack и каждый из них отображается в новой строке. Но при нажатии он дает подробную информацию об элементе массива, по которому щелкнули. Но во второй части текст объединяется и виден в абзаце. Но при щелчке он не может отобразить сведения о выбранном элементе. Мне просто нужно абзацное представление текста и каждый элемент, который можно щелкнуть.
Вот код
import SwiftUI
struct ContentView: View {
let dummyStrings = [
"1Lorem ipsum dolor sit amet",
"2consectetur adipiscing elit",
"3sed do eiusmod tempor incididunt",
"4ut labore et dolore magna aliqua",
"5Ut enim ad minim veniam",
"6quis nostrud exercitation ullamco",
"7laboris nisi ut aliquip ex ea commodo consequat",
"8Duis aute irure dolor in reprehenderit",
"9in voluptate velit esse cillum dolore",
"10 eu fugiat nulla pariatur"
]
var body: some View {
let concatenatedText = dummyStrings.joined(separator: " ")
return ScrollView {
Text(concatenatedText)
.font(.body)
.foregroundColor(.blue)
.lineSpacing(5)
.onTapGesture {
// Handle tap gesture here (e.g., print tapped portion)
print("Text tapped")
}
.padding()
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Один из способов — объединить все строки в AttributedString
, где с каждой строкой связан link
. link
будет URL
с любой информацией, которую вы хотите закодировать в нем. Затем вы можете перехватить действие openURL
и запустить любой код, который захотите.
Например, если вы хотите закодировать саму строку как путь URL-адреса
func encodeIntoAttributedString(_ str: String) -> AttributedString {
var attrStr = AttributedString(str)
attrStr.link = URL(filePath: str)
return attrStr
}
Используйте что-то вроде этого, чтобы соединить все вместе:
extension Array where Element == AttributedString {
func joined(separator: AttributedString = "") -> AttributedString {
guard let first else { return "" }
var result = first
for elem in self[1...] {
result += separator
result += elem
}
return result
}
}
Использование:
let text = [
"1Lorem ipsum dolor sit amet",
"2consectetur adipiscing elit",
"3sed do eiusmod tempor incididunt",
"4ut labore et dolore magna aliqua",
"5Ut enim ad minim veniam",
"6quis nostrud exercitation ullamco",
"7laboris nisi ut aliquip ex ea commodo consequat",
"8Duis aute irure dolor in reprehenderit",
"9in voluptate velit esse cillum dolore",
"10 eu fugiat nulla pariatur"
].map(encodeIntoAttributedString).joined(separator: " ")
var body: some View {
ScrollView {
Text(text)
// these modifiers could also be replaced by adding the corresponding attributes in encodeIntoAttributedString
.font(.body)
.foregroundColor(.blue)
.lineSpacing(5)
.padding()
.environment(\.openURL, OpenURLAction { x in
// here I am printing the string itself, which is encoded in the path
print(x.path(percentEncoded: false))
return .handled
})
}
}
Каким-то образом это работает, но URL-адрес всегда недействителен. Можете ли вы проверить это локально на своей стороне. @Подметальная машина
@MuaazAhmed да, URL-адреса недействительны, потому что мы просто кодируем в них строки, чтобы продемонстрировать, как узнать, какая часть текста прослушивается. Хотите ли вы, нажав на них, перейти на действительный URL-адрес? Измените encodeIntoAttributedString
, чтобы вместо этого использовать действительные URL-адреса.
Спасибо @Sweeper, сейчас мой источник данных находится в локальных файлах, просто предположим, что текущий случай, и при нажатии я хочу получить эту строку, нужно ли мне использовать какое-то другое решение?
@MuaazAhmed Мой ответ уже показывает вам, как это сделать. А именно, закодируйте строку в путь URL-адреса, а затем вы сможете получить ее, используя print(x.path(percentEncoded: false))
в замыкании OpenURLAction
.
var body: some View {
ScrollView {
HStack(alignment: .top, spacing: 0) {
ForEach(dummyStrings.indices, id: \.self) { index in
Text(dummyStrings[index])
.foregroundColor(.blue)
.onTapGesture {
print("Tapped on: \(dummyStrings[index])")
}
+ Text(index < dummyStrings.count - 1 ? " " : "")
}
}
.font(.body)
.lineSpacing(5)
.padding()
}
}
Попробуй это
Это позволит расположить каждую строку отдельно, вместо того, чтобы размещать объединенную строку как единый фрагмент текста.
Если цель состоит в том, чтобы каждый текстовый сегмент был ссылкой, вы можете использовать Markdown для встраивания ссылок в текст, см. Как показать HTML или Markdown в тексте SwiftUI?.