iOS UIPopoverController transparency / alpha

前端 未结 1 905
说谎
说谎 2021-01-06 04:49

I\'m making an iPad app where the client wants a popoverview with transparency (alpha). They gave me an example app, screenshot can be found here

I\'ve read that UIP

相关标签:
1条回答
  • 2021-01-06 05:11

    I created a subclass of UIView for you that should work for what you need...

    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
    

    Example Usage:

    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];
    

    Please note that this was made with ARC enabled, so if you are using reference counting this code will need some tweaking.

    For convenience, I have put the entire project in my dropbox, for you to download: http://dl.dropbox.com/u/25258177/personal/popovertest.zip

    0 讨论(0)
提交回复
热议问题