How to achieve "preview mode" of a child view - iOS, Swift, UIKit

46 Views Asked by At

I would like to achieve something like ChatGPT message bubble, examples are in attachment. If you try to long press in ChatGPT app on a message, view of a cell becomes "focused" and scaled based on pressed cell view height. You can see in attachments that focused view width is calculated by views height and that whole view is shown, no matter of its height.

So my question is how to create view like that, what to use? I approached this with two solutions. First one is to create a screenshot of a view, but then its an image and sometimes resolution is not good.

Second solution was to just grab view from a gesture, and add it as subview, but then it cannot be scaled, or maybe I couldn't achieve scaling. If message its too long, my content gets cut when it cannot longer fit in screen viewport.

Here is code what I tried so far:

    @objc func handleLongPress(_ gesture: UILongPressGestureRecognizer) {
    guard let tappedView = gesture.view else { return }
    tappedView.layer.cornerRadius = 8

    if gesture.state == .began {
        let blurEffect = UIBlurEffect(style: UIBlurEffect.Style.light)
        let blurEffectView = UIVisualEffectView(effect: blurEffect)
        blurEffectView.frame = view.bounds
        blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        view.addSubview(blurEffectView)
        
        view.addSubview(tappedView)
        view.bringSubviewToFront(tappedView)
                    
        let windowsHeight = UIScreen.main.bounds.height
        
        if tappedView.frame.height > windowsHeight {
            tappedView.snp.makeConstraints { make in
                make.edges.equalToSuperview()
            }

            UIView.animate(withDuration: 0.5, delay: 0, options: .curveEaseIn, animations: {
                tappedView.snp.remakeConstraints { make in
                    make.top.bottom.equalToSuperview().inset(50)
                    make.leading.trailing.equalToSuperview().inset(70)
                }
          }, completion: nil)
        } else {
            let cellFrameInViewport = contentView.tableView.convert(tappedView.frame, to: UIApplication.shared.keyWindow)
            print("cellFrameInViewport", cellFrameInViewport)
            tappedView.frame = cellFrameInViewport.inset(by: UIEdgeInsets(top: 0, left: 20, bottom: 0, right: 20))
        }
    } else if gesture.state == .ended {
        print("ended")
    } else if gesture.state == .cancelled {
        print("cancelled")
    }
}

The reason why I was checking this line: "if tappedView.frame.height > windowsHeight" It is because when view is smaller, lets say 100 height, I want it to be exactly where it was position in the first place, since it can fit screen, it doesn't need any scaling

Thanks in advance!

ChatGPT view ChatGPT view. My current implementation where content in view is cut when it cannot longer fit

0

There are 0 best solutions below