How to avoid Image size shrink when aligning - swift

New to this framework i know i'm not good at aligning part of UI yet.
My aligning problem is my image get shrink the more padding it has so if possible can you go easy and point out my mistake here? i am practicing align my item to top left corner.
struct MasterLabMerge: View {
var body: some View {
ZStack {
Color.gray.ignoresSafeArea()
Image(systemName: "note")
.frame(width: 300, height: 300)
.padding(.leading, -300)
.padding(.top, -500)
}
}
}

You need to add .resizable() to enable an image to grow in size.
Also, you can align your item to the top left in better ways.
Option 1 (I personally think this is the best):
ZStack {
Color.gray.ignoresSafeArea()
VStack {
HStack {
Image(systemName: "note")
.resizable()
.frame(width: 100, height: 100)
.padding(.leading)
Spacer()
}
Spacer()
}
}
Option 2:
ZStack {
Color.gray.ignoresSafeArea()
}
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Image(systemName: "note")
.resizable()
.frame(width: 100, height: 100)
.padding(.top)
}
}

Related

SwiftUI Centering Image between Views

I have an HStack that I am using as a tool bar. The HStack contains a button on the left, image in the middle, and then another HStack containing 2 buttons. Everything looks fine except for the image in the middle, it's slightly to the left. How can I get the image centered?
var toolbar: some View {
HStack(alignment: .center) {
Button {
UIImpactFeedbackGenerator(style: .light).impactOccurred()
presentationMode.wrappedValue.dismiss()
} label: {
Image(systemName: "xmark")
.tint(.black)
}
Spacer()
Image("nav_logo")
.resizable()
.frame(width: 30, height: 30)
Spacer()
optionsButton
}
.frame(height: 30)
}
var optionsButton: some View {
HStack {
Button {
UIPasteboard.general.string = viewModel.take.shareLinkString
self.buildBottomAlert(type: .linkCopied)
} label: {
Image("shareIcon")
}
.padding(.trailing, 10)
Button {
showingAlert = true
} label: {
Image("moreMenu")
}
}
The image in the middle is offset because the first button and optionsButton do not have the same width. But the SpacerĀ“s inside the containing Stack do have equal width.
To solve this you could wrap them in to a container that is big enough so both have the same width.
e.g.:
//GeometryReader to get the size of the container this is in
GeometryReader{proxy in
HStack(alignment: .center) {
//Hstack to wrap the button
HStack(){
Button {
UIImpactFeedbackGenerator(style: .light).impactOccurred()
presentationMode.wrappedValue.dismiss()
} label: {
Image(systemName: "xmark")
.tint(.black)
}
// Spacer to move the button to the left
Spacer()
}
// depending on the use case you would need to tweak this value
.frame(width: proxy.size.width / 4)
Spacer()
Image(systemName: "square.and.arrow.up.trianglebadge.exclamationmark")
.resizable()
.frame(width: 30, height: 30)
Spacer()
HStack(){
Spacer()
optionsButton
}
.frame(width: proxy.size.width / 4)
}
.frame(height: 30)
}

Unexpected layout issues with SwiftUI Image and ZStack

I'm trying to create a view composed of two parts - the top part is an image with a piece of text overlaid in the top left corner. The top part should take up 2/3 of the height of the view. The bottom part is text information and a button, contained in an HStack, and takes up the remaining 1/3 of the view height.
struct MainView: View {
var body: some View {
GeometryReader { gr in
VStack(spacing: 0) {
ImageInfoView()
.frame(height: gr.size.height * 0.66)
BottomInfoView()
}
.clipShape(RoundedRectangle(cornerRadius: 20))
}
}
}
struct ImageInfoView: View {
var body: some View {
ZStack(alignment: .topLeading) {
Image("testImage")
.resizable()
.aspectRatio(contentMode: .fill)
.overlay(Rectangle()
.fill(Color.black.opacity(0.5))
)
HStack {
Text("Top left text")
.foregroundColor(.white)
.padding()
}
}
}
}
struct BottomInfoView: View {
var body: some View {
HStack {
VStack(alignment:.leading) {
Text("Some title")
Text("Some subtitle")
}
Spacer()
Button("BUTTON") {
}
}
.padding()
.background(.gray)
}
}
In the below sample code, if I set the frame height to 400 I will see the top left text, but when I set it to 200, I do not. What is happening here? The text should be anchored to the top left corner of ImageInfoView no matter what. Further, when set to 400, why does the ImageInfoView take up more than 66% of the height?
struct TestView: View {
var body: some View {
MainView()
.frame(height: 200)
.padding([.leading, .trailing], 16)
}
}
An image's fill pushes ZStack boundaries, so Text goes off screen (see this for details).
A possible solution is to put image into overlay of other container so it respects provided space instead of imposing own.
Tested with Xcode 13.4 / iOS 15.5
ZStack(alignment: .topLeading) {
Color.clear.overlay( // << here !!
Image("testImage")
.resizable()
.aspectRatio(contentMode: .fill)
.overlay(Rectangle()
.fill(Color.black.opacity(0.5))
)
)
// ... other code as-is
This fixes the problem:
ZStack(alignment: .topLeading) {
GeometryReader { gr in
Image("testImage")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(maxWidth: gr.size.width, maxHeight: gr.size.height)
.overlay(Rectangle()
.fill(Color.black.opacity(0.5))
)
HStack {
Text("Top left text")
.foregroundColor(.white)
.padding()
}
}
}
}

SwiftUI NavigationLink doesn't work with Spacer

I build the following View:
NavigationView{
VStack(spacing: 120){
HStack{
Spacer()
NavigationLink(destination: LoginView()){
Image(systemName: "person.crop.circle")
.resizable()
.frame(width: 40, height: 40)
.foregroundColor(.primary)
.padding()
}
}
VStack{
Image("pic1")
.resizable()
.frame(width: 200, height: 160)
.padding()
Image(colorScheme == .dark ? "pic2" : "pic3")
.resizable()
.frame(width: 200, height: 65)
.padding()
}
Spacer(minLength: 250)
}
}
I need this Spacer(minLength: 250) to get the image (circle) on the top left corner. But when I do this, the Image does not work as a NavigationLink. When I delete this Spacer everything is centered and the Link works. How can I get it in the position I want and get the link work?
use navigationBarHidden(true):
NavigationView {
VStack(spacing: 120) {
...
Spacer() // no need for minHeight
}
.navigationBarHidden(true) // << here
}
not sure if you have got your issue sorted
but based on your question, if I understand it properly you want to have the Image(systemName: "person.crop.circle") in the top left corner when clicked it should navigate to the new View
if you want the image to be in the top right corner instead you just need to change the placement of the ToolbarItem
i can't post any images yet so I included a gif link
here is the code, i use the ToolbarItem and add NavigationLink in it
let me know if this help
Cheers,
Jono
NavigationView{
VStack(spacing: 120){
VStack{
Image("pic1")
.resizable()
.frame(width: 200, height: 160)
.padding()
Image(colorScheme == .dark ? "pic2" : "pic3")
.resizable()
.frame(width: 200, height: 65)
.padding()
}
Spacer(minLength: 250)
}
.toolbar {
ToolbarItem(placement: .navigationBarLeading){
NavigationLink(destination: LoginView()){
Image(systemName: "person.crop.circle")
.resizable()
.frame(width: 40, height: 40)
.foregroundColor(.primary)
.padding()
}
}
}
}

How to remove the leading and trailing space space in the cell SwiftUI

I am a beginner in SwiftUI and i am stuck on this.
I want to remove the leading and trailing white space in cell as in the picture [Sample output Picture][1]
That is the orange color should touch the left and right margin of the iPhone screen
[1]: https://i.stack.imgur.com/XhiFR.png
Here is my code -
{
var body : some View {
List(0 ..< 15) { item in
VStack() {
HStack{
VStack(alignment: .leading){
Text("sample text is t iu ")
.fontWeight(.medium)
Text("Sample text 2 jksbdkj")
}
Spacer()
Image("pro1")
.resizable()
.scaledToFit()
.frame( height: 50)
}
// bottom view of card
HStack(){
Image("pro2")
.resizable()
.scaledToFit()
.frame(width: 20, height: 20)
Text("0")
Text("+3")
Spacer()
Image(systemName: "pencil")
Image("pro3")
.resizable()
.scaledToFit()
.frame(width: 20, height: 20)
}
}
.background(Color.orange)
.listRowSeparator(.hidden)
}
.listStyle(.plain)
.background(Color.green)
}
}
I appreciate any help . Thanks!
i am a beginner in SwiftUI and learning my self.
How to change the color between the two cell in a list in SwiftUI Sample picture
I want the white colors to be grey.
Here is my code -
struct cardView: View{
var body : some View {
List(0 ..< 15) { item in
VStack() {
HStack{
VStack(alignment: .leading){
Text("sample text is t iu ")
.fontWeight(.medium)
Text("Sample text 2 jksbdkj")
}
Spacer()
Image("pro1")
.resizable()
.scaledToFit()
.frame( height: 50)
}
// bottom view of card
HStack(){
Image("pro2")
.resizable()
.scaledToFit()
.frame(width: 20, height: 20)
Text("0")
Text("+3")
Spacer()
Image(systemName: "pencil")
Image("pro3")
.resizable()
.scaledToFit()
.frame(width: 20, height: 20)
}
} .listRowInsets(EdgeInsets())
.background(Color.orange)
.listRowSeparator(.hidden)
Spacer()
}
.listStyle(.plain)
}
}
struct ContentView: View {
var body: some View {
ZStack{
cardView()
}.background(Color.black)
}
}
I would appreciate any help thanks.

onTapGesture does only partially work on a ZStack

I have build a ZStack containing an image, an overlay and a systemImage. I want to open a sheet when the user taps on this image but it only works when the user clicks on a very specific point on the very bottom of the ZStack. Does anyone know how I can make this work? And also why this doesn't work?
My code:
NavigationView {
VStack {
VStack {
ZStack {
if let image = pfimage {
Image (uiImage: image)
.resizable()
.frame(width: 100, height: 100)
} else {
Image ("testimage")
.resizable()
.frame(width: 100, height: 100)
}
Image(systemName: "photo")
.resizable()
.frame(width: 30, height: 25)
.foregroundColor(Color.white)
}
.clipShape(Circle())
.contentShape(Circle())
.onTapGesture {
print("tap")
changepfsheet = true
}
Text("Displayname")
.padding(.top)
.foregroundColor(Color.white)
.font(.title3)
}
.frame(width: UIScreen.main.bounds.width, height: 225)
.background(Color.red)
HStack {
Image(systemName: "person.2.circle")
TextField("Enter newdisplayname", text: $newdisplayname)
}
.padding()
.background(Color.gray.opacity(0.1))
.cornerRadius(10)
.padding(.horizontal)
.padding(.top, 25)
Text("Change displayname")
Spacer()
HStack {
Spacer()
Text("Change password")
.foregroundColor(Color.white)
Spacer()
Image(systemName: "key")
.foregroundColor(Color.white)
}
.padding()
.background(Color.red)
.cornerRadius(15)
.padding(.horizontal)
.padding(.bottom, 5)
HStack {
Spacer()
Text("Logout")
Spacer()
}
.padding(.horizontal)
.padding(.bottom, 20)
}
.edgesIgnoringSafeArea(.top)
Spacer()
}
.navigationBarHidden(false)
.navigationBarBackButtonHidden(false)
You have interfering tap gestures. Instead, just have one tap gesture on the ZStack. Now you can tap anywhere on it:
ZStack {
Image(uiImage: image)
.resizable()
.frame(width: 100, height: 100)
Color.black.opacity(0.5)
.frame(width: 100, height: 100)
Image(systemName: "photo")
.resizable()
.frame(width: 30, height: 25)
.foregroundColor(.white)
}
.clipShape(Circle())
.contentShape(Circle())
.onTapGesture {
print("tap")
showsheet = true
}
I suspect the real issue is that you using a NavigationView, and putting content behind where the title would be. That means that you can't click through the view that the title is in, even if it's an empty title. You should either remove the NavigationView (as you aren't making use of it) or don't ignore safe area and use a NavigationView as you should do.
Removing edgesIgnoringSafeArea(.top) makes your code work, because the content will no longer be behind the navigation bar.