SwiftUI stocking geometry effects and tabBar animation - swift

Hey guys I have some issues with my code. I just experimented a bit with the matchedGeometryEffect in SwiftUI and it works great. But now I ran into some issues:
I cannot just deactivate the tabBar when the DetailView is dismissed because the view jumps up a bit.
The View transition is sometimes buggy and the console gives me (constantly) the output
Multiple inserted views in matched geometry group Pair<String, ID>(first: "bg", second: SwiftUI.Namespace.ID(id: 415)) have `isSource: true`, results are undefined.
Is there a better way to animate this smoothly and disable the tabBar?
Here is my code:
struct FullscreenView: View {
#Namespace var animationNamespace
#State var shouldShowFullsceen = false
#State var shouldShowDetails = false
var body: some View {
Input()
.padding()
.onTapGesture {
withAnimation(.interactiveSpring(
response: 0.6,
dampingFraction: 0.7,
blendDuration: 0.7
)) {
shouldShowFullsceen = true
}
}
.overlay {
if shouldShowFullsceen {
Output()
.onTapGesture {
withAnimation(.interactiveSpring(
response: 0.6,
dampingFraction: 0.7,
blendDuration: 0.7
)) {
shouldShowFullsceen = false
shouldShowDetails = false
}
}
}
}
}
}
extension FullscreenView {
#ViewBuilder
func Input() -> some View {
Content()
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(BackgroundView())
}
#ViewBuilder
func Output() -> some View {
DetailedContent()
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(FullscreenBackground())
}
}
extension FullscreenView {
#ViewBuilder
func Content() -> some View {
Image("dog")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(maxHeight: 300)
.matchedGeometryEffect(id: "content", in: animationNamespace)
}
}
extension FullscreenView {
#ViewBuilder
func DetailedContent() -> some View {
VStack {
Content()
ScrollView(.vertical) {
Text(dummyText)
.padding()
.opacity(shouldShowDetails ? 1 : 0)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.padding()
}
.transition(.identity)
.onAppear {
withAnimation(.interactiveSpring(
response: 0.6,
dampingFraction: 0.7,
blendDuration: 0.7
).delay(0.1)) {
shouldShowDetails = true
}
}
}
}
extension FullscreenView {
#ViewBuilder
func BackgroundView() -> some View {
Color.orange
.clipShape(RoundedRectangle(cornerRadius: 15))
.matchedGeometryEffect(id: "bg", in: animationNamespace)
}
}
extension FullscreenView {
#ViewBuilder
func FullscreenBackground() -> some View {
BackgroundView()
.ignoresSafeArea()
}
}
struct FullscreenView_Previews: PreviewProvider {
static var previews: some View {
FullscreenView()
}
}

Regarding the animation and console warning:
Don't overlay Output view. Show either the Input or the Output View with if ... else, then .matchedGeometryEffect can do the transition.
You should use .matchedGeometryEffect with isSource: specified to true, for both image and background.
get rid of .transition(.identity).
Here is the full code with comments:
struct FullscreenView: View {
#Namespace var animationNamespace
#State var shouldShowFullsceen = false
#State var shouldShowDetails = false
var body: some View {
if shouldShowFullsceen == false { // show only one matched view at a time
Input()
.padding()
.onTapGesture {
withAnimation(.interactiveSpring(
response: 0.6,
dampingFraction: 0.7,
blendDuration: 0.7
)) {
shouldShowFullsceen = true
}
}
} else { // show only one matched view at a time
Output()
.onTapGesture {
withAnimation(.interactiveSpring(
response: 0.6,
dampingFraction: 0.7,
blendDuration: 0.7
)) {
shouldShowFullsceen = false
shouldShowDetails = false
}
}
}
}
func Input() -> some View {
Content()
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(BackgroundView())
}
func Output() -> some View {
DetailedContent()
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(FullscreenBackground())
}
func Content() -> some View {
Image(systemName: "tortoise")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(maxHeight: 300)
.padding()
.matchedGeometryEffect(id: "content", in: animationNamespace, isSource: true) // add isSource
}
func DetailedContent() -> some View {
VStack {
Content()
ScrollView(.vertical) {
Text("dummyText")
.padding()
.opacity(shouldShowDetails ? 1 : 0)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.padding()
}
// .transition(.identity) // take this out
.onAppear {
withAnimation(.interactiveSpring(
response: 0.6,
dampingFraction: 0.7,
blendDuration: 0.7
).delay(0.1)) {
shouldShowDetails = true
}
}
}
func BackgroundView() -> some View {
Color.orange
.clipShape(RoundedRectangle(cornerRadius: 15))
.matchedGeometryEffect(id: "bg", in: animationNamespace, isSource: true) // add isSource
}
func FullscreenBackground() -> some View {
BackgroundView()
.ignoresSafeArea()
}
}

Related

Construct View Like Pedantix SwiftUI

The problem is quite simple. I want to build something like Pedantix https://cemantix.certitudes.org/pedantix in SwiftUI.
I've this already :
So, I try to have my RoundedRectangle overlay to totally hide my text. And I want blocks to go at the line if needed, etc. I tried LazyHGrid (actually this), LazyVGrid, custom grid. But no results ...
import SwiftUI
struct Word: Identifiable, Equatable {
var id = UUID()
var text: String
var isFramed: Bool
var isTouched: Bool
}
struct ContentView: View {
#EnvironmentObject var service: Service
let rows = [
GridItem(.adaptive(minimum: 30)),
]
var body: some View {
GeometryReader { gr in
ScrollView {
VStack(alignment: .leading) {
HStack {
Spacer()
Image(systemName: "arrow.counterclockwise.circle")
.resizable()
.scaledToFit()
.frame(width: 24)
.onTapGesture {
service.loadRandomMovies(page: 1, completion: { _ in
service.loadMovie(id: service.randomMovieId ?? 0, completion: { _ in })
service.loadCredits(id: service.randomMovieId ?? 0, completion: { _ in })
})
}
}
HStack {
VStack {
RoundedRectangle(cornerRadius: 8)
.frame(width: 150, height: 250)
}
.padding()
VStack(alignment: .center) {
customTextView(with: service.frame(in: .title))
.padding(.bottom, 8)
customTextView(with: service.frame(in: .genres))
.padding(.bottom, 8)
.frame(width: gr.size.width * 0.8)
Text("\(service.movie?.releaseDate ?? "")")
.font(.title3)
.padding(.bottom, 8)
if service.movie?.tagline != "" {
Text("\"\(service.movie?.tagline ?? "")\"")
.font(.title3)
.padding(.bottom, 8)
.frame(alignment: .center)
}
customTextView(with: service.frame(in: .overview))
.padding(.bottom, 8)
.frame(width: gr.size.width * 0.8)
Text("\(service.credits?.cast.map({ $0.name }).joined(separator: " - ") ?? "")")
.fontWeight(.bold)
}
}
}
.padding()
}
.frame(width: gr.size.width)
}
}
}
extension ContentView {
#ViewBuilder
func customTextView(with words: [Word]) -> some View {
VStack {
LazyHGrid(rows: rows, spacing: 2) {
ForEach(words) { word -> AnyView in
if word.isFramed {
return AnyView(
Text("\(word.text)")
.padding(2)
.overlay(RoundedRectangle(cornerRadius: 4))
.overlay {
if word.isTouched {
Text("\(word.text.count)")
.foregroundColor(Color.cyan)
}
}
)
}
return AnyView(Text(word.text))
}
}
}
}
}
Do you think you could post your code so that we can see what you have done?

How to remove the cornerradius of sheets in swiftui?

Is there a way to remove the cornerRadius of a sheet? I tried it like this:
.sheet(isPresented: $showModal) {
Modal().cornerRadius(0, corners: [.topLeft, .topRight])
}
but it didn't work.
I know I can just use fullScreenCover but I still want to know if there is a solution to this.
According to my comment above you can create your own slide-in menu.
In the example below I added a close button as well as gesture control to close the view.
//
//
// SlideInMenu.swift
// SlideInMenu
//
// Created by Sebastian on 21.09.22.
//
import SwiftUI
var bounds = UIScreen.main.bounds
struct ContentView: View {
#State var selectedItem: String = ""
#State var showMenu = false
var body: some View {
ZStack() {
MainView(selectedItem: $selectedItem, showMenu: $showMenu)
.blur(radius: showMenu ? 3 : 0)
SlideView(selectedItem: $selectedItem, showMenu: $showMenu)
}
.edgesIgnoringSafeArea(.all)
}
}
struct MainView: View {
#Binding var selectedItem: String
#Binding var showMenu: Bool
var body: some View {
HStack(){
Spacer()
VStack() {
Spacer()
Text("This is your main View")
.foregroundColor(.white)
.padding()
Button(action: {
withAnimation(.linear(duration: 0.3)) {
self.showMenu.toggle()
}
}) {
Text("Show Menu")
.font(.system(size: 20, weight: .medium))
.foregroundColor(.white)
}
Spacer()
}
Spacer()
}.background(Color.blue)
}
}
struct SlideView: View {
#Binding var selectedItem: String
#Binding var showMenu: Bool
#State private var viewOffest: CGFloat = 100
#State private var offset = CGSize.zero
#State private var isDragging = false
var body: some View {
let dragGesture = DragGesture()
.onChanged { value in
withAnimation(.linear(duration: 0.2)) {
if value.translation.height >= 0 {
offset = value.translation
}
}
}
.onEnded { _ in
withAnimation(.linear(duration: 0.2)) {
isDragging = false
if offset.height > (bounds.height - viewOffest)/3 {
showMenu.toggle()
}
offset = .zero
}
}
ZStack() {
Color.black
.opacity(showMenu ? 0.5 : 0)
VStack() {
HStack() {
Spacer()
Spacer()
}
VStack(alignment: .leading) {
HStack() {
Spacer()
Text("Here is the menu")
.foregroundColor(.black)
Spacer()
}
HStack() {
Spacer()
Button(action: {
withAnimation(.linear(duration: 0.3)) {
self.showMenu.toggle()
}
}) {
Text("Close Menu")
.font(.system(size: 20, weight: .medium))
.foregroundColor(.red)
}
.padding()
Spacer()
}
Spacer()
}
.padding()
.background(Color.white)
.cornerRadius(0)
}
.offset(y: showMenu ? viewOffest + offset.height : bounds.height)
.gesture(dragGesture)
}
}
}
It is not possible for now perhaps we can in further update, nonetheless you can create your own custom view.

SwiftUI - in sheet have a fixed continue button that is not scrollable

As you can see even though I am trying to pull the sheet down, the continue button does not move down. How can I make my sheet to behave like that? In my app the continue button moves offscreen. This is how my app looks when the sheet is pulled down slightly:
I have also attached my code below, it looks aesthetic on both landscape and portrait orientation. Is there a way to pull this off without ruining how it looks on landscape on smaller devices such as the iPhone 7?
import SwiftUI
struct IntroView: View {
#State private var animationAmount: CGFloat = 1
#Environment(\.presentationMode) var presentationMode
#Environment(\.verticalSizeClass) var sizeClass
var body: some View {
VStack {
VStack {
Spacer()
if sizeClass == .compact {
HStack {
Text("Welcome to Demo").fontWeight(.heavy)
Text("App").foregroundColor(.orange).fontWeight(.heavy)
}
.padding(.bottom, 10)
}
else {
Text("Welcome to").fontWeight(.heavy)
HStack {
Text("Demo").fontWeight(.heavy)
Text("App").foregroundColor(.orange).fontWeight(.heavy)
}
.padding(.bottom, 30)
}
}//Intro VStack close
.font(.largeTitle)
.frame(maxWidth: .infinity, maxHeight: 180)
VStack (spacing: 30) {
HStack (spacing: 20) {
Image(systemName: "sparkle")
.foregroundColor(.yellow)
.font(.title2)
.scaleEffect(animationAmount)
.onAppear {
let baseAnimation = Animation.easeInOut(duration: 1)
let repeated = baseAnimation.repeatForever(autoreverses: true)
return withAnimation(repeated) {
self.animationAmount = 1.5
}
}
VStack (alignment: .leading) {
Text("All new design").fontWeight(.semibold)
Text("Easily view all your essentials here.")
.foregroundColor(.gray)
}
Spacer()
}//HStack 1
.padding([.leading, .trailing], 10)
HStack (spacing: 20) {
Image(systemName: "pin")
.foregroundColor(.red)
.font(.title2)
.padding(.trailing, 5)
.scaleEffect(animationAmount)
.onAppear {
let baseAnimation = Animation.easeInOut(duration: 1)
let repeated = baseAnimation.repeatForever(autoreverses: true)
return withAnimation(repeated) {
self.animationAmount = 1.5
}
}
VStack (alignment: .leading) {
Text("Pin favourites").fontWeight(.semibold)
Text("You can pin your favourite content on all devices")
.foregroundColor(.gray)
}
Spacer()
}//HStack 2
.padding([.leading, .trailing], 10)
.frame(maxWidth: .infinity, maxHeight: 100)
HStack (spacing: 20) {
Image(systemName: "moon.stars.fill")
.foregroundColor(.blue)
.font(.title2)
.scaleEffect(animationAmount)
.onAppear {
let baseAnimation = Animation.easeInOut(duration: 1)
let repeated = baseAnimation.repeatForever(autoreverses: true)
return withAnimation(repeated) {
self.animationAmount = 1.5
}
}
VStack (alignment: .leading) {
Text("Flexible").fontWeight(.semibold)
Text("Supports dark mode")
.foregroundColor(.gray)
}
Spacer()
}//HStack 3
.padding([.leading, .trailing], 10)
}//VStack for 3 criterias
.padding([.leading, .trailing], 20)
Spacer()
Button {
presentationMode.wrappedValue.dismiss()
UserDefaults.standard.set(true, forKey: "LaunchedBefore")
} label: {
Text("Continue")
.fontWeight(.medium)
.padding([.top, .bottom], 15)
.padding([.leading, .trailing], 90)
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(15)
}
.frame(maxWidth: .infinity, maxHeight: 100)
}//Main VStack
}
}
struct IntroView_Previews: PreviewProvider {
static var previews: some View {
IntroView()
}
}
Here is a demo of possible approach (tuning & effects are out of scope - try to make demo code short). The idea is to inject UIView holder with button above sheet so it persist during sheet drag down (because as findings shown any dynamic offsets gives some ugly undesired shaking effects).
Tested with Xcode 12 / iOS 14
// ... your above code here
}//VStack for 3 criterias
.padding([.leading, .trailing], 20)
Spacer()
// button moved from here into below background view !!
}.background(BottomView(presentation: presentationMode) {
Button {
presentationMode.wrappedValue.dismiss()
UserDefaults.standard.set(true, forKey: "LaunchedBefore")
} label: {
Text("Continue")
.fontWeight(.medium)
.padding([.top, .bottom], 15)
.padding([.leading, .trailing], 90)
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(15)
}
})
//Main VStack
}
}
struct BottomView<Content: View>: UIViewRepresentable {
#Binding var presentationMode: PresentationMode
private var content: () -> Content
init(presentation: Binding<PresentationMode>, #ViewBuilder _ content: #escaping () -> Content) {
_presentationMode = presentation
self.content = content
}
func makeUIView(context: Context) -> UIView {
let view = UIView()
DispatchQueue.main.async {
if let window = view.window {
let holder = UIView()
context.coordinator.holder = holder
// simple demo background to make it visible
holder.layer.backgroundColor = UIColor.gray.withAlphaComponent(0.5).cgColor
holder.translatesAutoresizingMaskIntoConstraints = false
window.addSubview(holder)
holder.heightAnchor.constraint(equalToConstant: 140).isActive = true
holder.bottomAnchor.constraint(equalTo: window.bottomAnchor, constant: 0).isActive = true
holder.leadingAnchor.constraint(equalTo: window.leadingAnchor, constant: 0).isActive = true
holder.trailingAnchor.constraint(equalTo: window.trailingAnchor, constant: 0).isActive = true
if let contentView = UIHostingController(rootView: content()).view {
contentView.backgroundColor = UIColor.clear
contentView.translatesAutoresizingMaskIntoConstraints = false
holder.addSubview(contentView)
contentView.topAnchor.constraint(equalTo: holder.topAnchor, constant: 0).isActive = true
contentView.bottomAnchor.constraint(equalTo: holder.bottomAnchor, constant: 0).isActive = true
contentView.leadingAnchor.constraint(equalTo: holder.leadingAnchor, constant: 0).isActive = true
contentView.trailingAnchor.constraint(equalTo: holder.trailingAnchor, constant: 0).isActive = true
}
}
}
return view
}
func updateUIView(_ uiView: UIView, context: Context) {
if !presentationMode.isPresented {
context.coordinator.holder.removeFromSuperview()
}
}
func makeCoordinator() -> Coordinator {
Coordinator()
}
class Coordinator {
var holder: UIView!
deinit {
holder.removeFromSuperview()
}
}
}
Simply add that :
.sheet(isPresented: self.$visibleSheet) {
IntroView(visibleSheet: self.$visibleSheet)
.presentation(shouldDismissOnDrag: false)
}
https://stackoverflow.com/a/61239704/7974174 :
extension View {
func presentation(shouldDismissOnDrag: Bool, onDismissalAttempt: (()->())? = nil) -> some View {
ModalView(view: self, shouldDismiss: shouldDismissOnDrag, onDismissalAttempt: onDismissalAttempt)
}
}
struct ModalView<T: View>: UIViewControllerRepresentable {
let view: T
let shouldDismiss: Bool
let onDismissalAttempt: (()->())?
func makeUIViewController(context: Context) -> UIHostingController<T> {
UIHostingController(rootView: view)
}
func updateUIViewController(_ uiViewController: UIHostingController<T>, context: Context) {
uiViewController.parent?.presentationController?.delegate = context.coordinator
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, UIAdaptivePresentationControllerDelegate {
let modalView: ModalView
init(_ modalView: ModalView) {
self.modalView = modalView
}
func presentationControllerShouldDismiss(_ presentationController: UIPresentationController) -> Bool {
modalView.shouldDismiss
}
func presentationControllerDidAttemptToDismiss(_ presentationController: UIPresentationController) {
modalView.onDismissalAttempt?()
}
}
}
It disables the sheet closing by dragging the sheet down. If you want to close the sheet with the button do not use presentationMode anymore. Pass a binding of self.$visibleSheet then modify to false from inside...

SwiftUI - How to limit the scope of animation to only the onAppear Transition

I'm new to SwiftUI and working through some sample projects to get the hang of it and I'm getting stuck on limiting the scope of the animation I set for the .transition for an AnimationModifier so it only impacts the animation of the transition and nothing else in the view.
While the separate transitions are respected for onAppear() and another for onDisappear(). The animation in the AnimatableModifier is overriding the removal over the item from the grid even when explicitly declared
I've tried explcicitly setting the Animation to the .offset transition in both the AnimatableModifier and for the CardView in the GameView, and when I do, no animation is triggered at all:
.transition(AnyTransition.offset(CGSize.init(width: randomXLocation, height: -offset.height-50)).animation(Animation.easeInOut(duration: 1.25).delay(delay)))
So, there's gotta be a way to limit the scope or explicitly declare the animation for transition or two separate Animations in the Animation Modifier, but I'm not finding any resources on how to move forward.
GameView.swift
struct GameView: View {
#ObservedObject var viewModel: SetGameViewModel
#State var delay: Double = 0.1
var body: some View {
GeometryReader { geometry in
VStack {
Grid(newItems: self.viewModel.newCards,
items: self.viewModel.cards.itemsAtWithIds(ids: self.viewModel.idOfCardsToDisplay)) { card in
CardView(card: card, bodyGeoProxy: geometry, delay: self.delay).onTapGesture {
self.viewModel.choose(card: card)
}
.transition(AnyTransition.offset(CGSize.init(width: randomXLocation, height: -offset.height-50)))
.animation(Animation.easeInOut(duration: 1.25).delay(delay))
.onAppear() {
let maxDelay: Double = Double(self.viewModel.cards.itemsAtWithIds(ids: self.viewModel.idOfCardsToDisplay).count)*0.2 + 0.2
if self.delay < 2.5 {
self.delay = self.delay + 0.2
} else if self.delay >= maxDelay {
self.delay = 0.1
}
}
}
HStack{
Button(action: {
self.viewModel.dealThreeCards()
}) {
Text("Hit Me")
}
Spacer()
Text("Score: \(self.viewModel.score)")
Spacer()
Button(action: {
self.viewModel.dealThreeCards()
}) {
Text("New Game")
}
}
}
}
}
}
GameView.swift
struct CardView: View{
var card: SetGame<SoloSetCardContent>.Card
var bodyGeoProxy: GeometryProxy
var delay: Double
var body: some View {
GeometryReader { geometry in
self.body(for: geometry)
}
}
init(card: SetGame<SoloSetCardContent>.Card, bodyGeoProxy: GeometryProxy, delay: Double) {
self.card = card
self.bodyGeoProxy = bodyGeoProxy
self.delay = delay
}
#ViewBuilder
func body(for geometryProxy: GeometryProxy) -> some View {
ZStack {
if card.isSelected {
RoundedRectangle(cornerRadius: 5)
.fill(Color.gray)
.frame(width: geometryProxy.size.width-4, height: geometryProxy.size.height-4, alignment: .center)
.border(Color.blue, width: 2)
.animation(nil)
} else {
RoundedRectangle(cornerRadius: 5)
.fill(Color.gray)
.frame(width: geometryProxy.size.width-4, height: geometryProxy.size.height-4, alignment: .center)
.border(Color.red, width: 2)
.animation(nil)
}
VStack {
ForEach(0..<self.card.content.deckShapes.count) { index in
VStack {
Spacer(minLength: 5)
ShapeView(setShape: self.card.content.deckShapes[index])
.frame(width: (geometryProxy.size.width-geometryProxy.size.width/5), height: geometryProxy.size.height/5, alignment: .center)
Spacer(minLength: 5)
}
}
}
}
.deal(delay: self.delay, offset: bodyGeoProxy.size)
}
}
Dealer.Swift - AnimatableModifier
struct Dealer: AnimatableModifier {
#State var show: Bool = false
var delay: Double
var offset: CGSize
var randomXLocation: CGFloat {
CGFloat.random(in: -offset.width ..< offset.width)
}
func body(content: Content) -> some View {
ZStack {
if show {
content
.transition(AnyTransition.offset(CGSize.init(width: randomXLocation, height: -offset.height-450)))
.animation(Animation.easeInOut(duration: 1.25).delay(delay))
}
}
.onAppear {
withAnimation {
self.show = true
}
}
.onDisappear {
withAnimation {
self.show = false
}
}
}
}
extension View {
func deal(delay: Double, offset: CGSize) -> some View {
self.modifier(Dealer(delay: delay, offset: offset))
}
}
I was able to resolve this by removing the Animation from the body content (and elsewhere) and adding to withAnimation portion of the .onAppear method in body function of the AnimationModifier
func body(content: Content) -> some View {
ZStack {
if show {
content
.transition(.asymmetric(insertion: .offset(CGSize.init(width: randomXLocation, height: -offset.height-50)),
removal: .offset(CGSize.init(width: randomXLocation, height: offset.height+50))))
}
}
.onDisappear {
withAnimation (Animation.easeInOut(duration: 1.25).delay(0)) {
self.show = false
}
}
.onAppear {
withAnimation (Animation.easeInOut(duration: 1.25).delay(self.delay)) {
self.show = true
}
}
}

Presenting - Show a view on top in SwiftUI (I don't want to navigate)

Hey There I want to show a custom View in the middle of View I've tried to add ZStack and centered but doesn't work.. here's my code
var body: some View {
VStack(alignment: .leading, spacing: 8) {
headerView.padding().background(Color.white)
ZStack(alignment: .center) {
if(incomeFill_show) {
BudgetAlert(amount: .constant("400"))
}
List() {
VStack {
Section(header: self.getHeaderView()) {
ForEach(categoriesData) { category in
HStack(alignment: .bottom) {
CategoryProgressView(category: category, value: .constant(.random(in: 0.1 ... 1)))
self.valuesText(category: category)
}
}
.colorMultiply(Colors.SharedColors.backgroundColor)
}
}
}
.colorMultiply(Colors.SharedColors.backgroundColor)
.onAppear {UITableView.appearance().separatorStyle = .none}
.onDisappear { UITableView.appearance().separatorStyle = .singleLine }
}
}.background(Colors.SharedColors.backgroundColor)
}
all I want is to show BudgetAlert() with blurred background like this:
I solved it by placing
if(incomeFill_show) {
BudgetAlert(amount: .constant("400"))
}
at the bottom of the List: like this
var body: some View {
VStack(alignment: .leading, spacing: 8) {
headerView.padding().background(Color.white)
ZStack(alignment: .center) {
List() {
VStack {
Section(header: self.getHeaderView()) {
ForEach(categoriesData) { category in
HStack(alignment: .bottom) {
CategoryProgressView(category: category, value: .constant(.random(in: 0.1 ... 1)))
self.valuesText(category: category)
}
}
.colorMultiply(Colors.SharedColors.backgroundColor)
}
}
}
.colorMultiply(Colors.SharedColors.backgroundColor)
.onAppear {UITableView.appearance().separatorStyle = .none}
.onDisappear { UITableView.appearance().separatorStyle = .singleLine }
if(incomeFill_show) {
BudgetAlert(amount: .constant("400"))
}
}
}.background(Colors.SharedColors.backgroundColor)
}
}
for blurred background you can see this code here:
var body: some View {
VStack {
Spacer()
ZStack(alignment: .center) {
RoundedRectangle(cornerRadius: 10).foregroundColor(Color.white)
VStack {
Text("Add your Income").font(Fonts.mediumFont)
HStack(alignment: .center, spacing: 0) {
CustomTextField(placeHolderLabel: "Amount", val: $amount, keyboardType: UIKeyboardType.decimalPad).padding()
HStack {
Button("\(currency.rawValue)"){
self.show_currencyActionsheet = true
}
.font(Fonts.callout)
.foregroundColor(Colors.textFieldFloatingLabel)
.actionSheet(isPresented: self.$show_currencyActionsheet) {self.actionSheetCurrency}
Image(systemName: "chevron.down")
.imageScale(.small)
}.padding()
}.padding([.leading,.trailing])
Button(action: {
self.callBack()
}) {
Text(" Add Income ").font(Fonts.callout).foregroundColor(Color.white)
}
.padding()
.background(Colors.darkGreen)
.clipShape(Capsule())
}
}.frame(minHeight: 150, idealHeight: 182, maxHeight: 200)
.padding()
Spacer()
}.background(VisualEffectView(effect: UIBlurEffect(style: .dark))
.edgesIgnoringSafeArea(.all))
}
struct VisualEffectView: UIViewRepresentable {
var effect: UIVisualEffect?
func makeUIView(context: UIViewRepresentableContext<Self>) -> UIVisualEffectView { UIVisualEffectView() }
func updateUIView(_ uiView: UIVisualEffectView, context: UIViewRepresentableContext<Self>) { uiView.effect = effect }
}
but I prefer to go with faded background