2011-12-07 84 views
4

我正在制作一个iPad应用程序,客户端需要透明度(alpha)的popoverview。 他们给了我一个示例应用程序,截图可以发现hereiOS UIPopoverController透明度/ alpha

我读过UIPopoverController是最差的东西来定制,因为只有几个属性来设置。 LINK & LINK

我降低一个子视图的alpha尝试过,但随后的视图的内容被TRANSPARANT了。

我是否错过了一个选项,或者做错了什么来改变它?

此外,我没有什么经验与子类,所以任何建议,如果这种情况下,将不胜感激。

-Jasper

+0

我敢肯定,这是由子类完成的,让我张望了一下惹的意见,我会尽快给您回复。 –

+0

我也这么认为,我正在研究它,但它可能需要一些时间.. –

+0

我已更新[this](http://stackoverflow.com/questions/4678456/transparent-uipopover/8417471#8417471)问题。如果你做popoverController.contentViewController.view.alpha = 0.5;内部视图+内容将是透明的,而不是UIPopoverController本身。 – Jasper

回答

9

我创建的UIView你一个子类,它应该为你所需要的工作...

PopoverView.h:

// 
// PopoverView.h 
// popovertest 
// 
// Created by Richard Ross III on 12/7/11. 
// Copyright (c) 2011 Ultimate Computer Services Inc. All rights reserved. 
// 
#import <UIKit/UIKit.h> 
#import <CoreGraphics/CoreGraphics.h> 

@interface PopoverView : UIView 
{ 
    UIColor *backgroundColor; 
    CGSize contentSize; 
    UIViewController *contentViewController; 
    CGSize borders; 
} 

@property(nonatomic, retain) UIColor *backgroundColor; 
@property(readonly, assign) CGSize contentSize; 
@property(nonatomic, retain) UIViewController *contentViewController; 
@property(nonatomic, assign) CGSize borders; 

@end 

PopoverView.m

// 
// PopoverView.m 
// popovertest 
// 
// Created by Richard Ross III on 12/7/11. 
// Copyright (c) 2011 Ultimate Computer Services Inc. All rights reserved. 
// 

#import "PopoverView.h" 

@implementation PopoverView 

@synthesize backgroundColor, borders, contentSize, contentViewController; 

-(void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
{ 
    if ([keyPath isEqualToString:@"frame"] || [keyPath isEqualToString:@"borders"]) 
    { 
     contentSize = CGRectInset(self.frame, borders.width, borders.height).size; 
     contentViewController.view.frame = CGRectMake(borders.width, borders.height, contentSize.width, contentSize.height); 
    } 
} 

- (id)initWithFrame:(CGRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) { 
     // Initialization code 
     self.opaque = NO; 
     self.clipsToBounds = NO; 
     self.backgroundColor = [UIColor colorWithRed:50/256 green:50/256 blue:50/256 alpha:0.75f]; 
     self.borders = CGSizeMake(25, 25); 
     contentSize = CGRectInset(frame, borders.width * 2, borders.height * 2).size; 
     self.userInteractionEnabled = YES; 

     [self addObserver:self forKeyPath:@"frame"  options:kNilOptions context:nil]; 
     [self addObserver:self forKeyPath:@"borders" options:kNilOptions context:nil]; 
    } 

    return self; 
} 

-(void) setContentViewController:(UIViewController *)contentViewController_ 
{ 
    if (contentViewController_ != self->contentViewController) 
    { 
     [self->contentViewController.view removeFromSuperview]; 

     self->contentViewController = contentViewController_; 
     [self addSubview:contentViewController_.view]; 
     contentViewController_.view.frame = CGRectMake(borders.width, borders.height, contentSize.width, contentSize.height); 
    } 
} 

void CGContextDrawRoundedRect(CGContextRef context, CGColorRef color, CGRect bounds, CGFloat radius); 

void CGContextDrawRoundedRect(CGContextRef context, CGColorRef color, CGRect bounds, CGFloat radius) 
{ 
    CGContextSetFillColorWithColor(context, color); 

    // If you were making this as a routine, you would probably accept a rectangle 
    // that defines its bounds, and a radius reflecting the "rounded-ness" of the rectangle. 
    CGRect rrect = bounds; 

    // NOTE: At this point you may want to verify that your radius is no more than half 
    // the width and height of your rectangle, as this technique degenerates for those cases. 

    // In order to draw a rounded rectangle, we will take advantage of the fact that 
    // CGContextAddArcToPoint will draw straight lines past the start and end of the arc 
    // in order to create the path from the current position and the destination position. 

    // In order to create the 4 arcs correctly, we need to know the min, mid and max positions 
    // on the x and y lengths of the given rectangle. 
    CGFloat minx = CGRectGetMinX(rrect), midx = CGRectGetMidX(rrect), maxx = CGRectGetMaxX(rrect); 
    CGFloat miny = CGRectGetMinY(rrect), midy = CGRectGetMidY(rrect), maxy = CGRectGetMaxY(rrect); 

    // Next, we will go around the rectangle in the order given by the figure below. 
    //  minx midx maxx 
    // miny 2  3  4 
    // midy 1 9    5 
    // maxy 8  7  6 
    // Which gives us a coincident start and end point, which is incidental to this technique, but still doesn't 
    // form a closed path, so we still need to close the path to connect the ends correctly. 
    // Thus we start by moving to point 1, then adding arcs through each pair of points that follows. 
    // You could use a similar tecgnique to create any shape with rounded corners. 

    // Start at 1 
    CGContextMoveToPoint(context, minx, midy); 
    // Add an arc through 2 to 3 
    CGContextAddArcToPoint(context, minx, miny, midx, miny, radius); 
    // Add an arc through 4 to 5 
    CGContextAddArcToPoint(context, maxx, miny, maxx, midy, radius); 
    // Add an arc through 6 to 7 
    CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, radius); 
    // Add an arc through 8 to 9 
    CGContextAddArcToPoint(context, minx, maxy, minx, midy, radius); 
    // Close the path 
    CGContextClosePath(context); 
    // Fill the path 
    CGContextDrawPath(context, kCGPathFill); 
} 

- (void)drawRect:(CGRect)rect 
{ 
    CGContextRef currentContext = UIGraphicsGetCurrentContext(); 
    CGColorRef color = [backgroundColor CGColor]; 

    CGContextDrawRoundedRect(currentContext, color, CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height), 10); 
} 


@end 

ArrowView.h:

// 
// ArrowView.h 
// popovertest 
// 
// Created by Richard Ross III on 12/7/11. 
// Copyright (c) 2011 Ultimate Computer Services Inc. All rights reserved. 
// 

#import <UIKit/UIKit.h> 

@interface ArrowView : UIView 
{ 
    UIColor *arrowColor; 
} 

@property(nonatomic, retain) UIColor *arrowColor; 

@end 

ArrowView.m:

// 
// ArrowView.m 
// popovertest 
// 
// Created by Richard Ross III on 12/7/11. 
// Copyright (c) 2011 Ultimate Computer Services Inc. All rights reserved. 
// 

#import "ArrowView.h" 

#define CGRectCenter(rect) CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect)) 
#define CGSizeDiv(size, div) CGSizeMake(size.width/div, size.height/div) 

@implementation ArrowView 

@synthesize arrowColor; 

- (id)initWithFrame:(CGRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) { 
     // Initialization code 
     self.opaque = NO; 
    } 
    return self; 
} 

// Only override drawRect: if you perform custom drawing. 
// An empty implementation adversely affects performance during animation. 
- (void)drawRect:(CGRect)rect 
{ 
    // Drawing code 
    CGContextRef currentContext = UIGraphicsGetCurrentContext(); 

    CGContextSetFillColorWithColor(currentContext, arrowColor.CGColor); 

    CGPoint arrowLocation = CGRectCenter(self.bounds); 
    CGSize arrowSize = CGSizeDiv(self.frame.size, 1); 

    CGPoint arrowTip = CGPointMake(arrowLocation.x, arrowLocation.y + (arrowSize.height/2)); 
    CGPoint arrowLeftFoot = CGPointMake(arrowLocation.x - (arrowSize.width/2), arrowLocation.y - (arrowSize.height/2)); 
    CGPoint arrowRightFoot = CGPointMake(arrowLocation.x + (arrowSize.width/2), arrowLocation.y - (arrowSize.height/2)); 

    // now we draw the triangle 
    CGContextMoveToPoint(currentContext, arrowTip.x, arrowTip.y); 
    CGContextAddLineToPoint(currentContext, arrowLeftFoot.x, arrowLeftFoot.y); 
    CGContextAddLineToPoint(currentContext, arrowRightFoot.x, arrowRightFoot.y); 

    CGContextClosePath(currentContext); 
    CGContextDrawPath(currentContext, kCGPathFill); 
} 

@end 

PopoverViewController.h:

// 
// PopoverViewController.h 
// popovertest 
// 
// Created by Richard Ross III on 12/7/11. 
// Copyright (c) 2011 Ultimate Computer Services Inc. All rights reserved. 
// 

#import <UIKit/UIKit.h> 
#import "PopoverView.h" 
#import "ArrowView.h" 

@interface PopoverViewController : UIViewController 
{ 
    PopoverView *popover; 
    ArrowView *arrow; 

    UIPopoverArrowDirection arrowDirection; 

    UIViewController *parentViewController; 

} 

// for managing the content 
@property(readonly, retain) PopoverView *popover; 

// the arrow 
@property(readonly, retain) ArrowView *arrow; 
@property(nonatomic, assign) UIPopoverArrowDirection arrowDirection; 

-(void) presentModallyInViewController:(UIViewController *) controller animated:(BOOL) animated; 
-(void) dismissModallyFromViewController:(UIViewController *) controller animated:(BOOL) animated; 

-(void) dismiss; 

@end 

PopoverViewController.m:

// 
// PopoverViewController.m 
// popovertest 
// 
// Created by Richard Ross III on 12/7/11. 
// Copyright (c) 2011 Ultimate Computer Services Inc. All rights reserved. 
// 

#import "PopoverViewController.h" 

#define degreestoradians(x) (M_PI * x/180) 

@implementation PopoverViewController 

@synthesize arrowDirection, arrow, popover; 

-(void) updateArrowPosition 
{ 
    if (arrowDirection & UIPopoverArrowDirectionUp) 
    { 
     arrow.frame = CGRectMake((popover.frame.origin.x) + (popover.frame.size.width/2) - (arrow.frame.size.width/2), popover.frame.origin.y - (arrow.frame.size.height), arrow.frame.size.width, arrow.frame.size.height); 
     arrow.transform = CGAffineTransformMakeRotation(degreestoradians(180)); 
    } 
    else if (arrowDirection & UIPopoverArrowDirectionLeft) 
    { 
     arrow.frame = CGRectMake((popover.frame.origin.x) - (arrow.frame.size.width), (popover.frame.origin.y) + (popover.frame.size.height/2) - (arrow.frame.size.height/2), arrow.frame.size.width, arrow.frame.size.height); 
     arrow.transform = CGAffineTransformMakeRotation(degreestoradians(90)); 
    } 
    else if (arrowDirection & UIPopoverArrowDirectionRight) 
    { 
     arrow.frame = CGRectMake((popover.frame.origin.x) + (popover.frame.size.width), (popover.frame.origin.y) + (popover.frame.size.height/2) - (arrow.frame.size.height/2), arrow.frame.size.width, arrow.frame.size.height); 
     arrow.transform = CGAffineTransformMakeRotation(degreestoradians(-90)); 
    } 
    else if (arrowDirection & UIPopoverArrowDirectionDown) 
    { 
     arrow.frame = CGRectMake((popover.frame.origin.x) + (popover.frame.size.width/2) - (arrow.frame.size.width/2), popover.frame.origin.y + popover.frame.size.height, arrow.frame.size.width, arrow.frame.size.height); 
    } 
    else 
    { 
     NSLog(@"unknown direction %i", arrowDirection); 
    } 
} 

-(void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
{ 
    [self updateArrowPosition]; 
} 

-(void) dismiss 
{ 
    [self dismissModallyFromViewController:parentViewController animated:YES]; 
} 

-(void) presentModallyInViewController:(UIViewController *)controller animated:(BOOL)animated 
{ 
    [controller.view addSubview:self.view]; 

    if (animated) 
    { 
     self.view.alpha = 0.0f; 

     [UIView beginAnimations:@"Modal Entrance" context:nil]; 
     [UIView setAnimationDuration:0.25]; 

     self.view.alpha = 1.0f; 

     [UIView commitAnimations]; 
    } 
} 

-(void) dismissModallyFromViewController:(UIViewController *)controller animated:(BOOL)animated 
{ 
    if (animated) 
    { 
     [UIView animateWithDuration:0.25 animations:^{ 
      self.view.alpha = 0.0f; 
     } completion:^(BOOL finished) { 
      [controller dismissModalViewControllerAnimated:NO]; 
     }]; 
    } 
    else 
    { 
     [controller dismissModalViewControllerAnimated:NO]; 
    } 
} 

-(id) init 
{ 
    if (self = [super init]) 
    { 
     popover = [PopoverView new]; 
     arrow = [ArrowView new]; 

     popover.backgroundColor = [UIColor colorWithRed:50/255 green:50/255 blue:50/255 alpha:0.75]; 
     arrow.arrowColor  = [UIColor colorWithRed:50/255 green:50/255 blue:50/255 alpha:0.75]; 
     arrow.frame    = CGRectMake(0, 0, 20, 20); 

     [self addObserver:self forKeyPath:@"arrowDirection" options:kNilOptions context:nil]; 
     [popover addObserver:self forKeyPath:@"frame"  options:kNilOptions context:nil]; 



     [self.view addSubview:popover]; 
     [self.view addSubview:arrow]; 

     arrowDirection = UIPopoverArrowDirectionRight; 
    } 

    return self; 
} 

-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    [self dismiss]; 
} 


@end 

实例应用:

PopoverViewController *popController = [[PopoverViewController alloc] init]; 

UIButton *contentView = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 
[contentView setTitle:@"Hello World!" forState:UIControlStateNormal]; 

UIViewController *controller = [[UIViewController alloc] init]; 
controller.view = contentView; 

popController.popover.contentViewController = controller; 
popController.popover.frame = CGRectMake(100, 100, 300, 400); 

[popController presentModallyInViewController:self animated:YES]; 

请注意,这是用ARC启用的,所以如果你使用引用计数这个代码将需要一些调整。

为了方便,我已经把整个项目在我的Dropbox,供您下载: http://dl.dropbox.com/u/25258177/personal/popovertest.zip

+0

我只是快速看过它,它正是我所期待的!我明天会更彻底地研究它。非常感谢Richard为此付出了时间和精力:-) – Jasper

+0

@Richard J. Ross III,您为代码片段选择了哪些许可证?我想在我的项目中使用代码,并想知道我应该如何评价你。 –

+1

@AndreySolovyov StackOverflow作为一个整体(包括本答案)使用[CC-by-SA](http://creativecommons.org/licenses/by-sa/3.0/)许可证,并且需要署名。我绝不会在这里放置任何我的代码的进一步限制。 –