AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / user-25330435

Artem T's questions

Martin Hope
Artem T
Asked: 2025-04-07 21:51:03 +0800 CST

SwiftUI alinha a visualização para centralizar scrollView

  • 5

Minha tarefa é criar uma scrollview, que recebe um array de strings e uma sobreposição, localizada no centro. Quando alguma visualização entra nessa sobreposição, ela deve se alinhar imediatamente às suas bordas, ou seja, estar no centro da tela. A lista deve começar no meio da tela com o primeiro elemento. Eu estava procurando uma solução aqui .

Eu tenho estrutura

struct Region: Equatable, Hashable {
    let name: String
}

Estrutura de Chave de Preferência

struct ViewOffsetKey: PreferenceKey {
    static var defaultValue: [String: CGRect] = [:]
    
    static func reduce(value: inout [String: CGRect], nextValue: () -> [String: CGRect]) {
        value.merge(nextValue(), uniquingKeysWith: { $1 })
    }
}

e subView

struct RegionView: View {
    
    let name: String
    
    var body: some View {
        HStack {
            Text(self.name)
                .foregroundColor(.white)
                .font(.system(.body))
            
            Spacer()
        }
        .padding(16)
        .frame(width: 348, alignment: .topLeading)
        .background(Color.black)
        .cornerRadius(50)
        .id(name)
        .background(GeometryReader {
            Color.clear.preference(key: ViewOffsetKey.self,
                                   value: [name: $0.frame(in: .global)])
        })
    }
}

A visualização principal é realizada por meio de CurrentValueSubject e AnyPublisher. Verifico se a subView intercepta um retângulo com altura 1 e, em seguida, a escrevo como exibida. Quando a rolagem termina, chamo o método scrollTo.

struct RegionListView: View {
    let detector: CurrentValueSubject<[String: CGRect], Never>
    let publisher: AnyPublisher<[String: CGRect], Never>
    
    let regions: [Region] = [
        Region(name: "Region 1"),
        Region(name: "Region 2"),
        Region(name: "Region 3"),
        Region(name: "Region 4"),
        Region(name: "Region 5"),
        Region(name: "Region 6"),
        Region(name: "Region 7"),
        Region(name: "Region 8"),
        Region(name: "Region 9"),
        Region(name: "Region 10"),
        Region(name: "Region 11"),
        Region(name: "Region 12"),
        Region(name: "Region 13"),
        Region(name: "Region 14"),
        Region(name: "Region 15"),
        Region(name: "Region 16"),
        Region(name: "Region 17"),
        Region(name: "Region 18"),
        Region(name: "Region 19"),
        Region(name: "Region 20"),
    ]
    
    @State private var topVisibleChildId: String?
    
    init() {
        let detector = CurrentValueSubject<[String: CGRect], Never>([:])
        self.publisher = detector
            .debounce(for: .seconds(0.1), scheduler: DispatchQueue.main)
            .dropFirst()
            .eraseToAnyPublisher()
        self.detector = detector
    }
    
    var body: some View {
        GeometryReader { geometryReader in
            ScrollViewReader { proxy in
                ScrollView {
                    VStack(spacing: 8) {
                        ForEach(self.regions, id: \.self) { region in
                            RegionView(name: region.name)
                        }
                    }
                    .frame(maxWidth: .infinity)
                    .onPreferenceChange(ViewOffsetKey.self) { childFrames in
                        detector.send(childFrames)
                        
                        var visibleChildIds = [String]()
                        let screenMid = geometryReader.size.height / 2 + 56
                        
                        for (id, childFrame) in childFrames where childFrame.intersects(CGRect(x: 0, y: Int(screenMid), width: .max, height: 56)) {
                            print("id \(id) childFrame \(childFrame)")
                            visibleChildIds.append(id)
                        }
                        
                        visibleChildIds.sort()
                        
                        if let first = visibleChildIds.first {
                            topVisibleChildId = first
                        }
                    }
                }
                .safeAreaPadding(.top, geometryReader.size.height / 2 - 28)
                .safeAreaPadding(.bottom, geometryReader.size.height / 2 - 28)
                .background(Color.black)
                .onReceive(publisher) { _ in
                    proxy.scrollTo(topVisibleChildId, anchor: .center)
                }
                .overlay(
                    Text("Top Visible Child: \(topVisibleChildId ?? "")")
                        .padding()
                        .background(Color.blue.opacity(1))
                        .foregroundColor(.white)
                        .cornerRadius(10),
                    alignment: .top
                )
                
                .overlay(
                    Rectangle()
                        .frame(maxWidth: .infinity)
                        .frame(height: 56)
                        .foregroundColor(Color.clear)
                        .border(.green, width: 4),
                    alignment: .center
                )
            }
        }
    }
}

Minha pergunta: é possível implementar um comportamento em que a mudança de células seja semelhante à escolha de um horário ao definir um alarme? Ou seja, a célula não precisará ser rolada para o centro se o usuário não terminar de rolar no meio. Espero ter explicado claramente.

  • 1 respostas
  • 39 Views

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Reformatar números, inserindo separadores em posições fixas

    • 6 respostas
  • Marko Smith

    Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não?

    • 2 respostas
  • Marko Smith

    Problema com extensão desinstalada automaticamente do VScode (tema Material)

    • 2 respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Martin Hope
    Fantastic Mr Fox Somente o tipo copiável não é aceito na implementação std::vector do MSVC 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant Encontre o próximo dia da semana usando o cronógrafo 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor O inicializador de membro do construtor pode incluir a inicialização de outro membro? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul O C++20 mudou para permitir a conversão de `type(&)[N]` de matriz de limites conhecidos para `type(&)[]` de matriz de limites desconhecidos? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann Como/por que {2,3,10} e {x,3,10} com x=2 são ordenados de forma diferente? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve