iOS_26PopoverController簡單使用 – iPhone手機開發技術文章 iPhone軟體開發教學課程

最終效果圖:

UIImage分類,Point2Color:vc3Ryb25nPjwvcD4KPHA+PHByZSBjbGFzcz0=”brush:java;”>//
// UIImage+Point2Color.h
// 26_popOverCtrl
//
// Created by beyond on 14-8-31.
// Copyright (c) 2014年 com.beyond. All rights reserved.
//

#import

@interface UIImage (Point2Color)
// 傳入 一個點坐標,返回圖片上該點的顏色對象
– (UIColor *)colorFromPoint:(CGPoint)point;
@end

//
//  UIImage+Point2Color.m
//  26_popOverCtrl
//
//  Created by beyond on 14-8-31.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//  分類,傳入一個point,獲取該點的顏色

#import "UIImage+Point2Color.h"

@implementation UIImage (Point2Color)

// 傳入 一個點坐標,返回圖片上該點的顏色對象
// 將圖片寫入內存,再依據【點】中取顏色
- (UIColor *)colorFromPoint:(CGPoint)point
{
	UIColor *color = nil;
    // 得到取色圖片的引用
	CGImageRef inImage = self.CGImage;
    // 調用自定義方法:從_imgView裡面的image的引用,創建並返回對應的上下文
	CGContextRef contexRef = [self ARGBBitmapContextFromImage:inImage];
    // 如果創建該圖片對應的上下文失敗
	if (contexRef == NULL){
        NSLog(@"取色圖片--創建對應的上下文失敗~");
        return nil;
    }
	// 準備將【取色圖片】寫入剛才創建出來的上下文
    size_t w = CGImageGetWidth(inImage);
	size_t h = CGImageGetHeight(inImage);
	CGRect rect = {{0,0},{w,h}};
    // 調試輸出rect:--{{0, 0}, {225, 250}}
	
	// 將位圖寫入(渲染)已經創建好的  上下文工作空間
	CGContextDrawImage(contexRef, rect, inImage);
	
	// 得到位圖上下文 內存數據塊的首地址,用指針記住,作為基地址
	unsigned char* dataPoint = CGBitmapContextGetData (contexRef);
    NSLog(@"----首地址,指針%p",dataPoint);
    // ----首地址,指針0x8b3f000
	if (dataPoint != NULL) {
		//offset 即:根據觸摸點的xy,定位到位圖內存空間中的一個特定像素
        //4 的意思是每一個像素點,占4個字節
        // w是每一行所有點的總數
        // 根據所在行,所在列,算出在內存塊中的偏移地址,然後乘以4,因為每一個點在內存中占四個字節
		int offset = 4*((w*round(point.y))+round(point.x));
        // alpha 為內存基地址+偏移地址
		int alpha =  dataPoint[offset];
        // red 為內存基地址+偏移地址+1   其他類似
		int red = dataPoint[offset+1];
		int green = dataPoint[offset+2];
		int blue = dataPoint[offset+3];
        NSLog(@"偏移地址: %i colors: RGBA %i %i %i  %i",offset,red,green,blue,alpha);
        // offset: 150908 colors: RGB A 255 0 254  255
        // 根據RGBA 生成顏色對象
		color = [UIColor colorWithRed:(red/255.0f) green:(green/255.0f) blue:(blue/255.0f) alpha:(alpha/255.0f)];
	}
	
	// 操作完成後,釋放上下文對象
	CGContextRelease(contexRef);
	// 從內存中釋放掉 加載到內存的圖像數據
	if (dataPoint) { free(dataPoint); }
    // 返回圖片上該點對應的顏色
	return color;
}



// 自定義方法2:通過_imgView裡面的image的引用,創建並返回對應的上下文,即根據CGImageRef來創建一個ARGBBitmapContext
- (CGContextRef)ARGBBitmapContextFromImage:(CGImageRef) inImage
{
    // 要創建的上下文
	CGContextRef    context = NULL;
    // 色彩空間
	CGColorSpaceRef colorSpace;
    // 位圖數據在內存空間的首地址
	void *          bitmapData;
    // 每一行的字節數
	int             bitmapBytesPerRow;
    // 圖片總的占的字節數
    int             bitmapByteCount;
	
	// 得到圖片的寬度和高度,將要使用整個圖片,創建上下文
	size_t pixelsWide = CGImageGetWidth(inImage);
	size_t pixelsHigh = CGImageGetHeight(inImage);
	
	// 每一行占多少字節. 本取色圖片中的每一個像素點占4個字節;
    // 紅 綠 藍 透明度 各占一個字節(8位  取值范圍0~255)
    // 每一行的字節數,因為每一個像素點占4個字節(包含RGBA)(其中一個R就是一個字節,占8位,取值是2的8次方 0~255)
	bitmapBytesPerRow   = (pixelsWide * 4);
    // 圖片總的占的字節數
	bitmapByteCount     = (bitmapBytesPerRow * pixelsHigh);
	
	// 使用指定的 色彩空間(RGB)
	colorSpace = CGColorSpaceCreateDeviceRGB();
	if (colorSpace == NULL)
	{
		fprintf(stderr, "創建並分配色彩空間 出錯\n");
		return NULL;
	}
	
	// 為取色圖片數據  分配所有的內存空間
    // 所有畫到取色圖片上下文的操作,都將被渲染到此內存空間
	bitmapData = malloc( bitmapByteCount );
	if (bitmapData == NULL)
	{
		fprintf (stderr, "內存空間分配失敗~");
		CGColorSpaceRelease( colorSpace );
		return NULL;
	}
	
	// 創建位圖上下文. 使用 pre-multiplied ARGB, ARGB中的每一個成員都占8個bit位,即一字節,一個像素共占4個字節
    // 無論原取色圖片的格式是什麼(CMYK或Grayscale),都將通過CGBitmapContextCreate方法,轉成指定的ARGB格式
	context = CGBitmapContextCreate (bitmapData,
									 pixelsWide,
									 pixelsHigh,
									 8,      // bits per component
									 bitmapBytesPerRow,
									 colorSpace,
									 (CGBitmapInfo)kCGImageAlphaPremultipliedFirst);
	if (context == NULL)
	{
		free (bitmapData);
		fprintf (stderr, "位圖上下文創建失敗~");
	}
	
	// 在返回上下文之前 必須記得釋放 色彩空間  
	CGColorSpaceRelease( colorSpace );
	
	return context;
}

@end

ColorPicker控制器及其代理

//
//  ColorPickerController.h
//  26_popOverCtrl
//
//  Created by beyond on 14-8-31.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//

#import 
@protocol ColorPickerDelegate;
@interface ColorPickerController : UIViewController

// 成員:代理,到時個通知該代理,選擇的顏色是啥~
@property (weak, nonatomic) id delegate;
@end

//
//  ColorPickerController.m
//  26_popOverCtrl
//
//  Created by beyond on 14-8-31.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//

#import "ColorPickerController.h"
// 分類
#import "UIImage+Point2Color.h"
// 顏色選擇完畢,通知代理
#import "ColorPickerDelegate.h"
@interface ColorPickerController ()

@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end

@implementation ColorPickerController

#pragma mark - 生命周期方法
- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // 重要~~~指定 當前控制器在popover中顯示的大小(跟 圖片 一樣)
    self.preferredContentSize = self.imageView.image.size;
}
// 觸摸結束時,獲取點擊的坐標,調用UIImage分類方法,獲取圖片上該點的顏色
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    // 有人需要該點的顏色,才進行取色
    if ([self.delegate respondsToSelector:@selector(colorPickerController:didSelectedColor:)]) {
        // 獲得觸摸點
        UITouch *touch = [touches anyObject];
        CGPoint point = [touch locationInView:touch.view];
        
        // 獲得顏色
        UIColor *color = [self.imageView.image colorFromPoint:point];
        // 告訴代理,該點對應的顏色
        [self.delegate colorPickerController:self didSelectedColor:color];
    }
}


@end
//
//  ColorPickerDelegate.h
//  26_popOverCtrl
//
//  Created by beyond on 14-8-31.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
//  顏色選擇控制器的代理,當它解碼出用戶點擊處的顏色時,通知代理

#import 
@class ColorPickerController;
@protocol ColorPickerDelegate 



@optional
- (void)colorPickerController:(ColorPickerController *)ctrl didSelectedColor:(UIColor *)color;


@end

主控制器

//
//  BeyondViewController.m
//  26_popOverCtrl
//
//  Created by beyond on 14-8-31.
//  Copyright (c) 2014年 com.beyond. All rights reserved.
// 00000000
// 99999999

#import "BeyondViewController.h"

// 點擊左邊Item,彈出Nana控制器
#import "NanaViewController.h"
// 點擊中間的按鈕,彈出顏色選擇控制器
#import "ColorPickerController.h"
// 代理方法
#import "ColorPickerDelegate.h"

@interface BeyondViewController ()

- (IBAction)menuClick:(UIBarButtonItem *)sender;

- (IBAction)colorButtonClick:(UIButton *)sender;

// UIPopoverController  不能是局部變量,必須是成員變量
@property (nonatomic, strong) UIPopoverController *menuPopover;
// UIPopoverController  不能是局部變量,必須是成員變量
@property (nonatomic, strong) UIPopoverController *colorPopover;

@end


@implementation BeyondViewController

#pragma mark - 懶加載 getter方法
- (UIPopoverController *)menuPopover
{
    if (_menuPopover == nil) {
        // 1.創建內容控制器
        NanaViewController *nana = [[NanaViewController alloc] init];
        UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:nana];
        
        // 2.創建popover
        self.menuPopover = [[UIPopoverController alloc] initWithContentViewController:nav];
    }
    // 返回popOver
    return _menuPopover;
}

- (UIPopoverController *)colorPopover
{
    if (_colorPopover == nil) {
        // 1.創建內容控制器
        ColorPickerController *cpvc = [[ColorPickerController alloc] init];
        cpvc.delegate = self;
        
        // 2.創建popover
        self.colorPopover = [[UIPopoverController alloc] initWithContentViewController:cpvc];
        // 重要~~~點擊popOver之外的陰影,使點擊事件可以穿透...
        // self.colorPopover.passthroughViews = @[self.colorButton];
    }
    return _colorPopover;
}


#pragma mark - 顏色選擇控制器的代理方法
- (void)colorPickerController:(ColorPickerController *)cpvc didSelectedColor:(UIColor *)color
{
    self.view.backgroundColor = color;
}

#pragma mark - 監聽按鈕點擊
/**
 *  點擊菜單,在指定位置,彈出popOver
 */
- (IBAction)menuClick:(UIBarButtonItem *)sender
{
    // 顯示到哪個位置
    [self.menuPopover presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}


/**
 *  點擊瞭顏色按鈕,在指定位置,彈出popOver
 */
- (IBAction)colorButtonClick:(UIButton *)sender
{
    [self.colorPopover presentPopoverFromRect:sender.bounds inView:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
@end

You May Also Like