2013-07-29 87 views
2

放大一個簡單的UIButton我有一個大問題。如何在iOS中平滑放大和縮小UIButton

  • 要重現該問題,只是做一個簡單的項目,包含2 UIButtons一個XIB:一個被放大,另外一個激活變焦方法。

  • 要放大的UIButton是一個自定義button,裏面有一些簡單的文字和背景圖片。

然後使用下面的代碼:

.H

#import <UIKit/UIKit.h> 

@interface ViewController : UIViewController { 
    UIButton* buttonToZoom; 
} 

@property (nonatomic, retain) IBOutlet UIButton* buttonToZoom; 

-(IBAction)zoomIt:(id)sender; 
CGPoint CGRectFindCenter(CGRect rect); 
- (void) zoom:(BOOL)zoomIt animated:(BOOL)animated; 

@end 

.M

#import "ViewController.h" 

@implementation ViewController 

@synthesize buttonToZoom; 

#pragma mark - View lifecycle 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    CGRect theRect = self.buttonToZoom.bounds; 

    CGRect deleteBtnMaxiRect = CGRectMake(self.view.bounds.size.width - theRect.size.width - 10, 
              10, 
              theRect.size.width, 
              theRect.size.height); 

    CGRect deleteBtnMiniRect = CGRectMake(CGRectFindCenter(deleteBtnMaxiRect).x - 1, 
              CGRectFindCenter(deleteBtnMaxiRect).y - 1, 
              2, 
              2); 

    self.buttonToZoom.frame = deleteBtnMaxiRect; // Ensures its correct size at default position 
    [self zoom:NO animated:NO]; // makes it disapear 
} 

-(IBAction)zoomIt:(id)sender { 
    static BOOL zoomInOut = YES; 

    [self zoom:zoomInOut animated:YES]; 
    zoomInOut = !zoomInOut; 
} 

CGPoint CGRectFindCenter(CGRect rect) 
{ 
    return CGPointMake(rect.origin.x + rect.size.width/2.0, rect.origin.y + rect.size.height/2.0); 
} 

- (CGAffineTransform)translatedAndScaledTransformFromRect:(CGRect)fromRect toRect:(CGRect)toRect { 

    CGSize scales = CGSizeMake(toRect.size.width/fromRect.size.width, toRect.size.height/fromRect.size.height); 
    CGPoint offset = CGPointMake(CGRectGetMidX(toRect) - CGRectGetMidX(fromRect), CGRectGetMidY(toRect) - CGRectGetMidY(fromRect)); 

    NSLog(@"scales %@", [NSValue valueWithCGSize:scales]); 

    CGAffineTransform scaleTransform = CGAffineTransformMakeScale(scales.width, scales.height); 
    CGAffineTransform offsetTransform = CGAffineTransformMakeTranslation(offset.x, offset.y); 
    return scaleTransform;// CGAffineTransformConcat(scaleTransform, offsetTransform); 

    // return CGAffineTransformMake(scales.width, 0, 0, scales.height, offset.x, offset.y); 

} 

- (void) zoom:(BOOL)zoomIt animated:(BOOL)animated 
{ 
    static CGRect theRect; 
    if (CGRectIsEmpty(theRect)) theRect = CGRectMake(0, 0, 87, 33); 

    CGRect deleteBtnMaxiRect = CGRectMake(self.view.bounds.size.width - theRect.size.width - 10, 
              10, 
              theRect.size.width, 
              theRect.size.height); 

    CGRect deleteBtnMiniRect = CGRectMake(CGRectFindCenter(deleteBtnMaxiRect).x - 1, 
              CGRectFindCenter(deleteBtnMaxiRect).y - 1, 
              2, 
              2); 

    NSLog(@"------------------------------------------------ mini %@", [NSValue valueWithCGRect:deleteBtnMiniRect]); 
    NSLog(@"------------------------------------------------ maxi %@", [NSValue valueWithCGRect:deleteBtnMaxiRect]); 

    if (animated == YES) { 
     [UIView beginAnimations:@"editingModeAnimation" context:nil]; 
     [UIView setAnimationDuration:1.3]; 
     [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; 
     [UIView setAnimationTransition:UIViewAnimationTransitionNone forView:self.view cache:NO]; 
     [UIView setAnimationDelegate:self]; 
    } 

    if (zoomIt == YES) { 
     if (CGRectEqualToRect(self.buttonToZoom.frame, deleteBtnMaxiRect)) return; 
     NSLog(@"Zoom"); 

     NSLog(@"################################################ before bounds %@", [NSValue valueWithCGRect:self.buttonToZoom.bounds]); 
     NSLog(@"################################################ before frame %@", [NSValue valueWithCGRect:self.buttonToZoom.frame]); 
     self.buttonToZoom.alpha = 1.0; 
     self.buttonToZoom.transform = [self translatedAndScaledTransformFromRect:deleteBtnMiniRect toRect:deleteBtnMaxiRect]; 
     [UIView setAnimationDidStopSelector:@selector(animate_EndEditing)]; 
    } 
    else { 
     if (CGRectEqualToRect(self.buttonToZoom.frame, deleteBtnMiniRect)) return; 
     NSLog(@"Reduce"); 

     NSLog(@"################################################ before bounds %@", [NSValue valueWithCGRect:self.buttonToZoom.bounds]); 
     NSLog(@"################################################ before frame %@", [NSValue valueWithCGRect:self.buttonToZoom.frame]); 
     self.buttonToZoom.alpha = 1.0; // for test 
     self.buttonToZoom.transform = [self translatedAndScaledTransformFromRect:deleteBtnMaxiRect toRect:deleteBtnMiniRect]; 
     [UIView setAnimationDidStopSelector:@selector(animate_EndEditing)]; 
    } 

    if (animated == YES) [UIView commitAnimations]; 
    else { 
      NSLog(@"################################################ after bounds %@", [NSValue valueWithCGRect:self.buttonToZoom.bounds]); 
      NSLog(@"################################################ after frame %@", [NSValue valueWithCGRect:self.buttonToZoom.frame]); 
    } 
} 

- (void) animate_EndEditing 
{ 
    NSLog(@"################################################ after bounds %@", [NSValue valueWithCGRect:self.buttonToZoom.bounds]); 
    NSLog(@"################################################ after frame %@", [NSValue valueWithCGRect:self.buttonToZoom.frame]); 
} 

@end 

這給出了以下日誌:

點擊放大:

Launch 

2013-07-30 00:42:31.008 test[651:207] ------------------------------------------------ mini NSRect: {{265.5, 25.5}, {2, 2}} 
2013-07-30 00:42:31.009 test[651:207] ------------------------------------------------ maxi NSRect: {{223, 10}, {87, 33}} 
2013-07-30 00:42:31.010 test[651:207] Reduce 
2013-07-30 00:42:31.010 test[651:207] ################################################ before bounds NSRect: {{0, 0}, {141, 37}} 
2013-07-30 00:42:31.011 test[651:207] ################################################ before frame NSRect: {{169, 10}, {141, 37}} 
2013-07-30 00:42:31.011 test[651:207] scales NSSize: {0.022988506, 0.060606062} 
2013-07-30 00:42:31.011 test[651:207] ################################################ after bounds NSRect: {{0, 0}, {141, 37}} 
2013-07-30 00:42:31.012 test[651:207] ################################################ after frame NSRect: {{237.8793, 27.378788}, {3.2413793, 2.2424242}} 



Zoom in 

2013-07-30 00:43:09.497 test[651:207] ------------------------------------------------ mini NSRect: {{265.5, 25.5}, {2, 2}} 
2013-07-30 00:43:09.498 test[651:207] ------------------------------------------------ maxi NSRect: {{223, 10}, {87, 33}} 
2013-07-30 00:43:09.498 test[651:207] Zoom 
2013-07-30 00:43:09.499 test[651:207] ################################################ before bounds NSRect: {{0, 0}, {141, 37}} 
2013-07-30 00:43:09.500 test[651:207] ################################################ before frame NSRect: {{237.8793, 27.378788}, {3.2413793, 2.2424242}} 
2013-07-30 00:43:09.500 test[651:207] scales NSSize: {43.5, 16.5} 
2013-07-30 00:43:10.801 test[651:207] ################################################ after bounds NSRect: {{0, 0}, {141, 37}} 
2013-07-30 00:43:10.802 test[651:207] ################################################ after frame NSRect: {{-2827.25, -276.75}, {6133.5, 610.5}} 



Zoom Out 

2013-07-30 00:43:29.889 test[651:207] ------------------------------------------------ mini NSRect: {{265.5, 25.5}, {2, 2}} 
2013-07-30 00:43:29.890 test[651:207] ------------------------------------------------ maxi NSRect: {{223, 10}, {87, 33}} 
2013-07-30 00:43:29.890 test[651:207] Reduce 
2013-07-30 00:43:29.891 test[651:207] ################################################ before bounds NSRect: {{0, 0}, {141, 37}} 
2013-07-30 00:43:29.892 test[651:207] ################################################ before frame NSRect: {{-2827.25, -276.75}, {6133.5, 610.5}} 
2013-07-30 00:43:29.892 test[651:207] scales NSSize: {0.022988506, 0.060606062} 
2013-07-30 00:43:31.193 test[651:207] ################################################ after bounds NSRect: {{0, 0}, {141, 37}} 
2013-07-30 00:43:31.194 test[651:207] ################################################ after frame NSRect: {{237.8793, 27.378788}, {3.2413793, 2.2424242}} 

而下面的視覺效果:

放大

enter image description here

後放大後出

enter image description here

,如果我試圖迫使這個代碼只是AVEC微型和馬克西rects的NSLog的:

if (zoomIt) { 
    self.buttonToZoom.bounds = CGRectMake(0, 0, deleteBtnMiniRect.size.width, deleteBtnMiniRect.size.height); 
    self.buttonToZoom.center = CGRectFindCenter(deleteBtnMiniRect); 
} 
else { 
    self.buttonToZoom.bounds = CGRectMake(0, 0, deleteBtnMaxiRect.size.width, deleteBtnMaxiRect.size.height); 
    self.buttonToZoom.center = CGRectFindCenter(deleteBtnMaxiRect); 
} 

放大是確定的,但縮小(縮小標籤)做weirds事情:

2013-07-30 01:11:19.988 test[1210:207] ######################################################################################### 
2013-07-30 01:11:19.990 test[1210:207] ------------------------------------------------ mini NSRect: {{265.5, 25.5}, {2, 2}} 
2013-07-30 01:11:19.990 test[1210:207] ------------------------------------------------ maxi NSRect: {{223, 10}, {87, 33}} 
2013-07-30 01:11:19.991 test[1210:207] Reduce 
2013-07-30 01:11:19.991 test[1210:207] ################################################ before bounds NSRect: {{0, 0}, {87, 33}} 
2013-07-30 01:11:19.992 test[1210:207] ################################################ before frame NSRect: {{223, 10}, {87, 33}} 
2013-07-30 01:11:19.992 test[1210:207] scales NSSize: {0.022988506, 0.060606062} 
2013-07-30 01:11:19.993 test[1210:207] ################################################ after bounds NSRect: {{0, 0}, {87, 33}} 
2013-07-30 01:11:19.993 test[1210:207] ################################################ after frame NSRect: {{265.5, 25.5}, {2, 2}} 
2013-07-30 01:11:21.730 test[1210:207] ######################################################################################### 
2013-07-30 01:11:21.730 test[1210:207] ------------------------------------------------ mini NSRect: {{265.5, 25.5}, {2, 2}} 
2013-07-30 01:11:21.731 test[1210:207] ------------------------------------------------ maxi NSRect: {{223, 10}, {87, 33}} 
2013-07-30 01:11:21.731 test[1210:207] Zoom 
2013-07-30 01:11:21.732 test[1210:207] ################################################ before bounds NSRect: {{0, 0}, {2, 2}} 
2013-07-30 01:11:21.733 test[1210:207] ################################################ before frame NSRect: {{266.47702, 26.439394}, {0.045977011, 0.12121212}} 
2013-07-30 01:11:21.733 test[1210:207] scales NSSize: {43.5, 16.5} 
2013-07-30 01:11:23.034 test[1210:207] ################################################ after bounds NSRect: {{0, 0}, {2, 2}} 
2013-07-30 01:11:23.035 test[1210:207] ################################################ after frame NSRect: {{223, 10}, {87, 33}} 
2013-07-30 01:11:24.858 test[1210:207] ######################################################################################### 
2013-07-30 01:11:24.858 test[1210:207] ------------------------------------------------ mini NSRect: {{265.5, 25.5}, {2, 2}} 
2013-07-30 01:11:24.859 test[1210:207] ------------------------------------------------ maxi NSRect: {{223, 10}, {87, 33}} 
2013-07-30 01:11:24.860 test[1210:207] Reduce 
2013-07-30 01:11:24.860 test[1210:207] ################################################ before bounds NSRect: {{0, 0}, {87, 33}} 
2013-07-30 01:11:24.860 test[1210:207] ################################################ before frame NSRect: {{-1625.75, -245.75}, {3784.5, 544.5}} 
2013-07-30 01:11:24.861 test[1210:207] scales NSSize: {0.022988506, 0.060606062} 
2013-07-30 01:11:26.162 test[1210:207] ################################################ after bounds NSRect: {{0, 0}, {87, 33}} 
2013-07-30 01:11:26.163 test[1210:207] ################################################ after frame NSRect: {{265.5, 25.5}, {2, 2}} 

的問題

  1. 爲什麼zoomin渲染會給出如此大的圖像?這遠遠低於87x33的期望值。

  2. 爲什麼按鈕永遠不會達到2號和2號?

  3. 爲什麼邊界永遠不會改變,並保持定義在xib中的原始按鈕大小?

+1

有沒有你正在使用的老派風格的動畫代碼,而不是UIView的動畫塊的一個原因? – Jsdodgers

+0

@Jsdodgers:不,沒有理由,除了快速寫下這個例子。 – Oliver

回答

6

請使用UIView基於塊的動畫的方法來做到這一點..

//for zoom in 
[UIView animateWithDuration:0.5f animations:^{ 
    self.btn.transform = CGAffineTransformMakeScale(1.5, 1.5); 
}]; 

// for zoom out 
[UIView animateWithDuration:0.5f animations:^{ 
    self.btn.transform = CGAffineTransformMakeScale(1, 1); 
}];