How to put LazyVGrid next to Image swiftUI on MacOS (11.4) - swift

(MacOS app)
I am trying to place a lazyvgrid next to an image. to have the image in a specific size and let the LazyVGrid take the rest of the width. I set the frame of the image but than the grid does not take the extra space and there are extra empty space to the left and right of the image and the grid.
import SwiftUI
struct ContentView: View {
var body: some View {
HStack{
LazyVGrid(columns: [GridItem(
.adaptive(minimum: 40)
)]){
Text("Placeholder")
Text("Placeholder")
}
.padding()
.background(Color.blue)
Image("bla")
.resizable()
//.scaledToFit()
.frame(width: 100, height: 100)
.background(Color.pink)
}
}
}

try something like this:
struct ContentView: View {
var body: some View {
HStack {
LazyVGrid(columns: [GridItem(.adaptive(minimum: 40))]){
Text("Placeholder")
Text("Placeholder")
}
.padding()
// put this here if you want the width and the height to expand
// .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
.background(Color.blue)
// put this here if you want just the width to expand
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
Image(systemName: "globe")
.resizable()
//.scaledToFit()
.frame(width: 100, height: 100)
.background(Color.pink)
}.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
}
}

Related

SWIFTUI: .overlay breaks alignment

I have this bit of code below where I'm trying to have a rectangle centered in the screen, where I overlay a text outupt from some function and a share button. The concept works, except that when I add the .overlay, the "text box" (the rectangle with the text and share button overlayed to it) lose the centered alignment and they move to the left.If I remove the .overlay, the rectangle is centered but the content remains behind it. What am I doing wrong? Thanks.
GeometryReader { geometry in // Debug alignment
VStack(alignment: .center) { //TextBox
Rectangle()
.fill(Color.cyan)
.cornerRadius(20)
.frame(width: geometry.size.width * 0.75, height: 200, alignment: .center)
.overlay(
ScrollView {
HStack(alignment: .top){
VStack(alignment: .center) {
Text(responseText)
.foregroundColor(.black)
.frame(minWidth: 0, maxWidth: .infinity, alignment: .center)
.layoutPriority(2)
}
ShareLink(item: responseText){
Image(systemName: "square.and.arrow.up")
.resizable()
.scaledToFit()
.frame(width: 25, height: 25)
}
}
}
)
} //Vstack Top
} //Geo Reader
I tried to center the recantgle while using the .overlay to put the conetent on top of it but the centered aligment gets lost. I also tried to use a ZStack instead of a .overlay but the content remains hidden behind.
GeometryReader positions its children at its top left. The VStack child of GeometryReader hugs its children—in this case, its single child, which is a Rectangle with a fixed frame.
Put the Rectangle in a container that expands to the size of the enclosing GeometryReader and centers the Rectangle within the expanded size.
For example, add a frame(maxWidth: .infinity, maxHeight: .infinity) modifier on the VStack:
GeometryReader { geometry in // Debug alignment
VStack {
Rectangle()
.fill(Color.cyan)
etc. etc.
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
Result:
But if you don't have anything else to put in the VStack, you can remove it and put the frame modifier directly on the Rectangle, after the overlay:
GeometryReader { geometry in // Debug alignment
Rectangle()
.fill(Color.cyan)
.cornerRadius(20)
.frame(width: geometry.size.width * 0.75, height: 200)
.overlay(
ScrollView {
HStack(alignment: .top){
Text(responseText)
.foregroundColor(.black)
ShareLink(item: responseText) {
Image(systemName: "square.and.arrow.up")
.resizable()
.scaledToFit()
.frame(width: 25, height: 25)
}
}
}
)
.frame(maxWidth: .infinity, maxHeight: .infinity)
}

SwiftUI - How to position Images with NavigationLink

I'm trying to make a converter app using SwiftUI. I added navigationlinks on the Home Screen these buttons go to the right places,no problem until here. However, I couldn't position it.
Currently, when I position them with .position, they appear in different places on different devices.
How should I do the positioning here?
I want to provide an image that will be the same on all devices as in the screenshot.
Thanks for your help.
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView{
VStack() {
// WEIGHT * MASS
NavigationLink(destination: UnitView()) {
Image(systemName: "scalemass")
.font(.system(size: 60))
.padding()
.frame(width: 150, height: 150, alignment: .center)
.background(Rectangle().fill(Color.purple.opacity(0.5))
.shadow(radius: 3)).cornerRadius(20)
.foregroundColor(.black)
.overlay(Text("Mass")
.foregroundColor(.black)
.padding()
.font(.system(size: 22)),
alignment: .bottom )}
.position(x:110, y:100)
//DISTANCE *
NavigationLink(destination: DistanceView()) {
Image(systemName: "figure.walk")
.font(.system(size: 60))
.padding()
.frame(width: 150, height: 150, alignment: .center)
.background(Rectangle().fill(Color.orange.opacity(0.5))
.shadow(radius: 3)).cornerRadius(20)
.foregroundColor(.black)
.overlay(Text("Distance")
.foregroundColor(.black)
.padding()
.font(.system(size: 22)),
alignment: .bottom )}
.position(x:110, y:100)
//TEMPERATURE *
NavigationLink(destination: TemperatureView()) {
Image(systemName: "thermometer.sun")
.font(.system(size: 56))
.padding()
.frame(width: 150, height: 150, alignment: .center)
.background(Rectangle().fill(Color.yellow.opacity(0.5))
.shadow(radius: 3)).cornerRadius(20)
.foregroundColor(.black)
.overlay(Text("Temperature")
.foregroundColor(.black)
.padding()
.font(.system(size: 21)),
alignment: .bottom )}
.position(x:280, y:-84)
// TIME *
NavigationLink(destination: TimeView()) {
Image(systemName: "clock")
.font(.system(size: 60))
.padding()
.frame(width: 150, height: 150, alignment: .center)
.background(Rectangle().fill(Color.blue.opacity(0.5))
.shadow(radius: 3)).cornerRadius(20)
.foregroundColor(.black)
.overlay(Text("Time")
.foregroundColor(.black)
.padding()
.font(.system(size: 21)),
alignment: .bottom ) }
.position(x:280, y:-444)
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Sample
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
VStack {
Image("example-image")
.resizable()
.frame(width: 100, height: 100)
.cornerRadius(10)
NavigationLink(destination: DetailView()) {
Text("View Details")
.foregroundColor(.white)
.padding()
.background(Color.blue)
.cornerRadius(10)
}
.padding(.top, 20)
}
}
}
}
struct DetailView: View {
var body: some View {
Text("Details View")
}
}
In this example, we use a VStack to position an image and a NavigationLink. The image is resized to 100x100 and given a corner radius of 10 using the frame and cornerRadius modifiers. The NavigationLink leads to a DetailView that simply displays the text "Details View". The text inside the NavigationLink is styled to have white foreground color, padding, a blue background color, and a corner radius of 10. The .padding(.top, 20) adds some space between the image and the link.

SwiftUI: Prevent word break for long words

How do I prevent word breaking for long words, e.g adjust font size to fit width?
Requirements:
The outer gray frame must have the same fixed size.
The should be 2 lines.
var body: some View {
VStack {
Spacer()
Image(systemName: "square")
.resizable()
.frame(width: 50, height: 50)
Spacer()
Text("Acknowledgement for the rest")
.allowsTightening(true)
.minimumScaleFactor(0.01)
.lineLimit(2)
.multilineTextAlignment(.center)
}
.padding()
.frame(width: 140, height: 150, alignment: .center)
.background(
ZStack {
RoundedRectangle(cornerRadius: 10)
.foregroundColor(Color(hex: "f9f9f9"))
}
)
}
use fixedSize modifier:
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
Spacer()
Image(systemName: "square")
.resizable()
.frame(width: 50, height: 50)
Spacer()
Text("Acknowledgement for the rest")
.fixedSize() // <<: Here
.allowsTightening(true)
.minimumScaleFactor(0.01)
.lineLimit(nil)
.multilineTextAlignment(.center)
}
.padding()
.frame(height: 150)
.background(
ZStack {
RoundedRectangle(cornerRadius: 10)
.foregroundColor(Color.blue)
}
)
}
}
as you mention in the comment
The text coming in is dynamic. Is might be very long or very short. I
want to adjust the font size to fit.
it will adjust the font size to fit the width.
struct ContentView: View {
#State var acknowledgementString = "acknowledgement for the rest"
let mainWidth : CGFloat = 350//140
var body: some View {
Text(acknowledgementString)
.font(.system(size: 100))
.minimumScaleFactor(0.01)
.lineLimit(1)
.frame(width: mainWidth,height: mainWidth,alignment: .center )
.background(Color.red)
.onTapGesture {
acknowledgementString += " extra"
}
}
}

How to put an Image on top of a Color View in SwiftUI

I have an image that needs to be put in the top center of my view. How can I do so?
struct MyTextField: View
{
#ObservedObject var model: TextFieldModel
var body: some View
{
VStack(alignment: .leading, spacing: -60)
{
Color.black.position(CGPoint(x: 200, y: -50)).frame(width: 417, height: 120,
alignment: .top)
.background(Image(("appIconLogo")).resizable().frame(width: 50, height: 50))
//Spacer(minLength: 5)
VStack(alignment: .leading, spacing: 30)
{
Text("Welcome!")
.font(.system(size: 60, design: .rounded))
.foregroundColor(.black)
iTextField("Search Your Ticker", text: $model.text, isEditing: $model.isEditing)
.foregroundColor(.black)
.showsClearButton(true)
.onReturn
{
print($model.text)
NotificationCenter.default.post(name: Notification.Name(rawValue:
"isValidTicker"), object: nil)
}
.foregroundColor(.black)
.style(height: 58, font: nil, paddingLeading: 25, cornerRadius: 6,
hasShadow: true, image: Image(systemName: "magnifyingglass"))
.foregroundColor(.black)
}
}
.position(CGPoint(x: 200.0, y: 150.0))
.padding()
}
}
But my View looks like this. How can I move my image to the top center of the page where the black color is?
Here is a demo of possible layout. Prepared with Xcode 12.1 / iOS 14.1.
struct MyTextField: View
{
var body: some View
{
VStack {
Color.black
.frame(height: 120)
.overlay(Image(("plant")).resizable().frame(width: 50, height: 50))
.edgesIgnoringSafeArea(.top)
VStack(alignment: .leading, spacing: 30)
{
Text("Welcome!")
.font(.system(size: 60, design: .rounded))
.foregroundColor(.black)
.padding(.leading)
// .. other code
}.frame(maxWidth: .infinity, alignment: .leading)
}.frame(maxHeight: .infinity, alignment: .top)
}
}
It's a little confusing what you are trying to do in your code, but I think this might get you started. I made a background layer that extends to the edge of the screen, and then put a Content layer on top of it, where you can put the Image at the top of the VStack.
You should try to avoid setting exact width/height/CGPoints whenever possible in SwiftUI.
var body: some View {
ZStack {
// Background
Color.white
.edgesIgnoringSafeArea(.all)
// Content
VStack(spacing: 20) {
Image(systemName: "heart.fill") // Image here
Text("Welcome!") // Title
.font(.system(size: 60, design: .rounded))
.frame(maxWidth: .infinity, alignment: .leading)
.foregroundColor(.black)
TextField("Search your ticker", text: $textFieldText) // Textfield
.frame(height: 50)
.background(Color.gray)
.cornerRadius(10)
Spacer()
}
.padding()
}
}

SwiftUI multiple TextField causing lags

I am using many TextFields in my SwiftUI Mac OS app. I am a main form, where the user adds data, which is composed of multiple Stacks/ views which contain TextFields/ and Text()
I noticed a strange bug, when I am using many TextFields combined in different views, I get some very heavy lags when selecting the TextField. Also when I skip to the next one with Tab it takes time.
It is really strange behavior and I am not sure what is causing that. I have a different view with many TextFields aswell, where everything is working smooth.
Also sometimes I can not jump back to the prior TextField with Shift+Tab.
Edit: I could figure out how to get rid of it. However, only if I remove one view. I don't want to.
My main container looks like that:
HStack
{
//Left Side
VStack{
Text("Here is the next #1")
}
VStack
{
//The View posted below
ViewBelow()
}
}
If I remove the first VStack, the issue is solved. Nothing lagging. If I add it, it is there again.
Just to give you a neckline of my code (many Stacks with TextFields)
ZStack
{
VStack
{
HStack
{
Text("Personal Data")
.font(.title)
.fontWeight(.bold)
.padding(.horizontal, 0)
.padding(.vertical, 5)
Spacer()
}
Divider()
.padding(.bottom, 5)
//Personal Data Types
HStack(spacing: 0)
{
//Left Element
VStack(alignment: .center)
{
Text("Vorname")
.foregroundColor(Color.gray)
} .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
//Right Elemenet
VStack()
{
Text("Nachname")
.foregroundColor(Color.gray)
}
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
}.frame(minWidth: 0, maxWidth: .infinity)
HStack(spacing: 0)
{
VStack(alignment: .center)
{
//Left Element
if (self.editMode)
{
TextField("Enter some text", text: $s_test)
.frame(maxWidth:250)
}
else
{
Text(self.person.firstName)
.font(.body)
}
} .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
VStack()
{
//Left Element
if (self.editMode)
{
TextField("Enter some text", text: self.$s_test)
.frame(maxWidth:250)
}
else
{
Text(self.person.lastName)
.font(.body)
}
}
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
}.frame(minWidth: 0, maxWidth: .infinity)
.padding(.top, 0)
//Personal Data Types
HStack(spacing: 0)
{
//Left Element
VStack(alignment: .center)
{
Text("Nickname")
.foregroundColor(Color.gray)
} .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
//Right Elemenet
VStack()
{
Text("Birthday")
.foregroundColor(Color.gray)
}
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
}.frame(minWidth: 0, maxWidth: .infinity)
.padding(.top, 10)
HStack(spacing: 0)
{
VStack(alignment: .center)
{
//Left Element
if (self.editMode)
{
TextField("Enter some text", text: self.$s_test)
.frame(maxWidth:250)
}
else
{
Text(self.person.nickname)
.font(.body)
}
} .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
VStack()
{
//Right Element
if (self.editMode)
{
TextField("Enter some text", text: self.$s_test)
.frame(maxWidth:250)
}
else
{
Text(self.person.birthdate)
.font(.body)
}
}
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
}.frame(minWidth: 0, maxWidth: .infinity)
.padding(.top, 0)
}
Maybe someone experienced the same already.. I am not quiet sure how to solve it. I removed many views, then it is working better. However I am not sure if it is just the quantity of TextFields or some bug in the other view.
I demonstrate the lag in the Gif. I press instantly when I hover above the TextField. See that lag..