I'm attempting to have a NavigationLink load a view from the bottom of the screen instead of transitioning from the right, but the "obvious" approach (using a .transition(.move(edge: .bottom))) doesn't seem to be having any effect.
The below is inside a NavigationView:
List {
ForEach(self.message, id: \.self) { message in
HStack(alignment: .center) {
MessageListCell(....)
}
}
}
and MessageListCell:
var body: some View {
HStack {
VStack(alignment: .leading, spacing: 0) {
Text(person.firstName).lineLimit(1)
.foregroundColor(.main)
}
Spacer()
NavigationLink(destination: MessageDetail(otherPerson: otherPerson,
subject: subject,
profileHandler: { ProfileReducer($0) })
.transition(.move(edge: .bottom)),
tag: 1, selection: $action) {
NextButton("Proceed")
}
}
}
Tapping the NextButton consistently transitions from the right side of the screen instead of the bottom. I've tried variations on the above but I'm starting to think that transition might not be the right approach.
Related
How can I implement play buttons that navigate to different views in the corner of each music category item? Here is an image of what I am looking for:
Here is my code:
struct ScrollCategories: View {
var body: some View {
ZStack {
ScrollView {
LazyVGrid (columns: [GridItem(.fixed(200)), GridItem(.fixed(200))]) {
ForEach(musics) { sub in
ZStack {
VStack(alignment: .leading) {
//Hidden Code
} // END OF VSTACK
NavigationLink {
// Naviagte to a different view!
Onboarding()
} label: {
Image(systemName: "play.circle")
.font(.system(size: 30))
.padding(.leading, -72.0)
.padding(.bottom, 130.0)
}
} // END OF ZSTACK
}// END OF FOR EACH
} // END OF GRID ITEM
} // END OF SCROLL VIEW
} //END OF ZSTACK
}
}
As you can see, I have a navigation link, yet it does not show in the preview or simulator.
Here is an image of what the preview looks like:
Your navigation link is there. You just use padding too high that it was out of the frame. You can use ZStack with alignment to put on the left-top corner and add padding to make it nice.
ZStack(alignment: .topLeading) { <- positioning for each View
VStack(alignment: .leading) {
//Hidden Code
} // END OF VSTACK// END OF VSTACk
NavigationLink {
// Navigate to a different view!
Onboarding()
} label: {
Image(systemName: "play.circle")
.font(.system(size: 30))
.padding( {{ put your desire padding }})
}
} // END OF ZSTACK
I have a navigation view with tab views inside. The reason for this arrangement is to make the tab views disappear when within the navigation views.
I am trying to place a button at the top right corner of the screen (outside the safe area). If EntryView is called directly, the view correctly places the button ("Save") in the corner without use of offset() or position() view modifiers.
When the tab view is called before EntryView, the Save button appears an inch or so below where I would like it to appear. With offset() or position() I can move the button text back where I would like it to appear, but the tappable area doesn't move to the new location.
I have tried different arrangements of ZStack and VStack, but the arrangement below is the closest I have come to getting the button to work in the upper right corner.
Here is where I would like the button to appear: https://i.stack.imgur.com/AMdKQ.png
Is there any way to move the tappable area up to where the text is located?
Or is there some better way to draw the top part of the view?
This code can be dropped directly into Xcode for analysis.
struct ContentView: View {
#State private var selectedTab: Tabs = .home
var body: some View {
NavigationView {
TabView (selection: $selectedTab) {
EntryView()
.tabItem {
Label("Home", systemImage: "house.circle.fill")
}.tag(Tabs.home)
HistoryView()
.tabItem {
Label("History", systemImage: "clock.fill")
}.tag(Tabs.history)
}
}
}
}
struct EntryView: View {
var body: some View {
GeometryReader { g in
ZStack (alignment: .top) {
Color.blue
.frame(height: (g.safeAreaInsets.top) * 0.6, alignment: .top)
.ignoresSafeArea()
HStack {
Spacer()
Button(action: {
print("Save tapped!")
}) {
Text("Save")
.font(Font.title3.bold())
.foregroundColor(.red)
.offset(y: g.size.height * -0.14)
// .position(x: g.size.width * 0.90, y: g.size.height * -0.115)
}
}
.padding(.trailing, 10)
}
}
}
}
struct HistoryView: View {
var body: some View {
VStack (alignment: .leading) {
Text("History Tab")
.padding(.top)
}
}
}
enum Tabs: String {
case home
case history
}
I have tried to use Buttons and Navigation Links from various examples when researched on this channel and on the net. The NavigationLink would be ok, except that the NavigationView is pushing everything down in my view.
I have a view that contains an image and a text like this: ( x Close) but when I use the code below, the Close button is not doing anything.
In ContentView() I have a (?) button that takes me from WalkthroughView(), then to the PageTabView, then to this view, TabDetailsView:
ContentView():
ZStack {
NavigationView {
VStack {
Text("Hello World")
.padding()
.font(.title)
.background(Color.red)
.foregroundColor(.white)
}
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button {
withAnimation {
showOnBoarding = true
}
} label: {
Image(systemName: "questionmark.circle.fill")
}
}
}
}
.accentColor(.red)
.disabled(showOnBoarding)
.blur(radius: showOnBoarding ? 3.0 : 0)
if showOnBoarding {
WalkthroughView(isWalkthroughViewShowing: $isWalkthroughViewShowing)
}
}
.onAppear {
if !isWalkthroughViewShowing {
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
withAnimation {
showOnBoarding.toggle()
isWalkthroughViewShowing = true
}
}
}
}
WalkthroughView():
var body: some View {
ZStack {
GradientView()
VStack {
PageTabView(selection: $selection)
// shows Previous/Next buttons only
ButtonsView(selection: $selection)
}
}
.transition(.move(edge: .bottom))
}
PageTabView():
var body: some View {
TabView(selection: $selection) {
ForEach(tabs.indices, id: \.self) { index in
TabDetailsView(index: index)
}
}
.tabViewStyle(PageTabViewStyle())
}
below, is the TabDetailsView():
At the top of the view is this Close button, when pressed, should send me back to ContentView, but nothing is happening.
struct TabDetailsView: View {
#Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
let index: Int
then, inside the body:
VStack(alignment: .leading) {
Spacer()
VStack(alignment: .leading) {
// Button to close each walkthrough page...
Button(action: {
self.presentationMode.wrappedValue.dismiss()
}) {
Image(systemName: "xmark.circle.fill")
Text("Close")
}
.padding(.leading)
.font(.title2)
.accentColor(.orange)
Spacer()
VStack {
Spacer()
Image(tabs[index].image)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 415)
.padding(.leading, 10)
Text(tabs[index].title)
.font(.title)
.bold()
Text(tabs[index].text)
.padding()
Spacer()
}
.foregroundColor(.white)
}
}
if showOnBoarding {
WalkthroughView(isWalkthroughViewShowing: $isWalkthroughViewShowing)
}
Inserting view like above is not a presentation in standard meaning, that's why provided code does not work.
As this view is shown via showOnBoarding it should be hidden also via showOnBoarding, thus the solution is to pass binding to this state into view where it will be toggled back.
Due to deep hierarchy the most appropriate way is to use custom environment value. For simplicity let's use ResetDefault from https://stackoverflow.com/a/61847419/12299030 (you can rename it in your code)
So required modifications:
if showOnBoarding {
WalkthroughView(isWalkthroughViewShowing: $isWalkthroughViewShowing)
.environment(\.resetDefault, $showOnBoarding)
}
and in child view
struct TabDetailsView: View {
#Environment(\.resetDefault) var showOnBoarding
// .. other code
Button(action: {
self.showOnBoarding.wrappedValue.toggle()
}) {
Image(systemName: "xmark.circle.fill")
Text("Close")
}
I know this has been solved in iOS 14 but my current project is in iOS 13 and we have to release it fast. I tried multiple approach from stack but no luck. I just want to click a button and scroll to the bottom of the ScrollView, thats it. I was surprised there is not built in function in SwiftUI for this !!!
struct ContentView: View {
var items = [Color.red, Color.orange, Color.yellow, Color.green,Color.blue, Color.purple, Color.red, Color.orange, Color.yellow, Color.green,Color.blue, Color.purple]
var body: some View {
ZStack {
ScrollView(Axis.Set.vertical, showsIndicators: false) {
VStack {
ForEach(self.items, id: \.self) { item in
// 3.
Circle()
.fill(item)
.frame(width: 100, height: 100)
}
}
}
VStack {
Spacer()
HStack {
Spacer()
Button(action: {
// scroll to bottom
}) {
Text("Button")
}
}
.padding(.trailing, 20)
.padding(.bottom, 20)
}
}
}
}
If anybody could help
After a few hours search i found this amazing library that does exactly as you want
ScrollView{ proxy in
Button("click"){
proxy.scrollTo(200)
}.foregroundColor(.red)
ForEach(0..<1000){ index in
Text("\(index)")
.scrollId(index)
}
}
What is an effective & effecient way to get the Dismiss button (X) into the top right corner?
I'm struggling with container alignment... can't say I GROK it.
Needless to say ... this ain't it!
var body: some View {
ZStack {
Image("Biz-card_2020")
.resizable()
.edgesIgnoringSafeArea(.all)
HStack(alignment: .top) {
VStack() {
Spacer(minLength: 5) // vertical space
HStack() {
Spacer()
// close Welcome page (X) button
Button(action: {
//print(" - Button to dismiss page \(self.isPresented)")
self.isPresented = false // dismiss the Welcome view
//print(" - after action Button to dismiss Welcome page \(self.isPresented)")
}, label: {
Image(systemName: "xmark.circle" )
.scaledFont(name: "Georgia", size: Const.titleText)
.minimumScaleFactor(0.3)
.accentColor(.white)
.padding(10)
})
}
Spacer()
}
}
}
}
You need to remove Spacer(minLength: 5) and replace it with padding for HStack.
Spacer(minLength: 5) doesn't mean its length will be exactly 5 (only that the minimum length will be 5).
You may also want to extract close button to another function for clarity.
Try the following:
struct ContentView: View {
...
var body: some View {
ZStack {
Image("Biz-card_2020")
.resizable()
.edgesIgnoringSafeArea(.all)
closeButton
}
}
var closeButton: some View {
VStack {
HStack {
Spacer()
Button(action: {
...
}) {
Image(systemName: "xmark.circle")
.padding(10)
}
}
.padding(.top, 5)
Spacer()
}
}
}
ZStack can be configured using .topTrailing etc. You should use those alignments to configure your view. Using something like Spacer() is going to cause the rest of your views to get pushed down.
ZStack(alignment: .topTrailing) {
// your code here
}
If you need to move your code a bit more, use either padding, or offset modifiers.