Swift内在ContentSize使用最大帧来缩放LPLinkPreview

问题描述 投票:0回答:1

您好,我正在创建一个链接预览,为了将自定义框架设置为预览,我必须覆盖内在内容大小并放置我自己的大小。我传递了frame.width和frame.height,它们应该在视图中反映 .frame(maxWidth: 300, maxHeight: 400) 。如果预览最初小于 300*400,我希望它保持当前大小,如果它大于它,则应缩小到 300x400。我面临的问题是将frame.width和frame.height传递给override vartrinsicContentSize导致预览缩放到300x400,这应该只是最大帧,而不是默认帧。因此,诸如此 SO 线程之类的较小预览会拉伸到 300x400 的大小。我如何修改它以在保持最大帧的同时不拉伸预览。

我尝试传递下面的代码,但没有成功。我也尝试过 .scaledToFill、.scalledToFit、.aspectRation(... fit/fill) 但没有一个成功

return CGSize(width: super.intrinsicContentSize.width, height: super.intrinsicContentSize.height)
import SwiftUI

struct SwiftUIView: View {
    @State var text = "https://stackoverflow.com/questions/77101513/resize-swift-ui-real-link-to-fit-frame/77102190?noredirect=1#comment135923413_77102190"
    var body: some View {
        if let url = checkForFirstUrl(text: text){
            LinkPreviewView(url: url)
                .frame(maxWidth: 300, maxHeight: 400)
                .aspectRatio(contentMode: .fit)
        }
    }
}

struct LinkPreviewView: UIViewRepresentable {
    let url: URL
    
    func makeUIView(context: Context) -> UIView {
        let linkView = CustomLinkView()
        return linkView
    }

    func updateUIView(_ uiView: UIView, context: Context) {
        let provider = LPMetadataProvider()
        provider.startFetchingMetadata(for: url) { metaData, error in
            guard let data = metaData, error == nil else { return }
            DispatchQueue.main.async {
                if let linkPreview = uiView as? CustomLinkView {
                    linkPreview.metadata = data
                }
            }
        }
    }
}

class CustomLinkView: LPLinkView {
    
    init() {
        super.init(frame: .zero)
    }
        
    override var intrinsicContentSize: CGSize {
        return CGSize(width: frame.width, height: frame.height)
    }
}

func checkForFirstUrl(text: String) -> URL? {
    let types: NSTextCheckingResult.CheckingType = .link

    do {
        let detector = try NSDataDetector(types: types.rawValue)
        let matches = detector.matches(in: text, options: .reportCompletion, range: NSMakeRange(0, text.count))
        if let firstMatch = matches.first {
            return firstMatch.url
        }
    } catch {
        print("")
    }

    return nil
}
ios swift xcode swiftui preview
1个回答
0
投票

我通过使用 linkView.systemLayoutSizeFitting(UIView.layoutFittingExpandedSize) 动态选择大小找到了解决方案这里是代码:

import SwiftUI

struct SwiftUIView: View {
    @State var text = "https://wp.titan.email/mail/"
    @State var size: CGFloat = .zero
    @State var size2: CGFloat = .zero
    var body: some View {
        VStack {
            if let url = checkForFirstUrl(text: text){
                LinkPreviewView(url: url, width: $size, height: $size2, message: true)
                    .frame(width: size, height: size2, alignment: .leading)
                    .aspectRatio(contentMode: .fill)
                    .cornerRadius(15)
                    .padding(.bottom, 200)
            }
        }
    }
}

import LinkPresentation
import UIKit
import SwiftUI

struct LinkPreviewView: UIViewRepresentable {
    let url: URL
    @Binding var width: CGFloat
    @Binding var height: CGFloat
    
    func makeUIView(context: Context) -> UIView {
        let linkView = CustomLinkView()
        
        let provider = LPMetadataProvider()
        provider.startFetchingMetadata(for: url) { metaData, error in
            guard let data = metaData, error == nil else { return }
            DispatchQueue.main.async {
                linkView.metadata = data
                let linksize = linkView.systemLayoutSizeFitting(UIView.layoutFittingExpandedSize)
                let width = linksize.width
                let height = linksize.height
                
                let goal = widthOrHeight(width: true) * 0.8
                if width > goal {
                    self.width = goal
                } else {
                    self.width = width
                }
                if height > 400 {
                   self.height = 400
                } else {
                   self.height = height
                }
            }
        }
        return linkView
    }

        func updateUIView(_ uiView: UIView, context: Context) { }
    }
    
    class CustomLinkView: LPLinkView {
        
        init() {
            super.init(frame: .zero)
        }
            
        override var intrinsicContentSize: CGSize {
            return CGSize(width: frame.width, height: frame.height)
        }
    }
    
    func checkForFirstUrl(text: String) -> URL? {
        let types: NSTextCheckingResult.CheckingType = .link
    
        do {
            let detector = try NSDataDetector(types: types.rawValue)
            let matches = detector.matches(in: text, options: .reportCompletion, range: NSMakeRange(0, text.count))
            if let firstMatch = matches.first {
                return firstMatch.url
            }
        } catch {
            print("")
        }
    
        return nil
    }
© www.soinside.com 2019 - 2024. All rights reserved.