iosswiftswiftuiswiftui-tabview

SwiftUI TabView: Add Top Padding To TabItems


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


Solution

  • 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()
    }