I have encountered this problem during UI building. Previously, I've been asking here about NavigationView and why NavigationLink wasn't working. I fixed this problem with NavigationView at the top of my ScrollView. Now FrameView works just fine: opens and closes it in preview, which means I'm doing it right.
Here's the catch: When I add this LongFrameScrollView to my main view HomeView, it appears in some sort of frame and doesn't open link in full screen.
What am I doing wrong? How to fix that? Providing the code:
// Long frame view
import SwiftUI
struct LongFrameView: View {
var body: some View {
NavigationLink {
PlayerView()
} label: {
ZStack {
Rectangle()
.fill(LinearGradient(gradient: Gradient(colors: [Color(red: 0.268, green: 0.376, blue: 0.587), Color(red: 0.139, green: 0.267, blue: 0.517)]),
startPoint: .leading,
endPoint: .trailing))
.frame(width: 310, height: 62)
.cornerRadius(8)
HStack {
Image("mountains")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 70, height: 62)
.cornerRadius(8, corners: [.topLeft, .bottomLeft])
VStack(alignment: .leading) {
Text("Sense of anxiety")
.font(.custom("Manrope-Bold", size: 14))
.foregroundColor(.white)
Text("11 MIN")
.font(.custom("Manrope-Medium", size: 12))
.foregroundColor(.white)
}
Spacer()
}
}
.frame(width: 310, height: 62)
}
}
}
// Scroll View with LongFrame. Works fine in the preview
struct LongFrameScrollView: View {
let rows = Array(repeating: GridItem(.fixed(70), spacing: 10, alignment: .leading), count: 2)
var body: some View {
NavigationView {
ScrollView(.horizontal, showsIndicators: false) {
LazyHGrid(rows: rows, spacing: 10) {
// PLACEHOLDER UNTIL SERVER IS READY
LongFrameView()
LongFrameView()
LongFrameView()
LongFrameView()
}
}
.padding([.horizontal, .bottom], 10)
}
}
}
var body: some View {
ScrollView(.vertical, showsIndicators: false) {
VStack(alignment: .center) {
///
// Long frame. There is more view, but we'll just ignore them
LongFrameScrollView()
.padding(.bottom)
///
}
.padding(.top, 10)
}
.background(
Image("background2")
.resizable()
.aspectRatio(contentMode: .fill)
)
}
}
The reason why it wasn't working correctly is because it was in TabView. So, in order to work, our TabView must be in NavigationView and we must delete from all child views NavigationView.
Related
I am rewriting the existing UIKit cell using SwiftUI. The problem is Spacer() cuts Text() and shows less text than the UIKit version (Ethereum C... vs Ethere...). The goal is to have the graph always in the same position in all cells and show more symbols in Text().
var body: some View {
VStack(alignment: .center) {
ZStack {
HStack(spacing: .designSystem(.small)) {
KFImage(viewModel.tradable.logoURL)
.serialize(by: SVGCacheSerializer())
.setProcessor(SVGProcessor())
.scaleFactor(Layout.scaleFactor)
.resizable()
.placeholder {
Circle()
.fill(Color(viewModel.tradable.placeholderColor == nil ? .gray : UIColor(hex: viewModel.tradable.placeholderColor!)))
}
.frame(width: Layout.imageWidth, height: Layout.imageHeight)
.clipShape(RoundedRectangle(cornerRadius: Layout.imageWidth / 2))
.overlay(RoundedRectangle(cornerRadius: Layout.imageWidth / 2).stroke(.white, lineWidth: 2 / UIScreen.main.scale))
VStack(alignment: .leading, spacing: .designSystem(.extraSmall3)) {
Text(viewModel.name).font(.subheadline).fontWeight(.semibold).lineLimit(1)
Text(viewModel.symbol).font(.caption2).foregroundColor(Color(ThemeManager.current.neutral50))
}
Spacer()
AssetLineChartViewRepresentable(viewModel: chartViewModel).frame(width: 65, height: 20)
Spacer()
VStack(alignment: .trailing, spacing: .designSystem(.extraSmall3)) {
percentChangeView(assetPercentChangeType: viewModel.assetPercentChangeType)
Text(viewModel.priceString).font(.caption2).foregroundColor(Color(ThemeManager.current.neutral50))
}
}
.padding([.leading, .trailing])
if !viewModel.shouldHideSeparator {
VStack {
Spacer()
Divider().padding(.leading)
}
}
}
}
.frame(height: Layout.frameHeight)
.background(
backgroundView(assetPositionType: viewModel.corners)
)
}
Removing Spacer()
Im currently working on a project for iOS using SwiftUI. I have 3 pages (MainMenu, CalendarList, and DateDetails.)
On the 2nd page (CalenderList) there is an empty space between the top of the screen and the actual NavigationBarTitle.
on the third page, you can see the back button (to the MainMenu) and there is two empty spaces at the top.
I've seen people use .navigationBarHidden to fix this, but i haven't been able to implement it in a way that fixes the problem.
Am i using NavigationView() incorrectly? or is there a special trick?
Here is the code for the MainMenu:
import SwiftUI
struct MainMenu: View {
var body: some View {
NavigationView {
VStack {
Text("Calendar")
.font(.largeTitle)
.fontWeight(.heavy)
.foregroundColor(Color(red: 0.055, green: 0.173, blue: 0.322))
.padding(.top, 55.0)
Text("Main Menu")
.font(.headline)
.foregroundColor(Color(red: 0.635, green: 0.635, blue: 0.635, opacity: 1.0))
/*Image("Logo")
.resizable()
.frame(width: 150.0, height: 150.0)*/
Spacer()
HStack {
NavigationLink(destination: CalendarList()) {
Image(systemName: "calendar")
.resizable()
.frame(width: 75.0, height: 75.0)
.padding()
}
NavigationLink(destination: CalendarList()) {
Image(systemName: "gear")
.resizable()
.frame(width: 75.0, height: 75.0)
.padding()
}
}
HStack {
NavigationLink(destination: StudentInfo()) {
Image(systemName: "info.circle")
.resizable()
.frame(width: 75.0, height: 75.0)
.padding()
}
NavigationLink(destination: CalendarList()) {
Image(systemName: "exclamationmark.circle")
.resizable()
.frame(width: 75.0, height: 75.0)
.padding()
}
}
Spacer()
}
}
}
}
Here is the code for CalendarList (page 2):
import SwiftUI
struct CalendarList: View {
var body: some View {
NavigationView {
List(calendarData, id: \.date) { Calendar in
if Calendar.collab {
NavigationLink(destination: DateDetails(calendar: Calendar)) {
CalendarRow(calendar: Calendar)
}
} else {
CalendarRow(calendar: Calendar)
}
}
.navigationBarTitle(Text("Schedule"))
}
}
}
And here is the code for DateDetails (page 3):
import SwiftUI
struct DateDetails: View {
var calendar: Calendar
var body: some View {
NavigationView {
VStack (alignment: .center) {
//Image("Logo")
HStack {
Text(calendar.month.prefix(4) + ".")
.font(.largeTitle)
Text(String(calendar.date).suffix(1))
.font(.largeTitle)
Spacer()
}
HStack {
Text(calendar.schedule)
.font(.title)
Spacer()
}
Spacer()
.frame(height: 30.0)
Text(calendar.info)
.font(.body)
Spacer()
}
.navigationBarTitle(String(calendar.date).prefix(4).suffix(2) + "/" + String(calendar.date).suffix(2))
.padding()
}
}
}
Only use NavigationView at the top level, you don't need to add it in every subscreen, just remove it from CalendarList and DateDetails and it will fix your spacing issue
I think you can delete the NavigationView of DateDetails.
If you want to change the navigationbar, you may want to edit navigationBarItems or change navigationBarHidden to true and customize it.
https://www.hackingwithswift.com/quick-start/swiftui/how-to-add-bar-items-to-a-navigation-view
I'm trying to make the circles fit into the HStack such that the HStack size does not increase.
How can I make the circles fit without specifying a fixed frame?
struct ContentView: View {
var body: some View {
NavigationView {
Form {
HStack {
Circle()
.fill(Color.red)
.aspectRatio(1, contentMode: .fit)
Text("Hello")
}
HStack {
Circle()
.fill(Color.blue)
.aspectRatio(1, contentMode: .fit)
Text("Hello")
}
}
}
}
}
Here is a sample of various containers to chose from. SwiftUI will do all the layout, automatically handle rotations and device resolutions.
struct CirclesView: View {
var body: some View {
VStack(spacing: 0) {
Label("Circles", systemImage: "circle").font(.system(size: 24, weight: .black, design: .rounded)).foregroundColor(.pink)
HStack {
Circle()
.foregroundColor(.yellow)
.frame(width: 32, height: 32)
Text("This is a yellow circle")
Spacer()
}
Circle()
.foregroundColor(.orange)
.shadow(radius: 10)
.frame(width: 75)
Divider()
HStack {
VStack {
Circle().foregroundColor(.blue)
Text("Blue").font(.title3)
HStack {
Circle().foregroundColor(.purple)
Text("Purple").font(.caption)
}
}
.padding()
.background(Color.yellow)
ZStack(alignment: Alignment(horizontal: .center, vertical: .center)) {
Circle().foregroundColor(.green)
Text("Green").foregroundColor(.primary)
}
}
}
}
}
When I embed my Button inside a NavigationLink and I set the destination to a Text View, the view doesn't transition upon clicking the button, although it sometimes does transition if I just randomly click around the button. What am I doing wrong?
Here is what I'm working with...
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView{
VStack{
Spacer()
VStack(spacing: 50){
NavigationLink(destination: Text("Testing")){
awButton(content: "Request Support", backColor: Color(#colorLiteral(red: 0.1764705926, green: 0.01176470611, blue: 0.5607843399, alpha: 1)))
}
}
Spacer()
}
.navigationBarTitle(Text("AccessWeb"))
.navigationBarItems(trailing: HStack{
Image(systemName: "bell")
.font(.system(size: 30))
Image(systemName:"person.circle")
.font(.system(size: 30))
Text("Tester")
.font(.system(size: 20))
})
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct awButton: View {
var content : String
var backColor : Color
var body: some View {
Button(action: {}, label: {
VStack {
HStack {
Image(uiImage: #imageLiteral(resourceName: "awText"))
.resizable()
.frame(width: 30, height: 20)
.padding(.leading)
Spacer()
}
.padding(.top)
HStack {
Text("\(content)")
.font(.title)
.fontWeight(.semibold)
.offset(y: 10.0)
}
Spacer()
}
})
.foregroundColor(Color(#colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)))
.frame(width: 300, height: 150, alignment: .center)
.background(backColor)
.clipShape(RoundedRectangle(cornerRadius: 20, style: .continuous))
}
}
The NavigationLink wraps everything in a button already (or at least something that receives click/tap events), so by also including a Button in your custom view, you're preventing those tap events from getting to the original NavigationLink.
But, since your action is empty, you can just take out your Button wrapper:
struct awButton: View {
var content : String
var backColor : Color
var body: some View {
VStack {
HStack {
Image(systemName: "pencil")
.resizable()
.frame(width: 30, height: 20)
.padding(.leading)
Spacer()
}
.padding(.top)
HStack {
Text("\(content)")
.font(.title)
.fontWeight(.semibold)
.offset(y: 10.0)
}
Spacer()
}
.foregroundColor(Color(#colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)))
.frame(width: 300, height: 150, alignment: .center)
.background(backColor)
.clipShape(RoundedRectangle(cornerRadius: 20, style: .continuous))
}
}
I am used to Interface Builder and layout constraints but now I want to convert my app to Swift UI. What I am trying to do right now is align the top edge of the view marked with a 1 to be within a certain distance of the safe area bottom edge (marked with a 2) so that the top edge that is now at 1 will then be at position 3. I tried using spacers but then it will look different on smaller devices such as an iPhone 8. In IB I could have used a simple layout constraint. How does this work in Swift UI? I have attached the relevant code and an image. Thank you for your help.
struct ContentView: View {
init() {
UINavigationBar.appearance().backgroundColor = .orange
}
var body: some View {
NavigationView {
VStack{
Spacer()
ZStack{
Rectangle()
.fill(Color(hue: 0, saturation: 0, brightness: 0, opacity: 0.1))
Image("")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 100, height: 150)
.clipShape(Circle())
.overlay(Circle().stroke(Color.white, lineWidth: 4))
.shadow(radius: 10)
}.frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.width, alignment: .center)
Spacer(minLength: 100)
ZStack(alignment: .bottom){
ExtractedView()
.edgesIgnoringSafeArea(.bottom)
}
}
.navigationBarTitle(Text("You See"))
.navigationBarHidden(false)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.previewDevice("iPhone")
}
}
struct ExtractedView: View {
#State private var name: String = ""
var body: some View {
VStack{
ZStack(alignment: .top){
VStack{
RoundedRectangle(cornerRadius: 50)
.frame(width: 60, height: 7)
.padding(.top)
Button(action: /*#START_MENU_TOKEN#*/{}/*#END_MENU_TOKEN#*/) {
Text("Start advertising")
.font(.headline)
.foregroundColor(Color.black)
}.padding(.top)
TextField("Test", text: $name)
.padding(.all)
.background(Color.white.cornerRadius(20))
.padding()
}
RoundedRectangle(cornerRadius: 30)
.fill(Color(hue: 0, saturation: 0, brightness: 0, opacity: 0.1))
.zIndex(-5)
}
}
}
}
Ok, so I was able to solve my problem. The trick is to create two VStacks with different frame alignments. The outer VStack has top alignment so that the Discover view can be at the top. The inner VStack has a bottom alignment so that the sheet can be pulled up from the bottom. Space will be filled from the bottom up in this case.
VStack{
Discover()
.padding(.top, 60.0)
VStack{
Text("Recent Messages:")
.font(.headline)
DetailSheet()
.offset(x: 0, y: 0)
}.frame(width: g.size.width, height: (g.size.height - g.size.width - 80 + 200), alignment: .bottom)
}
.frame(width: g.size.width, height: g.size.height, alignment: .top)
you can try this:
offset -10 is just your offset you want to have....
i hope i understood you right, i am not so sure...
var body: some View {
VStack{
// ZStack(alignment: .top){
VStack{
RoundedRectangle(cornerRadius: 50)
.frame(width: 60, height: 7)
.padding(.top)
Button(action: /*#START_MENU_TOKEN#*/{}/*#END_MENU_TOKEN#*/) {
Text("Start advertising")
.font(.headline)
.foregroundColor(Color.black)
}.padding(.top)
TextField("Test", text: $name)
.padding(.all)
.background(Color.white.cornerRadius(20))
.padding()
}.background(RoundedRectangle(cornerRadius: 30)
.fill(Color(hue: 0, saturation: 0, brightness: 0, opacity: 0.1))
).offset(y:-10)
}
// }