全屏显示中心儿童视图

时间:2020-06-26 08:56:43

标签: swiftui

我正在尝试在登录页面上构建一个简单的加载微调器视图,用于调用LoginAPI的按钮位于VStack中,然后位于HStack中->将“登录按钮”放在屏幕底部。 我还在不同的提取视图上创建了所有屏幕,这意味着我在主contentView上没有所有上下文

出于上下文目的,触发加载微调器视图(成功/失败的登录)的信息位于屏幕底部的子视图中,然后微调器视图根据其父视图的边界居中->位于底部

我的最终目标是将加载微调器视图放置在屏幕中央。有没有一种方法可以覆盖父视图的所有约束,并迫使子视图位于所有其他视图的顶部并居中?

当前输出:

The loading image should be placed on the middle of the screen

正在加载蜘蛛视图:

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)
                }
            }
        }
    }
}

谢谢, 丹尼尔

1 个答案:

答案 0 :(得分:2)

有两种方法可以实现这一目标:

使用ZStack

ZStack {
   VStack(spacing: 0) {
                                     
   } 

   if self.loading {
     LoadingIndicator() 
   }            
}

现在,由于我们已经将所有内容包装在ZStack中,因此底部的内容将显示在所有内容的顶部(忽略它)。因此,您的LoadingIndicator将显示在其父项的中心(现在是整个屏幕)。我将它包装在if中,因为如果某些名为loading的变量设置为true,我只想显示该指标。您可以尝试搜索有关ZStack示例用法的信息,我相信那里有很多。

使用.overlay()

VStack(spacing: 0) {
                                     
}
.overlay(
   if self.loading {
     LoadingIndicator() 
   } 
)

它以相同的原理工作。请注意,您可能需要将if语句包装在Group {}或VStack {}或else中。