0

I have some views with many details with fixed sizes, and am trying to use scaleEffect() to reduce them proportionally to fit better smaller devices. However, when using scaleEffect() on a ScrollView, I noticed that it has a larger effect than expected on the axis of the ScrollView. Small example below:

import SwiftUI

struct FancyItemView: View {
    
    var body: some View {
        Rectangle()
            .fill(.red)
            .frame(width: 100, height: 100)
    }
}

struct ItemDisplayView: View {
    var sizeAdjustment: Double
    
    var body: some View {
        ScrollView(.horizontal){
            FancyItemView()
        }
        .background(.blue)
        .scaleEffect(sizeAdjustment)
        .frame(width: 150 * sizeAdjustment, height: 100 * sizeAdjustment)
        .border(.black)
    }
}

struct ContentView: View {
    
    var body: some View {
        VStack{
            ItemDisplayView(sizeAdjustment: 1)
            ItemDisplayView(sizeAdjustment: 0.8)
            ItemDisplayView(sizeAdjustment: 1.2)
        }
        .background(.gray)
        
    }
}


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Screenshot of the resulting view: https://i.stack.imgur.com/POvjw.png

In this example I am using only one item view, but in my real code the ScrollView contains titles and grids of items. I may be able to work around this issue by applying scaleEffect to the other views around ScrollView and not applying to it, but that would make the code much more confusing. So I am wondering if there is anything I am missing to make scaleEffect work properly with ScrollView.

Thanks

jo'taH
  • 1

1 Answers1

1

I don´t think .scaleEffect is the propper tool here. It is more for visual presentation/animation than for laying out views. Get rid of the .scaleEffect modifier and pass your scale var through to your Controll and style it appropriatly.

struct FancyItemView: View {
    var sizeAdjustment: Double
    var body: some View {
        Rectangle()
            .fill(.red)
            .frame(width: 100 * sizeAdjustment, height: 100 * sizeAdjustment)
    }
}

struct ItemDisplayView: View {
    var sizeAdjustment: Double
    
    var body: some View {
        ScrollView(.horizontal){
            FancyItemView(sizeAdjustment: sizeAdjustment) // pass the multiplier to the ChildView
        }
        .background(.blue)
 //       .scaleEffect(sizeAdjustment) // remove this
 //       .frame(width: 150 * sizeAdjustment, height: 100 * sizeAdjustment) // you probably don´t want this either
 // or at least get rid of the multiplier
        .border(.black)
    }
}
burnsi
  • 6,194
  • 13
  • 17
  • 27
  • Thanks for helping. The approach you suggest works and appear easy in this example, but I was trying to avoid it because in the actual app I have many subviews with hard coded sizes inside the ScrollView, so I end up having to make adjustments in many places and worry that this leads to more messy (error-prone) code. – jo'taH May 17 '22 at 06:38
  • @jo'taH Hardcoding sizes seems pretty wrong for SwiftUI anyway. Try to rethink your aproach. – burnsi May 17 '22 at 07:40