我正在尝试在登录页面上构建一个简单的加载微调器视图,用于调用LoginAPI的按钮位于VStack中,然后位于HStack中->将“登录按钮”放在屏幕底部。 我还在不同的提取视图上创建了所有屏幕,这意味着我在主contentView上没有所有上下文
出于上下文目的,触发加载微调器视图(成功/失败的登录)的信息位于屏幕底部的子视图中,然后微调器视图根据其父视图的边界居中->位于底部
我的最终目标是将加载微调器视图放置在屏幕中央。有没有一种方法可以覆盖父视图的所有约束,并迫使子视图位于所有其他视图的顶部并居中?
当前输出:
正在加载蜘蛛视图:
struct LoadingIndicator: View {
@State var animate = false
var body : some View {
GeometryReader{ geo in
VStack{
Circle()
.trim(from: 0, to: 0.8)
.stroke(AngularGradient(gradient: .init(colors: [.orange,.yellow]), center: .center), style: StrokeStyle(lineWidth: 8, lineCap: .round))
.frame(width: 45, height: 45,alignment: .center)
.rotationEffect(.init(degrees: self.animate ? 360 : 0))
.animation(Animation.linear(duration: 0.7).repeatForever(autoreverses: false))
Text("Please Wait...")
.padding(.top)
}.padding(20)
.background(Color.white)
.cornerRadius(15)
.onAppear{
self.animate.toggle()
}
}
.background(Color.black.opacity(0.45).edgesIgnoringSafeArea(.all))
.edgesIgnoringSafeArea(.all)
}
}
登录按钮视图-触发正在加载的纺纱器视图
struct LoginButton: View {
@Binding var email: String
@Binding var pwd: String
@Binding var token: String
@Binding var userIdentification: String
@Binding var isAuthorized: Bool
@State var animateLoading = false
let accountModuleLoginAPI = APIGlobalVariables.AccountModule.Login
var body: some View {
ZStack{
VStack{
// disable back button from navigation view
NavigationLink(destination: DriverLocationMapView()
.onAppear(){
self.animateLoading = false
}
.navigationBarBackButtonHidden(true)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
.edgesIgnoringSafeArea(.all), isActive: self.$isAuthorized){
Text("")
}
Button(action: {
// payload data initialization
let loginData = LoginPayload(username: self.email, password: self.pwd)
let postRequest = APIRequest(endpoint: self.accountModuleLoginAPI)
print("login data: \(loginData.username) and \(loginData.password)")
print("post request: \(postRequest)")
self.animateLoading = true
postRequest.loginRequest(loginData, completion: { result in
switch result{
case .success(let message):
print("Success Message: \(message)")
do{
self.token = try result.get().token
self.userIdentification = try result.get().userIdentification
self.isAuthorized = true
print("userIdentification: \(self.userIdentification)")
print("token: \(self.token)")
}catch{
print("catch")
self.animateLoading = false
self.isAuthorized = false
}
case .failure(let failure):
print("Failure Message: \(failure)")
self.animateLoading = false
self.isAuthorized = false
}
})
})
{
Text("Login")
.font(.headline)
.frame(width: 140, height: 35)
.background(Color.black)
.foregroundColor(Color.white)
.clipShape(Capsule())
.padding(10)
} } if self.animateLoading {
LoadingIndicator()
} } } }
主要内容视图-创建布局和登录按钮的位置
struct ContentView: View {
@State var email = "";
@State var pwd = "";
@State var height: CGFloat = 0;
@State var token = "";
@State var AccessTypeIndex = 0
@State var userIdentification = ""
@State var isAuthorized = false
var body: some View {
NavigationView {
ScrollView(self.height == 0 ? .init() : .vertical, showsIndicators: false){
ZStack {
BackgroundImage()
VStack{
//LogoImage()
AccessType(AccessTypeIndex: self.$AccessTypeIndex)
if AccessTypeIndex==0 {
LoginInputFields(email: self.$email, pwd: self.$pwd)
LoginButton(email: self.$email, pwd: self.$pwd, token: self.$token, userIdentification: self.$userIdentification, isAuthorized: self.$isAuthorized)
}else if AccessTypeIndex==1{
// register fieds
SignUpView()
}
}
.padding(.top, UIApplication.shared.windows.first?.safeAreaInsets.top)
.padding(.bottom, UIApplication.shared.windows.first?.safeAreaInsets.bottom)
}
}.padding(.bottom, self.height)
.background(Color.black.opacity(0.03).edgesIgnoringSafeArea(.all))
.edgesIgnoringSafeArea(.all)
.onAppear{
// keyboard did show
NotificationCenter.default.addObserver(forName: UIResponder.keyboardDidShowNotification, object: nil, queue: .main) { (not) in
let data = not.userInfo![UIResponder.keyboardFrameEndUserInfoKey] as! NSValue
let keyboardheight = data.cgRectValue.height
self.height = keyboardheight - (UIApplication.shared.windows.first?.safeAreaInsets.bottom)!
print(self.height)
}
// keyboard did hide
NotificationCenter.default.addObserver(forName: UIResponder.keyboardDidHideNotification, object: nil, queue: .main) { (_) in
self.height = 0
print(self.height)
}
}
}
}
}
谢谢, 丹尼尔
答案 0 :(得分:2)
有两种方法可以实现这一目标:
ZStack {
VStack(spacing: 0) {
}
if self.loading {
LoadingIndicator()
}
}
现在,由于我们已经将所有内容包装在ZStack中,因此底部的内容将显示在所有内容的顶部(忽略它)。因此,您的LoadingIndicator将显示在其父项的中心(现在是整个屏幕)。我将它包装在if中,因为如果某些名为loading的变量设置为true,我只想显示该指标。您可以尝试搜索有关ZStack示例用法的信息,我相信那里有很多。
VStack(spacing: 0) {
}
.overlay(
if self.loading {
LoadingIndicator()
}
)
它以相同的原理工作。请注意,您可能需要将if语句包装在Group {}或VStack {}或else中。