SwiftUI TabView: Add Top Padding To TabItems

60 views Asked by At

I would like to add some space on top of the TabView() elements, since I feel like the top of the Label images is too close to the edge of the TabView().

I'm posting here because I've already tried to add .padding(.top, value) // where value is an int like 20. The thing is, this acts weirdly and adds padding to the top of the screen (see comment in code block below).

This is the entire ContentView.swift file:

import SwiftUI
import WidgetKit
import UserNotifications
import UIKit

struct ContentView: View {
    @StateObject var sharedVars = SharedVarsBetweenTabs()
    
    var body: some View {
        TabView {
            HomeView()
                .tabItem {
                    Label("Home", systemImage: "house.fill")
                }
            AppearanceView()
                .tabItem {
                    Label("Appearance", systemImage: "paintbrush.fill")
                }
            QuotesView()
                .tabItem {
                    Label("Quotes", systemImage: "quote.bubble.fill")
                }
        }
        // This is where I tried putting .padding(.top, 20)
        .environmentObject(sharedVars)
        .accentColor(.blue)
        .onAppear {
            UITabBar.appearance().backgroundColor = UIColor.black
            UITabBar.appearance().unselectedItemTintColor = UIColor.white
        }
    }
}

class SharedVarsBetweenTabs: ObservableObject {
    @Published var colorPaletteIndex = 0
}

Inside of the views, they all have a VStack with these same attributes:

.frame(maxWidth: .infinity)
        .padding()
        .background(ColorPaletteView(colors: [colorPalettes[safe: sharedVars.colorPaletteIndex]?[0] ?? Color.clear])) // This corresponds to the blue int he screenshot

This is currently what it looks like:

iPhone simulator screenshot

1

There are 1 answers

3
J W On

A few days ago, I met someone who wanted to edit the text, and the idea came into use.

\(^o^)/

Solution: reduce the size + leave the top blank

Others: Text Process: https://stackoverflow.com/a/78169838/23574168

Show Image

Function:

func resizeImage(_ image: UIImage, targetSize: CGSize) -> UIImage? {
  let size = image.size
  
  // Calculate the scaling factor to fit the image to the target dimensions while maintaining the aspect ratio
  let widthRatio = targetSize.width / size.width
  let heightRatio = targetSize.height / size.height
  let ratio = min(widthRatio, heightRatio)
  
  let newSize = CGSize(width: size.width * ratio, height: size.height * ratio)
  let yOffset = (targetSize.height - newSize.height) // Leave the top blank and align the bottom
  
  //Create a new image context
  let renderer = UIGraphicsImageRenderer(size: targetSize)
  let newImage = renderer.image { context in
    // Fill the background with a transparent color
    context.cgContext.setFillColor(UIColor.clear.cgColor)
    context.cgContext.fill(CGRect(origin: .zero, size: targetSize))
    
    // draw new image
    image.draw(in: CGRect(x: 0, y: yOffset, width: newSize.width, height: newSize.height))
  }
  
  return newImage
}

Complete:


import SwiftUI
import UIKit

struct ContentView: View {
  
  var body: some View {
    TabView {
      Text("1")
        .tabItem {
          VStack {
            Spacer(minLength: 20)
            Image(uiImage: resizeImage(UIImage(systemName: "house.fill")!, targetSize: CGSize(width: 20, height: 27))!)
            Text("Home")
          }
        }
      Text("2")
        .tabItem {
          Spacer(minLength: 20)
          Image(uiImage: resizeImage(UIImage(systemName: "paintbrush.fill")!, targetSize: CGSize(width: 20, height: 27))!)
          Text("Appearance")
        }
      Text("3")
        .tabItem {
          Spacer(minLength: 20)
          Image(uiImage: resizeImage(UIImage(systemName: "quote.bubble.fill")!, targetSize: CGSize(width: 20, height: 27))!)
          Text("Quotes")
        }
    }
    .accentColor(.blue)
    .onAppear {
      UITabBar.appearance().backgroundColor = UIColor.black
      UITabBar.appearance().unselectedItemTintColor = UIColor.white
    }
  }

  func resizeImage(_ image: UIImage, targetSize: CGSize) -> UIImage? {
    let size = image.size
    
    // Calculate the scaling factor to fit the image to the target dimensions while maintaining the aspect ratio
    let widthRatio = targetSize.width / size.width
    let heightRatio = targetSize.height / size.height
    let ratio = min(widthRatio, heightRatio)
    
    let newSize = CGSize(width: size.width * ratio, height: size.height * ratio)
    let yOffset = (targetSize.height - newSize.height) // Leave the top blank and align the bottom
    
    //Create a new image context
    let renderer = UIGraphicsImageRenderer(size: targetSize)
    let newImage = renderer.image { context in
      // Fill the background with a transparent color
      context.cgContext.setFillColor(UIColor.clear.cgColor)
      context.cgContext.fill(CGRect(origin: .zero, size: targetSize))
      
      // draw new image
      image.draw(in: CGRect(x: 0, y: yOffset, width: newSize.width, height: newSize.height))
    }
    
    return newImage
  }
}

#Preview {
  ContentView()
}