Há uma pergunta semelhante aqui no stackoverflow sobre como fazer isso quando todos são do mesmo tamanho, mas não quando são de tamanhos diferentes. Tenho 4 visualizações em um HStack que quero espaçar uniformemente, mas como o Picker é maior do que os outros 3, é impossível fazer isso usando o Spacer e, como agora são 4 em vez de 3, também não posso mais usar o alinhamento. Qual é a solução para garantir que todos sejam espaçados uniformemente?
import SwiftUI
@EnvironmentObject var captureDelegate: CaptureDelegate
let images = ["person.slash.fill", "person.fill", "person.2.fill", "person.2.fill", "person.2.fill"]
@Binding var timerPress: Bool
private var rotationAngle: Angle {
switch captureDelegate.orientationLast {
case .landscapeRight:
return .degrees(90)
case .landscapeLeft:
return .degrees(-90) // Fixes the upside-down issue
default:
return .degrees(0)
}
}
var body: some View {
HStack() {
Image(systemName: "gearshape")
.resizable()
.frame(width: 25, height: 25)
.foregroundStyle(captureDelegate.cameraPressed ? Color(white: 0.4) : .white )
.disabled(captureDelegate.cameraPressed)
.rotationEffect(rotationAngle)
.frame(maxWidth: .infinity, alignment: .leading)
.onTapGesture {
if !captureDelegate.cameraPressed {
}
}
Image(systemName: "timer")
.resizable()
.frame(width: 25, height: 25)
.foregroundStyle(captureDelegate.cameraPressed ? Color(white: 0.4) : .white )
.disabled(captureDelegate.cameraPressed)
.rotationEffect(rotationAngle)
.frame(maxWidth: .infinity)
.onTapGesture {
if !captureDelegate.cameraPressed {
timerPress.toggle()
}
}
Image(systemName: "timer")
.resizable()
.frame(width: 25, height: 25)
.foregroundStyle(captureDelegate.cameraPressed ? Color(white: 0.4) : .white )
.disabled(captureDelegate.cameraPressed)
.rotationEffect(rotationAngle)
.frame(maxWidth: .infinity)
.onTapGesture {
if !captureDelegate.cameraPressed {
timerPress.toggle()
}
}
Picker("Pick a number of people", selection: $captureDelegate.userSelectedNumber) {
ForEach(0...4, id: \.self) { i in
HStack(spacing: 70) {
Image(systemName: self.images[i])
.resizable()
.frame(width: 20, height: 20)
.rotationEffect(rotationAngle)
Text("\(i)")
.font(.system(size: 42))
.rotationEffect(rotationAngle)
}.tag(i)
.rotationEffect(rotationAngle)
}
}
.tint(.white)
.clipped()
.foregroundStyle(captureDelegate.cameraPressed ? Color(white: 0.4) : .white )
.disabled(captureDelegate.cameraPressed)
.rotationEffect(rotationAngle)
.animation(.easeInOut(duration: 0.5), value: rotationAngle)
.frame(maxWidth: .infinity, alignment: .trailing)
}
.font(.system(size: 24))
.padding([.leading,.trailing], 15)
}
}
Tentei usar o espaçador, mas não funciona porque eles não são todos do mesmo tamanho. Quando eu tinha 3 visualizações, obtive sucesso usando o alinhamento à esquerda no centro e à direita, mas agora que há 4 visualizações, não funciona mais.
Aqui tentei usar um ZStack para posicioná-los, colocando as duas vistas centrais no mesmo HStack:
ZStack {
HStack {
Image(systemName: "gearshape")
.resizable()
.frame(width: 25, height: 25)
.foregroundStyle(captureDelegate.cameraPressed ? Color(white: 0.4) : .white )
.disabled(captureDelegate.cameraPressed)
.rotationEffect(rotationAngle)
.frame(maxWidth: .infinity, alignment: .leading)
.onTapGesture {
if !captureDelegate.cameraPressed {
}
}
Picker("Pick a number of people", selection: $captureDelegate.userSelectedNumber) {
ForEach(0...4, id: \.self) { i in
HStack(spacing: 70) {
Image(systemName: self.images[i])
.resizable()
.frame(width: 20, height: 20)
.rotationEffect(rotationAngle)
Text("\(i)")
.font(.system(size: 42))
.rotationEffect(rotationAngle)
}.tag(i)
.rotationEffect(rotationAngle)
}
}
.tint(.white)
.clipped()
.foregroundStyle(captureDelegate.cameraPressed ? Color(white: 0.4) : .white )
.disabled(captureDelegate.cameraPressed)
.rotationEffect(rotationAngle)
.animation(.easeInOut(duration: 0.5), value: rotationAngle)
.frame(maxWidth: .infinity, alignment: .trailing)
}
HStack {
Text("\(captureDelegate.totalPhotosToTake)")
.font(.system(size: 15))
.foregroundStyle(.white)
.fontWeight(.bold)
.padding(.horizontal, 9)
.padding(.vertical, 5)
.overlay(
RoundedRectangle(cornerRadius: 5).stroke(.white, lineWidth: 2)
)
.frame(maxWidth: .infinity, alignment: .center)
Image(systemName: "timer")
.resizable()
.frame(width: 25, height: 25)
.foregroundStyle(captureDelegate.cameraPressed ? Color(white: 0.4) : .white )
.disabled(captureDelegate.cameraPressed)
.rotationEffect(rotationAngle)
.onTapGesture {
if !captureDelegate.cameraPressed {
timerPress.toggle()
}
}
.frame(maxWidth: .infinity, alignment: .center)
}
}
.font(.system(size: 24))
.padding([.leading,.trailing], 15)
E mudar os alinhamentos das duas vistas centrais de central para teste e entrelinha produz este efeito:
A tentativa do ZStack pode ser feita para funcionar com o uso de espaçadores para atingir o posicionamento de 1/3 e 2/3
Usar a
ZStack
é certamente uma maneira de dispor os itens. Não tenho certeza se sua solução usingSpacer
é precisa (especialmente porque anHStack
adiciona espaçamento entre os itens), mas ainda pode ser adequada para o propósito .Se você quer uma solução precisa, acho que a largura da tela precisa ser conhecida.
Quando a largura da tela é conhecida, a largura dos itens do meio pode ser ampliada para dois terços da largura da tela (com alinhamento central). Então, esses itens podem ser alinhados à borda inicial ou final do
ZStack
usando um quadro commaxWidth: .infinity
(como para o primeiro e o último itens).Seus itens estão espalhados por toda a largura da tela. Então, uma maneira de encontrar a largura da tela é usar
.containerRelativeFrame
. O contêiner, neste caso, é a tela.Como o alinhamento dos itens do meio é baseado na largura total da tela, você não deve aplicar nenhum preenchimento horizontal ao contêiner (agora o
ZStack
). Para manter o primeiro e o último itens longe das laterais, aplique preenchimento a esses itens individualmente.Visualmente, isso ainda não parece muito certo para mim. Mas agora você tem mais controle do espaçamento, então o layout pode ser ajustado, seja alterando a fração da largura da tela para os itens do meio, ou alterando o preenchimento. Por exemplo:
Picker
)ZStack