IOS Swift MQTT won't publish message to Raspberry Pi - ios

l am quite new to iOS development and just having a hard time trying to make MQTT publish messages from my phone. l wish to use the app I have built to control the raspberry pi wheels (the step motors more specifically). I made a button to connect to the robot.
struct ConnectToRobot: View {
var body: some View {
Button {
print("Connect to robot")
mqttClient.connect()
} label: {
Image(systemName: "circle")
.renderingMode(.template)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 100, height: 100)
.foregroundColor(.white)
}
}
}
When l press the button from the app in my phone, it connects to the raspberry pi and it shows me the message "subscribing", "subscribed". However, when l press any other buttons on the app, like "forward" or anything else it seems to not work at all. Here is the code from the RPi:
#For checking the connection status
def connectionStatus(client, userdata, flags, rc):
print("subscribing")
mqttClient.subscribe("robot/move")
print("subscribed")
#movement control
def messageDecoder(client, userdata, msg):
message = msg.payload.decode(encoding='UTF-8')
if message == "f":
forward()
mess2 = msg.payload.decode(encoding='UTF-8')
print("^^^ forward! ^^^")
elif message == "b":
backward()
print("\/ backward \/")
elif message == "l":
left()
print("<- left")
elif message == "r":
right()
print("-> right")
elif message == "fl":
diagFL()
print("\ Diagonal Front Left")
elif message == "fr":
diagFR()
print("/ Diag Front Right")
elif message == "bl":
diagBL()
print("/ Diag Back Left")
elif message == "br":
diagBR()
print("\ Diag back Right")
elif message == "cw":
cw()
print("O Clockwise")
elif message == "ccw":
ccw()
print("O Counter Clockwise")
elif message == "s":
stop()
else:
print("?!? Unknown message?!?")
# Set up calling functions to mqttClient
mqttClient.on_connect = connectionStatus
mqttClient.on_message = messageDecoder
# Connect to the MQTT server & loop forever.
# CTRL-C will stop the program from running.
mqttClient.connect(serverAddress)
mqttClient.loop_forever()
This is my swiftUI code below:
import SwiftUI
import CocoaMQTT
let mqttClient = CocoaMQTT(clientID: "Robot", host: "raspberrypi.local", port: 1883)
struct ContentView: View {
var body: some View {
ZStack {
VStack{
HStack {
VStack {
BackwardLeft()
Backward()
BackwardRight()
}
VStack{
Left()
ConnectToRobot()
Right()
}
VStack {
ForwardLeft()
Forward()
ForwardRight()
}
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
//First VStack
//Back left
struct BackwardLeft: View {
var body: some View {
Button {
print("Move back left")
} label: {
Image(systemName: "arrow.up.left.square")
.renderingMode(.template)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 100, height: 100)
.foregroundColor(.white)
}
}
}
//Backward
struct Backward: View {
var body: some View {
Button (action: {
mqttClient.publish("robot/move", withString: "b")
print("Move back")
}, label: {
Image(systemName: "arrow.left.square")
.renderingMode(.template)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 100, height: 100)
.foregroundColor(.white)
})
}
}
//Back Right
struct BackwardRight: View {
var body: some View {
Button {
print("Back right")
} label: {
Image(systemName: "arrow.down.left.square")
.renderingMode(.template)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 100, height: 100)
.foregroundColor(.white)
}
}
}
//Second VStack
//Left
struct Left: View {
var body: some View {
Button {
mqttClient.allowUntrustCACertificate = true
mqttClient.publish("robot/move", withString: "l")
print("Move left")
} label: {
Image(systemName: "arrow.up.square")
.renderingMode(.template)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 100, height: 100)
.foregroundColor(.white)
}
}
}
//MQTT Connection
struct ConnectToRobot: View {
var body: some View {
Button {
print("Connect to robot")
mqttClient.connect()
} label: {
Image(systemName: "circle")
.renderingMode(.template)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 100, height: 100)
.foregroundColor(.white)
}
}
}
//Right
struct Right: View {
var body: some View {
Button {
print("Move right")
mqttClient.publish("robot/move", withString: "r")
} label: {
Image(systemName: "arrow.down.square")
.renderingMode(.template)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 100, height: 100)
.foregroundColor(.white)
}
}
}
//Third VStack
//Forward left
struct ForwardLeft: View {
var body: some View {
Button {
print("Move foward left")
} label: {
Image(systemName: "arrow.up.right.square")
.renderingMode(.template)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 100, height: 100)
.foregroundColor(.white)
}
}
}
//Forward
struct Forward: View {
var body: some View {
Button {
mqttClient.publish("robot/move", withString: "f")
print("Move forward")
} label: {
Image(systemName: "arrow.right.square")
.renderingMode(.template)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 100, height: 100)
.foregroundColor(.white)
}
}
}
//Forward right
struct ForwardRight: View {
var body: some View {
Button {
print("Move top right")
} label: {
Image(systemName: "arrow.down.right.square")
.renderingMode(.template)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 100, height: 100)
.foregroundColor(.white)
}
}
}
I am not sure what is wrong, because when l press connect the message shows up on the PI terminal but when l press a direction button nothing shows up. I am thinking it might be a connection issue or something l did wrong in the IOS code. Thanks in advance
I tried to change the swiftUI code but it didn't work

Related

How to drag to expand for safe area content?

I have a content in the safe area that reveals details on a button tap. I would like to allow the user to drag the handle to expand the content details as well, almost like the bottom sheet behaviour.
This is what I have so far:
struct ContentView: View {
#State private var isExpanded = false
var body: some View {
ScrollView {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundColor(.accentColor)
Text("Hello, world!")
}
.frame(maxWidth: .infinity)
.padding()
}
.safeAreaInset(edge: .bottom) {
VStack(spacing: 24) {
Capsule()
.frame(width: 50, height: 5)
.opacity(0.5)
HStack(spacing: 16) {
Image(systemName: "list.bullet")
Spacer()
VStack {
Text("Track 2")
}
.font(.caption)
Spacer()
Image(systemName: "backward.fill")
Image(systemName: "play.fill")
Image(systemName: "forward.fill")
Spacer()
Button {
withAnimation {
isExpanded.toggle()
}
} label: {
Image(systemName: "ellipsis.circle")
}
}
if isExpanded {
HStack {
Image(systemName: "airplayaudio")
Image(systemName: "timer")
Spacer()
Text("Artist")
}
}
}
.padding([.bottom, .horizontal])
.padding(.top, 8)
.background(.ultraThinMaterial)
}
}
}
How can I add functionality to the Capsule to drag the handle to expand that animates in a way to stretch the content in an elastic way (not just swipe to expand, but to drag the content until the user let's go)?
You can use a DragGesture on your Capsule:
.gesture(
DragGesture()
.onEnded { value in
withAnimation(.spring()) {
let swipingUp = value.translation.height < 0
withAnimation {
isExpanded = swipingUp ? true: false
}
}
}
)
To allow for a stretch, you can use onChanged paired with a State variable:
struct ContentView: View {
#State private var isExpanded = false
#State private var stretch = CGFloat.zero
var body: some View {
ScrollView {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundColor(.accentColor)
Text("Hello, world!")
}
.frame(maxWidth: .infinity)
.padding()
}
.safeAreaInset(edge: .bottom) {
VStack(spacing: 24) {
Capsule()
.frame(width: 50, height: 5)
.opacity(0.5)
.gesture(
DragGesture()
.onChanged { newValue in
withAnimation(.spring()) {
stretch = abs(newValue.translation.height)
}
}.onEnded { value in
withAnimation(.spring()) {
isExpanded = value.translation.height < 0
stretch = .zero
}
}
)
HStack(spacing: 16) {
Image(systemName: "list.bullet")
Spacer()
VStack {
Text("Track 2")
}
.font(.caption)
Spacer()
Image(systemName: "backward.fill")
Image(systemName: "play.fill")
Image(systemName: "forward.fill")
Spacer()
Button {
withAnimation {
isExpanded.toggle()
}
} label: {
Image(systemName: "ellipsis.circle")
}
}
if isExpanded {
HStack {
Image(systemName: "airplayaudio")
Image(systemName: "timer")
Spacer()
Text("Artist")
}
}
if stretch > 0 && !isExpanded {
Color.clear
.frame(height: stretch)
}
}.padding([.bottom, .horizontal])
.padding(.top, 8)
.background(.ultraThinMaterial)
}
}
}

onAppear SwiftUI iOS 14.4

I would like to display the details of a tourist destination when a destination is selected. Below is the syntax that I created, I call self.presenter.getDetail(request: destination.id) which is in .onAppear, when the program starts and I press a destination, xcode says that self.presenter.detailDestination!.like doesn't exist or nil. Even when I insert print ("TEST") what happens is error nil from self.presenter.detailDestination!.like
struct DetailView: View {
#Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
#State private var showingAlert = false
#ObservedObject var presenter: GetDetailPresenter<
Interactor<String, DestinationDomainModel, GetDetailDestinationRepository<
GetDestinationLocaleDataSource, GetDetailDestinationRemoteDataSource,
DetailDestinationTransformer>>,
Interactor<String, DestinationDomainModel, UpdateFavoriteDestinationRepository<
FavoriteDestinationLocaleDataSource, DetailDestinationTransformer>>>
var destination: DestinationDomainModel
var body: some View {
ZStack {
if presenter.isLoading {
loadingIndicator
} else {
ZStack {
GeometryReader { geo in
ScrollView(.vertical) {
VStack {
self.imageCategory
.padding(EdgeInsets.init(top: 0, leading: 0, bottom: 0, trailing: 0))
.frame(width: geo.size.width, height: 270)
self.content
.padding()
}
}
}
.edgesIgnoringSafeArea(.all)
.padding(.bottom, 80)
VStack {
Spacer()
favorite
.padding(EdgeInsets.init(top: 0, leading: 16, bottom: 10, trailing: 16))
}
}
}
}
.onAppear {
self.presenter.getDetail(request: destination.id)
}
.navigationBarBackButtonHidden(true)
.navigationBarItems(leading: btnBack)
}
}
extension DetailView {
var btnBack : some View { Button(action: {
self.presentationMode.wrappedValue.dismiss()
}) {
HStack {
Image(systemName: "arrow.left.circle.fill")
.aspectRatio(contentMode: .fill)
.foregroundColor(.black)
Text("Back")
.foregroundColor(.black)
}
}
}
var spacer: some View {
Spacer()
}
var loadingIndicator: some View {
VStack {
Text("Loading...")
ActivityIndicator()
}
}
var imageCategory: some View {
WebImage(url: URL(string: self.destination.image))
.resizable()
.indicator(.activity)
.transition(.fade(duration: 0.5))
.aspectRatio(contentMode: .fill)
.frame(width: UIScreen.main.bounds.width, height: 270, alignment: .center)
.clipShape(RoundedCorner(radius: 30, corners: [.bottomLeft, .bottomRight]))
}
var header: some View {
VStack(alignment: .leading) {
Text("\(self.presenter.detailDestination!.like) Peoples Like This")
.padding(.bottom, 10)
Text(self.presenter.detailDestination!.name)
.font(.largeTitle)
.bold()
.padding(.bottom, 5)
Text(self.presenter.detailDestination!.address)
.font(.system(size: 18))
.bold()
Text("Coordinate: \(self.presenter.detailDestination!.longitude), \(self.presenter.detailDestination!.latitude)")
.font(.system(size: 13))
}
}
var favorite: some View {
Button(action: {
self.presenter.updateFavoriteDestination(request: String(self.destination.id))
self.showingAlert.toggle()
}) {
if self.presenter.detailDestination!.isFavorite == true {
Text("Remove From Favorite")
.font(.system(size: 20))
.bold()
.onAppear {
self.presenter.getDetail(request: destination.id)
}
} else {
Text("Add To Favorite")
.font(.system(size: 20))
.bold()
}
}
.alert(isPresented: $showingAlert) {
if self.presenter.detailDestination!.isFavorite == true {
return Alert(title: Text("Info"), message: Text("Destination Has Added"),
dismissButton: .default(Text("Ok")))
} else {
return Alert(title: Text("Info"), message: Text("Destination Has Removed"),
dismissButton: .default(Text("Ok")))
}
}
.frame(width: UIScreen.main.bounds.width - 32, height: 50)
.buttonStyle(PlainButtonStyle())
.foregroundColor(Color.white)
.background(Color.red)
.cornerRadius(12)
}
var description: some View {
VStack(alignment: .leading) {
Text("Description")
.font(.system(size: 17))
.bold()
.padding(.bottom, 7)
Text(self.presenter.detailDestination!.placeDescription)
.font(.system(size: 15))
.multilineTextAlignment(.leading)
.lineLimit(nil)
.lineSpacing(5)
}
}
var content: some View {
VStack(alignment: .leading, spacing: 0) {
header
.padding(.bottom)
description
}
}
}
onAppear is called during the first render. That means that any values referred to in the view hierarchy (detailDestination in this case) will be rendered during this pass -- not just after onAppear.
In your header, you refer to self.presenter.detailDestination!.like. On the first render, there is not a guarantee that onAppear will have completed it's actions before you force unwrap detailDestination
The simplest solution to this is probably to only conditionally render the rest of the view if detailDestination exists. It looks like you're already trying to do this with isLoading, but there must be a mismatch of states -- my guess is before isLoading is even set to true.
So, your content view could be something like:
if self.presenter.detailDestination != nil {
VStack(alignment: .leading, spacing: 0) {
header
.padding(.bottom)
description
}
} else {
EmptyView()
}
This is all assuming that your presenter has a #Published property that will trigger a re-render of your current component when detailDestination is actually loaded.

SwiftUI List not propagating touches

Trying to work with SwiftUI and experiencing a weird issue. I have a List of Views that should be clickable to push to a detail view, swipable to delete, and have a couple of interactive elements in the view. The list is more or less set up as follows:
NavigationView {
ZStack(alignment: .top) {
if viewModel.value != nil {
List {
ForEach(viewModel.value!, id: \.address) { model in
VStack {
NavigationLink(destination: AliasDetailView(alias: model) { msg in
self.toastText = msg
self.showCopiedToast = true
}) {
ModelRow(alias: alias) { msg in
self.toastText = msg
self.showCopiedToast = true
}
}
}
}
.onDelete(perform: self.deleteModel)
}
.listStyle(PlainListStyle())
.alert(isPresented: $showDefaultAlert) {
Alert(title: Text("Default Address"),
message: Text("Would you like to set this as your default address?"),
primaryButton: .default(Text("Yes")) {
NSUbiquitousKeyValueStore.default.set(self.targetAddress, forKey: SettingsKeys.DefaultAddress)
NSUbiquitousKeyValueStore.default.synchronize()
print("Stored key")
self.targetAddress = ""
}, secondaryButton: .cancel({
NSUbiquitousKeyValueStore.default.set("NONE", forKey: SettingsKeys.DefaultAddress)
NSUbiquitousKeyValueStore.default.synchronize()
self.targetAddress = ""
}))
}
} else {
Text("Loading...")
}
VStack {
Spacer()
.alert(isPresented: $showInvalidAddressAlert) {
Alert(title: Text("Invalid Email"), message: Text("Please enter a valid address."), dismissButton: .default(Text("Ok")))
}
// Begin Floating action button
HStack {
Spacer()
Button(action: {
addModelAction()
}, label: {
Text("+")
.font(.largeTitle)
.frame(width: 77, height: 70)
.foregroundColor(.white)
.padding(.bottom, 7)
})
.background(Color.blue)
.cornerRadius(38.5)
.padding()
.shadow(color: Color.black.opacity(0.3),
radius: 3, x: 3, y: 3)
.alert(isPresented: $showAccountLimitAlert) {
Alert(title: Text("Account Limit Reached"), message: Text("You are currently at your account limit for models. Upgrade your account to create more."), dismissButton: .default(Text("Ok")))
}
}
}
}
.navigationBarTitle("Models")
.navigationBarItems(trailing:
Button(action: {
self.showSettingsModal = true
}) {
Image(systemName: "gearshape")
.font(.title)
}
)
.addPartialSheet(style: PartialSheetStyle(
backgroundColor: .black,
handlerBarColor: .secondary,
enableCover: true,
coverColor: Color.black.opacity(0.6),
blurEffectStyle: .dark))
.popup(isPresented: $showCopiedToast, type: .toast, position: .bottom, autohideIn: 2) {
HStack {
Text(self.toastText)
}
.frame(width: 200, height: 60)
.background(Color(red: 0.85, green: 0.8, blue: 0.95))
.cornerRadius(30.0)
.padding(15)
}
.sheet(isPresented: $showSettingsModal) {
SettingsView()
.environmentObject(ProductsStore.shared)
}
I've included everything in the body because I have a suspicion its related to something else blocking the touches. I've tried removing some things but can't seem to identify it. Here is the view code for the row:
HStack {
VStack(alignment: .leading) {
HStack {
VStack(alignment: .leading) {
Text(model.address)
.font(.headline)
.lineLimit(1)
.truncationMode(.tail)
Text("➜ \(model.target)")
.font(.subheadline)
.foregroundColor(.secondary)
}
Spacer()
VStack {
Image(systemName: "doc.on.doc")
.frame(width: 35, height: 38)
.font(.headline)
.foregroundColor(.accentColor)
.onTapGesture {
copyAlias()
}
}
}
HStack {
Text("Received: \(model.received)")
Spacer()
Toggle("", isOn: $isActive)
.labelsHidden()
.onReceive([self.isActive].publisher.first()) { value in
if value != prevActive {
toggleModel()
}
}
}
}
}
Also note: The list view does work if you hold the elements. i.e. Tapping a row will not trigger the navigation link but holding the cell will eventually trigger it.
Turns out it was the Toast Library I was using. Likely however their view modifier works its capturing touches.

Editing NavigationBarItems and NavigationBarTitle in SwiftUI inside TabView

I'm trying to change the navigation bar title and leading & trailing items in a SwiftUI app.
Here is the situation:
A user logs in, then he gets transferred to a view inside a TabView.
Before login, in the welcome screen and login & register screens I have no navigation bar title, but after login, I want to add the navigation bar items and title.
What is important to know is that my after-login-view is inside a TabView.
If I wrap my after-login-view in a new NavigationView and then change the navigation bar items and title it works! but it shows me 2 navigation bars:
which is not what I want.
here is the code I use :
This is the after-Login-View
import SwiftUI
struct DiscoveryView: View {
var body: some View {
List{
Text("List Items")
}.offset(y: 10)
.navigationBarTitle("", displayMode: .inline)
.navigationBarItems(leading:
Text("Discovery").font(Font.custom("Quicksand- Bold", size: 24))
, trailing:
Button(action: {
}) {
HStack{
Text("120").font(Font.custom("Quicksand-Bold", size: 15)).foregroundColor(Color("BlueColor"))
Text("following").font(Font.custom("Quicksand-Bold", size: 15)).foregroundColor(Color.black)
}
}
).navigationBarBackButtonHidden(true)
}
}
This is the TabView:
struct TabController : View {
#State private var selection = 0
var body: some View {
TabView(selection: $selection){
DiscoveryView()
.tabItem {
VStack {
Image(systemName: "list.dash")
Text("Discover")
}
}.tag(1)
ExploreView()
.tabItem {
VStack {
Image(systemName: "square.and.pencil")
Text("Explore")
}
}.tag(2)
SelfProfileView()
.tabItem{
VStack {
Image(systemName: "person.circle")
Text("Profile")
}
}.tag(3)
}.accentColor(Color("BlueColor"))
}
}
This is the code of the login page:
import SwiftUI
struct LoginView: View {
var body: some View {
ZStack{
VStack{
Image("mainLogo").resizable().frame(width: 250, height: 125)
Text("").frame(width: UIScreen.main.bounds.width, height: 100)
HStack{
TextField("Username / Email", text: $email)
.padding(.leading, 10)
.frame(width: 313, height: 49)
.background(RoundedRectangle(cornerRadius: 4).stroke( Color.black.opacity(0.3)).frame(width: 313, height: 39).background(Color("GrayColor")))
}
Text("").frame(width: UIScreen.main.bounds.width, height: 40)
HStack {
HStack{
if self.visable{
TextField("Password", text: $password)
.padding(.horizontal)
} else {
SecureField("Password", text: $password)
.padding(.horizontal)
}
Button(action: {
self.visable.toggle()
}){
Image(systemName: self.visable ? "eye.slash" : "eye")
.padding(.trailing, 20)
.foregroundColor(Color.black)
}
}.background(RoundedRectangle(cornerRadius: 4).stroke( Color.black.opacity(0.3)).frame(width: 313, height: 39).background(Color("GrayColor")) )
}.padding(.horizontal, 40).padding(.vertical)
Text("").frame(width: UIScreen.main.bounds.width, height: 100)
Button(action: {
//pass email password and conpassword to cognito
DSManager().signIn(username: self.email, password: self.password, error: {
error in
if let error = error{
self.error = error.errorString
self.alert.toggle()
print(error.errorString)
}
else{
DSManager().getSelfUserInformation(response: {
userInfo, userCollections,dsError in
if let dsError = dsError{
self.error = dsError.errorString
self.alert.toggle()
print(dsError.errorString)
}
if let userInfo = userInfo{
print("success")
//use userInfo to load stuff for profile page
if let userCollections = userCollections{
self.profileInfo.setProperties(userInfo: userInfo, collections: userCollections)
}
else{
self.profileInfo.setProperties(userInfo: userInfo, collections: [:])
}
self.isComplete.toggle()
}
})
}
})
}) {
Text("Login")
.fontWeight(.semibold)
.frame(width: 313, height: 48)
.background(fillAllFields() ? Color("YellowColor") : Color.gray)
.foregroundColor(Color.white)
.font(.system(size: 17))
.cornerRadius(15)
.shadow(color: Color("GrayColor"), radius: 0, x: 3, y: 3)
}.disabled(!fillAllFields())
NavigationLink(destination: ProfileView(), isActive: $isComplete) {
EmptyView()
}
Spacer()
}
.padding()
.navigationBarTitle("", displayMode: .inline)
if self.alert {
ErrorView(err: $error, alert: $alert)
}
}
}
func fillAllFields() -> Bool {
if self.email == "" || self.password == "" {
return false
}
return true
}
}
As mentioned, I'm trying to edit bar items and title of a view inside and tab view .
Thanks!
So as per your updated question, I added DiscoveryView Inside NavigationView and it worked as expected. I have added code and screenshot as well.
struct TabController : View {
#State private var selection = 0
var body: some View {
TabView(selection: $selection) {
NavigationView {
DiscoveryView()
}
.tabItem {
VStack {
Image(systemName: "list.dash")
Text("Discover")
}
}.tag(1)
Text("Explore View")
.tabItem {
VStack {
Image(systemName: "square.and.pencil")
Text("Explore")
}
}.tag(2)
Text("SelfProfileView")
.tabItem{
VStack {
Image(systemName: "person.circle")
Text("Profile")
}
}.tag(3)
}.accentColor(Color("BlueColor"))
}}

SwiftUI strange behavior in List and NavigationView - Blur function is changing y offset

I've a List of object, in NavigationView, If I blur it, the view is changing the offset, seems it force edgesIgnoringSafeArea at list view:
case 1: If I blur it, the view is changing the offset.
case 2: If I put something before List in VStack, the offset is right (with the space of the object)
case 3: the workaround I found, is to add offset y:1 at the blur effect
struct Test: View {
#State private var arr = [1,2,3,4]
var body: some View {
TabView {
NavigationView {
HStack {
VStack {
List {
ForEach (arr, id:\.self) { _ in
Image(systemName: "person")
.resizable()
.frame(width: 150, height: 150)
}
}
}
VStack {
List {
ForEach (arr, id:\.self) { _ in
Image(systemName: "person")
.resizable()
.frame(width: 150, height: 150)
}
}
.blur(radius: 3)
}
}
.navigationBarTitle(Text("TITLE"), displayMode: .inline)
}
.navigationViewStyle(DoubleColumnNavigationViewStyle())//DoubleColumnNavigationViewStyle())
.tabItem {
Image(systemName: "message")
Text("LIST + LIST BLUR")
}
.tag(1)
NavigationView {
HStack {
VStack {
List {
ForEach (arr, id:\.self) { _ in
Image(systemName: "person")
.resizable()
.frame(width: 150, height: 150)
}
}
}
VStack {
Text("2").frame(width: 0, height: 0)
List {
ForEach (arr, id:\.self) { _ in
Image(systemName: "person")
.resizable()
.frame(width: 150, height: 150)
}
}
.blur(radius: 3)
}
}
.navigationBarTitle(Text("TITLE"), displayMode: .inline)
}
.tabItem {
VStack {
Image(systemName: "circle")
Text("LIST+VSTACKBLUR")
}
}
.tag(2)
NavigationView {
HStack {
VStack {
List {
ForEach (arr, id:\.self) { _ in
Image(systemName: "person")
.resizable()
.frame(width: 150, height: 150)
}
}
}
VStack {
List {
ForEach (arr, id:\.self) { _ in
Image(systemName: "person")
.resizable()
.frame(width: 150, height: 150)
}
}
.blur(radius: 3).offset(y:1)
}
}
.navigationBarTitle(Text("TITLE"), displayMode: .inline)
}
.tabItem {
VStack {
Image(systemName: "circle")
Text("List+BLUR+OFFSET")
}
}
}
}
}
struct Test_Previews: PreviewProvider {
static var previews: some View {
Test()
}
}
UPDATE:
I can't blur inside list because I'm using an extension of View to show personal TextFieldAlert
extension View {
func textFieldAlert(isShowing: Binding<Bool>,
text: Binding<String>,
title: String, grayText: String, onReturnPressed: #escaping () -> Void) -> some View {
TextFieldAlert(isShowing: isShowing,
text: text,
presenting: { self },
title: title, grayText: grayText, onReturnPressed:
onReturnPressed)
}
}
struct TextFieldAlert<Presenting>: View where Presenting: View {
#Binding var isShowing: Bool
#Binding var text: String
let presenting: () -> Presenting
let title: String
var grayText:String
let onReturnPressed: () -> Void
func returnFunction() {//quando l'utenti schiaccia ok o invio}
self.isShowing = false
self.onReturnPressed()
}
var body: some View {
GeometryReader { (deviceSize: GeometryProxy) in
ZStack {
if self.isShowing {
self.presenting()
.blur(radius: 3).offset(y:1) //I've added this
.disabled(self.isShowing)
}
else {
self.presenting()
.disabled(self.isShowing)
}
VStack {
Spacer()
.frame(height: 8)
Text(self.title)
Divider()
TextField(self.grayText, text: self.$text, onCommit: {
self.returnFunction()
})
Divider()
Spacer()
.frame(height: 10)
HStack {
Button(action: {
withAnimation {
self.returnFunction()
}
}) {
Text("OK")
.frame(width: 150, height: 30)
.background(Color.white)
//.foregroundColor(.white)
.cornerRadius(15)
}
}
}
.padding()
.background(Color.white)
.clipShape(RoundedRectangle(cornerRadius: 15))
.frame(
width: 250,//deviceSize.size.width*0.6,
height: 220//deviceSize.size.height*0.6
)
.offset(y: -100)
.shadow(radius: 20)
.opacity(self.isShowing ? 1 : 0)
ZStack {
Circle().frame(width: 40, height: 40)
.foregroundColor(Color.white)
Image(systemName: "pencil.circle.fill")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 50, height: 50)
.clipShape(Circle())
.foregroundColor(Color.blue)
}
.offset(x:0, y: -220/3 - 110)//-deviceSize.size.height*0.6/6 - 110)
.opacity(self.isShowing ? 1 : 0)
}
}
}
}

Resources