I'm trying to achieve a SwiftUI text alignment as illustrated by this image. The goal is to align the top of text ".0" with the top edge of "7" (purple line) and the bottom edge of "kts" with the bottom edge of "7" (red line).
Here is my current SwiftUI code:
HStack(alignment: .lastTextBaseline, spacing: 3) {
Text("7")
.font(.system(size: 70))
.foregroundColor(Color.green)
.multilineTextAlignment(.center)
.minimumScaleFactor(0.3)
VStack(alignment: .leading, spacing: 5) {
Text(".7")
.font(.system(size: 24))
.foregroundColor(Color.green)
Text("kts")
.font(.system(size: 18))
.foregroundColor(Color.white)
}
}
This code works for the alignment shown by the red line.
What approach would you recommend to also align the top of "7" and ".0" as shown by the purple line?
You can use Stacks to stack font. There is no issue for the bottom line, but You can get help from the UIFont that gives you the information you need like:
struct ContentView: View {
let bigFont = UIFont.systemFont(ofSize: 70)
let smallFont = UIFont.systemFont(ofSize: 24)
var body: some View {
ZStack(alignment: Alignment(horizontal: .leading, vertical: .center)) {
HStack(alignment: .firstTextBaseline, spacing: 0) {
Text("7").font(Font(bigFont))
Text("kts").font(Font(smallFont))
}
HStack(alignment: .firstTextBaseline, spacing: 0) {
Text("7")
.font(Font(bigFont))
.opacity(0)
Text(".0")
.font(Font(smallFont))
.baselineOffset((bigFont.capHeight - smallFont.capHeight))
}
}
}
}
More information:
Here is an image about the description of the Font for more information:
Related
I am trying to use a custom made header for a view and the child views of the ScrollView seem to ignore the shadow and go over top of it. Is there a simple fix or should I set up the all the Views in a different way?
I have tried rearranging the order of the views and using ZStack instead of VStack, but then I have to deal with spacing issues revolving around the top of the ScrollView being covered by the header. I have also tried rearranging the order of modifiers, but I am clearly missing something.
import SwiftUI
struct Test: View {
var body: some View {
NavigationView {
GeometryReader { proxy in
let safeAreaTop = proxy.safeAreaInsets.top
let deviceWidth = proxy.size.width
VStack(spacing: 0) {
HeaderView()
.padding(.top, safeAreaTop)
.background(Color.white)
.shadow(color: .black.opacity(0.1), radius: 5, x: 0, y: 5)
ScrollView(.vertical, showsIndicators: false) {
VStack(spacing: 0) {
Text("Title")
ForEach(0..<12, id: \.self) { index in
RoundedRectangle(cornerRadius: 20, style: .continuous)
.fill(Color.white)
.frame(width: deviceWidth / 1.5, height: 200)
.shadow(color: .black.opacity(0.3), radius: 5, x: 0, y: 5)
}
}
Spacer(minLength: 0)
}
}
}
}
}
#ViewBuilder
func HeaderView() -> some View {
VStack {
HStack {
ForEach(0..<5, id: \.self) { index in
Spacer()
Text("Tab\(index)")
Spacer()
}
}
.padding(.horizontal)
}
}
}
You need to add a little spacing between your HeaderView and ScrollView to show the bottom shadow of HeaderView.
You can achieve this by either setting spacing for your VStack or by adding top padding to your ScrollView.
Spacing with VStack:
VStack(spacing: 5) {
HeaderView()
.padding(.top, safeAreaTop)
.background(Color.white)
.shadow(color: .black.opacity(0.1), radius: 5, x: 0, y: 5)
ScrollView(.vertical, showsIndicators: false) {
//Content of ScrollView
}
}
Top padding to ScrollView:
VStack(spacing: 0) {
HeaderView()
.padding(.top, safeAreaTop)
.background(Color.white)
.shadow(color: .black.opacity(0.1), radius: 5, x: 0, y: 5)
ScrollView(.vertical, showsIndicators: false) {
//Content of ScrollView
}
.padding(.top, 5)
}
I want to align the two buttons on the bottom of my Text. How can I align an H-stack
container on bottom of a view ??
ZStack{
VStack{
Color.white.ignoresSafeArea()
Text("TAP TO SEE MORE")
.foregroundColor(Color.black)
.font(.system(size: 30))
.bold()
HStack(alignment: .center, spacing: 50, content: {
Button("Admin"){
}
Button("Employee"){
}
})
}
}
I want to have this content in the middle of screen
ZStack{
Color.white.ignoresSafeArea()
VStack{
Text("TAP TO SEE MORE")
.foregroundColor(Color.black)
.font(.system(size: 30))
.bold()
HStack(alignment: .center, spacing: 50, content: {
Button("Admin"){
}
Button("Employee"){
}
})
}
}
This should fix it.
The problem was that you had Color.white.ingoresSafeArea() inside the VStack, which was placing it above the text and buttons instead of behind, which caused the text etc. to be pushed to the bottom.
You have to move Color inside the ZStack instead of VStack:
ZStack {
Color.gray.ignoresSafeArea() // <-- here
VStack{
Text("TAP TO SEE MORE")
.foregroundColor(Color.black)
.font(.system(size: 30))
.bold()
HStack(alignment: .center, spacing: 50) {
Button("Admin") { }
Button("Employee") { }
}
}
}
I have a list in swiftUI and I want the background to be somewhat see through. However there seems to be a white background applied to both scrollview and List. I was wondering if anyone had a work around or way to change it so when .background(Color.white.opacity(0.7)) is applied to the list, it can be translucent and not have the same affect as .background(Color.white).
Here is my code for the view that I am trying to implement the desired effect. The wordPosts is simply just a custom data struct used to populate the list item data. I've already trying changing the cell and tableview appearance using UIkit on init which did not work.
struct ProfileWordsView: View {
init(){
UITableView.appearance().backgroundColor = .clear
UITableViewCell.appearance().backgroundColor = .clear
}
var body: some View {
List {
ForEach(wordPosts) { post in
Group {
VStack(alignment: .leading) {
HStack(alignment: .top) {
RoundedRectangle(cornerRadius: 5)
.fill()
.frame(width: 4)
VStack(alignment: .leading, spacing: 0) {
HStack(spacing: 5) {
Text(post.title).font(.custom("Gilroy-SemiBold", size: 20)).foregroundColor(.black).lineLimit(1)
Text("• \(post.timestamp)").font(.custom("Gilroy-SemiBold", size: 19)).foregroundColor(.gray)
}
HStack {
Text(post.text).font(.custom("Gilroy-Regular", size: 16)).foregroundColor(Color.black.opacity(0.7)).padding(.top, 5)
}
}
Spacer()
VStack {
Button(action: {}) {
Image(systemName: "chevron.up")
.resizable()
.frame(width: 20, height: 15)
.font(Font.title3)
.foregroundColor(.gray)
.padding(.bottom, 6)
}
Text("\(post.rizz)").font(.custom("Gilroy-SemiBold", size: 18)).foregroundColor(.gray)
Button(action: {}) {
Image(systemName: "chevron.down")
.resizable()
.frame(width: 20, height: 15)
.font(Font.title3)
.foregroundColor(.gray)
}
}
}
}.listRowInsets(EdgeInsets(top: 10, leading: 5, bottom: 10, trailing: 10))
}.listRowBackground(Color.clear)
}
.listRowSeparator(.hidden)
}.edgesIgnoringSafeArea(.all).listStyle(.plain)
}
}
I'm not sure if it is possible for your code but I'd recommend using a scrollview instead. They are transparent by default, so that should help. You can always add a frame with a semi-transparent color if you want to have a semi-transparent background instead.
The following code produces a simple VStack with Text views that show no spacing in-between them (rows 1 & 2).
However, adding an image to the 3rd row (green) adds unwanted spacing above and below the entire row.
struct ContentView: View {
var body: some View {
VStack {
HStack {
Text("one thing")
}.background(Color(.yellow))
HStack {
Text("nothing")
}.background(Color(.red))
HStack {
Text("three")
Image(systemName: "star")
.resizable()
.frame(width: 8, height: 8)
}.background(Color(.green))
HStack {
Text("three things")
}.background(Color(.red))
}
}
}
How can I avoid the additional unwanted space?
The space shows independent of image size (even with an image just a few pixels in dimension).
And, of course, I'd like to know why the space is generated.
Thanks for any help
Screenshot of above code:
You may adjust the spacing of VStack:
var body: some View {
VStack (spacing: 0) {
HStack {
Text("one thing")
}.background(Color(.yellow))
HStack {
Text("nothing")
}.background(Color(.red))
HStack {
Text("three")
Image(systemName: "star")
.resizable()
.frame(width: 8, height: 8)
}.background(Color(.green))
HStack {
Text("three things")
}.background(Color(.red))
}
}
Sorry if this is a simple question but I'm just starting out with SwiftUI and I'm trying to figure out how to make a 2x2 grid of views based on the width of the screen. Meaning that each square has a width and height of have the screen width and they are arranged in a 2x2 grid with no padding.
I've been trying with two HStacks with two views in each placed on top of each other but the view size inside the HStack seems to dictate the HStack's height.
Code for Views I'm trying to arrange into the 2x2 grid:
var body: some View {
VStack {
TextField("0", text: $value)
.multilineTextAlignment(.center)
.textFieldStyle(PlainTextFieldStyle())
.font(.system(size: 40, weight: .semibold, design: .rounded))
.border(Color.black)
.padding()
Text(title)
.padding([.leading, .bottom, .trailing])
.font(.system(size: 14, weight: .regular, design: .rounded))
}
.background(Color.green)
.cornerRadius(10)
.overlay(RoundedRectangle(cornerRadius: 10).stroke(Color.black, lineWidth: 5))
}
I find that using A combination of HStacks, VStacks and aspectRatio(_ aspectRatio: CGFloat? = nil, contentMode: ContentMode) works best for forcing certain proportions on views:
struct ContentView: View {
var body: some View {
VStack(spacing: 0) {
HStack(spacing: 0) {
Rectangle().fill(Color.red)
.aspectRatio(1.0, contentMode: .fit)
Rectangle().fill(Color.green)
.aspectRatio(1.0, contentMode: .fill)
}
HStack(spacing: 0) {
Rectangle().fill(Color.blue)
.aspectRatio(1.0, contentMode: .fit)
Rectangle().fill(Color.yellow)
.aspectRatio(1.0, contentMode: .fill)
}
}.aspectRatio(contentMode: .fit)
}
}
Results in a layout like this:
This can be done using a GeometryReader:
struct ContentView: View
{
var body: some View
{
GeometryReader
{ geometry in
self.useProxy(geometry)
}
}
func useProxy(_ geometry: GeometryProxy) -> some View
{
let dimension = min(geometry.size.width, geometry.size.height)
return VStack
{
HStack(spacing: 0)
{
Text("Top Left")
.frame(width: dimension / 2, height: dimension / 2)
.border(Color.black)
Text("Top Right")
.frame(width: dimension / 2, height: dimension / 2)
.border(Color.black)
}
HStack(spacing: 0)
{
Text("Bottom Left")
.frame(width: dimension / 2, height: dimension / 2)
.border(Color.black)
Text("Bottom Right")
.frame(width: dimension / 2, height: dimension / 2)
.border(Color.black)
}
}
}
}
Watch (the first part of) this WWDC video to hear about the layout system of SwiftUI.