J'espérais que quelqu'un pourrait m'aider. J'essaie de permettre à un utilisateur de pincer le zoom sur un UIImageView (avec un niveau maximum et minimum autorisés). Mais pour une raison quelconque, cela ne fonctionne pas correctement. L'image s'agrandit un peu puis rebondit. Je vous remercie.
voici le zoom func
func zoom(sender:UIPinchGestureRecognizer) {
if sender.state == .Ended || sender.state == .Changed {
let currentScale = self.view.frame.size.width / self.view.bounds.size.width
var newScale = currentScale*sender.scale
if newScale < 1 {
newScale = 1
}
if newScale > 9 {
newScale = 9
}
let transform = CGAffineTransformMakeScale(newScale, newScale)
self.imageView?.transform = transform
sender.scale = 1
}
}
J'ai décidé d'ajouter l'imageView à un UIScrollView. Il permet à l'utilisateur de zoomer et de faire un panoramique. Voici le code que j'ai utilisé.
pour régler le zoom max/min, j'ai utilisé:
scrollImg.minimumZoomScale = 1.0
scrollImg.maximumZoomScale = 10.0
voici le reste du code.
var vWidth = self.view.frame.width
var vHeight = self.view.frame.height
var scrollImg: UIScrollView = UIScrollView()
scrollImg.delegate = self
scrollImg.frame = CGRectMake(0, 0, vWidth!, vHeight!)
scrollImg.backgroundColor = UIColor(red: 90, green: 90, blue: 90, alpha: 0.90)
scrollImg.alwaysBounceVertical = false
scrollImg.alwaysBounceHorizontal = false
scrollImg.showsVerticalScrollIndicator = true
scrollImg.flashScrollIndicators()
scrollImg.minimumZoomScale = 1.0
scrollImg.maximumZoomScale = 10.0
defaultView!.addSubview(scrollImg)
imageView!.layer.cornerRadius = 11.0
imageView!.clipsToBounds = false
scrollImg.addSubview(imageView!)
Je devais aussi ajouter ceci aussi
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
return self.imageView
}
prototype de fonction Swift 3 et supérieur
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return self.mainImage
}
Zoom à pincement UIImageView avec UIScrollView || zoom de l'image ios en Swift 3 et Xcode 8 lettre RL de la vidéo Youtube
définir uiscrollview Delegate dans le storyboard
class PhotoDetailViewController: UIViewController, UIScrollViewDelegate {
@IBOutlet weak var scrollView: UIScrollView!
@IBOutlet weak var imgPhoto: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
scrollView.minimumZoomScale = 1.0
scrollView.maximumZoomScale = 6.0
// scrollView.delegate = self - it is set on the storyboard.
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return imgPhoto
}
L’option pour Swift 4
class ViewController: UIViewController, UIScrollViewDelegate {
@IBOutlet weak var scrolView: UIScrollView!
@IBOutlet weak var imgPhoto: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
scrolView.delegate = self
scrolView.minimumZoomScale = 1.0
scrolView.maximumZoomScale = 10.0
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return imgPhoto
}
}
Vous pouvez utiliser ImageScrollView Open Source, une vue zoomable et défilable. http://github.com/huynguyencong/ImageScrollView
Comme cette source ouverte, ajoutez ImageView à ScrollView
open class ImageScrollView: UIScrollView {
var zoomView: UIImageView? = nil
}
extension ImageScrollView: UIScrollViewDelegate{
public func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return zoomView
}
public func scrollViewDidZoom(_ scrollView: UIScrollView) {
adjustFrameToCenter()
}
}
À mon avis, le problème est votre détermination de currentScale. Il est toujours égal à 1, car vous modifiez l'échelle de votre imageView. Vous devez affecter votre currentScale comme suit:
let currentScale = self.imageView?.frame.size.width / self.imageView?.bounds.size.width
Swift 3 solution
Par défaut UIImageView's
userInteration
est désactivé. Activez-le avant d'ajouter des gestes dans UIImageView
.
imgView.isUserInteractionEnabled = true
Le facteur d'échelle relatif aux points des deux touches en coordonnées d'écran
var lastScale:CGFloat!
func zoom(gesture:UIPinchGestureRecognizer) {
if(gesture.state == .began) {
// Reset the last scale, necessary if there are multiple objects with different scales
lastScale = gesture.scale
}
if (gesture.state == .began || gesture.state == .changed) {
let currentScale = gesture.view!.layer.value(forKeyPath:"transform.scale")! as! CGFloat
// Constants to adjust the max/min values of zoom
let kMaxScale:CGFloat = 2.0
let kMinScale:CGFloat = 1.0
var newScale = 1 - (lastScale - gesture.scale)
newScale = min(newScale, kMaxScale / currentScale)
newScale = max(newScale, kMinScale / currentScale)
let transform = (gesture.view?.transform)!.scaledBy(x: newScale, y: newScale);
gesture.view?.transform = transform
lastScale = gesture.scale // Store the previous scale factor for the next pinch gesture call
}
}
Swift 3 solution
C'est le code que j'ai utilisé. J'ai ajouté imageView à scrollView en tant que sous-vue.
class ZoomViewController: UIViewController,UIScrollViewDelegate {
@IBOutlet weak var scrollView:UIScrollView!
@IBOutlet weak var imageView:UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
scrollView.delegate = self
scrollView.minimumZoomScale = 1.0
scrollView.maximumZoomScale = 10.0//maximum zoom scale you want
scrollView.zoomScale = 1.0
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return imageView
}
Je me suis retrouvé ici, cherchant probablement le mauvais chemin.
J'étais après avoir mon imageView dans contentMode = .centre. Mais je jugeais que le zoom était trop important et que je cherchais un moyen de faire un zoom arrière. Voici comment:
self.imageView.contentScaleFactor = 3
1 est comme si vous faisiez quelque chose. Plus que 1 effectue un zoom arrière ... 3 fonctionne pour moi, mais vous devez le tester.
J'ai posté une réponse ici pour la fonctionnalité de zoom avec à la fois pincer et taper deux fois Swift 3. Fonctionne parfaitement.
Je pense que le plus gros problème est à la fin de votre func
, vous avez sender.scale = 1
. Si vous supprimez cette ligne de code, votre image ne doit pas simplement rebondir à chaque fois.
En utilisant Swift 5.0, voici comment cela fonctionne pour moi:
let myImageView = UIImageView(image: myImage)
myImageView.isUserInteractionEnabled = true
let pinchMethod = UIPinchGestureRecognizer(target: self, action: #selector(pinchImage(sender:)))
myImageView.addGestureRecognizer(pinchMethod)
@objc func pinchImage(sender: UIPinchMethodRecognizer) {
guard let sender.view != nil else { return }
if let scale = (sender.view?.transform.scaledBy(x: sender.scale, y: sender.scale)) {
guard scale.a > 1.0 else { return }
guard scale.d > 1.0 else { return }
sender.view?.transform = scale
sender.scale = 1.0
}
}
Vous pouvez utiliser scale.a, scale.b, scale.c, scale.d, scale.tx et scale.ty pour définir vos limites d’échelle.
C'est une vieille question, mais je ne vois aucune réponse qui explique ce qui ne va pas avec le code original.
Cette ligne:
let currentScale = self.view.frame.size.width / self.view.bounds.size.width
Travaille sur la vue principale plutôt que sur l'imageView afin que le calcul de l'échelle soit toujours ~ 1
Ce simple changement le fait se comporter comme prévu
let currentScale = sender.view!.frame.size.width / sender.view!.bounds.size.width
en se changeant en expéditeur (et en obligeant la vue à se défaire), le calcul de la balance fonctionne comme prévu.