What is this SwiftUI view called? - swift

What is this SwiftUI popup View called (The one that says that I have earned 30 Bits)?

In terms of a standard UI component that causes a view like that to pop up, there is none.
However, you can create one yourself.
The basic frame is most likely a Capsule, which you can create by doing this:
VStack {
Text("My info")
}
.frame(width: 300, height: 50)
.background(
Capsule()
.fill(Color.white)
)
You can put that on top of the rest of your view hierarchy using a ZStack

Related

SwiftUI: disable interactions on transparent parts of ScrollView

Assuming I have a horizontal ScrollView, where the first item has a view a lot taller than the rest. Is there any way to limit the interaction to the visible elements (black rectangles in the image below)?
ScrollView(.horizontal) {
HStack(alignment: .bottom) {
VStack(alignment: .center, spacing: 1) {
Rectangle()
.frame(width: 20, height: 70)
Rectangle()
.frame(width: 40, height: 40)
}
ForEach((1...10), id: \.self) { _ in
Rectangle()
.frame(width: 40, height: 40)
}
}
}
.background(.yellow)
I don't want to have the invisible area here blocking everything beneath that view, so everything in the red area should not scroll on the scrollview.
In my case, there’s a zoomable ScrollView in horizontal and vertical direction behind it and text all over it that can be tapped on (live text image view).
Here are my ideas, I was either not smart enough to properly implement them or it's simply not possible:
allowsHitTesting(false) on ScrollView and enable on the child views: child views can't be enabled if parent is off
.contentShape(...) on ScrollView: doesn't disable scrolling, also I found no way to manually draw the contentshape around the content
move the first item down and use .offset(y: -300) on the first item to move it back up: item is clipped outside the ScrollView
use UIViewRepresentable with UIScrollView and gestureRecognizerShouldBegin(...) to let all gestures on that area through: I don't know how to implement that (would this be possible?)
move the first item outside the ScrollView: in theory works, but not ideal since the item no longer scrolls and I couldn't get the animations of reordering right
detach the "upper" view, track the position of the item inside the ScrollView and move the upper view manually: probably would lag behind, also not a very elegant solution
Is one of them actually possible? Any other ideas? Thanks :)
How about something like this:
ZStack(alignment: .top) {
ScrollView(.horizontal) {
HStack(alignment: .bottom) {
Rectangle()
.frame(width: 20, height: 90)
ForEach((1...15), id: \.self) { _ in
Rectangle()
.frame(width: 20, height: 20)
}
}
}
.background(.yellow)
Text("test")
.frame(width: 100, height: 50)
.background(.red)
}
Text is in front of you ScrollView and can't be hit, thus not triggering your ScrollView. From your question, it's hard to guess, what content lies behind your ScrollView and if any further culprits may apply.

ProgressView vs View inside ZStack behave differently

I have 2 views inside a ZStack. One is ProgressView() and another one is Circle().
In this ZStack, i have a green background color with onTapGesture event.
I notice that whenever i click on the ProgressView() the event of background color do not trigger but when i click on the Circle() it trigger the event of background color.
So why is that if both of these are on top of background color? i think it should not trigger the event for both views.
ZStack() {
Color.green.ignoresSafeArea(.all)
.onTapGesture {
print("checked")
}
VStack() {
ProgressView()
Circle().frame(width: 30, height: 30, alignment: .leading)
}
}
They are actually not. Let's consider view hierarchy below (from view debug mode)
Shape is a native SwiftUI view and it is just rendered into the same backend as background and, actually by default not hit-testable.
ProgressView in contrary has UIKit backend, because it just representable of UIView, and all UIViews are added above native SwiftUI view (note, even if they are put into background). And by default this opaque UIView does not pass touch events through to SwiftUI.
That's it.
*changed to yellow color for better visibility
As #Asperi wrote your VStack is in front of the Color View.
But one can use the modifier allowsHitTesting.
With this gesture are not processed by this view.
#State var text: String = "Hello World"
var body: some View {
ZStack() {
Color.green.ignoresSafeArea(.all)
.onTapGesture {
text = "Green tapped"
}
VStack() {
ProgressView()
Circle().frame(width: 30, height: 30, alignment: .leading)
Text(text)
}
.allowsHitTesting(false)
}
}
This seems like a normal behavior.
However, if you want to get rid of this problem, you can always wrap your stack with a simple blank onTapGesture{}.
VStack {
}.onTapGesture{}
onTapGesture{} will get your stack rid of this problem, plus it will not affect your sub view and buttons inside the stack. Your Button inside the stack will behave normally.

SwiftUI horizontal ScrollView wanting to auto centre item

I’m very new to SwiftUI and trying to figure out the best way to handle this.
I have set up a card view and that I have in a horizontal ScrollView. I am trying to get it to snap or align to the next card so it is always central. Think App Store apps or games tab in the header, I want it to behave like this.
I have searched around a lot for this but cant seem to find a solution, at least in SwiftUI. I implemented a similar thing in a UIKit app but I’m looking for a native SwiftUI solution if at all possible. This is what I implemented previously https://github.com/BenEmdon/CenteredCollectionView Though I am trying to seek a lighter and native SwiftUI way of doing this if at all possible as I always felt this was a little heavy for what I need.
The code I have so far is as follows:
ScrollView(.horizontal,
content: {
HStack {
CardView(card: cardDetails)
CardView(card: cardDetails)
CardView(card: cardDetails)
CardView(card: cardDetails)
}
.padding(.leading, 10)
})
.frame(height: 250)
struct CardView: View {
let card: Card
var body: some View {
ZStack {
RoundedRectangle(cornerRadius: 25, style: .continuous)
.fill(Color.white)
VStack {
Text(card.prompt)
.font(.largeTitle)
.foregroundColor(.black)
Text(card.answer)
.font(.title)
.foregroundColor(.gray)
}
.padding(20)
.multilineTextAlignment(.center)
}
.frame(width: 450, height: 250)
}
}
Any input will be greatly appreciated, thank you in advance for your help.
Here is an image from the App Store, the header section is similar to what I want to achieve, when you scroll through these it scrolls on a per item basis and almost snaps to the next item rather than a free scroll:

SwiftUI Mac Positioning view absolute inside other view

I am trying to position a view absolutely inside a other view in SwiftUI for MacOS.
I am basically having a VStack, with a ScrollView/ List inside. How can I position a view absolute in a corner. Even when the window gets shrinked it should stay there. It even may overlap with the content of the ListView.
I couldn't really figure it out how to do it. I used a different approach at the moment, with using a new VStack then use Spacer() and put a new HStack right at the bottom with an item aligned right. This works but basically don't overlap. The views are separated.
Here is a demo... I want to achieve that yellow circle. It can basically be an Image or another View..
Even when the window gets smaller, it will stay there:
Here is the code I used... it is just a simple scroll view with content.
ScrollView(content: {
HStack
{
Spacer()
Text("Test Test TestTest Test TestTest Test Test")
Spacer()
}
...
}).frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color(.red))
It can be used ZStack as below
struct TestCircleWithList: View {
var body: some View {
ZStack(alignment: .bottomTrailing) {
ScrollView(content: {
HStack
{
Spacer()
Text("Test Test TestTest Test TestTest Test Test")
Spacer()
}
}).frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color(.red))
Circle().fill(Color.yellow)
.frame(width: 80, height: 80)
.padding(20)
}
}
}

What is the alternative for SwiftUI of UIKit's "pushViewController" in a barButtonItem

I'm working on a very simple app in SwiftUI and I have managed to create a NavigationButton for my List that takes me to the DetailViewController.
In the up right corner I wanted to have a "+" button to add things to my List:
navigationBarItems(trailing:
NavigationButton(destination: DetailVC()) {
Image(systemName: "plus")
.resizable()
.frame(width: 20, height: 20)
}
)
The problem is that when I tap on the button it doesn't navigate to my DetailVC.
I also tried this:
.navigationBarItems(trailing:
PresentationButton(destination: DetailVC()) {
Image(systemName: "plus")
.resizable()
.frame(width: 20, height: 20)
}
)
With this code the problem is that it doesn't present the DetailVC with a "Back" button, but it shows up from the bottom and there is no way to go back in my ContentView
What is the correct item to put in the navigation bar to navigate correctly?
Thank you, Nico
In SwiftUI you use a NavigationButton to navigate your app.
Just replace your PresentationButton with a NavigationButton:
.navigationBarItems(trailing:
NavigationButton(destination: DetailVC()) {
Image(systemName: "plus")
.resizable()
.frame(width: 20, height: 20)
}
)
Apple Docs:
https://developer.apple.com/documentation/swiftui/navigationbutton (deprecated)
EDIT:
The NavigationButton was deprecated, so it should no longer be used.
Instead there is a NavigationLink view, which should work. This struct is new and I wasn't able to test it yet but the code for the button itself should look like this:
NavigationLink(destination: DetailVC()) { }
Apple Docs:
https://developer.apple.com/documentation/swiftui/navigationlink
I made sample to display list and details. Hope this sample app will help you.
https://github.com/Shiju86/ListViewSwiftUI
and that's right, NavigationButton is no more and instead of this apple provide us NaviagtionLink.
NavigationLink should be how do do this. However in iOS 13.2 and 13.3 this appears to be broken/unreliable when used within a header (and completely broke my app: I figured out a work around by moving the NavigationLink out of the header and making the something else a modal).
It works better (but still with quirks) within standard Views themselves. Ridiculously you may want to consider using a modal instead of child View as that seems to actually work.