How to make a text appear on the screen after pressing the button? - swift

I want to make the text display on the screen according to the different scenes after pressing the button. For example, if model A is displayed, text "A" will be appeared on the screen. Similarly, if model B is displayed, text "B" will also be appeared. I am currently creating Augmented Reality app using SwiftUI interface and RealityKit but not sure what to do in the next step.
Here is my code:
import SwiftUI
import RealityKit
struct ContentView : View {
#State var arView = ARView(frame: .zero)
var body: some View {
ZStack {
ARViewContainer(arView: $arView)
HStack {
Spacer()
Button("information") {
print(self.arView.scene.name)
print(arView.scene.anchors.startIndex)
print(arView.scene.anchors.endIndex)
}
Spacer()
Button("remove") {
stop()
}
Spacer()
}
} .edgesIgnoringSafeArea(.all)
}
func stop() {
arView.scene.anchors.removeAll()
}
}
struct ARViewContainer: UIViewRepresentable {
#Binding var arView: ARView
func makeUIView(context: Context) -> ARView {
let boxAnchor = try! Experience1.loadBox()
let crownAnchor = try! Experience1.loadCrown()
arView.scene.anchors.append(boxAnchor)
arView.scene.anchors.append(crownAnchor)
return arView
}
func updateUIView(_ uiView: ARView, context: Context) { }
}
From the code above, if boxAnchor and crownAnchor and displayed, text "Box" and "Crown" will be appeared on the screen respectively. Anyone who knows how to do that please guide me or suggest a tutorial that I can use to study.
Sorry if I use the wrong technical terms. Thank you

Use Combine's reactive subscriber and MVVM's bindings to update string values for Text views.
import SwiftUI
import RealityKit
import Combine
struct ContentView : View {
#State private var arView = ARView(frame: .zero)
#State private var str01: String = "...some text..."
#State private var str02: String = "...some text..."
var body: some View {
ZStack {
ARViewContainer(arView: $arView, str01: $str01, str02: $str02)
.ignoresSafeArea()
VStack {
Spacer()
Text(str01)
.foregroundColor(.white)
.font(.largeTitle)
Divider()
Text(str02)
.foregroundColor(.white)
.font(.largeTitle)
Spacer()
}
}
}
}
The miracle happens in the escaping closure of subscribe(to:) instance method. What will be the conditions in the if-statements is up to you.
struct ARViewContainer: UIViewRepresentable {
#Binding var arView: ARView
#Binding var str01: String
#Binding var str02: String
#State var subs: [AnyCancellable] = []
func makeUIView(context: Context) -> ARView {
let boxAnchor = try! Experience.loadBox()
let crownAnchor = try! Experience.loadCrown()
print(arView.scene.anchors.count)
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
arView.scene.anchors.append(boxAnchor)
arView.scene.anchors.append(crownAnchor)
print(arView.scene.anchors.count)
}
return arView
}
func updateUIView(_ view: ARView, context: Context) {
DispatchQueue.main.async {
_ = view.scene.subscribe(to: SceneEvents.DidAddEntity.self) { _ in
if view.scene.anchors.count > 0 {
if view.scene.anchors[0].isAnchored {
str01 = "Crown"
str02 = "Cube"
}
}
}.store(in: &subs)
}
}
}

Related

Create sphere when screen tapped with adjustable radius in RealityKit [duplicate]

I'm creating an app in RealityKit that generates a shape based on user input. For example, if the user enters a radius of 0.1 meters, the shape (sphere in my case) will have a radius of 0.1 meters, same logic for 0.2, 0.3, etc. The code all works, but I want to make it so the sphere appears when the user taps the screen.
Here is my code for the page that takes in user input:
class UserInput: ObservableObject {
#Published var score: Float = 0.0
}
struct PreviewView: View {
#ObservedObject var input = UserInput()
var body: some View {
NavigationView {
ZStack {
Color.black
VStack {
Text("Change the radius of your AR sphere")
.foregroundColor(.white)
Text("\(String(format: "%.1f", self.input.score)) meters")
.foregroundColor(.white)
.bold()
.font(.title)
.padding(10)
Button(action: {self.input.score += 0.1})
{
Text("Increment by 0.1 meters")
}
.padding(10)
Button(action: {self.input.score -= 0.1})
{
Text("Decrease by 0.1 meters")
}
.padding(10)
NavigationLink(destination: Reality(input: self.input)) {
Text("View in AR")
.bold()
.padding(.top,30)
}
}
}
.ignoresSafeArea()
}
}
Here is the code for the Reality ARView:
struct Reality: UIViewRepresentable {
#ObservedObject var input: UserInput
func makeUIView(context: Context) -> ARView {
let arView = ARView(frame: .zero)
let model = ModelEntity(mesh: .generateSphere(radius: input.score))
let anchor = AnchorEntity(plane: .horizontal)
anchor.addChild(model)
arView.scene.anchors.append(anchor)
return arView
}
func updateUIView(_ uiView: ARView, context: Context) {}
}
There are tons of examples of generating shapes when the user touches the screen, that's not my issue. The fact that I'm taking in user input is what makes this difficult.
Here is some code that does what I want, but without user input. It has some physics built in that I plan on implementing once I get the user input to work.
struct ARViewContainer: UIViewRepresentable {
func makeUIView(context: Context) -> ARView {
let arView = ARView(frame: .zero)
let planeAnchorEntity = AnchorEntity(plane: .horizontal)
let plane = ModelEntity(mesh: MeshResource.generatePlane(width: 1, depth: 1), materials: [SimpleMaterial(color: .white, isMetallic: true)])
plane.physicsBody = PhysicsBodyComponent(massProperties: .init(mass: 1), material: .generate(friction: 1, restitution: 1), mode: .kinematic)
plane.generateCollisionShapes(recursive: true)
planeAnchorEntity.addChild(plane)
arView.scene.anchors.append(planeAnchorEntity)
arView.installGestures([.scale,.rotation], for: plane)
arView.addGestureRecognizer(UITapGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.handleTap)))
context.coordinator.view = arView
return arView
}
func makeCoordinator() -> Coordinator {
Coordinator()
}
func updateUIView(_ uiView: ARView, context: Context) {}
}
Here is the Coordinator class that generates the box that I want to be adjustable in size:
class Coordinator {
weak var view: ARView?
#objc func handleTap(_ recognizer: UITapGestureRecognizer) {
guard let view = view else { return }
let location = recognizer.location(in: view)
let results = view.raycast(from: location, allowing: .estimatedPlane, alignment: .horizontal)
if let result = results.first {
let anchorEntity = AnchorEntity(raycastResult: result)
let box = ModelEntity(mesh: MeshResource.generateBox(size: 0.3),materials: [SimpleMaterial(color: .black, isMetallic: true)])
box.physicsBody = PhysicsBodyComponent(massProperties: .init(mass: 0.5), material: .generate(), mode: .dynamic)
box.generateCollisionShapes(recursive: true)
box.position = simd_make_float3(0,0.7,0)
//static means body cannot be moved
//dynamic means it can move
//kinematic means user moved the object
anchorEntity.addChild(box)
view.scene.anchors.append(anchorEntity)
}
}
}
I tried fusing these two projects into what I want, but I get all sorts of errors I have no idea how to fix, and when I try something new, a bunch of other errors appear. I think it boils down to the #ObservedObject and the fact that I have multiple classes/structs compared my project with user input. The user input will go into the coordinator class, but ultimately it is the ARViewContainer that actually renders the view.
If anyone can help me out, I would be incredibly grateful.
To increase / decrease sphere's radius and then position sphere by tap, use the following code.
Now, with working button and coordinator, it will be much easier to implement a raycasting.
import SwiftUI
import RealityKit
struct ContentView : View {
var body: some View {
PrevView().ignoresSafeArea()
}
}
Reality view.
struct Reality: UIViewRepresentable {
#Binding var input: Float
let arView = ARView(frame: .zero)
class ARCoordinator: NSObject {
var manager: Reality
init(_ manager: Reality) {
self.manager = manager
super.init()
let recognizer = UITapGestureRecognizer(target: self,
action: #selector(tapped))
manager.arView.addGestureRecognizer(recognizer)
}
#objc func tapped(_ recognizer: UITapGestureRecognizer) {
if manager.arView.scene.anchors.isEmpty {
let model = ModelEntity(mesh: .generateSphere(radius:
manager.input))
let anchor = AnchorEntity(world: [0, 0,-2])
// later use AnchorEntity(world: result.worldTransform)
anchor.addChild(model)
manager.arView.scene.anchors.append(anchor)
}
}
}
func makeCoordinator() -> ARCoordinator { ARCoordinator(self) }
func makeUIView(context: Context) -> ARView { return arView }
func updateUIView(_ uiView: ARView, context: Context) { }
}
PrevView view.
struct PrevView: View {
#State private var input: Float = 0.0
var body: some View {
NavigationView {
ZStack {
Color.black
VStack {
Text("\(String(format: "%.1f", input)) meters")
.foregroundColor(.yellow)
HStack {
Spacer()
Button(action: { $input.wrappedValue -= Float(0.1) }) {
Text("Decrease").foregroundColor(.red)
}
Spacer()
Button(action: { $input.wrappedValue += Float(0.1) }) {
Text("Increase").foregroundColor(.red)
}
Spacer()
}
NavigationLink(destination: Reality(input: $input)
.ignoresSafeArea()) {
Text("View in AR")
}
}
}.ignoresSafeArea()
}
}
}

User input to change size of shape that is generated by tap

I'm creating an app in RealityKit that generates a shape based on user input. For example, if the user enters a radius of 0.1 meters, the shape (sphere in my case) will have a radius of 0.1 meters, same logic for 0.2, 0.3, etc. The code all works, but I want to make it so the sphere appears when the user taps the screen.
Here is my code for the page that takes in user input:
class UserInput: ObservableObject {
#Published var score: Float = 0.0
}
struct PreviewView: View {
#ObservedObject var input = UserInput()
var body: some View {
NavigationView {
ZStack {
Color.black
VStack {
Text("Change the radius of your AR sphere")
.foregroundColor(.white)
Text("\(String(format: "%.1f", self.input.score)) meters")
.foregroundColor(.white)
.bold()
.font(.title)
.padding(10)
Button(action: {self.input.score += 0.1})
{
Text("Increment by 0.1 meters")
}
.padding(10)
Button(action: {self.input.score -= 0.1})
{
Text("Decrease by 0.1 meters")
}
.padding(10)
NavigationLink(destination: Reality(input: self.input)) {
Text("View in AR")
.bold()
.padding(.top,30)
}
}
}
.ignoresSafeArea()
}
}
Here is the code for the Reality ARView:
struct Reality: UIViewRepresentable {
#ObservedObject var input: UserInput
func makeUIView(context: Context) -> ARView {
let arView = ARView(frame: .zero)
let model = ModelEntity(mesh: .generateSphere(radius: input.score))
let anchor = AnchorEntity(plane: .horizontal)
anchor.addChild(model)
arView.scene.anchors.append(anchor)
return arView
}
func updateUIView(_ uiView: ARView, context: Context) {}
}
There are tons of examples of generating shapes when the user touches the screen, that's not my issue. The fact that I'm taking in user input is what makes this difficult.
Here is some code that does what I want, but without user input. It has some physics built in that I plan on implementing once I get the user input to work.
struct ARViewContainer: UIViewRepresentable {
func makeUIView(context: Context) -> ARView {
let arView = ARView(frame: .zero)
let planeAnchorEntity = AnchorEntity(plane: .horizontal)
let plane = ModelEntity(mesh: MeshResource.generatePlane(width: 1, depth: 1), materials: [SimpleMaterial(color: .white, isMetallic: true)])
plane.physicsBody = PhysicsBodyComponent(massProperties: .init(mass: 1), material: .generate(friction: 1, restitution: 1), mode: .kinematic)
plane.generateCollisionShapes(recursive: true)
planeAnchorEntity.addChild(plane)
arView.scene.anchors.append(planeAnchorEntity)
arView.installGestures([.scale,.rotation], for: plane)
arView.addGestureRecognizer(UITapGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.handleTap)))
context.coordinator.view = arView
return arView
}
func makeCoordinator() -> Coordinator {
Coordinator()
}
func updateUIView(_ uiView: ARView, context: Context) {}
}
Here is the Coordinator class that generates the box that I want to be adjustable in size:
class Coordinator {
weak var view: ARView?
#objc func handleTap(_ recognizer: UITapGestureRecognizer) {
guard let view = view else { return }
let location = recognizer.location(in: view)
let results = view.raycast(from: location, allowing: .estimatedPlane, alignment: .horizontal)
if let result = results.first {
let anchorEntity = AnchorEntity(raycastResult: result)
let box = ModelEntity(mesh: MeshResource.generateBox(size: 0.3),materials: [SimpleMaterial(color: .black, isMetallic: true)])
box.physicsBody = PhysicsBodyComponent(massProperties: .init(mass: 0.5), material: .generate(), mode: .dynamic)
box.generateCollisionShapes(recursive: true)
box.position = simd_make_float3(0,0.7,0)
//static means body cannot be moved
//dynamic means it can move
//kinematic means user moved the object
anchorEntity.addChild(box)
view.scene.anchors.append(anchorEntity)
}
}
}
I tried fusing these two projects into what I want, but I get all sorts of errors I have no idea how to fix, and when I try something new, a bunch of other errors appear. I think it boils down to the #ObservedObject and the fact that I have multiple classes/structs compared my project with user input. The user input will go into the coordinator class, but ultimately it is the ARViewContainer that actually renders the view.
If anyone can help me out, I would be incredibly grateful.
To increase / decrease sphere's radius and then position sphere by tap, use the following code.
Now, with working button and coordinator, it will be much easier to implement a raycasting.
import SwiftUI
import RealityKit
struct ContentView : View {
var body: some View {
PrevView().ignoresSafeArea()
}
}
Reality view.
struct Reality: UIViewRepresentable {
#Binding var input: Float
let arView = ARView(frame: .zero)
class ARCoordinator: NSObject {
var manager: Reality
init(_ manager: Reality) {
self.manager = manager
super.init()
let recognizer = UITapGestureRecognizer(target: self,
action: #selector(tapped))
manager.arView.addGestureRecognizer(recognizer)
}
#objc func tapped(_ recognizer: UITapGestureRecognizer) {
if manager.arView.scene.anchors.isEmpty {
let model = ModelEntity(mesh: .generateSphere(radius:
manager.input))
let anchor = AnchorEntity(world: [0, 0,-2])
// later use AnchorEntity(world: result.worldTransform)
anchor.addChild(model)
manager.arView.scene.anchors.append(anchor)
}
}
}
func makeCoordinator() -> ARCoordinator { ARCoordinator(self) }
func makeUIView(context: Context) -> ARView { return arView }
func updateUIView(_ uiView: ARView, context: Context) { }
}
PrevView view.
struct PrevView: View {
#State private var input: Float = 0.0
var body: some View {
NavigationView {
ZStack {
Color.black
VStack {
Text("\(String(format: "%.1f", input)) meters")
.foregroundColor(.yellow)
HStack {
Spacer()
Button(action: { $input.wrappedValue -= Float(0.1) }) {
Text("Decrease").foregroundColor(.red)
}
Spacer()
Button(action: { $input.wrappedValue += Float(0.1) }) {
Text("Increase").foregroundColor(.red)
}
Spacer()
}
NavigationLink(destination: Reality(input: $input)
.ignoresSafeArea()) {
Text("View in AR")
}
}
}.ignoresSafeArea()
}
}
}

ARKit camera tracking state can’t show on SwiftUI

I’m trying to show the camera tracking state info on top of device screen, but still get errors for all my efforts. I’m very confused with how ARView works with SwiftUI, for showing AR experience and adding button icons on top of it is simple, but to getting data from session just looks more work need to be done, could someone help me this? Thanks!
Error in ViewModel: ‘description is a get-only property’
Content View
import SwiftUI
import ARKit
import RealityKit
struct ContentView: View {
#StateObject var vm = ViewModel()
var body: some View {
ZStack{
ARViewContainer()
.edgesIgnoringSafeArea(.all)
.environmentObject(vm)
VStack{
Text(vm.sessionInfoLabel)
.font(.title3)
.foregroundColor(.red)
Spacer()
HStack{
Button{
} label: {
Image(systemName: "person.2")
.padding()
.font(.title)
}
Spacer()
Button{
} label: {
Image(systemName: "target")
.padding()
.font(.title)
}
}
.padding()
}
}
}
}
struct ARViewContainer: UIViewRepresentable {
#EnvironmentObject var vm: ViewModel
func makeUIView(context: Context) -> ARView {
return vm.arView
}
func updateUIView(_ uiView: ARView, context: Context) {
}
}
ViewModel
import SwiftUI
import ARKit
import RealityKit
class ViewModel: ObservableObject {
#Published var arView: ARView
var sessionInfoLabel = ""
init() {
arView = ARView.init(frame: .zero)
let config = ARWorldTrackingConfiguration()
config.planeDetection = .horizontal
arView.session.delegate = arView
arView.session.run(config)
}
}
extension ARView: ARSessionDelegate {
public func session(_ session: ARSession, cameraDidChangeTrackingState camera: ARCamera) {
camera.trackingState.description = ViewModel().sessionInfoLabel
}
}
extension ARCamera.TrackingState: CustomStringConvertible {
public var description: String {
switch self {
case .normal:
return "Normal"
case .notAvailable:
return "Not Available"
case .limited(.initializing):
return "Initializing"
case .limited(.excessiveMotion):
return "Excessive Motion"
case .limited(.insufficientFeatures):
return "Insufficient Features"
case .limited(.relocalizing):
return "Relocalizing"
case .limited:
return "Unspecified Reason"
}
}
}

SwiftUI playing Lottie animation

I was playing with the Lottie animations, these days, but I have some trouble how to stop them from the View.
Here is my ContentView, where I am playing the animation. I have one button which shows the boolean value in real-time:
struct ContentView: View {
#State var isShowing : Bool = true
var body: some View {
ZStack {
Color.green.opacity(0.3)
VStack {
VStack {
LottieDosi(isShowing: .constant(isShowing)){Text("")}
Button(action: {self.isShowing.toggle()}) {
Text("Button is \(String(isShowing))")
.padding(10)
.background(Color.white)
.cornerRadius(40)
}
}.padding(.horizontal, 30)
}
}.edgesIgnoringSafeArea(.all)
}
}
and here is my LottieView:
struct LottieView: UIViewRepresentable {
#Binding var isAnimating: Bool
#State var name : String
var loopMode: LottieLoopMode = .loop
var animationView = AnimationView()
func makeUIView(context: UIViewRepresentableContext<LottieView>) -> UIView {
let view = UIView()
animationView.animation = Animation.named(name)
animationView.contentMode = .scaleAspectFill
animationView.loopMode = .loop
animationView.play()
animationView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(animationView)
NSLayoutConstraint.activate([
animationView.widthAnchor.constraint(equalTo: view.widthAnchor),
animationView.heightAnchor.constraint(equalTo: view.heightAnchor)
])
return view
}
func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<LottieView>) {
isAnimating ? animationView.play() : animationView.stop()
}
}
struct LottieDosi<Content>: View where Content: View {
#Binding var isShowing: Bool
var content: () -> Content
var body: some View {
VStack {
LottieView(isAnimating: .constant(isShowing), name: "13728-sticker-4")
.frame(width: 175, height: 175)
}
}
}
I have a binding bool which has to change itself either to true or false, whenever I tap on the button. In other words, when I press the button I should be able to play and stop it. But somehow, this boolean value is not shared between the structs and the animation is constantly playing. I am new to swift UI, so I assume I am doing something very wrong, therefore I will appreciate some help.
Here you can see my animation
You've almost got it. You need to construct a Coordinator so that you can access the values inside your LottieView. It's straight forward to do.
Create a Coordinator class that conforms to NSObject
Pass in your LottieView.
Add the function makeCoordinator to your LottieView
Create an instance of your Coordinator in the makeCoordinator function
In your updateUIView access the animationView from the coordinator.
You shouldn't need a binding for the isAnimating as the LottieView is not passing any information back to your ContentView. You also don't need that #State for the name
Here is how I have gotten Lottie to play and pause in my apps. Note that some of the variable names are different to yours but it should be enough to get you to where you need to be.
import SwiftUI
import Lottie
struct LottieView: UIViewRepresentable {
typealias UIViewType = UIView
let filename: String
let animationView = AnimationView()
let isPaused: Bool
func makeUIView(context: UIViewRepresentableContext<LottieView>) -> UIView {
let view = UIView(frame: .zero)
let animation = Animation.named(filename)
animationView.animation = animation
animationView.contentMode = .scaleAspectFit
animationView.loopMode = .loop
animationView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(animationView)
NSLayoutConstraint.activate([
animationView.widthAnchor.constraint(equalTo: view.widthAnchor),
animationView.heightAnchor.constraint(equalTo: view.heightAnchor),
])
return view
}
func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<LottieView>) {
if isPaused {
context.coordinator.parent.animationView.pause()
} else {
context.coordinator.parent.animationView.play()
}
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject {
var parent: LottieView
init(_ parent: LottieView) {
self.parent = parent
}
}
}
My ContentView looks like the following:
struct ContentView: View {
#State private var isPaused: Bool = true
var body: some View {
VStack {
LottieView(filename: "loading", isPaused: isPaused)
.frame(width: 200, height: 200)
Button(action: {
self.isPaused.toggle()
}, label: {
Text(isPaused ? "Play" : "Pause")
})
}
}
}
Here it is working:

Adding a TextField to NavigationBar with SwiftUI

I've been fooling around with Xcode 11 and SwiftUI for the past few hours, attempting to implement a TextField in the NavigationBar. Generally, the first "Hello, World"-type application I build is a simple web browser: TextField and WKWebView.
However, I'm having an exceptionally difficult time trying to implement the TextField in a fixed .inline NavigationBar. Furthermore, I can't seem to find a single tutorial or piece of code anywhere online. I've gone through pages and pages of Google, as well as projects on GitHub, with no luck.
The only results that mention this topic in specific are Reddit threads and forum discussion posts – all of which ask the same question: "Has anyone been able to successfully implement a TextField in the NavigationBar?" No one has yet to respond with a solution.
Here's my current ContentView.swift – I have removed all of my programmatic attempts at implementing a TextField as it either crashes or throws errors:
import SwiftUI
import WebKit
let address = "https://developer.apple.com"
struct ContentView: View {
var body: some View {
NavigationView {
VStack {
WebView(request: URLRequest(url: URL(string: address)!))
.edgesIgnoringSafeArea(.bottom)
.edgesIgnoringSafeArea(.leading)
.edgesIgnoringSafeArea(.trailing)
}
.navigationBarTitle("TextField Placeholder", displayMode: NavigationBarItem.TitleDisplayMode.inline)
}
}
}
struct WebView: UIViewRepresentable {
let request: URLRequest
func makeUIView(context: Context) -> WKWebView {
return WKWebView()
}
func updateUIView(_ uiView: WKWebView, context: Context) {
uiView.load(request)
}
}
I don't know if it's exactly what you're trying to achieve, I think it might be a good solution:
import SwiftUI
import WebKit
let address = "https://developer.apple.com"
struct ContentView: View {
#State private var text = ""
var body: some View {
NavigationView {
GeometryReader { geometry in
VStack {
WebView(request: URLRequest(url: URL(string: address)!))
.edgesIgnoringSafeArea(.bottom)
.edgesIgnoringSafeArea(.leading)
.edgesIgnoringSafeArea(.trailing)
}
.navigationBarItems(leading:
HStack {
TextField("Type something here...", text: self.$text)
.background(Color.yellow)
}
.padding()
.frame(width: geometry.size.width)
.background(Color.green)
)
}
}
}
}
struct WebView: UIViewRepresentable {
let request: URLRequest
func makeUIView(context: Context) -> WKWebView {
return WKWebView()
}
func updateUIView(_ uiView: WKWebView, context: Context) {
uiView.load(request)
}
}
#if DEBUG
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
#endif
Copy-paste the code here above and let me know if I can try to improve my solution with something else. I coloured a couple of views of green and yellow just for a matter of debugging.
There is a new method in iOS 14+ that populates the toolbar or navigation bar with the specified items:
func toolbar<Content>(content: () -> Content) -> some View where Content : ToolbarContent
NavigationView {
GeometryReader { geometry in
ZStack {
Text("Hello")
}
.navigationBarTitle(" ", displayMode: .inline)
.navigationBarItems(leading:
HStack {
TextField("Seach for products, brands and more", text: self.$searchText)
}
.frame(width: geometry.size.width - 35,
height: 38,
alignment: .center)
.background(Color.white)
)
.background(NavigationConfigurator { nc in
nc.navigationBar.barTintColor = UIColor(red: 104.0/255.0, green: 194.0/255.0, blue: 25.0/255.0, alpha: 1.0)
})
}
}
.navigationViewStyle(StackNavigationViewStyle())
struct NavigationConfigurator: UIViewControllerRepresentable {
var configure: (UINavigationController) -> Void = { _ in }
func makeUIViewController(context: UIViewControllerRepresentableContext<NavigationConfigurator>) -> UIViewController {
UIViewController()
}
func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<NavigationConfigurator>) {
if let nc = uiViewController.navigationController {
self.configure(nc)
}
}
}