ฉันต้องการซูมเข้า / ออกวัตถุ UIImage เมื่อผู้ใช้ดำเนินการหยิกมาตรฐานบนแอปพลิเคชันของฉัน ฉันกำลังใช้ UIImageView เพื่อแสดงภาพของฉันหากรายละเอียดนั้นช่วยได้ในทางใดทางหนึ่ง
ฉันกำลังพยายามหาวิธีทำ แต่ก็ยังไม่มีโชค
เบาะแสใด ๆ ?
ฉันต้องการซูมเข้า / ออกวัตถุ UIImage เมื่อผู้ใช้ดำเนินการหยิกมาตรฐานบนแอปพลิเคชันของฉัน ฉันกำลังใช้ UIImageView เพื่อแสดงภาพของฉันหากรายละเอียดนั้นช่วยได้ในทางใดทางหนึ่ง
ฉันกำลังพยายามหาวิธีทำ แต่ก็ยังไม่มีโชค
เบาะแสใด ๆ ?
คำตอบ:
อีกวิธีง่ายๆในการทำเช่นนี้คือการจัดวางUIImageView
ไฟล์UIScrollView
. ดังที่ฉันอธิบายไว้ที่นี่คุณต้องตั้งค่า contentSize ของมุมมองแบบเลื่อนให้เหมือนกับUIImageView's
ขนาดของคุณ ตั้งค่าอินสแตนซ์ตัวควบคุมของคุณให้เป็นผู้รับมอบสิทธิ์ของมุมมองการเลื่อนและใช้viewForZoomingInScrollView:
และscrollViewDidEndZooming:withView:atScale:
วิธีการเพื่ออนุญาตให้มีการซูมด้วยนิ้วและการแพนภาพ นี่คือสิ่งที่โซลูชันของ Ben ทำได้อย่างมีประสิทธิภาพโดยมีน้ำหนักเบากว่าเล็กน้อยเนื่องจากคุณไม่มีค่าใช้จ่ายในการดูเว็บแบบเต็ม
ปัญหาหนึ่งที่คุณอาจพบคือการปรับขนาดภายในมุมมองแบบเลื่อนมาในรูปแบบของการแปลงที่ใช้กับรูปภาพ ซึ่งอาจทำให้เกิดความพร่ามัวเมื่อมีปัจจัยการซูมสูง สำหรับสิ่งที่สามารถวาดใหม่ได้คุณสามารถทำตามคำแนะนำของฉันได้ที่นี่เพื่อให้การแสดงผลที่คมชัดยิ่งขึ้นหลังจากท่าทางการบีบนิ้วเสร็จสิ้น สามารถใช้โซลูชันของ hniels ในจุดนั้นเพื่อปรับขนาดภาพของคุณใหม่
ตามที่คนอื่นอธิบายวิธีแก้ปัญหาที่ง่ายที่สุดคือใส่ UIImageView ของคุณลงใน UIScrollView ฉันทำสิ่งนี้ในไฟล์ Interface Builder .xib
ใน viewDidLoad ตั้งค่าตัวแปรต่อไปนี้ ตั้งค่าคอนโทรลเลอร์ของคุณให้เป็น UIScrollViewDelegate
- (void)viewDidLoad {
[super viewDidLoad];
self.scrollView.minimumZoomScale = 0.5;
self.scrollView.maximumZoomScale = 6.0;
self.scrollView.contentSize = self.imageView.frame.size;
self.scrollView.delegate = self;
}
คุณต้องใช้วิธีการต่อไปนี้เพื่อส่งคืน imageView ที่คุณต้องการซูม
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.imageView;
}
ในเวอร์ชันก่อน iOS9 คุณอาจต้องเพิ่มวิธีการมอบสิทธิ์ที่ว่างเปล่านี้:
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale
{
}
เอกสารแอปเปิ้ลไม่ได้งานที่ดีของการอธิบายวิธีการทำเช่นนี้:
scrollViewDidEndZooming :
วิธีการ
โซลูชันของ Shefali สำหรับ UIImageView ใช้งานได้ดี แต่ต้องมีการปรับเปลี่ยนเล็กน้อย:
- (void)pinch:(UIPinchGestureRecognizer *)gesture {
if (gesture.state == UIGestureRecognizerStateEnded
|| gesture.state == UIGestureRecognizerStateChanged) {
NSLog(@"gesture.scale = %f", gesture.scale);
CGFloat currentScale = self.frame.size.width / self.bounds.size.width;
CGFloat newScale = currentScale * gesture.scale;
if (newScale < MINIMUM_SCALE) {
newScale = MINIMUM_SCALE;
}
if (newScale > MAXIMUM_SCALE) {
newScale = MAXIMUM_SCALE;
}
CGAffineTransform transform = CGAffineTransformMakeScale(newScale, newScale);
self.transform = transform;
gesture.scale = 1;
}
}
(โซลูชันของ Shefali มีข้อเสียตรงที่ไม่ได้ปรับขนาดอย่างต่อเนื่องในขณะที่บีบนิ้วนอกจากนี้เมื่อเริ่มการบีบนิ้วใหม่ขนาดภาพปัจจุบันจะถูกรีเซ็ต)
โค้ดด้านล่างช่วยในการซูม UIImageView โดยไม่ต้องใช้ UIScrollView:
-(void)HandlePinch:(UIPinchGestureRecognizer*)recognizer{
if ([recognizer state] == UIGestureRecognizerStateEnded) {
NSLog(@"======== Scale Applied ===========");
if ([recognizer scale]<1.0f) {
[recognizer setScale:1.0f];
}
CGAffineTransform transform = CGAffineTransformMakeScale([recognizer scale], [recognizer scale]);
imgView.transform = transform;
}
}
โปรดทราบว่าคุณไม่เคยซูมเข้าบนไฟล์UIImage
. เคย.
แต่คุณกำลังซูมเข้าและออกจากส่วนview
ที่แสดงไฟล์UIImage
.
ในกรณีนี้คุณควรเลือกที่จะสร้างแบบกำหนดเองUIView
ด้วยการวาดแบบกำหนดเองเพื่อแสดงภาพUIImageView
ซึ่งจะแสดงภาพให้คุณหรือUIWebView
ต้องใช้ HTML เพิ่มเติมเพื่อสำรองข้อมูล
ในทุกกรณีที่คุณจะต้องดำเนินการtouchesBegan
, touchesMoved
และชอบที่จะตรวจสอบสิ่งที่ผู้ใช้จะพยายามที่จะทำ (ซูมกระทะ ฯลฯ )
นี่คือวิธีแก้ปัญหาที่ฉันเคยใช้มาก่อนซึ่งไม่ต้องการให้คุณใช้ UIWebView
- (UIImage *)scaleAndRotateImage(UIImage *)image
{
int kMaxResolution = 320; // Or whatever
CGImageRef imgRef = image.CGImage;
CGFloat width = CGImageGetWidth(imgRef);
CGFloat height = CGImageGetHeight(imgRef);
CGAffineTransform transform = CGAffineTransformIdentity;
CGRect bounds = CGRectMake(0, 0, width, height);
if (width > kMaxResolution || height > kMaxResolution) {
CGFloat ratio = width/height;
if (ratio > 1) {
bounds.size.width = kMaxResolution;
bounds.size.height = bounds.size.width / ratio;
}
else {
bounds.size.height = kMaxResolution;
bounds.size.width = bounds.size.height * ratio;
}
}
CGFloat scaleRatio = bounds.size.width / width;
CGSize imageSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef));
CGFloat boundHeight;
UIImageOrientation orient = image.imageOrientation;
switch(orient) {
case UIImageOrientationUp: //EXIF = 1
transform = CGAffineTransformIdentity;
break;
case UIImageOrientationUpMirrored: //EXIF = 2
transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0);
transform = CGAffineTransformScale(transform, -1.0, 1.0);
break;
case UIImageOrientationDown: //EXIF = 3
transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height);
transform = CGAffineTransformRotate(transform, M_PI);
break;
case UIImageOrientationDownMirrored: //EXIF = 4
transform = CGAffineTransformMakeTranslation(0.0, imageSize.height);
transform = CGAffineTransformScale(transform, 1.0, -1.0);
break;
case UIImageOrientationLeftMirrored: //EXIF = 5
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width);
transform = CGAffineTransformScale(transform, -1.0, 1.0);
transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
break;
case UIImageOrientationLeft: //EXIF = 6
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeTranslation(0.0, imageSize.width);
transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
break;
case UIImageOrientationRightMirrored: //EXIF = 7
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeScale(-1.0, 1.0);
transform = CGAffineTransformRotate(transform, M_PI / 2.0);
break;
case UIImageOrientationRight: //EXIF = 8
boundHeight = bounds.size.height;
bounds.size.height = bounds.size.width;
bounds.size.width = boundHeight;
transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0);
transform = CGAffineTransformRotate(transform, M_PI / 2.0);
break;
default:
[NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"];
}
UIGraphicsBeginImageContext(bounds.size);
CGContextRef context = UIGraphicsGetCurrentContext();
if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) {
CGContextScaleCTM(context, -scaleRatio, scaleRatio);
CGContextTranslateCTM(context, -height, 0);
}
else {
CGContextScaleCTM(context, scaleRatio, -scaleRatio);
CGContextTranslateCTM(context, 0, -height);
}
CGContextConcatCTM(context, transform);
CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef);
UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return imageCopy;
}
สามารถอ่านบทความได้ที่ฝ่ายสนับสนุนของ Apple ที่: http://discussions.apple.com/message.jspa?messageID=7276709#7276709
คำตอบของ Shafali และ JRV รวมถึงการแพนกล้องและการบีบนิ้วเพื่อซูม:
#define MINIMUM_SCALE 0.5
#define MAXIMUM_SCALE 6.0
@property CGPoint translation;
- (void)pan:(UIPanGestureRecognizer *)gesture {
static CGPoint currentTranslation;
static CGFloat currentScale = 0;
if (gesture.state == UIGestureRecognizerStateBegan) {
currentTranslation = _translation;
currentScale = self.view.frame.size.width / self.view.bounds.size.width;
}
if (gesture.state == UIGestureRecognizerStateEnded || gesture.state == UIGestureRecognizerStateChanged) {
CGPoint translation = [gesture translationInView:self.view];
_translation.x = translation.x + currentTranslation.x;
_translation.y = translation.y + currentTranslation.y;
CGAffineTransform transform1 = CGAffineTransformMakeTranslation(_translation.x , _translation.y);
CGAffineTransform transform2 = CGAffineTransformMakeScale(currentScale, currentScale);
CGAffineTransform transform = CGAffineTransformConcat(transform1, transform2);
self.view.transform = transform;
}
}
- (void)pinch:(UIPinchGestureRecognizer *)gesture {
if (gesture.state == UIGestureRecognizerStateEnded || gesture.state == UIGestureRecognizerStateChanged) {
// NSLog(@"gesture.scale = %f", gesture.scale);
CGFloat currentScale = self.view.frame.size.width / self.view.bounds.size.width;
CGFloat newScale = currentScale * gesture.scale;
if (newScale < MINIMUM_SCALE) {
newScale = MINIMUM_SCALE;
}
if (newScale > MAXIMUM_SCALE) {
newScale = MAXIMUM_SCALE;
}
CGAffineTransform transform1 = CGAffineTransformMakeTranslation(_translation.x, _translation.y);
CGAffineTransform transform2 = CGAffineTransformMakeScale(newScale, newScale);
CGAffineTransform transform = CGAffineTransformConcat(transform1, transform2);
self.view.transform = transform;
gesture.scale = 1;
}
}
วิธีที่ง่ายที่สุดในการทำสิ่งนี้หากสิ่งที่คุณต้องการคือการซูมด้วยนิ้วมือคือการวางภาพของคุณไว้ในช่องUIWebView
(เขียนโค้ด html wrapper จำนวนเล็กน้อยอ้างอิงภาพของคุณและคุณก็ทำเสร็จแล้ว) วิธี complcated มากขึ้นในการทำเช่นนี้คือการใช้touchesBegan
, touchesMoved
และtouchesEnded
การติดตามของนิ้วมือของผู้ใช้และปรับมุมมองของคุณเปลี่ยนคุณสมบัติเหมาะสม
โปรดทราบว่าคุณไม่ต้องการซูมเข้า / ออก UIImage ให้พยายามย่อ / ขยายมุมมองซึ่งมี UIImage View Controller แทน
ฉันได้แก้ปัญหาสำหรับปัญหานี้แล้ว ดูรหัสของฉัน:
@IBAction func scaleImage(sender: UIPinchGestureRecognizer) {
self.view.transform = CGAffineTransformScale(self.view.transform, sender.scale, sender.scale)
sender.scale = 1
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
view.backgroundColor = UIColor.blackColor()
}
หมายเหตุ: อย่าลืมเชื่อมต่อ PinchGestureRecognizer