2012-07-03 21 views
21

Tôi muốn đặt UIImageView với UIImage và đặt hình ảnh này bên trong một UIScrollView để thu phóng hình ảnh này; và tôi muốn điều này UIImageViewUIScrollView để vừa với hình ảnh ở chính giữa của chế độ xem ... có thể không?IOS: thêm imageview vào chế độ xem cuộn để phóng to thu nhỏ

+0

Vì vậy, bạn muốn hình ảnh để phóng to với một nhúm, nhưng mọi thứ khác trong giao diện cuộn để giữ nguyên? – woz

+0

yes ............. – CrazyDev

+0

Vâng, điều đó hoàn toàn có thể xảy ra. Bạn đã thử bất cứ điều gì cả? Hầu hết những gì bạn mô tả có thể được thực hiện trong trình tạo giao diện/bảng phân cảnh –

Trả lời

76
  1. Đặt điều khiển xem của bạn lên như một <UIScrollViewDelegate>
  2. Vẽ bạn UIScrollView kích thước bạn muốn cho hình chữ nhật ở trung tâm của quan điểm. Đặt mức thu phóng tối đa trong thanh tra thành một cái gì đó lớn hơn 1. Giống như 4 hoặc 10.
  3. Nhấp chuột phải vào chế độ xem cuộn và kết nối đại biểu với bộ điều khiển chế độ xem của bạn.
  4. Vẽ UIImageView của bạn trong UIScrollView và thiết lập nó với bất kỳ hình ảnh nào bạn muốn. Làm cho nó có cùng kích thước với UIScrollView.
  5. Ctrl + kéo biểu mẫu bạn UIImageView vào bộ điều khiển View của bạn để tạo IBOutlet cho số UIImageView, gọi nó là thông minh như imageView.
  6. Thêm mã này:

    -(UIView *) viewForZoomingInScrollView:(UIScrollView *)scrollView 
    { 
        return self.imageView; 
    } 
    
  7. Chạy ứng dụng và nhúm và chảo đến khi nội dung của trái tim của bạn.

+0

Bạn có thể làm ví dụ về điều này nhưng theo chương trình không? – fawrkes

+1

cho đến nay giải pháp đơn giản và rõ ràng nhất mà tôi đã tìm thấy – anthonypliu

+0

@Justin Paulson Chúng tôi có thể hạn chế thu phóng kích thước hình ảnh không. Tôi không muốn người dùng thu nhỏ kích thước hình ảnh. Bạn có thể giúp tôi không? –

29

Tải xuống thisthis tệp. Bạn sẽ cần chúng để xử lý các chạm.

Thêm vào quan điểm của bạn scrollview đại biểu <UIScrollViewDelegate> và tuyên bố các cửa hàng:

@property (nonatomic, retain) IBOutlet UIScrollView *imageScrollView; 
@property (nonatomic, retain) UIImageView *imageView; 

nhập các tập tin tải về bên trong màn hình và làm:

#import "TapDetectingImageView.h" 

#define ZOOM_STEP 2.0 
@interface myView (UtilityMethods) 
- (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center; 
@end 


@implementation myView 
@synthesize imageScrollView, imageView; 


- (void)viewDidLoad 
{ 

    [super viewDidLoad]; 

    //Setting up the scrollView  
    imageScrollView.bouncesZoom = YES; 
    imageScrollView.delegate = self; 
    imageScrollView.clipsToBounds = YES; 

    //Setting up the imageView 
    imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"myImage.png"]]; 
    imageView.userInteractionEnabled = YES; 
    imageView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin); 

    //Adding the imageView to the scrollView as subView 
    [imageScrollView addSubview:imageView]; 
    imageScrollView.contentSize = CGSizeMake(imageView.bounds.size.width, imageView.bounds.size.height); 
    imageScrollView.decelerationRate = UIScrollViewDecelerationRateFast; 

    //UITapGestureRecognizer set up 
    UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)]; 
    UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)]; 
    UITapGestureRecognizer *twoFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTwoFingerTap:)]; 

    [doubleTap setNumberOfTapsRequired:2]; 
    [twoFingerTap setNumberOfTouchesRequired:2]; 

    //Adding gesture recognizer 
    [imageView addGestureRecognizer:doubleTap]; 
    [imageView addGestureRecognizer:twoFingerTap]; 

    [singleTap release]; 
    [doubleTap release]; 
    [twoFingerTap release]; 

    // calculate minimum scale to perfectly fit image width, and begin at that scale 
    float minimumScale = 1.0;//This is the minimum scale, set it to whatever you want. 1.0 = default 
    imageScrollView.maximumZoomScale = 4.0; 
    imageScrollView.minimumZoomScale = minimumScale; 
    imageScrollView.zoomScale = minimumScale; 
    [imageScrollView setContentMode:UIViewContentModeScaleAspectFit]; 
    [imageView sizeToFit]; 
    [imageScrollView setContentSize:CGSizeMake(imageView.frame.size.width, imageView.frame.size.height)]; 



} 

- (void)scrollViewDidZoom:(UIScrollView *)aScrollView { 
    CGFloat offsetX = (imageScrollView.bounds.size.width > imageScrollView.contentSize.width)? 
    (imageScrollView.bounds.size.width - imageScrollView.contentSize.width) * 0.5 : 0.0; 
    CGFloat offsetY = (imageScrollView.bounds.size.height > imageScrollView.contentSize.height)? 
    (imageScrollView.bounds.size.height - imageScrollView.contentSize.height) * 0.5 : 0.0; 
    imageView.center = CGPointMake(imageScrollView.contentSize.width * 0.5 + offsetX, 
            imageScrollView.contentSize.height * 0.5 + offsetY); 
} 

- (void)viewDidUnload { 
    self.imageScrollView = nil; 
    self.imageView = nil; 
} 



#pragma mark UIScrollViewDelegate methods 

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView { 
    return imageView; 
} 

#pragma mark TapDetectingImageViewDelegate methods 

- (void)handleDoubleTap:(UIGestureRecognizer *)gestureRecognizer { 
    // zoom in 
    float newScale = [imageScrollView zoomScale] * ZOOM_STEP; 

    if (newScale > self.imageScrollView.maximumZoomScale){ 
     newScale = self.imageScrollView.minimumZoomScale; 
     CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gestureRecognizer locationInView:gestureRecognizer.view]]; 

     [imageScrollView zoomToRect:zoomRect animated:YES]; 

    } 
    else{ 

     newScale = self.imageScrollView.maximumZoomScale; 
     CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gestureRecognizer locationInView:gestureRecognizer.view]]; 

     [imageScrollView zoomToRect:zoomRect animated:YES]; 
    } 
} 


- (void)handleTwoFingerTap:(UIGestureRecognizer *)gestureRecognizer { 
    // two-finger tap zooms out 
    float newScale = [imageScrollView zoomScale]/ZOOM_STEP; 
    CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gestureRecognizer locationInView:gestureRecognizer.view]]; 
    [imageScrollView zoomToRect:zoomRect animated:YES]; 
} 

#pragma mark Utility methods 

- (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center { 

    CGRect zoomRect; 

    // the zoom rect is in the content view's coordinates. 
    // At a zoom scale of 1.0, it would be the size of the imageScrollView's bounds. 
    // As the zoom scale decreases, so more content is visible, the size of the rect grows. 
    zoomRect.size.height = [imageScrollView frame].size.height/scale; 
    zoomRect.size.width = [imageScrollView frame].size.width/scale; 

    // choose an origin so as to get the right center. 
    zoomRect.origin.x = center.x - (zoomRect.size.width/2.0); 
    zoomRect.origin.y = center.y - (zoomRect.size.height/2.0); 

    return zoomRect; 
} 

Xong!

Về cơ bản, mã này làm là thêm imageView làm chế độ xem phụ của imageScrollView.

Sau đó, nó sẽ thêm các phương thức lớp TapDetecting vào scrollView, để nhận biết số lượng vòi - pinch người dùng thực hiện và thêm chức năng thu phóng.

Bạn có thể đặt minimumScale của hình ảnh, nếu bạn để lại 1.0 hình ảnh sẽ được hiển thị dưới dạng (nếu bạn đặt nó thấp hơn một chút), và maximumZoomScale, tôi đề nghị bạn rời khỏi nó đến 4, nó là tốt!

Bây giờ, bạn có thể tải hình ảnh theo chương trình từ đó.

Điều cuối cùng bạn phải làm là chèn UIScrollView vào trong tệp xib của bạn và liên kết nó với imageScrollView. Bạn sẽ có hình ảnh ở trung tâm hoàn hảo, bạn có thể nhấn đúp vào nó để thu phóng, chụm để thu phóng khi bạn thiết lập trong mã.

+1

Điều này giống như một công thức nấu ăn. Các bước phải nhưng bạn không giải thích lý do tại sao anh ta nên làm theo cách này. Điều này sẽ giúp anh ta và những người khác cuối cùng hơn. – Pfitz

+0

Đây là mã cơ bản tôi đang sử dụng trong các ứng dụng của mình. Tôi sẽ giải thích – Phillip

+0

Đừng làm cho tôi sai - mã là tốt, nhưng tại sao cũng quan trọng. Nếu không, anh ta sẽ không biết cách giải quyết một vấn đề tương tự. – Pfitz

0

Với Swift 4 và iOS 11, bạn có thể sử dụng một trong hai giải pháp sau để giải quyết vấn đề của mình.


# 1. Sử dụng insets

ViewController.swift

final class ViewController: UIViewController { 

    private let scrollView = ImageScrollView(image: UIImage(named: "image")!) 

    override func viewDidLoad() { 
     view.backgroundColor = .black 
     view.addSubview(scrollView) 

     scrollView.frame = view.frame 
     scrollView.autoresizingMask = [.flexibleWidth, .flexibleHeight] 
    } 

} 

ImageScrollView.swift

import UIKit 

final class ImageScrollView: UIScrollView { 

    private let imageView = UIImageView() 
    override var frame: CGRect { 
     didSet { 
      if frame.size != oldValue.size { setZoomScale() } 
     } 
    } 

    required init(image: UIImage) { 
     super.init(frame: .zero) 

     imageView.image = image 
     imageView.sizeToFit() 
     addSubview(imageView) 
     contentSize = imageView.bounds.size 

     contentInsetAdjustmentBehavior = .never // Adjust content according to safe area if necessary 
     showsVerticalScrollIndicator = false 
     showsHorizontalScrollIndicator = false 
     alwaysBounceHorizontal = true 
     alwaysBounceVertical = true 
     delegate = self 
    } 

    required init?(coder aDecoder: NSCoder) { 
     fatalError("init(coder:) has not been implemented") 
    } 

    // MARK: - Helper methods 

    func setZoomScale() { 
     let widthScale = frame.size.width/imageView.bounds.width 
     let heightScale = frame.size.height/imageView.bounds.height 
     let minScale = min(widthScale, heightScale) 
     minimumZoomScale = minScale 
     zoomScale = minScale 
    } 

} 
extension ImageScrollView: UIScrollViewDelegate { 

    func viewForZooming(in scrollView: UIScrollView) -> UIView? { 
     return imageView 
    } 

    func scrollViewDidZoom(_ scrollView: UIScrollView) { 
     let imageViewSize = imageView.frame.size 
     let scrollViewSize = scrollView.bounds.size 
     let verticalInset = imageViewSize.height < scrollViewSize.height ? (scrollViewSize.height - imageViewSize.height)/2 : 0 
     let horizontalInset = imageViewSize.width < scrollViewSize.width ? (scrollViewSize.width - imageViewSize.width)/2 : 0 
     scrollView.contentInset = UIEdgeInsets(top: verticalInset, left: horizontalInset, bottom: verticalInset, right: horizontalInset) 
    } 

} 

# 2. Sử dụng Auto Layout

ViewController.swift

import UIKit 

final class ViewController: UIViewController { 

    private let scrollView = ImageScrollView(image: UIImage(named: "image")!) 

    override func viewDidLoad() { 
     view.backgroundColor = .black 
     view.addSubview(scrollView) 

     scrollView.translatesAutoresizingMaskIntoConstraints = false 
     scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true 
     scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true 
     scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true 
     scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true 
    } 

    override func viewDidLayoutSubviews() {   
     scrollView.setZoomScale() 
    } 

} 

ImageScrollView.swift

import UIKit 

final class ImageScrollView: UIScrollView { 

    private let imageView = UIImageView() 
    private var imageViewBottomConstraint = NSLayoutConstraint() 
    private var imageViewLeadingConstraint = NSLayoutConstraint() 
    private var imageViewTopConstraint = NSLayoutConstraint() 
    private var imageViewTrailingConstraint = NSLayoutConstraint() 

    required init(image: UIImage) { 
     super.init(frame: .zero) 

     imageView.image = image 
     imageView.sizeToFit() 
     addSubview(imageView) 

     imageView.translatesAutoresizingMaskIntoConstraints = false 
     imageViewLeadingConstraint = imageView.leadingAnchor.constraint(equalTo: leadingAnchor) 
     imageViewTrailingConstraint = imageView.trailingAnchor.constraint(equalTo: trailingAnchor) 
     imageViewTopConstraint = imageView.topAnchor.constraint(equalTo: topAnchor) 
     imageViewBottomConstraint = imageView.bottomAnchor.constraint(equalTo: bottomAnchor) 
     NSLayoutConstraint.activate([imageViewLeadingConstraint, imageViewTrailingConstraint, imageViewTopConstraint, imageViewBottomConstraint]) 

     contentInsetAdjustmentBehavior = .never // Adjust content according to safe area if necessary 
     showsVerticalScrollIndicator = false 
     showsHorizontalScrollIndicator = false 
     alwaysBounceHorizontal = true 
     alwaysBounceVertical = true 
     delegate = self 
    } 

    required init?(coder aDecoder: NSCoder) { 
     fatalError("init(coder:) has not been implemented") 
    } 

    // MARK: - Helper methods 

    func setZoomScale() { 
     let widthScale = frame.size.width/imageView.bounds.width 
     let heightScale = frame.size.height/imageView.bounds.height 
     let minScale = min(widthScale, heightScale) 
     minimumZoomScale = minScale 
     zoomScale = minScale 
    } 

} 
extension ImageScrollView: UIScrollViewDelegate { 

    func viewForZooming(in scrollView: UIScrollView) -> UIView? { 
     return imageView 
    } 

    func scrollViewDidZoom(_ scrollView: UIScrollView) { 
     let yOffset = max(0, (bounds.size.height - imageView.frame.height)/2) 
     imageViewTopConstraint.constant = yOffset 
     imageViewBottomConstraint.constant = yOffset 

     let xOffset = max(0, (bounds.size.width - imageView.frame.width)/2) 
     imageViewLeadingConstraint.constant = xOffset 
     imageViewTrailingConstraint.constant = xOffset 

     layoutIfNeeded() 
    } 

} 

Nguồn: