Ios 如何在SwiftUI上将来电视图显示为顶部?
我试图模拟如何在所有视图的顶部显示调用视图。但我有一些不明确的观点:Ios 如何在SwiftUI上将来电视图显示为顶部?,ios,swift,swiftui,Ios,Swift,Swiftui,我试图模拟如何在所有视图的顶部显示调用视图。但我有一些不明确的观点: 有没有办法让它变得更简单 在这种情况下,视图层次结构是否受保护 AppView.swift import SwiftUI struct AppView: View { @ObservedObject var callVM: CallViewModel init() { self.callVM = CallViewModel() } var bo
- 有没有办法让它变得更简单
- 在这种情况下,视图层次结构是否受保护
import SwiftUI
struct AppView: View {
@ObservedObject var callVM: CallViewModel
init() {
self.callVM = CallViewModel()
}
var body: some View {
VStack {
IncomingCallView(rootView: appView, isActive: self.$callVM.isIncomingCallActive)
TabView {
TabOne()
.tabItem {
Image(systemName: "list.dash")
Text("Menu")
}
TabTwo()
.tabItem {
Image(systemName: "square.and.pencil")
Text("Order")
}
}
}
.onAppear(perform: load)
}
var appView: some View {
Text("")
}
func load() {
self.callVM.getCall()
}
}
struct AppView_Previews: PreviewProvider {
static var previews: some View {
AppView()
}
}
import SwiftUI
struct IncomingCallView<RootView: View>: View {
private let rootView: RootView
@Binding var isActive: Bool
init(rootView: RootView, isActive: Binding<Bool>) {
self.rootView = rootView
self._isActive = isActive
}
var body: some View {
rootView
.background(Activator(isActive: $isActive))
}
struct Activator: UIViewRepresentable {
@Binding var isActive: Bool
@State private var myWindow: UIWindow? = nil
func makeUIView(context: Context) -> UIView {
let view = UIView()
DispatchQueue.main.async {
self.myWindow = view.window
}
return view
}
func updateUIView(_ uiView: UIView, context: Context) {
guard let holder = myWindow?.rootViewController?.view else { return }
if isActive && context.coordinator.controller == nil {
context.coordinator.controller = UIHostingController(rootView: loadingView)
let view = context.coordinator.controller!.view
view?.backgroundColor = UIColor.black.withAlphaComponent(1)
view?.isUserInteractionEnabled = true
view?.translatesAutoresizingMaskIntoConstraints = false
holder.addSubview(view!)
holder.isUserInteractionEnabled = true
view?.leadingAnchor.constraint(equalTo: holder.leadingAnchor).isActive = true
view?.trailingAnchor.constraint(equalTo: holder.trailingAnchor).isActive = true
view?.topAnchor.constraint(equalTo: holder.topAnchor).isActive = true
view?.bottomAnchor.constraint(equalTo: holder.bottomAnchor).isActive = true
} else if !isActive {
context.coordinator.controller?.view.removeFromSuperview()
context.coordinator.controller = nil
holder.isUserInteractionEnabled = true
}
}
func makeCoordinator() -> Coordinator {
Coordinator()
}
class Coordinator {
var controller: UIViewController? = nil
}
private var loadingView: some View {
HStack(spacing: 20) {
Button(action: {
print("acceptCall pressed")
// change UI for accepted call
}) {
Image("acceptCall")
.resizable()
.frame(width: 50, height: 50, alignment: .center)
.aspectRatio(contentMode: .fit)
}
Button(action: {
// close the view
print("rejectCall pressed")
self.isActive = false
}) {
Image("rejectCall")
.resizable()
.frame(width: 50, height: 50, alignment: .center)
.aspectRatio(contentMode: .fit)
}
}
.frame(width: 300, height: 300)
.background(Color.primary.opacity(0.7))
.cornerRadius(10)
}
}
}
CallViewModel.swift
import Foundation
class CallViewModel: ObservableObject {
@Published public var isIncomingCallActive = Bool()
init() {
self.isIncomingCallActive = false
}
func getCall() {
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
self.isIncomingCallActive = true
}
}
}
IncomingCallView.swift
import SwiftUI
struct AppView: View {
@ObservedObject var callVM: CallViewModel
init() {
self.callVM = CallViewModel()
}
var body: some View {
VStack {
IncomingCallView(rootView: appView, isActive: self.$callVM.isIncomingCallActive)
TabView {
TabOne()
.tabItem {
Image(systemName: "list.dash")
Text("Menu")
}
TabTwo()
.tabItem {
Image(systemName: "square.and.pencil")
Text("Order")
}
}
}
.onAppear(perform: load)
}
var appView: some View {
Text("")
}
func load() {
self.callVM.getCall()
}
}
struct AppView_Previews: PreviewProvider {
static var previews: some View {
AppView()
}
}
import SwiftUI
struct IncomingCallView<RootView: View>: View {
private let rootView: RootView
@Binding var isActive: Bool
init(rootView: RootView, isActive: Binding<Bool>) {
self.rootView = rootView
self._isActive = isActive
}
var body: some View {
rootView
.background(Activator(isActive: $isActive))
}
struct Activator: UIViewRepresentable {
@Binding var isActive: Bool
@State private var myWindow: UIWindow? = nil
func makeUIView(context: Context) -> UIView {
let view = UIView()
DispatchQueue.main.async {
self.myWindow = view.window
}
return view
}
func updateUIView(_ uiView: UIView, context: Context) {
guard let holder = myWindow?.rootViewController?.view else { return }
if isActive && context.coordinator.controller == nil {
context.coordinator.controller = UIHostingController(rootView: loadingView)
let view = context.coordinator.controller!.view
view?.backgroundColor = UIColor.black.withAlphaComponent(1)
view?.isUserInteractionEnabled = true
view?.translatesAutoresizingMaskIntoConstraints = false
holder.addSubview(view!)
holder.isUserInteractionEnabled = true
view?.leadingAnchor.constraint(equalTo: holder.leadingAnchor).isActive = true
view?.trailingAnchor.constraint(equalTo: holder.trailingAnchor).isActive = true
view?.topAnchor.constraint(equalTo: holder.topAnchor).isActive = true
view?.bottomAnchor.constraint(equalTo: holder.bottomAnchor).isActive = true
} else if !isActive {
context.coordinator.controller?.view.removeFromSuperview()
context.coordinator.controller = nil
holder.isUserInteractionEnabled = true
}
}
func makeCoordinator() -> Coordinator {
Coordinator()
}
class Coordinator {
var controller: UIViewController? = nil
}
private var loadingView: some View {
HStack(spacing: 20) {
Button(action: {
print("acceptCall pressed")
// change UI for accepted call
}) {
Image("acceptCall")
.resizable()
.frame(width: 50, height: 50, alignment: .center)
.aspectRatio(contentMode: .fit)
}
Button(action: {
// close the view
print("rejectCall pressed")
self.isActive = false
}) {
Image("rejectCall")
.resizable()
.frame(width: 50, height: 50, alignment: .center)
.aspectRatio(contentMode: .fit)
}
}
.frame(width: 300, height: 300)
.background(Color.primary.opacity(0.7))
.cornerRadius(10)
}
}
}
导入快捷界面
结构IncomingCallView:视图{
私有let rootView:rootView
@绑定变量是活动的:Bool
init(rootView:rootView,isActive:Binding){
self.rootView=rootView
self.\u isActive=isActive
}
var body:一些观点{
根视图
.background(激活器(isActive:$isActive))
}
结构激活器:UIViewRepresentable{
@绑定变量是活动的:Bool
@状态私有变量myWindow:UIWindow?=nil
func makeUIView(上下文:context)->UIView{
let view=UIView()
DispatchQueue.main.async{
self.myWindow=view.window
}
返回视图
}
func updateUIView(uiView:uiView,context:context){
guard let holder=myWindow?.rootViewController?.view else{return}
如果isActive&&context.coordinator.controller==nil{
context.coordinator.controller=UIHostingController(根视图:loadingView)
让view=context.coordinator.controller!.view
视图?.backgroundColor=UIColor.black.withAlphaComponent(1)
视图?.isUserInteractionEnabled=true
视图?.translatesAutoResizengMaskintoConstraints=false
holder.addSubview(视图!)
holder.isUserInteractionEnabled=true
视图?.leadingAnchor.constraint(等式:holder.leadingAnchor).isActive=true
视图?.trailingAnchor.constraint(等式:holder.trailingAnchor).isActive=true
视图?.topAnchor.constraint(等式:holder.topAnchor).isActive=true
视图?.bottomAnchor.constraint(等式:holder.bottomAnchor).isActive=true
}否则,我会主动的{
context.coordinator.controller?.view.removeFromSuperview()
context.coordinator.controller=nil
holder.isUserInteractionEnabled=true
}
}
func makeCoordinator()->Coordinator{
协调员()
}
班级协调员{
var控制器:UIViewController?=nil
}
私有变量加载视图:一些视图{
HStack(间距:20){
按钮(操作:{
打印(“按下接受呼叫”)
//更改已接受呼叫的用户界面
}) {
图像(“接受呼叫”)
.可调整大小()
.框架(宽度:50,高度:50,对齐:。中心)
.aspectRatio(内容模式:.fit)
}
按钮(操作:{
//关闭视图
打印(“拒绝呼叫已按下”)
self.isActive=false
}) {
图像(“拒绝呼叫”)
.可调整大小()
.框架(宽度:50,高度:50,对齐:。中心)
.aspectRatio(内容模式:.fit)
}
}
.框架(宽度:300,高度:300)
.背景(颜色.主色.不透明度(0.7))
.转弯半径(10)
}
}
}
swiftUI中的某些东西看起来像这样
struct-AppView:View{
@StateObject变量callVM=CallViewModel()
var body:一些观点{
ZStack{
TabView{
文本(“TabOne”)
.tabItem{
图像(系统名称:“list.dash”)
文本(“菜单”)
}
文本(“TabTwo”)
.tabItem{
图像(系统名称:“正方形和铅笔”)
文本(“命令”)
}
}
如果callVM.isIncomingCallActive{
ZStack{
颜色:绿色
VStack{
文本(“来电…”)
按钮(操作:{callVM.isIncomingCallActive=false}){
文本(“取消”)
}
}
}.edgesIgnoringSafeArea(.all)//你为什么在这里使用UIViewRepresentable
?为什么不在SwiftUI中全部使用?@youjin我发现你下面的建议在展示图纸模型时不起作用。你还有其他建议吗?看起来我应该返回UIViewRepresentable。问题是:嗨,谢谢。但我看到一些空白对于顶部(状态栏)和底部安全区域。我们可以全部覆盖它们吗?编辑代码以覆盖所有安全区域。刚刚添加了。edgesIgnoringSafeArea
,现在看起来和预期的一样。我设置了ObservedObject,它会继续工作。StateObject要求iOS14作为最低部署目标。同时,观察我认为的更改也会更好。