#swiftui
Вопрос:
Проблема в том, что я не понимаю, как исправить мое представление контента на экране и обрабатывать такие вещи, как вращение, или даже как сделать другие размеры экрана динамичными. Ниже приведен весь мой код просмотра. Когда я создаю новое приложение из коробки, оно выглядит хорошо в предварительном просмотре, так, как мне нравится. Тем не менее, размеры экрана меняются, и все, что мне нужно сделать, — это ввести магические числа, потому что нет супервизора или кадра для определения размера. Кроме того, я, кажется, не могу обрезать края экрана. Так что мой фоновый вид очень велик. Как это обрабатывается в SwiftUI?
import SwiftUI
import AuthenticationServices
struct LoginScreen: View {
var body: some View {
ZStack{
backgroundLayout
loginLayout
}
}
var loginLayout: some View {
VStack {
welcomeText
signInWithAppleButton
}
}
var backgroundLayout: some View {
ZStack{
Rectangle()
.foregroundColor(.init(.sRGB, red: 0, green: 0.750, blue: 0.750, opacity: 0.25))
Circle()
.foregroundColor(.blue)
.offset(x: 200, y: -200)
.aspectRatio(1/3, contentMode: .fill)
.clipped()
Circle()
.foregroundColor(.green)
.offset(x: -200, y: 200)
.aspectRatio(1/3, contentMode: .fill)
.clipped()
}
}
var welcomeText: some View {
HStack {
VStack {
Text("Sign Up")
.font(.largeTitle)
.bold()
Text("Sign In")
.font(.title)
.bold()
Text("Get Started!")
.font(.title2)
.bold()
}
.offset(x: -100, y: -150)
}
}
var signInWithAppleButton: some View {
SignInWithAppleButton(
.continue,
onRequest: { request in
request.requestedScopes = [.fullName, .email]
},
onCompletion: { result in
switch result {
case .success (let authenticationResults):
print("Authorization successful! :(authenticationResults)")
case .failure(let error):
print("Authorization failed: " error.localizedDescription)
}
}
)
.offset(x: 0, y: 150)
.frame(width: 200, height: 50, alignment: .center)
}
}
struct Login_Preview: PreviewProvider {
static var previews: some View {
LoginScreen()
}
}
Комментарии:
1. Если вы используете
ZStack
offset
, вы, вероятно, делаете что-то не так. ИспользуйтеVStack
илиHStack
вместо этого.2. Как я буду создавать слои с любым из них? И как бы я обрезал круги?
3. Вы, вероятно, захотите взглянуть на GeometryReader . Это дает вам контроль над чертежами, которые вы делаете. Со следующим обновлением SwiftUI вы также можете рассмотреть возможность использования a
Canvas
в качестве фона (хотя это все еще бета-версия).4. Я безуспешно пытался заглянуть в учебник геометрии. Не могли бы вы, пожалуйста, предоставить некоторый контекст того, как это могло бы удержать мое мнение с разумным смещением?
5. Чтобы понять ваше разочарование, я определенно был поставлен в тупик SwiftUI, особенно в самом начале. Было бы полезно разбить ваш вопрос на части, на которые можно ответить. Вот переписанный backgroundLayout , который делает фон размером с экран и центрирует круг в левом нижнем углу: gist.github.com/Baglan/7d16fa2dc124a436eac6eb62fda5ac8c
Ответ №1:
Попробовав несколько вещей, это все, что я смог придумать. Это не идеально и, конечно, не идеально, но, по крайней мере, работает примерно так, как ожидалось.
import SwiftUI
import AuthenticationServices
struct LoginScreen: View {
var body: some View {
loginLayout.background(backgroundLayout)
.statusBar(hidden: true)
}
var loginLayout: some View {
GeometryReader {geo in
VStack {
welcomeText.padding(.top, geo.size.height / 10)
Spacer()
signInWithAppleButton
.padding(.bottom, geo.size.height / 10)
}
}
}
var backgroundLayout: some View {
GeometryReader { geo in
let circleSize = min(geo.size.width, geo.size.height)
ZStack {
Rectangle()
.foregroundColor(.init(.sRGB, red: 0, green: 0.750, blue: 0.750, opacity: 0.25))
Circle()
.foregroundColor(.blue)
.offset(x: circleSize / 1.75,
y: -geo.size.height / 2.5)
.frame(width: circleSize, height: circleSize, alignment: .center)
Circle()
.foregroundColor(.green)
.offset(x: -circleSize / 1.75, y: geo.size.height / 2.5)
.frame(width: circleSize, height: circleSize, alignment: .center)
}
.frame(width: geo.size.width, height: geo.size.height, alignment: .top)
}
}
var welcomeText: some View {
GeometryReader { geo in
HStack {
VStack {
Text("Sign Up")
.font(.largeTitle)
.bold()
Text("Sign In")
.font(.title)
.bold()
Text("Get Started!")
.font(.title2)
.bold()
}
.padding(.leading, geo.size.width / 8)
Spacer()
}
}
}
var signInWithAppleButton: some View {
SignInWithAppleButton(
// Add this below for Continue with Apple button
.continue,
onRequest: { request in
request.requestedScopes = [.fullName, .email]
},
onCompletion: { result in
switch result {
case .success (let authenticationResults):
print("Authorization successful! :(authenticationResults)")
case .failure(let error):
print("Authorization failed: " error.localizedDescription)
}
}
)
.frame(width: 200, height: 50, alignment: .center)
}
}
struct Login_Preview: PreviewProvider {
static var previews: some View {
LoginScreen()
}
}