taler-ios

iOS apps for GNU Taler (wallet)
Log | Files | Refs | README | LICENSE

OptimalSize.swift (2853B)


      1 //  MIT License
      2 //  by Benzy Neez
      3 //  https://stackoverflow.com/questions/77631146/how-to-make-scrollview-shrink-to-fit-and-take-minimum-space-without-hacks
      4 //
      5 //  Permission is hereby granted, free of charge, to any person obtaining a copy of this software
      6 //  and associated documentation files (the "Software"), to deal in the Software without restriction,
      7 //  including without limitation the rights to use, copy, modify, merge, publish, distribute,
      8 //  sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
      9 //  furnished to do so, subject to the following conditions:
     10 //
     11 //  The above copyright notice and this permission notice shall be included in all copies or
     12 //  substantial portions of the Software.
     13 //
     14 //  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
     15 //  BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     16 //  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
     17 //  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     18 //  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     19 //
     20 /**
     21  * @author Marc Stibane
     22  */
     23 import SwiftUI
     24 
     25 @available(iOS 16.0, *)
     26 struct OptimalSize: Layout {
     27     let axes: Axis.Set
     28 
     29     /// Computes the optimal size for a ScrollView (which would grab all it could get otherwise)
     30     /// - Parameters:
     31     ///   - axes: Axes this content must fit in.
     32     init(_ axes: Axis.Set = [.horizontal, .vertical]) {
     33         self.axes = axes
     34     }
     35 
     36     public func sizeThatFits(
     37         proposal: ProposedViewSize,
     38         subviews: Subviews,
     39         cache: inout ()
     40     ) -> CGSize {
     41         let result: CGSize
     42         let horz = axes.contains(.horizontal)
     43         let vert = axes.contains(.vertical)
     44 
     45         if let firstSubview = subviews.first {
     46             let containerWidth = proposal.width ?? .infinity
     47             let containerHeight = proposal.height ?? .infinity
     48             let size = firstSubview.sizeThatFits(.init(width: vert ? containerWidth : nil,
     49                                                        height: horz ? containerHeight : nil))
     50             result = CGSize(width: min(size.width, containerWidth),
     51                             height: min(size.height, containerHeight))
     52         } else {
     53             result = .zero
     54         }
     55         return result
     56     }
     57 
     58     public func placeSubviews(
     59         in bounds: CGRect,
     60         proposal: ProposedViewSize,
     61         subviews: Subviews,
     62         cache: inout ()
     63     ) {
     64         if let firstSubview = subviews.first {
     65             firstSubview.place(
     66                 at: CGPoint(x: bounds.minX, y: bounds.minY),
     67                 proposal: .init(width: bounds.width, height: bounds.height)
     68             )
     69         }
     70     }
     71 }