Объедините несколько строк, каждая из которых должна быть кликабельна отдельно

Вот кусок кода, половина закомментирована. В первой части текстовые элементы из массива находятся в 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()
    }
}

Если цель состоит в том, чтобы каждый текстовый сегмент был ссылкой, вы можете использовать Markdown для встраивания ссылок в текст, см. Как показать HTML или Markdown в тексте SwiftUI?.

Benzy Neez 03.05.2024 13:42
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
1
87
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Один из способов — объединить все строки в 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-адрес всегда недействителен. Можете ли вы проверить это локально на своей стороне. @Подметальная машина

Muaaz Ahmed 03.05.2024 18:35

@MuaazAhmed да, URL-адреса недействительны, потому что мы просто кодируем в них строки, чтобы продемонстрировать, как узнать, какая часть текста прослушивается. Хотите ли вы, нажав на них, перейти на действительный URL-адрес? Измените encodeIntoAttributedString, чтобы вместо этого использовать действительные URL-адреса.

Sweeper 04.05.2024 02:24

Спасибо @Sweeper, сейчас мой источник данных находится в локальных файлах, просто предположим, что текущий случай, и при нажатии я хочу получить эту строку, нужно ли мне использовать какое-то другое решение?

Muaaz Ahmed 04.05.2024 10:09

@MuaazAhmed Мой ответ уже показывает вам, как это сделать. А именно, закодируйте строку в путь URL-адреса, а затем вы сможете получить ее, используя print(x.path(percentEncoded: false)) в замыкании OpenURLAction.

Sweeper 04.05.2024 10:11
  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()
    }
}

Попробуй это

Это позволит расположить каждую строку отдельно, вместо того, чтобы размещать объединенную строку как единый фрагмент текста.

Sweeper 03.05.2024 11:30

Другие вопросы по теме