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!


