├── CustomImagePicker.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── CustomImagePicker.xccheckout │ └── xcuserdata │ │ └── pnanda.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── pnanda.xcuserdatad │ └── xcschemes │ ├── CustomImagePicker.xcscheme │ └── xcschememanagement.plist ├── CustomImagePicker ├── AppDelegate.h ├── AppDelegate.m ├── CameraCell.h ├── CameraCell.m ├── CameraCell.xib ├── CameraCell_5.xib ├── CameraFocusSquare.h ├── CameraFocusSquare.m ├── ColorUtil.h ├── ColorUtil.m ├── CustomeImagePicker.h ├── CustomeImagePicker.m ├── CustomeImagePicker.xib ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist ├── OLGhostAlertView.h ├── OLGhostAlertView.m ├── PhotoCell.h ├── PhotoCell.m ├── PhotoCell.xib ├── PhotoPickerCell.h ├── PhotoPickerCell.m ├── PhotoPickerCell.xib ├── PhotoPickerCell_5.xib ├── RNActivityView.h ├── RNActivityView.m ├── UIView+RNActivityView.h ├── UIView+RNActivityView.m ├── ViewController.h ├── ViewController.m ├── ViewController.xib ├── YCameraViewController.h ├── YCameraViewController.m ├── YCameraViewController.xib └── main.m ├── CustomImagePickerTests ├── CustomImagePickerTests.m └── Info.plist ├── Header.h ├── LICENSE ├── README.md ├── images ├── camera.png ├── cameraorange.png ├── discard.png ├── discard@2x.png ├── flash-auto.png ├── flash-auto@2x.png ├── flash-off.png ├── flash-off@2x.png ├── flash.png ├── flash@2x.png ├── focus-crosshair.png ├── focus-crosshair@2x.png ├── front-camera.png ├── front-camera@2x.png ├── screenshot.jpg ├── take-snap.png ├── take-snap@2x.png └── tick.png └── screenshot.jpg /CustomImagePicker.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CustomImagePicker.xcodeproj/project.xcworkspace/xcshareddata/CustomImagePicker.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 27D9E7EA-F518-42A6-ADB4-CE3A7CF95D29 9 | IDESourceControlProjectName 10 | CustomImagePicker 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | B337A9954EDE3E34A0359B7F2DB649E2E7D266F5 14 | https://github.com/cspnanda/CustomImagePicker.git 15 | 16 | IDESourceControlProjectPath 17 | CustomImagePicker.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | B337A9954EDE3E34A0359B7F2DB649E2E7D266F5 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | https://github.com/cspnanda/CustomImagePicker.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | B337A9954EDE3E34A0359B7F2DB649E2E7D266F5 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | B337A9954EDE3E34A0359B7F2DB649E2E7D266F5 36 | IDESourceControlWCCName 37 | CustomImagePicker 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /CustomImagePicker.xcodeproj/project.xcworkspace/xcuserdata/pnanda.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cspnanda/CustomImagePicker/72f140b66a91e8f09506e29912cf1e4c76119479/CustomImagePicker.xcodeproj/project.xcworkspace/xcuserdata/pnanda.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /CustomImagePicker.xcodeproj/xcuserdata/pnanda.xcuserdatad/xcschemes/CustomImagePicker.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 94 | 100 | 101 | 102 | 103 | 105 | 106 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /CustomImagePicker.xcodeproj/xcuserdata/pnanda.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | CustomImagePicker.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 18B38D0D1A5B17FC005915E3 16 | 17 | primary 18 | 19 | 20 | 18B38D261A5B17FC005915E3 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /CustomImagePicker/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // CustomImagePicker 4 | // 5 | // Created by C S P Nanda on 1/5/15. 6 | // Copyright (c) 2015 C S P Nanda. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ViewController.h" 11 | 12 | @interface AppDelegate : UIResponder 13 | 14 | @property (strong, nonatomic) UIWindow *window; 15 | 16 | 17 | @end 18 | 19 | -------------------------------------------------------------------------------- /CustomImagePicker/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // CustomImagePicker 4 | // 5 | // Created by C S P Nanda on 1/5/15. 6 | // Copyright (c) 2015 C S P Nanda. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 21 | 22 | 23 | ViewController *livc = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil]; 24 | 25 | self.window.rootViewController = livc; 26 | [self.window makeKeyAndVisible]; 27 | return YES; 28 | 29 | 30 | 31 | 32 | return YES; 33 | } 34 | 35 | - (void)applicationWillResignActive:(UIApplication *)application { 36 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 37 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 38 | } 39 | 40 | - (void)applicationDidEnterBackground:(UIApplication *)application { 41 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 42 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 43 | } 44 | 45 | - (void)applicationWillEnterForeground:(UIApplication *)application { 46 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 47 | } 48 | 49 | - (void)applicationDidBecomeActive:(UIApplication *)application { 50 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 51 | } 52 | 53 | - (void)applicationWillTerminate:(UIApplication *)application { 54 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 55 | } 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /CustomImagePicker/CameraCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // PhotoCell.h 3 | // CustomImagePicker 4 | // 5 | // Created by Prasanna Nanda on 1/5/15. 6 | // Copyright (c) 2015 Prasanna Nanda. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "Header.h" 12 | 13 | @interface CameraCell : UICollectionViewCell 14 | - (void) setAsset:(ALAsset *)asset; 15 | - (void) setImage:(UIImage *)image; 16 | - (UIImageView*) getImageView; 17 | -(void) performSelectionAnimations; 18 | -(void) hideTick; 19 | -(void) showTick; 20 | @property(nonatomic, strong) ALAsset *asset; 21 | @end -------------------------------------------------------------------------------- /CustomImagePicker/CameraCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // PhotoCell.m 3 | // CustomImagePicker 4 | // 5 | // Created by Prasanna Nanda on 1/5/15. 6 | // Copyright (c) 2015 Prasanna Nanda. All rights reserved. 7 | // 8 | 9 | #import "CameraCell.h" 10 | 11 | @interface CameraCell () 12 | // 1 13 | @property(nonatomic, weak) IBOutlet UIImageView *photoImageView; 14 | @property(nonatomic, weak) IBOutlet UIImageView *tickView; 15 | 16 | @end 17 | 18 | @implementation CameraCell 19 | - (UIImageView*) getImageView; 20 | { 21 | return self.photoImageView; 22 | } 23 | - (id)initWithFrame:(CGRect)frame { 24 | 25 | self = [super initWithFrame:frame]; 26 | 27 | if (self) { 28 | // Initialization code 29 | NSArray *arrayOfViews = Nil; 30 | if(IS_IPHONE_6||IS_IPHONE_6P) 31 | arrayOfViews = [[NSBundle mainBundle] loadNibNamed:@"CameraCell" owner:self options:nil]; 32 | else 33 | arrayOfViews = [[NSBundle mainBundle] loadNibNamed:@"CameraCell_5" owner:self options:nil]; 34 | 35 | 36 | if ([arrayOfViews count] < 1) { 37 | return nil; 38 | } 39 | 40 | if (![[arrayOfViews objectAtIndex:0] isKindOfClass:[UICollectionViewCell class]]) { 41 | return nil; 42 | } 43 | 44 | self = [arrayOfViews objectAtIndex:0]; 45 | 46 | } 47 | 48 | return self; 49 | 50 | } 51 | 52 | -(void) showTick 53 | { 54 | [self.tickView setHidden:NO]; 55 | } 56 | -(void) hideTick 57 | { 58 | [self.tickView setHidden:YES]; 59 | } 60 | - (void) setAsset:(ALAsset *)asset 61 | { 62 | // 2 63 | _asset = asset; 64 | self.photoImageView.image = [UIImage imageWithCGImage:[asset thumbnail]]; 65 | } 66 | - (void) setImage:(UIImage *)image 67 | { 68 | [self.photoImageView setImage:image]; 69 | } 70 | @end -------------------------------------------------------------------------------- /CustomImagePicker/CameraCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /CustomImagePicker/CameraCell_5.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /CustomImagePicker/CameraFocusSquare.h: -------------------------------------------------------------------------------- 1 | // 2 | // CameraFocusSquare.h 3 | // 4 | // Created by Prasanna Nanda on 6/11/15. 5 | // Copyright (c) 2015 iosrecipe. All rights reserved. 6 | // 7 | 8 | #import 9 | #import "ColorUtil.h" 10 | @interface CameraFocusSquare : UIView 11 | @end 12 | -------------------------------------------------------------------------------- /CustomImagePicker/CameraFocusSquare.m: -------------------------------------------------------------------------------- 1 | // 2 | // CameraFocusSquare.m 3 | // 4 | // Created by Prasanna Nanda on 6/11/15. 5 | // Copyright (c) 2015 iosrecipe. All rights reserved. 6 | // 7 | 8 | #import "CameraFocusSquare.h" 9 | #import 10 | 11 | const float squareLength = 80.0f; 12 | @implementation CameraFocusSquare 13 | 14 | - (id)initWithFrame:(CGRect)frame 15 | { 16 | self = [super initWithFrame:frame]; 17 | if (self) { 18 | // Initialization code 19 | 20 | [self setBackgroundColor:[UIColor clearColor]]; 21 | [self.layer setBorderWidth:2.0]; 22 | [self.layer setCornerRadius:4.0]; 23 | [self.layer setBorderColor:[UIColor whiteColor].CGColor]; 24 | 25 | CABasicAnimation* selectionAnimation = [CABasicAnimation 26 | animationWithKeyPath:@"borderColor"]; 27 | selectionAnimation.toValue = (id)[ColorUtil colorFromHexString:@"#ff7f00" withAlpha:1.0].CGColor; 28 | selectionAnimation.repeatCount = 8; 29 | [self.layer addAnimation:selectionAnimation 30 | forKey:@"selectionAnimation"]; 31 | 32 | } 33 | return self; 34 | } 35 | @end -------------------------------------------------------------------------------- /CustomImagePicker/ColorUtil.h: -------------------------------------------------------------------------------- 1 | // 2 | // ColorUtil.h 3 | // 4 | // Created by İlyas Doğruer 5 | // 6 | 7 | #import 8 | #import 9 | #import 10 | #import 11 | #import 12 | #import 13 | 14 | @interface ColorUtil : NSObject 15 | 16 | +(UIColor *)colorFromHexString:(NSString *)hexString withAlpha:(float)alpha; 17 | +(UIColor *)colorFromHexValue:(UInt32)hexValue withAlpha:(float)alpha; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /CustomImagePicker/ColorUtil.m: -------------------------------------------------------------------------------- 1 | // 2 | // ColorUtil.m 3 | // 4 | // Created by İlyas Doğruer 5 | // 6 | 7 | #import "ColorUtil.h" 8 | 9 | @implementation ColorUtil 10 | 11 | +(UIColor *)colorFromHexString:(NSString *)hexString withAlpha:(float)alpha { 12 | unsigned rgbValue = 0; 13 | NSScanner *scanner = [NSScanner scannerWithString:hexString]; 14 | [scanner setScanLocation:1]; 15 | [scanner scanHexInt:&rgbValue]; 16 | 17 | CGFloat r = ((rgbValue & 0xFF0000) >> 16)/255.0f; 18 | CGFloat g = ((rgbValue & 0xFF00) >> 8)/255.0f; 19 | CGFloat b = (rgbValue & 0xFF)/255.0f; 20 | 21 | return [UIColor colorWithRed:r green:g blue:b alpha:alpha]; 22 | } 23 | 24 | +(UIColor *)colorFromHexValue:(UInt32)hexValue withAlpha:(float)alpha { 25 | int redValue = (hexValue >> 16) & 0xFF; 26 | int greenValue = (hexValue >> 8) & 0xFF; 27 | int blueValue = (hexValue) & 0xFF; 28 | 29 | CGFloat r = redValue / 255.0f; 30 | CGFloat g = greenValue / 255.0f; 31 | CGFloat b = blueValue / 255.0f; 32 | 33 | return [UIColor colorWithRed:r green:g blue:b alpha:alpha]; 34 | } 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /CustomImagePicker/CustomeImagePicker.h: -------------------------------------------------------------------------------- 1 | // 2 | // CustomeImagePicker.h 3 | // CustomImagePicker 4 | // 5 | // Created by Prasanna Nanda on 1/5/15. 6 | // Copyright (c) 2015 Prasanna Nanda. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "PhotoPickerCell.h" 12 | #import "CameraCell.h" 13 | #import "Header.h" 14 | #import "OLGhostAlertView.h" 15 | #import "YCameraViewController.h" 16 | #import 17 | #import 18 | 19 | @protocol CustomeImagePickerDelegate 20 | 21 | -(void)imageSelected:(NSArray*)arrayOfImages; 22 | -(void)imageSelectionCancelled; 23 | 24 | @end 25 | 26 | 27 | 28 | @interface CustomeImagePicker : UIViewController 29 | { 30 | AVCaptureSession *session; 31 | AVCaptureVideoPreviewLayer *captureVideoPreviewLayer; 32 | AVCaptureStillImageOutput *stillImageOutput; 33 | UIImage *croppedImageWithoutOrientation; 34 | 35 | } 36 | 37 | @property(nonatomic, weak) IBOutlet UICollectionView *collectionView; 38 | @property(nonatomic, strong) IBOutlet UICollectionView *nearByCollectionView; 39 | 40 | @property(nonatomic, weak) IBOutlet UIButton *skipButton; 41 | @property(nonatomic, weak) IBOutlet UIButton *nextButton; 42 | @property (nonatomic, strong) NSIndexPath *selectedItemIndexPath; 43 | @property (nonatomic, assign) NSInteger maxPhotos; 44 | @property (nonatomic,strong) IBOutlet NSLayoutConstraint *distanceFromButton; 45 | 46 | @property (nonatomic, strong) NSDictionary *whereamI; 47 | //@property (nonatomic, strong) NSMutableArray *selectedImages; 48 | //@property (nonatomic, strong) NSMutableArray *disselectedImages; 49 | @property (nonatomic, assign) BOOL hideSkipButton; 50 | @property (nonatomic, assign) BOOL hideNextButton; 51 | @property (nonatomic, strong) NSMutableArray *highLightThese; 52 | @property(nonatomic,weak) id delegate; 53 | // @property(nonatomic, weak) IBOutlet UIButton *nextButton; 54 | @property (nonatomic,strong) CLLocation *currentUserLocation; 55 | @property (nonatomic,assign) BOOL showOnlyPhotosWithGPS; 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /CustomImagePicker/CustomeImagePicker.m: -------------------------------------------------------------------------------- 1 | // 2 | // CustomeImagePicker.m 3 | // CustomImagePicker 4 | // 5 | // Created by Prasanna Nanda on 1/5/15. 6 | // Copyright (c) 2015 Prasanna Nanda. All rights reserved. 7 | // 8 | 9 | #import "CustomeImagePicker.h" 10 | #import "UIView+RNActivityView.h" 11 | @interface CustomeImagePicker () 12 | @property(nonatomic, strong) NSArray *assets; 13 | // @property(nonatomic,strong) UIImage *selectedImage; 14 | @end 15 | 16 | @implementation CustomeImagePicker 17 | @synthesize whereamI,skipButton,nextButton,hideNextButton,hideSkipButton,highLightThese,maxPhotos,distanceFromButton,nearByCollectionView,currentUserLocation,showOnlyPhotosWithGPS; 18 | // @synthesize selectedImages,disselectedImages; 19 | 20 | -(BOOL) checkForCamera 21 | { 22 | AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]; 23 | if(authStatus == AVAuthorizationStatusAuthorized) { 24 | // do your logic 25 | return YES; 26 | } 27 | return NO; 28 | } 29 | -(void) viewWillAppear:(BOOL)animated 30 | { 31 | [super viewWillAppear:animated]; 32 | if(highLightThese == Nil) 33 | highLightThese = [[NSMutableArray alloc] init]; 34 | 35 | } 36 | -(void) viewDidDisappear:(BOOL)animated 37 | { 38 | [super viewDidDisappear:animated]; 39 | [session stopRunning]; 40 | } 41 | -(void) viewDidAppear:(BOOL)animated 42 | { 43 | [super viewDidAppear:animated]; 44 | // if(showOnlyPhotosWithGPS==NO && [self checkForCamera] == YES) 45 | [self performSelector:@selector(initializeCamera) withObject:nil afterDelay:0.1]; 46 | } 47 | 48 | - (void)viewDidLoad 49 | { 50 | [super viewDidLoad]; 51 | if(hideSkipButton) 52 | { 53 | [skipButton setHidden:YES]; 54 | } 55 | if(hideNextButton) 56 | { 57 | [nextButton setHidden:YES]; 58 | } 59 | if([highLightThese count]>=1) 60 | [nextButton setHidden:NO]; 61 | else 62 | [nextButton setHidden:YES]; 63 | // selectedImages = [[NSMutableArray alloc] init]; 64 | // disselectedImages = [[NSMutableArray alloc] init]; 65 | [self.collectionView registerClass:[PhotoPickerCell class] forCellWithReuseIdentifier:@"PhotoPickerCell"]; 66 | [self.collectionView registerClass:[CameraCell class] forCellWithReuseIdentifier:@"CameraCell"]; 67 | 68 | UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init]; 69 | if(IS_IPHONE_6 || IS_IPHONE_6P) 70 | [flowLayout setItemSize:CGSizeMake(120, 120)]; 71 | else 72 | [flowLayout setItemSize:CGSizeMake(100, 100)]; 73 | [flowLayout setScrollDirection:UICollectionViewScrollDirectionVertical]; 74 | [self.collectionView setCollectionViewLayout:flowLayout]; 75 | 76 | _assets = [@[] mutableCopy]; 77 | __block NSMutableArray *tmpAssets = [@[] mutableCopy]; 78 | if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { 79 | ALAsset *asset = [[ALAsset alloc] init]; 80 | if(showOnlyPhotosWithGPS==NO) 81 | [tmpAssets insertObject:asset atIndex:0]; 82 | } 83 | ALAssetsLibrary *assetsLibrary = [CustomeImagePicker defaultAssetsLibrary]; 84 | [assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop) { 85 | [group setAssetsFilter:[ALAssetsFilter allPhotos]]; 86 | [group enumerateAssetsWithOptions:NSEnumerationReverse usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) { 87 | if(result) 88 | { 89 | if(showOnlyPhotosWithGPS == YES) 90 | { 91 | if([result valueForProperty:ALAssetPropertyLocation]) 92 | [tmpAssets addObject:result]; 93 | } 94 | else 95 | [tmpAssets addObject:result]; 96 | } 97 | } 98 | ]; 99 | 100 | } failureBlock:^(NSError *error) { 101 | NSLog(@"Error loading images %@", error); 102 | if([ALAssetsLibrary authorizationStatus] != ALAuthorizationStatusAuthorized) 103 | { 104 | [self displayErrorOnMainQueue:@"Photo Access Disabled" message:@"Please allow Photo Access in System Settings"]; 105 | } 106 | }]; 107 | self.assets = tmpAssets; 108 | dispatch_time_t popTime1 = dispatch_time(DISPATCH_TIME_NOW, 0.5 * NSEC_PER_SEC); 109 | dispatch_after(popTime1, dispatch_get_main_queue(), ^(void){ 110 | if(showOnlyPhotosWithGPS==YES) { 111 | OLGhostAlertView *ghastly = [[OLGhostAlertView alloc] initWithTitle:@"Photos with Location" message: @"Only Photos with Location Information are shown here." timeout:2.0 dismissible:YES]; 112 | [ghastly show]; 113 | } 114 | 115 | [self.collectionView reloadData]; 116 | }); 117 | 118 | // }); 119 | nextButton.layer.borderColor = [[UIColor whiteColor] CGColor]; 120 | nextButton.layer.borderWidth = 1.0f; 121 | nextButton.layer.cornerRadius = 5.0f; 122 | 123 | skipButton.layer.borderColor = [[UIColor whiteColor] CGColor]; 124 | skipButton.layer.borderWidth = 1.0f; 125 | skipButton.layer.cornerRadius = 5.0f; 126 | 127 | // dispatch_time_t popTime1 = dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC); 128 | // dispatch_after(popTime1, dispatch_get_main_queue(), ^(void){ 129 | // [self addLiveCamera]; 130 | // }); 131 | } 132 | - (void)displayErrorOnMainQueue:(NSString*) heading message:(NSString *)message 133 | { 134 | dispatch_async(dispatch_get_main_queue(), ^(void) { 135 | UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:heading 136 | message:message 137 | delegate:nil 138 | cancelButtonTitle:@"Dismiss" 139 | otherButtonTitles:nil]; 140 | [alertView show]; 141 | [alertView release]; 142 | }); 143 | } 144 | 145 | -(void) populateNearbyPhotos { 146 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ // 1 147 | ALAssetsLibrary *assetsLibrary = [CustomeImagePicker defaultAssetsLibrary]; 148 | [assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop) { 149 | [group setAssetsFilter:[ALAssetsFilter allPhotos]]; 150 | [group enumerateAssetsWithOptions:NSEnumerationReverse usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) { 151 | if(result) 152 | { 153 | NSDictionary *metadata = [[result defaultRepresentation] metadata]; 154 | NSMutableDictionary *GPSDictionary = [metadata objectForKey:(NSString *)kCGImagePropertyGPSDictionary]; 155 | if(GPSDictionary) 156 | { 157 | 158 | CLLocation *locFromPhoto = [[CLLocation alloc] initWithLatitude:[[GPSDictionary objectForKey:@"Latitude"] doubleValue] longitude:[[GPSDictionary objectForKey:@"Longitude"] doubleValue]]; 159 | 160 | 161 | CLLocationCoordinate2D loc = CLLocationCoordinate2DMake([[[whereamI objectForKey:@"location"] objectForKey:@"latitude"] doubleValue], [[[whereamI objectForKey:@"location"] objectForKey:@"longitude"] doubleValue]); 162 | CLLocation *userLocation = [[CLLocation alloc] initWithLatitude:loc.latitude longitude:loc.longitude]; 163 | 164 | 165 | CLLocationDistance distance = [locFromPhoto distanceFromLocation:userLocation]; 166 | NSLog(@"%f",distance); 167 | if(distance < 1000) 168 | { 169 | NSLog(@"Nearby"); 170 | } 171 | 172 | } 173 | } 174 | } 175 | ]; 176 | 177 | } failureBlock:^(NSError *error) { 178 | }]; 179 | }); 180 | } 181 | 182 | 183 | 184 | 185 | 186 | -(void) addLiveCamera 187 | { 188 | NSIndexPath *ip = [[NSIndexPath alloc] initWithIndex:0]; 189 | UICollectionViewCell *firstCell = [self.collectionView cellForItemAtIndexPath:ip]; 190 | } 191 | - (void)didReceiveMemoryWarning { 192 | [super didReceiveMemoryWarning]; 193 | // Dispose of any resources that can be recreated. 194 | } 195 | - (NSInteger) collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section 196 | { 197 | return self.assets.count; 198 | } 199 | -(void) showCamera 200 | { 201 | NSLog(@"Camera Selected"); 202 | } 203 | - (UICollectionViewCell *) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 204 | { 205 | static NSString *cellIdentifier = @"PhotoPickerCell"; 206 | static NSString *cameraCellIdentifier = @"CameraCell"; 207 | 208 | if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) 209 | { 210 | if(indexPath.row == 0 && indexPath.section == 0 && showOnlyPhotosWithGPS == NO) 211 | { 212 | CameraCell *cell = (CameraCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cameraCellIdentifier forIndexPath:indexPath]; 213 | ALAsset *asset = self.assets[indexPath.row]; 214 | ALAssetRepresentation *rep = [asset defaultRepresentation]; 215 | NSString *assetURL = [[rep url] absoluteString]; 216 | cell.asset = asset; 217 | cell.backgroundColor = [UIColor whiteColor]; 218 | if([highLightThese containsObject:assetURL]) 219 | { 220 | cell.layer.borderColor = [[UIColor orangeColor] CGColor]; 221 | cell.layer.borderWidth = 4.0; 222 | [cell setAlpha:1.0]; 223 | [cell setUserInteractionEnabled:YES]; 224 | } 225 | else 226 | { 227 | if([highLightThese count] == maxPhotos) 228 | { 229 | cell.layer.borderColor = nil; 230 | cell.layer.borderWidth = 0.0; 231 | [cell setAlpha:0.5]; 232 | [cell setUserInteractionEnabled:NO]; 233 | } 234 | else 235 | { 236 | cell.layer.borderColor = nil; 237 | cell.layer.borderWidth = 0.0; 238 | [cell setAlpha:1.0]; 239 | [cell setUserInteractionEnabled:YES]; 240 | } 241 | } 242 | return cell; 243 | } 244 | else 245 | { 246 | PhotoPickerCell *cell = (PhotoPickerCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath]; 247 | 248 | ALAsset *asset = self.assets[indexPath.row]; 249 | ALAssetRepresentation *rep = [asset defaultRepresentation]; 250 | NSString *assetURL = [[rep url] absoluteString]; 251 | cell.asset = asset; 252 | cell.backgroundColor = [UIColor whiteColor]; 253 | if([highLightThese containsObject:assetURL]) 254 | { 255 | cell.layer.borderColor = [[UIColor orangeColor] CGColor]; 256 | cell.layer.borderWidth = 4.0; 257 | [cell setAlpha:1.0]; 258 | [cell setUserInteractionEnabled:YES]; 259 | } 260 | else 261 | { 262 | if([highLightThese count] == maxPhotos) 263 | { 264 | cell.layer.borderColor = nil; 265 | cell.layer.borderWidth = 0.0; 266 | [cell setAlpha:0.5]; 267 | [cell setUserInteractionEnabled:NO]; 268 | } 269 | else 270 | { 271 | cell.layer.borderColor = nil; 272 | cell.layer.borderWidth = 0.0; 273 | [cell setAlpha:1.0]; 274 | [cell setUserInteractionEnabled:YES]; 275 | } 276 | } 277 | return cell; 278 | } 279 | } // Device with Camera 280 | else 281 | { 282 | PhotoPickerCell *cell = (PhotoPickerCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath]; 283 | 284 | ALAsset *asset = self.assets[indexPath.row]; 285 | ALAssetRepresentation *rep = [asset defaultRepresentation]; 286 | NSString *assetURL = [[rep url] absoluteString]; 287 | cell.asset = asset; 288 | cell.backgroundColor = [UIColor whiteColor]; 289 | if([highLightThese containsObject:assetURL]) 290 | { 291 | cell.layer.borderColor = [[UIColor orangeColor] CGColor]; 292 | cell.layer.borderWidth = 4.0; 293 | [cell setAlpha:1.0]; 294 | [cell setUserInteractionEnabled:YES]; 295 | } 296 | else 297 | { 298 | if([highLightThese count] == maxPhotos) 299 | { 300 | cell.layer.borderColor = nil; 301 | cell.layer.borderWidth = 0.0; 302 | [cell setAlpha:0.5]; 303 | [cell setUserInteractionEnabled:NO]; 304 | } 305 | else 306 | { 307 | cell.layer.borderColor = nil; 308 | cell.layer.borderWidth = 0.0; 309 | [cell setAlpha:1.0]; 310 | [cell setUserInteractionEnabled:YES]; 311 | } 312 | } 313 | return cell; 314 | } // Device Without Camera 315 | return Nil; 316 | } 317 | 318 | - (CGFloat) collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section 319 | { 320 | return 4; 321 | } 322 | 323 | - (CGFloat) collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section 324 | { 325 | return 1; 326 | } 327 | /* 328 | #pragma mark - Navigation 329 | 330 | // In a storyboard-based application, you will often want to do a little preparation before navigation 331 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 332 | // Get the new view controller using [segue destinationViewController]. 333 | // Pass the selected object to the new view controller. 334 | } 335 | */ 336 | 337 | + (ALAssetsLibrary *)defaultAssetsLibrary 338 | { 339 | static dispatch_once_t pred = 0; 340 | static ALAssetsLibrary *library = nil; 341 | dispatch_once(&pred, ^{ 342 | library = [[ALAssetsLibrary alloc] init]; 343 | }); 344 | return library; 345 | } 346 | 347 | -(void) collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath 348 | { 349 | ALAsset *asset = self.assets[indexPath.row]; 350 | ALAssetRepresentation *rep = [asset defaultRepresentation]; 351 | NSString *assetURL = [[rep url] absoluteString]; 352 | 353 | if([highLightThese containsObject:assetURL]) 354 | { 355 | [highLightThese removeObject:assetURL]; 356 | // if(![disselectedImages containsObject:indexPath]) 357 | // [disselectedImages addObject:indexPath]; 358 | // [collectionView reloadItemsAtIndexPaths:selectedImages]; 359 | // [collectionView reloadItemsAtIndexPaths:disselectedImages]; 360 | [collectionView reloadData]; 361 | } 362 | } 363 | 364 | - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { 365 | 366 | if(indexPath.row == 0 && indexPath.section == 0 && [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera] && showOnlyPhotosWithGPS == NO) 367 | { 368 | if([self checkForCamera] == YES) 369 | { 370 | YCameraViewController *ycv = [[YCameraViewController alloc] init]; 371 | [ycv setDelegate:self]; 372 | [ycv setCurrentUserLocation:currentUserLocation]; 373 | [self presentViewController:ycv animated:YES completion:^{ 374 | }]; 375 | } 376 | else 377 | { 378 | [self displayErrorOnMainQueue:@"Camera Access Disabled" message:@"Please allow Camera Access in System Settings"]; 379 | } 380 | 381 | } 382 | else 383 | { 384 | ALAsset *asset = self.assets[indexPath.row]; 385 | ALAssetRepresentation *rep = [asset defaultRepresentation]; 386 | NSString *assetURL = [[rep url] absoluteString]; 387 | 388 | if(![highLightThese containsObject:assetURL] && ([highLightThese count] < maxPhotos)) 389 | { 390 | [highLightThese addObject:assetURL]; 391 | } 392 | else 393 | { 394 | [highLightThese removeObject:assetURL]; 395 | } 396 | if([highLightThese count]>=1) 397 | [nextButton setHidden:NO]; 398 | else 399 | [nextButton setHidden:YES]; 400 | [collectionView reloadData]; 401 | } 402 | } 403 | -(IBAction)donePressed:(id)sender 404 | { 405 | if([highLightThese count] == 0) 406 | { 407 | NSLog(@"Please Select One"); 408 | } 409 | else 410 | { 411 | NSMutableArray *allImagesIPicked = [[NSMutableArray alloc] init]; 412 | for(NSString *ip in highLightThese) 413 | { 414 | [allImagesIPicked addObject:ip]; 415 | } // end of for loop 416 | [self dismissViewControllerAnimated:NO completion:^{ 417 | if ([self.delegate respondsToSelector:@selector(imageSelected:)]) { 418 | [self.delegate imageSelected:allImagesIPicked]; 419 | } 420 | }]; 421 | 422 | } 423 | } 424 | -(IBAction)skipPressed:(id)sender 425 | { 426 | // self.selectedImage = Nil; 427 | [self dismissViewControllerAnimated:NO completion:^{ 428 | if ([self.delegate respondsToSelector:@selector(imageSelected:)]) { 429 | [self.delegate imageSelected:Nil]; 430 | } 431 | }]; 432 | } 433 | -(UIImage *)imageByScalingAndCroppingForSize:(CGSize)targetSize sourceImage:(UIImage*)sourceImage 434 | { 435 | UIImage *newImage = nil; 436 | CGSize imageSize = sourceImage.size; 437 | CGFloat width = imageSize.width; 438 | CGFloat height = imageSize.height; 439 | CGFloat targetWidth = targetSize.width; 440 | CGFloat targetHeight = targetSize.height; 441 | CGFloat scaleFactor = 0.0; 442 | CGFloat scaledWidth = targetWidth; 443 | CGFloat scaledHeight = targetHeight; 444 | CGPoint thumbnailPoint = CGPointMake(0.0,0.0); 445 | 446 | if (CGSizeEqualToSize(imageSize, targetSize) == NO) 447 | { 448 | CGFloat widthFactor = targetWidth / width; 449 | CGFloat heightFactor = targetHeight / height; 450 | 451 | if (widthFactor > heightFactor) 452 | { 453 | scaleFactor = widthFactor; // scale to fit height 454 | } 455 | else 456 | { 457 | scaleFactor = heightFactor; // scale to fit width 458 | } 459 | 460 | scaledWidth = width * scaleFactor; 461 | scaledHeight = height * scaleFactor; 462 | 463 | // center the image 464 | if (widthFactor > heightFactor) 465 | { 466 | thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5; 467 | } 468 | else 469 | { 470 | if (widthFactor < heightFactor) 471 | { 472 | thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5; 473 | } 474 | } 475 | } 476 | 477 | UIGraphicsBeginImageContext(targetSize); // this will crop 478 | //UIGraphicsBeginImageContextWithOptions(targetSize, 1.0, 0.0); 479 | 480 | CGRect thumbnailRect = CGRectZero; 481 | thumbnailRect.origin = thumbnailPoint; 482 | thumbnailRect.size.width = scaledWidth; 483 | thumbnailRect.size.height = scaledHeight; 484 | 485 | [sourceImage drawInRect:thumbnailRect]; 486 | 487 | newImage = UIGraphicsGetImageFromCurrentImageContext(); 488 | 489 | if(newImage == nil) 490 | { 491 | NSLog(@"could not scale image"); 492 | } 493 | 494 | //pop the context to get back to the default 495 | UIGraphicsEndImageContext(); 496 | 497 | return newImage; 498 | } 499 | //- (UIImage *)fixrotation:(UIImage *)image{ 500 | // 501 | // 502 | // if (image.imageOrientation == UIImageOrientationUp) return image; 503 | // CGAffineTransform transform = CGAffineTransformIdentity; 504 | // 505 | // switch (image.imageOrientation) { 506 | // case UIImageOrientationDown: 507 | // case UIImageOrientationDownMirrored: 508 | // transform = CGAffineTransformTranslate(transform, image.size.width, image.size.height); 509 | // transform = CGAffineTransformRotate(transform, M_PI); 510 | // break; 511 | // 512 | // case UIImageOrientationLeft: 513 | // case UIImageOrientationLeftMirrored: 514 | // transform = CGAffineTransformTranslate(transform, image.size.width, 0); 515 | // transform = CGAffineTransformRotate(transform, M_PI_2); 516 | // break; 517 | // 518 | // case UIImageOrientationRight: 519 | // case UIImageOrientationRightMirrored: 520 | // transform = CGAffineTransformTranslate(transform, 0, image.size.height); 521 | // transform = CGAffineTransformRotate(transform, -M_PI_2); 522 | // break; 523 | // case UIImageOrientationUp: 524 | // case UIImageOrientationUpMirrored: 525 | // break; 526 | // } 527 | // 528 | // switch (image.imageOrientation) { 529 | // case UIImageOrientationUpMirrored: 530 | // case UIImageOrientationDownMirrored: 531 | // transform = CGAffineTransformTranslate(transform, image.size.width, 0); 532 | // transform = CGAffineTransformScale(transform, -1, 1); 533 | // break; 534 | // 535 | // case UIImageOrientationLeftMirrored: 536 | // case UIImageOrientationRightMirrored: 537 | // transform = CGAffineTransformTranslate(transform, image.size.height, 0); 538 | // transform = CGAffineTransformScale(transform, -1, 1); 539 | // break; 540 | // case UIImageOrientationUp: 541 | // case UIImageOrientationDown: 542 | // case UIImageOrientationLeft: 543 | // case UIImageOrientationRight: 544 | // break; 545 | // } 546 | // 547 | // // Now we draw the underlying CGImage into a new context, applying the transform 548 | // // calculated above. 549 | // CGContextRef ctx = CGBitmapContextCreate(NULL, image.size.width, image.size.height, 550 | // CGImageGetBitsPerComponent(image.CGImage), 0, 551 | // CGImageGetColorSpace(image.CGImage), 552 | // CGImageGetBitmapInfo(image.CGImage)); 553 | // CGContextConcatCTM(ctx, transform); 554 | // switch (image.imageOrientation) { 555 | // case UIImageOrientationLeft: 556 | // case UIImageOrientationLeftMirrored: 557 | // case UIImageOrientationRight: 558 | // case UIImageOrientationRightMirrored: 559 | // // Grr... 560 | // CGContextDrawImage(ctx, CGRectMake(0,0,image.size.height,image.size.width), image.CGImage); 561 | // break; 562 | // 563 | // default: 564 | // CGContextDrawImage(ctx, CGRectMake(0,0,image.size.width,image.size.height), image.CGImage); 565 | // break; 566 | // } 567 | // 568 | // // And now we just create a new UIImage from the drawing context 569 | // CGImageRef cgimg = CGBitmapContextCreateImage(ctx); 570 | // UIImage *img = [UIImage imageWithCGImage:cgimg]; 571 | // CGContextRelease(ctx); 572 | // CGImageRelease(cgimg); 573 | // return img; 574 | // 575 | //} 576 | 577 | -(IBAction)cancelPressed:(id)sender 578 | { 579 | // self.selectedImage = Nil; 580 | [self dismissViewControllerAnimated:NO completion:^{ 581 | if ([self.delegate respondsToSelector:@selector(imageSelectionCancelled)]) { 582 | [self.delegate imageSelectionCancelled]; 583 | } 584 | }]; 585 | 586 | } 587 | 588 | 589 | - (void) initializeCamera { 590 | if (session) 591 | [session release], session=nil; 592 | CameraCell *firstCell = (CameraCell*)[self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]; 593 | UIImageView *view = [firstCell getImageView]; 594 | session = [[AVCaptureSession alloc] init]; 595 | session.sessionPreset = AVCaptureSessionPresetLow; 596 | 597 | if (captureVideoPreviewLayer) 598 | [captureVideoPreviewLayer release], captureVideoPreviewLayer=nil; 599 | 600 | captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session]; 601 | [captureVideoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill]; 602 | 603 | captureVideoPreviewLayer.frame = view.bounds; 604 | [view.layer addSublayer:captureVideoPreviewLayer]; 605 | 606 | 607 | CALayer *viewLayer = [view layer]; 608 | [viewLayer setMasksToBounds:YES]; 609 | 610 | CGRect bounds = [view bounds]; 611 | [captureVideoPreviewLayer setFrame:bounds]; 612 | 613 | NSArray *devices = [AVCaptureDevice devices]; 614 | AVCaptureDevice *backCamera=nil; 615 | 616 | // check if device available 617 | if (devices.count==0) { 618 | NSLog(@"No Camera Available"); 619 | return; 620 | } 621 | 622 | for (AVCaptureDevice *device in devices) { 623 | 624 | NSLog(@"Device name: %@", [device localizedName]); 625 | 626 | if ([device hasMediaType:AVMediaTypeVideo]) { 627 | 628 | if ([device position] == AVCaptureDevicePositionBack) { 629 | NSLog(@"Device position : back"); 630 | backCamera = device; 631 | } 632 | } 633 | } 634 | NSError *error = nil; 635 | AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:backCamera error:&error]; 636 | if (!input) { 637 | NSLog(@"ERROR: trying to open camera: %@", error); 638 | } 639 | else 640 | { 641 | [session addInput:input]; 642 | if (stillImageOutput) 643 | [stillImageOutput release], stillImageOutput=nil; 644 | 645 | stillImageOutput = [[AVCaptureStillImageOutput alloc] init]; 646 | NSDictionary *outputSettings = [[[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey, nil] autorelease]; 647 | [stillImageOutput setOutputSettings:outputSettings]; 648 | 649 | [session addOutput:stillImageOutput]; 650 | 651 | [session startRunning]; 652 | } 653 | 654 | } 655 | 656 | 657 | -(void) doSomeThingWithImage:(NSDictionary*)params 658 | { 659 | UIImage *image = [params objectForKey:@"data"]; 660 | NSDictionary *metadata = [params objectForKey:@"metadata"]; 661 | params = Nil; 662 | ALAssetsLibrary *assetsLibrary = [CustomeImagePicker defaultAssetsLibrary]; 663 | [assetsLibrary writeImageToSavedPhotosAlbum:image.CGImage 664 | metadata:metadata 665 | completionBlock:^(NSURL *assetURL, NSError *error) { 666 | [self dismissViewControllerAnimated:NO completion:^{ 667 | NSMutableArray *allImagesIPicked = [[NSMutableArray alloc] init]; 668 | [allImagesIPicked addObject:assetURL.absoluteString]; 669 | // Now insert the Camera Image at 0 and 2 more 670 | if([highLightThese count]>=1) 671 | { 672 | int count = 1; 673 | for(NSString *ip in highLightThese) 674 | { 675 | [allImagesIPicked addObject:ip]; 676 | count++; 677 | if(count >= maxPhotos) 678 | break; 679 | } // end of for loop 680 | } 681 | if ([self.delegate respondsToSelector:@selector(imageSelected:)]) { 682 | [self.delegate imageSelected:allImagesIPicked]; 683 | } 684 | }]; 685 | 686 | 687 | 688 | }]; 689 | } 690 | 691 | 692 | 693 | /* YCameraView Delegate Start */ 694 | -(void)didFinishPickingImage:(UIImage *)image metadata:(NSDictionary *)metadata { 695 | // Use image as per your need 696 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ // 1 697 | dispatch_async(dispatch_get_main_queue(), ^{ 698 | [self.view showActivityView]; 699 | }); 700 | 701 | 702 | NSDictionary *extraParams = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:image,metadata,nil] forKeys:[NSArray arrayWithObjects:@"data",@"metadata",nil]]; 703 | 704 | [NSThread detachNewThreadSelector:@selector(doSomeThingWithImage:) toTarget:self withObject:extraParams]; 705 | 706 | }); 707 | 708 | } 709 | /* YCameraView Delegate End */ 710 | 711 | 712 | @end 713 | -------------------------------------------------------------------------------- /CustomImagePicker/CustomeImagePicker.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 36 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /CustomImagePicker/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /CustomImagePicker/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | mompop.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | CustomeImagePicker 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UIStatusBarHidden 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /CustomImagePicker/OLGhostAlertView.h: -------------------------------------------------------------------------------- 1 | // 2 | // OLGhostAlertView.h 3 | // 4 | // Originally created by Radu Dutzan. 5 | // (c) 2012 Onda. 6 | // 7 | 8 | #import 9 | 10 | typedef NS_ENUM(NSUInteger, OLGhostAlertViewPosition) { 11 | OLGhostAlertViewPositionBottom, 12 | OLGhostAlertViewPositionCenter, 13 | OLGhostAlertViewPositionTop 14 | }; 15 | 16 | typedef NS_ENUM(NSUInteger, OLGhostAlertViewStyle) { 17 | OLGhostAlertViewStyleDefault, // defaults to OLGhostAlertViewStyleDark 18 | OLGhostAlertViewStyleLight, 19 | OLGhostAlertViewStyleDark 20 | }; 21 | 22 | @interface OLGhostAlertView : UIView 23 | 24 | /** 25 | Equivalent to `initWithTitle:message:timeout:dismissible:`, but assumes default values for `message` (nil) `timeout` (4 seconds) and `dismissible` (YES). 26 | @param title The string that appears in the view's title label. 27 | */ 28 | - (id)initWithTitle:(NSString *)title; 29 | 30 | /** 31 | Equivalent to `initWithTitle:message:timeout:dismissible:`, but assumes default values for `timeout` (6 seconds) and `dismissible` (YES). 32 | @param title The string that appears in the view's title label. 33 | @param message Descriptive text that provides more details than the title. Can be nil. 34 | */ 35 | - (id)initWithTitle:(NSString *)title message:(NSString *)message; 36 | 37 | /** 38 | Initializes a new OLGhostAlertView instance. 39 | @param title The string that appears in the view's title label. 40 | @param message Descriptive text that provides more details than the title. Can be nil. 41 | @param timeout Time interval before the alert is automatically dismissed. 42 | @param dismissible Whether the alert can be dismissed with a tap or not. 43 | */ 44 | - (id)initWithTitle:(NSString *)title message:(NSString *)message timeout:(NSTimeInterval)timeout dismissible:(BOOL)dismissible; 45 | 46 | /** 47 | Shows the OLGhostAlertView on top of the frontmost view controller. 48 | */ 49 | - (void)show; 50 | 51 | /** 52 | Shows the OLGhostAlertView on top of the given `view`. 53 | */ 54 | - (void)showInView:(UIView *)view; 55 | 56 | /** 57 | Hides the OLGhostAlertView. 58 | */ 59 | - (void)hide; 60 | 61 | 62 | /** 63 | The vertical position of the view. 64 | 65 | The default value is `OLGhostAlertViewPositionBottom`. 66 | */ 67 | @property (nonatomic) OLGhostAlertViewPosition position; 68 | 69 | /** 70 | The visual style of the view. 71 | 72 | The view can have either light text on a dark background (`OLGhostAlertViewStyleDark`) or dark text over a light background (`OLGhostAlertViewStyleLight`). 73 | 74 | The default value is `OLGhostAlertViewStyleDefault`, which maps to `OLGhostAlertViewStyleLight`. 75 | */ 76 | @property (nonatomic) OLGhostAlertViewStyle style; 77 | 78 | /** 79 | A margin that prevents the alert from drawing above it. 80 | */ 81 | @property (nonatomic) CGFloat topContentMargin; 82 | 83 | /** 84 | A margin that prevents the alert from drawing below it. 85 | */ 86 | @property (nonatomic) CGFloat bottomContentMargin; 87 | 88 | /** 89 | A block to execute after the instance has been dismissed. 90 | */ 91 | @property (nonatomic, copy) void (^completionBlock)(void); 92 | 93 | /** 94 | The string that appears in the title of the alert. 95 | */ 96 | @property (nonatomic) NSString *title; 97 | 98 | /** 99 | Descriptive text that provides more details than the title. 100 | */ 101 | @property (nonatomic) NSString *message; 102 | 103 | /** 104 | The label that displays the title. 105 | */ 106 | @property (nonatomic, strong) UILabel *titleLabel; 107 | 108 | /** 109 | The label that displays the message. 110 | */ 111 | @property (nonatomic, strong) UILabel *messageLabel; 112 | 113 | /** 114 | Time interval before the alert is automatically dismissed. 115 | */ 116 | @property (nonatomic) NSTimeInterval timeout; 117 | 118 | /** 119 | Whether the alert can be dismissed with a tap or not. 120 | */ 121 | @property (nonatomic) BOOL dismissible; 122 | 123 | /** 124 | A Boolean value that indicates whether the view is currently visible on the screen. 125 | */ 126 | @property (nonatomic, readonly, getter=isVisible) BOOL visible; 127 | 128 | @end -------------------------------------------------------------------------------- /CustomImagePicker/OLGhostAlertView.m: -------------------------------------------------------------------------------- 1 | // 2 | // OLGhostAlertView.m 3 | // 4 | // Originally created by Radu Dutzan. 5 | // (c) 2012-2013 Onda. 6 | // 7 | 8 | #import 9 | #import "OLGhostAlertView.h" 10 | 11 | #define HORIZONTAL_PADDING 18.0 12 | #define VERTICAL_PADDING 14.0 13 | #define TITLE_FONT_SIZE 17 14 | #define MESSAGE_FONT_SIZE 14 15 | 16 | @interface OLGhostAlertView () 17 | 18 | @property (strong, nonatomic) UITapGestureRecognizer *dismissTap; 19 | @property UIInterfaceOrientation interfaceOrientation; 20 | @property CGFloat innerMargin; 21 | @property BOOL keyboardIsVisible; 22 | @property CGFloat keyboardHeight; 23 | @property (nonatomic, readwrite) BOOL visible; 24 | 25 | @end 26 | 27 | @implementation OLGhostAlertView 28 | 29 | #pragma mark - Initialization 30 | 31 | - (id)initWithFrame:(CGRect)frame 32 | { 33 | self = [super initWithFrame:frame]; 34 | if (self) { 35 | self.layer.cornerRadius = 5.0f; 36 | self.backgroundColor = [UIColor colorWithWhite:0 alpha:.45]; 37 | self.alpha = 0; 38 | 39 | self.layer.shadowColor = [UIColor colorWithWhite:0 alpha:0.1].CGColor; 40 | self.layer.shadowOffset = CGSizeMake(0, 0); 41 | self.layer.shadowOpacity = 1.0; 42 | self.layer.shadowRadius = 30.0; 43 | 44 | UIMotionEffectGroup *motionEffects = [UIMotionEffectGroup new]; 45 | 46 | UIInterpolatingMotionEffect *horizontalMotionEffect = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis]; 47 | horizontalMotionEffect.minimumRelativeValue = @-14; 48 | horizontalMotionEffect.maximumRelativeValue = @14; 49 | 50 | UIInterpolatingMotionEffect *verticalMotionEffect = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y" type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis]; 51 | verticalMotionEffect.minimumRelativeValue = @-18; 52 | verticalMotionEffect.maximumRelativeValue = @18; 53 | 54 | motionEffects.motionEffects = @[horizontalMotionEffect, verticalMotionEffect]; 55 | 56 | [self addMotionEffect:motionEffects]; 57 | 58 | _titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(HORIZONTAL_PADDING, VERTICAL_PADDING, 0, 0)]; 59 | _titleLabel.backgroundColor = [UIColor clearColor]; 60 | _titleLabel.textColor = [UIColor whiteColor]; 61 | _titleLabel.textAlignment = NSTextAlignmentCenter; 62 | _titleLabel.font = [UIFont boldSystemFontOfSize:TITLE_FONT_SIZE]; 63 | _titleLabel.numberOfLines = 0; 64 | _titleLabel.lineBreakMode = NSLineBreakByWordWrapping; 65 | _titleLabel.autoresizingMask = (UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight); 66 | 67 | [self addSubview:_titleLabel]; 68 | 69 | _messageLabel = [[UILabel alloc] initWithFrame:CGRectMake(HORIZONTAL_PADDING, 0, 0, 0)]; 70 | _messageLabel.backgroundColor = [UIColor clearColor]; 71 | _messageLabel.textColor = [UIColor whiteColor]; 72 | _messageLabel.textAlignment = NSTextAlignmentCenter; 73 | _messageLabel.font = [UIFont systemFontOfSize:MESSAGE_FONT_SIZE]; 74 | _messageLabel.numberOfLines = 0; 75 | _messageLabel.lineBreakMode = NSLineBreakByWordWrapping; 76 | _messageLabel.autoresizingMask = (UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight); 77 | 78 | [self addSubview:_messageLabel]; 79 | 80 | self.style = OLGhostAlertViewStyleDefault; 81 | _position = OLGhostAlertViewPositionBottom; 82 | 83 | _interfaceOrientation = [UIApplication sharedApplication].statusBarOrientation; 84 | 85 | if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) 86 | _innerMargin = 25; 87 | else 88 | _innerMargin = 50; 89 | 90 | _dismissTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hide)]; 91 | 92 | [[NSNotificationCenter defaultCenter] addObserver:self 93 | selector:@selector(didChangeOrientation:) 94 | name:UIApplicationDidChangeStatusBarOrientationNotification 95 | object:nil]; 96 | 97 | [[NSNotificationCenter defaultCenter] addObserver:self 98 | selector:@selector(keyboardWillShow:) 99 | name:UIKeyboardWillShowNotification 100 | object:nil]; 101 | 102 | [[NSNotificationCenter defaultCenter] addObserver:self 103 | selector:@selector(keyboardWillHide:) 104 | name:UIKeyboardWillHideNotification 105 | object:nil]; 106 | } 107 | return self; 108 | } 109 | 110 | - (id)initWithTitle:(NSString *)title message:(NSString *)message timeout:(NSTimeInterval)timeout dismissible:(BOOL)dismissible 111 | { 112 | self = [self initWithFrame:CGRectZero]; 113 | if (self) { 114 | self.title = title; 115 | self.message = message; 116 | self.timeout = timeout; 117 | self.dismissible = dismissible; 118 | } 119 | return self; 120 | } 121 | 122 | - (id)initWithTitle:(NSString *)title message:(NSString *)message 123 | { 124 | self = [self initWithTitle:title message:message timeout:6 dismissible:YES]; 125 | return self; 126 | } 127 | 128 | - (id)initWithTitle:(NSString *)title 129 | { 130 | self = [self initWithTitle:title message:nil timeout:4 dismissible:YES]; 131 | return self; 132 | } 133 | 134 | #pragma mark - Show and hide 135 | 136 | - (void)show 137 | { 138 | if (!self.title && !self.message) 139 | NSLog(@"OLGhostAlertView: Your alert doesn't have any content."); 140 | 141 | if (self.isVisible) return; 142 | 143 | UIViewController *parentController = [[[UIApplication sharedApplication] delegate] window].rootViewController; 144 | 145 | while (parentController.presentedViewController) 146 | parentController = parentController.presentedViewController; 147 | 148 | UIView *parentView = parentController.view; 149 | 150 | [self showInView:parentView]; 151 | } 152 | 153 | - (void)showInView:(UIView *)view 154 | { 155 | for (UIView *subview in [view subviews]) { 156 | if ([subview isKindOfClass:[OLGhostAlertView class]]) { 157 | OLGhostAlertView *otherOLGAV = (OLGhostAlertView *)subview; 158 | [otherOLGAV hide]; 159 | } 160 | } 161 | 162 | [view addSubview:self]; 163 | 164 | self.visible = YES; 165 | 166 | [UIView animateWithDuration:0.5 animations:^{ 167 | self.alpha = 1; 168 | } completion:^(BOOL finished) { 169 | [self performSelector:@selector(hide) withObject:nil afterDelay:self.timeout]; 170 | }]; 171 | } 172 | 173 | - (void)hide 174 | { 175 | [NSObject cancelPreviousPerformRequestsWithTarget:self]; 176 | 177 | [UIView animateWithDuration:0.5 animations:^{ 178 | self.alpha = 0; 179 | } completion:^(BOOL finished){ 180 | self.visible = NO; 181 | 182 | [self removeFromSuperview]; 183 | 184 | if (self.completionBlock) self.completionBlock(); 185 | }]; 186 | } 187 | 188 | #pragma mark - View layout 189 | 190 | - (void)layoutSubviews 191 | { 192 | CGFloat maxWidth = 0; 193 | CGFloat totalLabelWidth = 0; 194 | CGFloat totalHeight = 0; 195 | 196 | CGRect screenRect = self.superview.bounds; 197 | 198 | if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) { 199 | maxWidth = self.superview.bounds.size.width - 40.0 - (HORIZONTAL_PADDING * 2); 200 | } else { 201 | maxWidth = 520 - (HORIZONTAL_PADDING * 2); 202 | } 203 | 204 | CGSize constrainedSize = CGSizeZero; 205 | constrainedSize.width = maxWidth; 206 | constrainedSize.height = MAXFLOAT; 207 | 208 | CGSize titleSize = [self.title boundingRectWithSize:constrainedSize 209 | options:NSStringDrawingUsesLineFragmentOrigin 210 | attributes:@{NSFontAttributeName: self.titleLabel.font} 211 | context:nil].size; 212 | CGSize messageSize = CGSizeZero; 213 | 214 | if (self.message) { 215 | messageSize = [self.message boundingRectWithSize:constrainedSize 216 | options:NSStringDrawingUsesLineFragmentOrigin 217 | attributes:@{NSFontAttributeName: self.messageLabel.font} 218 | context:nil].size; 219 | 220 | totalHeight = titleSize.height + messageSize.height + floorf(VERTICAL_PADDING * 2.5); 221 | 222 | } else { 223 | totalHeight = titleSize.height + floorf(VERTICAL_PADDING * 2); 224 | } 225 | 226 | if (titleSize.width == maxWidth || messageSize.width == maxWidth) { 227 | totalLabelWidth = maxWidth; 228 | 229 | } else if (messageSize.width > titleSize.width) { 230 | totalLabelWidth = messageSize.width; 231 | 232 | } else { 233 | totalLabelWidth = titleSize.width; 234 | } 235 | 236 | CGFloat totalWidth = totalLabelWidth + (HORIZONTAL_PADDING * 2); 237 | 238 | CGFloat xPosition = floorf((screenRect.size.width / 2) - (totalWidth / 2)); 239 | 240 | CGFloat yPosition = 0; 241 | 242 | switch (self.position) { 243 | case OLGhostAlertViewPositionBottom: 244 | default: 245 | yPosition = screenRect.size.height - ceilf(totalHeight) - self.innerMargin - self.bottomContentMargin; 246 | break; 247 | 248 | case OLGhostAlertViewPositionCenter: 249 | yPosition = ceilf((screenRect.size.height / 2) - (totalHeight / 2)); 250 | break; 251 | 252 | case OLGhostAlertViewPositionTop: 253 | yPosition = self.innerMargin + self.topContentMargin; 254 | break; 255 | } 256 | 257 | self.frame = CGRectMake(xPosition, yPosition, ceilf(totalWidth), ceilf(totalHeight)); 258 | 259 | if (self.keyboardIsVisible && self.position == OLGhostAlertViewPositionBottom) { 260 | self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y - self.keyboardHeight, self.frame.size.width, self.frame.size.height); 261 | } 262 | 263 | self.titleLabel.frame = CGRectMake(self.titleLabel.frame.origin.x, ceilf(self.titleLabel.frame.origin.y), ceilf(totalLabelWidth), ceilf(titleSize.height)); 264 | 265 | if (self.messageLabel) { 266 | self.messageLabel.frame = CGRectMake(self.messageLabel.frame.origin.x, ceilf(titleSize.height) + floorf(VERTICAL_PADDING * 1.5), ceilf(totalLabelWidth), ceilf(messageSize.height)); 267 | } 268 | } 269 | 270 | - (void)keyboardWillShow:(NSNotification*)notification 271 | { 272 | NSDictionary *keyboardInfo = [notification userInfo]; 273 | CGSize keyboardSize = [[keyboardInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; 274 | 275 | self.keyboardIsVisible = YES; 276 | self.keyboardHeight = keyboardSize.height; 277 | 278 | [self setNeedsLayout]; 279 | } 280 | 281 | - (void)keyboardWillHide:(NSNotification*)notification 282 | { 283 | self.keyboardIsVisible = NO; 284 | 285 | [self setNeedsLayout]; 286 | } 287 | 288 | #pragma mark - Orientation handling 289 | 290 | - (void)didChangeOrientation:(NSNotification *)notification 291 | { 292 | self.interfaceOrientation = [UIApplication sharedApplication].statusBarOrientation; 293 | 294 | [self setNeedsLayout]; 295 | } 296 | 297 | #pragma mark - Setters 298 | 299 | - (void)setTitle:(NSString *)title 300 | { 301 | _title = title; 302 | 303 | self.titleLabel.text = title; 304 | 305 | [self setNeedsLayout]; 306 | } 307 | 308 | - (void)setMessage:(NSString *)message 309 | { 310 | _message = message; 311 | 312 | self.messageLabel.text = message; 313 | 314 | [self setNeedsLayout]; 315 | } 316 | 317 | - (void)setDismissible:(BOOL)dismissible 318 | { 319 | _dismissible = dismissible; 320 | 321 | if (dismissible) { 322 | [self addGestureRecognizer:self.dismissTap]; 323 | } else { 324 | if (self.gestureRecognizers) [self removeGestureRecognizer:self.dismissTap]; 325 | } 326 | } 327 | 328 | - (void)setStyle:(OLGhostAlertViewStyle)style 329 | { 330 | if (style == OLGhostAlertViewStyleDefault) style = OLGhostAlertViewStyleLight; 331 | 332 | _style = style; 333 | 334 | UIColor *backgroundColor = nil; 335 | UIColor *textColor = nil; 336 | 337 | if (style == OLGhostAlertViewStyleLight) { 338 | backgroundColor = [UIColor colorWithWhite:1 alpha:0.95]; 339 | textColor = [UIColor blackColor]; 340 | } else { 341 | backgroundColor = [UIColor colorWithWhite:0 alpha:.75]; 342 | textColor = [UIColor whiteColor]; 343 | } 344 | 345 | self.backgroundColor = backgroundColor; 346 | self.titleLabel.textColor = textColor; 347 | self.messageLabel.textColor = textColor; 348 | } 349 | 350 | - (void)setTopContentMargin:(CGFloat)topContentMargin 351 | { 352 | _topContentMargin = topContentMargin; 353 | [self setNeedsLayout]; 354 | } 355 | 356 | - (void)setBottomContentMargin:(CGFloat)bottomContentMargin 357 | { 358 | _bottomContentMargin = bottomContentMargin; 359 | [self setNeedsLayout]; 360 | } 361 | 362 | #pragma mark - Cleanup 363 | 364 | - (void)dealloc 365 | { 366 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 367 | 368 | [self removeGestureRecognizer:self.dismissTap]; 369 | } 370 | 371 | @end 372 | -------------------------------------------------------------------------------- /CustomImagePicker/PhotoCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // PhotoCell.h 3 | // CustomImagePicker 4 | // 5 | // Created by C S P Nanda on 1/5/15. 6 | // Copyright (c) 2015 C S P Nanda. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface PhotoCell : UICollectionViewCell 13 | - (void) setAsset:(ALAsset *)asset; 14 | -(void) performSelectionAnimations; 15 | -(void) hideTick; 16 | -(void) showTick; 17 | @property(nonatomic, strong) ALAsset *asset; 18 | @end -------------------------------------------------------------------------------- /CustomImagePicker/PhotoCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // PhotoCell.m 3 | // CustomImagePicker 4 | // 5 | // Created by C S P Nanda on 1/5/15. 6 | // Copyright (c) 2015 C S P Nanda. All rights reserved. 7 | // 8 | 9 | #import "PhotoCell.h" 10 | 11 | @interface PhotoCell () 12 | // 1 13 | @property(nonatomic, weak) IBOutlet UIImageView *photoImageView; 14 | @property(nonatomic, weak) IBOutlet UIImageView *tickView; 15 | 16 | @end 17 | 18 | @implementation PhotoCell 19 | 20 | - (id)initWithFrame:(CGRect)frame { 21 | 22 | self = [super initWithFrame:frame]; 23 | 24 | if (self) { 25 | // Initialization code 26 | NSArray *arrayOfViews = [[NSBundle mainBundle] loadNibNamed:@"PhotoCell" owner:self options:nil]; 27 | 28 | if ([arrayOfViews count] < 1) { 29 | return nil; 30 | } 31 | 32 | if (![[arrayOfViews objectAtIndex:0] isKindOfClass:[UICollectionViewCell class]]) { 33 | return nil; 34 | } 35 | 36 | self = [arrayOfViews objectAtIndex:0]; 37 | 38 | } 39 | 40 | return self; 41 | 42 | } 43 | 44 | -(void) showTick 45 | { 46 | [self.tickView setHidden:NO]; 47 | } 48 | -(void) hideTick 49 | { 50 | [self.tickView setHidden:YES]; 51 | } 52 | - (void) setAsset:(ALAsset *)asset 53 | { 54 | // 2 55 | _asset = asset; 56 | self.photoImageView.image = [UIImage imageWithCGImage:[asset thumbnail]]; 57 | } 58 | @end -------------------------------------------------------------------------------- /CustomImagePicker/PhotoCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /CustomImagePicker/PhotoPickerCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // PhotoCell.h 3 | // CustomImagePicker 4 | // 5 | // Created by Prasanna Nanda on 1/5/15. 6 | // Copyright (c) 2015 Prasanna Nanda. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "Header.h" 12 | 13 | @interface PhotoPickerCell : UICollectionViewCell 14 | - (void) setAsset:(ALAsset *)asset; 15 | - (void) setImage:(UIImage *)image; 16 | - (UIImageView*) getImageView; 17 | -(void) performSelectionAnimations; 18 | -(void) hideTick; 19 | -(void) showTick; 20 | @property(nonatomic, strong) ALAsset *asset; 21 | @end -------------------------------------------------------------------------------- /CustomImagePicker/PhotoPickerCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // PhotoCell.m 3 | // CustomImagePicker 4 | // 5 | // Created by Prasanna Nanda on 1/5/15. 6 | // Copyright (c) 2015 Prasanna Nanda. All rights reserved. 7 | // 8 | 9 | #import "PhotoPickerCell.h" 10 | 11 | @interface PhotoPickerCell () 12 | // 1 13 | @property(nonatomic, weak) IBOutlet UIImageView *photoImageView; 14 | @property(nonatomic, weak) IBOutlet UIImageView *tickView; 15 | 16 | @end 17 | 18 | @implementation PhotoPickerCell 19 | - (UIImageView*) getImageView; 20 | { 21 | return self.photoImageView; 22 | } 23 | - (id)initWithFrame:(CGRect)frame { 24 | 25 | self = [super initWithFrame:frame]; 26 | 27 | if (self) { 28 | // Initialization code 29 | NSArray *arrayOfViews = Nil; 30 | if(IS_IPHONE_6||IS_IPHONE_6P) 31 | arrayOfViews = [[NSBundle mainBundle] loadNibNamed:@"PhotoPickerCell" owner:self options:nil]; 32 | else 33 | arrayOfViews = [[NSBundle mainBundle] loadNibNamed:@"PhotoPickerCell_5" owner:self options:nil]; 34 | 35 | 36 | if ([arrayOfViews count] < 1) { 37 | return nil; 38 | } 39 | 40 | if (![[arrayOfViews objectAtIndex:0] isKindOfClass:[UICollectionViewCell class]]) { 41 | return nil; 42 | } 43 | 44 | self = [arrayOfViews objectAtIndex:0]; 45 | 46 | } 47 | 48 | return self; 49 | 50 | } 51 | 52 | -(void) showTick 53 | { 54 | [self.tickView setHidden:NO]; 55 | } 56 | -(void) hideTick 57 | { 58 | [self.tickView setHidden:YES]; 59 | } 60 | - (void) setAsset:(ALAsset *)asset 61 | { 62 | // 2 63 | _asset = asset; 64 | self.photoImageView.image = [UIImage imageWithCGImage:[asset thumbnail]]; 65 | } 66 | - (void) setImage:(UIImage *)image 67 | { 68 | [self.photoImageView setImage:image]; 69 | } 70 | @end -------------------------------------------------------------------------------- /CustomImagePicker/PhotoPickerCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /CustomImagePicker/PhotoPickerCell_5.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /CustomImagePicker/RNActivityView.h: -------------------------------------------------------------------------------- 1 | // 2 | // RNActivityView.h 3 | // Created by Romilson Nunes 4 | // 5 | 6 | #import 7 | #import 8 | #import 9 | 10 | @protocol RNActivityViewDelegate; 11 | 12 | 13 | typedef enum { 14 | /** Progress is shown using an UIActivityIndicatorView. This is the default. */ 15 | RNActivityViewModeIndeterminate, 16 | /** Progress is shown using a round, pie-chart like, progress view. */ 17 | RNActivityViewModeDeterminate, 18 | /** Progress is shown using a horizontal progress bar */ 19 | RNActivityViewModeDeterminateHorizontalBar, 20 | /** Progress is shown using a ring-shaped progress view. */ 21 | RNActivityViewModeAnnularDeterminate, 22 | /** Shows a custom view */ 23 | RNActivityViewModeCustomView, 24 | /** Shows only labels */ 25 | RNActivityViewModeText 26 | } RNActivityViewMode; 27 | 28 | typedef enum { 29 | /** Opacity animation */ 30 | RNActivityViewAnimationFade, 31 | /** Opacity + scale animation */ 32 | RNActivityViewAnimationZoom, 33 | RNActivityViewAnimationZoomOut = RNActivityViewAnimationZoom, 34 | RNActivityViewAnimationZoomIn 35 | } RNActivityViewAnimation; 36 | 37 | 38 | #ifndef rn_instancetype 39 | #if __has_feature(objc_instancetype) 40 | #define rn_instancetype instancetype 41 | #else 42 | #define rn_instancetype id 43 | #endif 44 | #endif 45 | 46 | typedef void (^RNActivityViewCompletionBlock)(); 47 | 48 | @interface RNActivityView : UIView 49 | 50 | + (rn_instancetype)showHUDAddedTo:(UIView *)view animated:(BOOL)animated; 51 | 52 | + (BOOL)hideHUDForView:(UIView *)view animated:(BOOL)animated; 53 | 54 | + (NSUInteger)hideAllHUDsForView:(UIView *)view animated:(BOOL)animated; 55 | 56 | + (rn_instancetype)HUDForView:(UIView *)view; 57 | 58 | + (NSArray *)allHUDsForView:(UIView *)view; 59 | 60 | - (id)initWithWindow:(UIWindow *)window; 61 | - (id)initWithView:(UIView *)view; 62 | 63 | - (void)show:(BOOL)animated; 64 | - (void)showWhileExecuting:(SEL)method onTarget:(id)target withObject:(id)object animated:(BOOL)animated; 65 | - (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block; 66 | - (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block completionBlock:(RNActivityViewCompletionBlock)completion; 67 | - (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block onQueue:(dispatch_queue_t)queue; 68 | - (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block onQueue:(dispatch_queue_t)queue 69 | completionBlock:(RNActivityViewCompletionBlock)completion; 70 | 71 | - (void)hide:(BOOL)animated; 72 | - (void)hide:(BOOL)animated afterDelay:(NSTimeInterval)delay; 73 | 74 | - (void) setupDefaultValues; 75 | 76 | @property (copy) RNActivityViewCompletionBlock completionBlock; 77 | @property (assign) RNActivityViewMode mode; // default is RNActivityViewModeIndeterminate. 78 | @property (assign) RNActivityViewAnimation animationType; 79 | @property (strong) UIView *customView; 80 | @property (weak) id delegate; 81 | @property (copy) NSString *labelText; // then no message is displayed. 82 | @property (copy) NSString *detailsLabelText; 83 | @property (assign) float opacity; // Defaults to 0.8 (80% opacity) 84 | @property (strong) UIColor *color; 85 | 86 | /** 87 | * The x-axis offset of the HUD relative to the centre of the superview. 88 | */ 89 | @property (assign) float xOffset; 90 | 91 | /** 92 | * The y-axis offset of the HUD relative to the centre of the superview. 93 | */ 94 | @property (assign) float yOffset; 95 | 96 | @property (assign) float margin; // Defaults to 20.0 97 | @property (assign) float cornerRadius; // Defaults to 10.0 98 | @property (assign) BOOL dimBackground; // Cover the HUD background view with a radial gradient 99 | 100 | /* 101 | * Grace period is the time (in seconds) that the invoked method may be run without 102 | * showing the HUD. If the task finishes before the grace time runs out, the HUD will 103 | * not be shown at all. 104 | * This may be used to prevent HUD display for very short tasks. 105 | * Defaults to 0 (no grace time). 106 | * Grace time functionality is only supported when the task status is known! 107 | * @see taskInProgress 108 | */ 109 | @property (assign) float graceTime; 110 | 111 | // The minimum time (in seconds) that the HUD is shown. 112 | // Defaults 0 (no minimum show time). 113 | @property (assign) float minShowTime; 114 | 115 | @property (assign) BOOL taskInProgress; 116 | 117 | @property (assign) BOOL removeFromSuperViewOnHide; // Defaults NO 118 | 119 | @property (strong) UIFont* labelFont; 120 | @property (strong) UIColor* labelColor; 121 | @property (strong) UIFont* detailsLabelFont; 122 | @property (strong) UIColor* detailsLabelColor; 123 | 124 | @property (assign) float progress; // 0.0 to 1.0 125 | @property (assign) CGSize minSize; // Defaults to CGSizeZero (no minimum size) 126 | @property (assign, getter = isSquare) BOOL square; 127 | 128 | @end 129 | 130 | /* 131 | Protocol 132 | */ 133 | @protocol RNActivityViewDelegate 134 | @optional 135 | - (void)hudWasHidden:(RNActivityView *)hud; 136 | @end 137 | 138 | 139 | /** 140 | * A progress view for showing definite progress by filling up a circle (pie chart). 141 | */ 142 | @interface RNRoundProgressView : UIView 143 | 144 | @property (nonatomic, assign) float progress; // Progress (0.0 to 1.0) 145 | @property (nonatomic, strong) UIColor *progressTintColor; // Defaults White 146 | @property (nonatomic, strong) UIColor *backgroundTintColor; // Defaults to translucent white (alpha 0.1) 147 | @property (nonatomic, assign, getter = isAnnular) BOOL annular; // Display mode - NO = round or YES = annular. Defaults to round. 148 | 149 | @end 150 | 151 | 152 | /** 153 | * A flat bar progress view. 154 | */ 155 | @interface RNBarProgressView : UIView 156 | 157 | @property (nonatomic, assign) float progress; // Progress (0.0 to 1.0) 158 | @property (nonatomic, strong) UIColor *lineColor; // Defaults to white 159 | @property (nonatomic, strong) UIColor *progressRemainingColor; // Defaults to clear 160 | @property (nonatomic, strong) UIColor *progressColor; // Defaults to white 161 | 162 | @end 163 | -------------------------------------------------------------------------------- /CustomImagePicker/RNActivityView.m: -------------------------------------------------------------------------------- 1 | // 2 | // RNActivityView.m 3 | // Created by Romilson Nunes 4 | // 5 | 6 | #import "RNActivityView.h" 7 | #import 8 | 9 | 10 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 60000 11 | #define RNLabelAlignmentCenter NSTextAlignmentCenter 12 | #else 13 | #define RNLabelAlignmentCenter UITextAlignmentCenter 14 | #endif 15 | 16 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 17 | #define MB_TEXTSIZE(text, font) [text length] > 0 ? [text \ 18 | sizeWithAttributes:@{NSFontAttributeName:font}] : CGSizeZero; 19 | #else 20 | #define MB_TEXTSIZE(text, font) [text length] > 0 ? [text sizeWithFont:font] : CGSizeZero; 21 | #endif 22 | 23 | #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 70000 24 | #define MB_MULTILINE_TEXTSIZE(text, font, maxSize, mode) [text length] > 0 ? [text \ 25 | boundingRectWithSize:maxSize options:(NSStringDrawingUsesLineFragmentOrigin) \ 26 | attributes:@{NSFontAttributeName:font} context:nil].size : CGSizeZero; 27 | #else 28 | #define MB_MULTILINE_TEXTSIZE(text, font, maxSize, mode) [text length] > 0 ? [text \ 29 | sizeWithFont:font constrainedToSize:maxSize lineBreakMode:mode] : CGSizeZero; 30 | #endif 31 | 32 | 33 | static const CGFloat kPadding = 4.f; 34 | static const CGFloat kLabelFontSize = 16.f; 35 | static const CGFloat kDetailsLabelFontSize = 12.f; 36 | 37 | 38 | @interface RNActivityView () 39 | 40 | - (void)setupLabels; 41 | - (void)registerForKVO; 42 | - (void)unregisterFromKVO; 43 | - (NSArray *)observableKeypaths; 44 | - (void)registerForNotifications; 45 | - (void)unregisterFromNotifications; 46 | - (void)updateUIForKeypath:(NSString *)keyPath; 47 | - (void)hideUsingAnimation:(BOOL)animated; 48 | - (void)showUsingAnimation:(BOOL)animated; 49 | - (void)done; 50 | - (void)updateIndicators; 51 | - (void)handleGraceTimer:(NSTimer *)theTimer; 52 | - (void)handleMinShowTimer:(NSTimer *)theTimer; 53 | - (void)setTransformForCurrentOrientation:(BOOL)animated; 54 | - (void)cleanUp; 55 | - (void)launchExecution; 56 | - (void)deviceOrientationDidChange:(NSNotification *)notification; 57 | - (void)hideDelayed:(NSNumber *)animated; 58 | 59 | @property (atomic, strong) UIView *indicator; 60 | @property (atomic, strong) NSTimer *graceTimer; 61 | @property (atomic, strong) NSTimer *minShowTimer; 62 | @property (atomic, strong) NSDate *showStarted; 63 | @property (atomic, assign) CGSize size; 64 | 65 | @end 66 | 67 | 68 | @implementation RNActivityView { 69 | BOOL useAnimation; 70 | SEL methodForExecution; 71 | id targetForExecution; 72 | id objectForExecution; 73 | UILabel *label; 74 | UILabel *detailsLabel; 75 | BOOL isFinished; 76 | CGAffineTransform rotationTransform; 77 | } 78 | 79 | #pragma mark - Properties 80 | 81 | @synthesize animationType; 82 | @synthesize delegate; 83 | @synthesize opacity; 84 | @synthesize color; 85 | @synthesize labelFont; 86 | @synthesize labelColor; 87 | @synthesize detailsLabelFont; 88 | @synthesize detailsLabelColor; 89 | @synthesize indicator; 90 | @synthesize xOffset; 91 | @synthesize yOffset; 92 | @synthesize minSize; 93 | @synthesize square; 94 | @synthesize margin; 95 | @synthesize dimBackground; 96 | @synthesize graceTime; 97 | @synthesize minShowTime; 98 | @synthesize graceTimer; 99 | @synthesize minShowTimer; 100 | @synthesize taskInProgress; 101 | @synthesize removeFromSuperViewOnHide; 102 | @synthesize customView; 103 | @synthesize showStarted; 104 | @synthesize mode; 105 | @synthesize labelText; 106 | @synthesize detailsLabelText; 107 | @synthesize progress; 108 | @synthesize size; 109 | @synthesize completionBlock; 110 | 111 | #pragma mark - Class methods 112 | 113 | + (rn_instancetype)showHUDAddedTo:(UIView *)view animated:(BOOL)animated { 114 | RNActivityView *hud = [[self alloc] initWithView:view]; 115 | [view addSubview:hud]; 116 | [hud show:animated]; 117 | return hud; 118 | } 119 | 120 | + (BOOL)hideHUDForView:(UIView *)view animated:(BOOL)animated { 121 | RNActivityView *hud = [self HUDForView:view]; 122 | if (hud != nil) { 123 | hud.removeFromSuperViewOnHide = YES; 124 | [hud hide:animated]; 125 | return YES; 126 | } 127 | return NO; 128 | } 129 | 130 | + (NSUInteger)hideAllHUDsForView:(UIView *)view animated:(BOOL)animated { 131 | NSArray *huds = [RNActivityView allHUDsForView:view]; 132 | for (RNActivityView *hud in huds) { 133 | hud.removeFromSuperViewOnHide = YES; 134 | [hud hide:animated]; 135 | } 136 | return [huds count]; 137 | } 138 | 139 | + (rn_instancetype)HUDForView:(UIView *)view { 140 | NSEnumerator *subviewsEnum = [view.subviews reverseObjectEnumerator]; 141 | for (UIView *subview in subviewsEnum) { 142 | if ([subview isKindOfClass:self]) { 143 | return (RNActivityView *)subview; 144 | } 145 | } 146 | return nil; 147 | } 148 | 149 | + (NSArray *)allHUDsForView:(UIView *)view { 150 | NSMutableArray *huds = [NSMutableArray array]; 151 | NSArray *subviews = view.subviews; 152 | for (UIView *aView in subviews) { 153 | if ([aView isKindOfClass:self]) { 154 | [huds addObject:aView]; 155 | } 156 | } 157 | return [NSArray arrayWithArray:huds]; 158 | } 159 | 160 | #pragma mark - Setup 161 | 162 | - (void) setupDefaultValues { 163 | // Set default values for properties 164 | self.animationType = RNActivityViewAnimationFade; 165 | self.mode = RNActivityViewModeIndeterminate; 166 | self.labelText = nil; 167 | self.detailsLabelText = nil; 168 | self.opacity = 0.8f; 169 | self.color = nil; 170 | self.labelFont = [UIFont boldSystemFontOfSize:kLabelFontSize]; 171 | self.labelColor = [UIColor whiteColor]; 172 | self.detailsLabelFont = [UIFont boldSystemFontOfSize:kDetailsLabelFontSize]; 173 | self.detailsLabelColor = [UIColor whiteColor]; 174 | self.xOffset = 0.0f; 175 | self.yOffset = 0.0f; 176 | self.dimBackground = NO; 177 | self.margin = 20.0f; 178 | self.cornerRadius = 10.0f; 179 | self.graceTime = 0.0f; 180 | self.minShowTime = 0.0f; 181 | self.removeFromSuperViewOnHide = NO; 182 | self.minSize = CGSizeZero; 183 | self.square = NO; 184 | 185 | 186 | // Transparent background 187 | self.opaque = NO; 188 | self.backgroundColor = [UIColor clearColor]; 189 | // Make it invisible for now 190 | self.alpha = 0.0f; 191 | 192 | taskInProgress = NO; 193 | rotationTransform = CGAffineTransformIdentity; 194 | 195 | methodForExecution = nil; 196 | targetForExecution = nil; 197 | objectForExecution = nil; 198 | } 199 | 200 | #pragma mark - Lifecycle 201 | 202 | - (id)initWithFrame:(CGRect)frame { 203 | self = [super initWithFrame:frame]; 204 | if (self) { 205 | // Set default values for properties 206 | [self setupDefaultValues]; 207 | self.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin 208 | | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; 209 | 210 | [self setupLabels]; 211 | [self updateIndicators]; 212 | [self registerForKVO]; 213 | [self registerForNotifications]; 214 | } 215 | return self; 216 | } 217 | 218 | - (id)initWithView:(UIView *)view { 219 | NSAssert(view, @"View must not be nil."); 220 | return [self initWithFrame:view.bounds]; 221 | } 222 | 223 | - (id)initWithWindow:(UIWindow *)window { 224 | return [self initWithView:window]; 225 | } 226 | 227 | - (void)dealloc { 228 | [self unregisterFromNotifications]; 229 | [self unregisterFromKVO]; 230 | } 231 | 232 | #pragma mark - Show & hide 233 | 234 | - (void)show:(BOOL)animated { 235 | useAnimation = animated; 236 | // If the grace time is set postpone the HUD display 237 | if (self.graceTime > 0.0) { 238 | self.graceTimer = [NSTimer scheduledTimerWithTimeInterval:self.graceTime target:self 239 | selector:@selector(handleGraceTimer:) userInfo:nil repeats:NO]; 240 | } 241 | // ... otherwise show the HUD imediately 242 | else { 243 | [self setNeedsDisplay]; 244 | [self showUsingAnimation:useAnimation]; 245 | } 246 | } 247 | 248 | - (void)hide:(BOOL)animated { 249 | useAnimation = animated; 250 | // If the minShow time is set, calculate how long the hud was shown, 251 | // and pospone the hiding operation if necessary 252 | if (self.minShowTime > 0.0 && showStarted) { 253 | NSTimeInterval interv = [[NSDate date] timeIntervalSinceDate:showStarted]; 254 | if (interv < self.minShowTime) { 255 | self.minShowTimer = [NSTimer scheduledTimerWithTimeInterval:(self.minShowTime - interv) target:self 256 | selector:@selector(handleMinShowTimer:) userInfo:nil repeats:NO]; 257 | return; 258 | } 259 | } 260 | // ... otherwise hide the HUD immediately 261 | [self hideUsingAnimation:useAnimation]; 262 | } 263 | 264 | - (void)hide:(BOOL)animated afterDelay:(NSTimeInterval)delay { 265 | [self performSelector:@selector(hideDelayed:) withObject:[NSNumber numberWithBool:animated] afterDelay:delay]; 266 | } 267 | 268 | - (void)hideDelayed:(NSNumber *)animated { 269 | [self hide:[animated boolValue]]; 270 | } 271 | 272 | #pragma mark - Timer callbacks 273 | 274 | - (void)handleGraceTimer:(NSTimer *)theTimer { 275 | // Show the HUD only if the task is still running 276 | if (taskInProgress) { 277 | [self setNeedsDisplay]; 278 | [self showUsingAnimation:useAnimation]; 279 | } 280 | } 281 | 282 | - (void)handleMinShowTimer:(NSTimer *)theTimer { 283 | [self hideUsingAnimation:useAnimation]; 284 | } 285 | 286 | #pragma mark - View Hierrarchy 287 | 288 | - (void)didMoveToSuperview { 289 | // We need to take care of rotation ourselfs if we're adding the HUD to a window 290 | if ([self.superview isKindOfClass:[UIWindow class]]) { 291 | [self setTransformForCurrentOrientation:NO]; 292 | } 293 | } 294 | 295 | #pragma mark - Internal show & hide operations 296 | 297 | - (void)showUsingAnimation:(BOOL)animated { 298 | if (animated && animationType == RNActivityViewAnimationZoomIn) { 299 | self.transform = CGAffineTransformConcat(rotationTransform, CGAffineTransformMakeScale(0.5f, 0.5f)); 300 | } else if (animated && animationType == RNActivityViewAnimationZoomOut) { 301 | self.transform = CGAffineTransformConcat(rotationTransform, CGAffineTransformMakeScale(1.5f, 1.5f)); 302 | } 303 | self.showStarted = [NSDate date]; 304 | // Fade in 305 | if (animated) { 306 | [UIView beginAnimations:nil context:NULL]; 307 | [UIView setAnimationDuration:0.30]; 308 | self.alpha = 1.0f; 309 | if (animationType == RNActivityViewAnimationZoomIn || animationType == RNActivityViewAnimationZoomOut) { 310 | self.transform = rotationTransform; 311 | } 312 | [UIView commitAnimations]; 313 | } 314 | else { 315 | self.alpha = 1.0f; 316 | } 317 | } 318 | 319 | - (void)hideUsingAnimation:(BOOL)animated { 320 | // Fade out 321 | if (animated && showStarted) { 322 | [UIView beginAnimations:nil context:NULL]; 323 | [UIView setAnimationDuration:0.30]; 324 | [UIView setAnimationDelegate:self]; 325 | [UIView setAnimationDidStopSelector:@selector(animationFinished:finished:context:)]; 326 | // 0.02 prevents the hud from passing through touches during the animation the hud will get completely hidden 327 | // in the done method 328 | if (animationType == RNActivityViewAnimationZoomIn) { 329 | self.transform = CGAffineTransformConcat(rotationTransform, CGAffineTransformMakeScale(1.5f, 1.5f)); 330 | } else if (animationType == RNActivityViewAnimationZoomOut) { 331 | self.transform = CGAffineTransformConcat(rotationTransform, CGAffineTransformMakeScale(0.5f, 0.5f)); 332 | } 333 | 334 | self.alpha = 0.02f; 335 | [UIView commitAnimations]; 336 | } 337 | else { 338 | self.alpha = 0.0f; 339 | [self done]; 340 | } 341 | self.showStarted = nil; 342 | } 343 | 344 | - (void)animationFinished:(NSString *)animationID finished:(BOOL)finished context:(void*)context { 345 | [self done]; 346 | } 347 | 348 | - (void)done { 349 | [NSObject cancelPreviousPerformRequestsWithTarget:self]; 350 | isFinished = YES; 351 | self.alpha = 0.0f; 352 | if (removeFromSuperViewOnHide) { 353 | [self removeFromSuperview]; 354 | } 355 | if (self.completionBlock) { 356 | self.completionBlock(); 357 | self.completionBlock = NULL; 358 | } 359 | if ([delegate respondsToSelector:@selector(hudWasHidden:)]) { 360 | [delegate performSelector:@selector(hudWasHidden:) withObject:self]; 361 | } 362 | } 363 | 364 | #pragma mark - Threading 365 | 366 | - (void)showWhileExecuting:(SEL)method onTarget:(id)target withObject:(id)object animated:(BOOL)animated { 367 | methodForExecution = method; 368 | targetForExecution = target; 369 | objectForExecution = object; 370 | // Launch execution in new thread 371 | self.taskInProgress = YES; 372 | [NSThread detachNewThreadSelector:@selector(launchExecution) toTarget:self withObject:nil]; 373 | // Show HUD view 374 | [self show:animated]; 375 | } 376 | 377 | 378 | - (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block { 379 | dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 380 | [self showAnimated:animated whileExecutingBlock:block onQueue:queue completionBlock:NULL]; 381 | } 382 | 383 | - (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block completionBlock:(void (^)())completion { 384 | dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 385 | [self showAnimated:animated whileExecutingBlock:block onQueue:queue completionBlock:completion]; 386 | } 387 | 388 | - (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block onQueue:(dispatch_queue_t)queue { 389 | [self showAnimated:animated whileExecutingBlock:block onQueue:queue completionBlock:NULL]; 390 | } 391 | 392 | - (void)showAnimated:(BOOL)animated whileExecutingBlock:(dispatch_block_t)block onQueue:(dispatch_queue_t)queue 393 | completionBlock:(RNActivityViewCompletionBlock)completion { 394 | self.taskInProgress = YES; 395 | self.completionBlock = completion; 396 | dispatch_async(queue, ^(void) { 397 | block(); 398 | dispatch_async(dispatch_get_main_queue(), ^(void) { 399 | [self cleanUp]; 400 | }); 401 | }); 402 | [self show:animated]; 403 | } 404 | 405 | 406 | - (void)launchExecution { 407 | @autoreleasepool { 408 | #pragma clang diagnostic push 409 | #pragma clang diagnostic ignored "-Warc-performSelector-leaks" 410 | // Start executing the requested task 411 | [targetForExecution performSelector:methodForExecution withObject:objectForExecution]; 412 | #pragma clang diagnostic pop 413 | // Task completed, update view in main thread (note: view operations should 414 | // be done only in the main thread) 415 | [self performSelectorOnMainThread:@selector(cleanUp) withObject:nil waitUntilDone:NO]; 416 | } 417 | } 418 | 419 | - (void)cleanUp { 420 | taskInProgress = NO; 421 | targetForExecution = nil; 422 | objectForExecution = nil; 423 | [self hide:useAnimation]; 424 | } 425 | 426 | #pragma mark - UI 427 | 428 | - (void)setupLabels { 429 | label = [[UILabel alloc] initWithFrame:self.bounds]; 430 | label.adjustsFontSizeToFitWidth = NO; 431 | label.textAlignment = RNLabelAlignmentCenter; 432 | label.opaque = NO; 433 | label.backgroundColor = [UIColor clearColor]; 434 | label.textColor = self.labelColor; 435 | label.font = self.labelFont; 436 | label.text = self.labelText; 437 | [self addSubview:label]; 438 | 439 | detailsLabel = [[UILabel alloc] initWithFrame:self.bounds]; 440 | detailsLabel.font = self.detailsLabelFont; 441 | detailsLabel.adjustsFontSizeToFitWidth = NO; 442 | detailsLabel.textAlignment = RNLabelAlignmentCenter; 443 | detailsLabel.opaque = NO; 444 | detailsLabel.backgroundColor = [UIColor clearColor]; 445 | detailsLabel.textColor = self.detailsLabelColor; 446 | detailsLabel.numberOfLines = 0; 447 | detailsLabel.font = self.detailsLabelFont; 448 | detailsLabel.text = self.detailsLabelText; 449 | [self addSubview:detailsLabel]; 450 | } 451 | 452 | - (void)updateIndicators { 453 | 454 | BOOL isActivityIndicator = [indicator isKindOfClass:[UIActivityIndicatorView class]]; 455 | BOOL isRoundIndicator = [indicator isKindOfClass:[RNRoundProgressView class]]; 456 | 457 | if (mode == RNActivityViewModeIndeterminate && !isActivityIndicator) { 458 | // Update to indeterminate indicator 459 | [indicator removeFromSuperview]; 460 | self.indicator = [[UIActivityIndicatorView alloc] 461 | initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; 462 | [(UIActivityIndicatorView *)indicator startAnimating]; 463 | [self addSubview:indicator]; 464 | } 465 | else if (mode == RNActivityViewModeDeterminateHorizontalBar) { 466 | // Update to bar determinate indicator 467 | [indicator removeFromSuperview]; 468 | self.indicator = [[RNBarProgressView alloc] init]; 469 | [self addSubview:indicator]; 470 | } 471 | else if (mode == RNActivityViewModeDeterminate || mode == RNActivityViewModeAnnularDeterminate) { 472 | if (!isRoundIndicator) { 473 | // Update to determinante indicator 474 | [indicator removeFromSuperview]; 475 | self.indicator = [[RNRoundProgressView alloc] init]; 476 | [self addSubview:indicator]; 477 | } 478 | if (mode == RNActivityViewModeAnnularDeterminate) { 479 | [(RNRoundProgressView *)indicator setAnnular:YES]; 480 | } 481 | } 482 | else if (mode == RNActivityViewModeCustomView && customView != indicator) { 483 | // Update custom view indicator 484 | [indicator removeFromSuperview]; 485 | self.indicator = customView; 486 | [self addSubview:indicator]; 487 | } else if (mode == RNActivityViewModeText) { 488 | [indicator removeFromSuperview]; 489 | self.indicator = nil; 490 | } 491 | } 492 | 493 | #pragma mark - Layout 494 | 495 | - (void)layoutSubviews { 496 | 497 | // Entirely cover the parent view 498 | UIView *parent = self.superview; 499 | if (parent) { 500 | self.frame = parent.bounds; 501 | } 502 | CGRect bounds = self.bounds; 503 | 504 | // Determine the total widt and height needed 505 | CGFloat maxWidth = bounds.size.width - 4 * margin; 506 | CGSize totalSize = CGSizeZero; 507 | 508 | CGRect indicatorF = indicator.bounds; 509 | indicatorF.size.width = MIN(indicatorF.size.width, maxWidth); 510 | totalSize.width = MAX(totalSize.width, indicatorF.size.width); 511 | totalSize.height += indicatorF.size.height; 512 | 513 | CGSize labelSize = MB_TEXTSIZE(label.text, label.font); 514 | labelSize.width = MIN(labelSize.width, maxWidth); 515 | totalSize.width = MAX(totalSize.width, labelSize.width); 516 | totalSize.height += labelSize.height; 517 | if (labelSize.height > 0.f && indicatorF.size.height > 0.f) { 518 | totalSize.height += kPadding; 519 | } 520 | 521 | CGFloat remainingHeight = bounds.size.height - totalSize.height - kPadding - 4 * margin; 522 | CGSize maxSize = CGSizeMake(maxWidth, remainingHeight); 523 | CGSize detailsLabelSize = MB_MULTILINE_TEXTSIZE(detailsLabel.text, detailsLabel.font, maxSize, detailsLabel.lineBreakMode); 524 | totalSize.width = MAX(totalSize.width, detailsLabelSize.width); 525 | totalSize.height += detailsLabelSize.height; 526 | if (detailsLabelSize.height > 0.f && (indicatorF.size.height > 0.f || labelSize.height > 0.f)) { 527 | totalSize.height += kPadding; 528 | } 529 | 530 | totalSize.width += 2 * margin; 531 | totalSize.height += 2 * margin; 532 | 533 | // Position elements 534 | CGFloat yPos = round(((bounds.size.height - totalSize.height) / 2)) + margin + yOffset; 535 | CGFloat xPos = xOffset; 536 | indicatorF.origin.y = yPos; 537 | indicatorF.origin.x = round((bounds.size.width - indicatorF.size.width) / 2) + xPos; 538 | indicator.frame = indicatorF; 539 | yPos += indicatorF.size.height; 540 | 541 | if (labelSize.height > 0.f && indicatorF.size.height > 0.f) { 542 | yPos += kPadding; 543 | } 544 | CGRect labelF; 545 | labelF.origin.y = yPos; 546 | labelF.origin.x = round((bounds.size.width - labelSize.width) / 2) + xPos; 547 | labelF.size = labelSize; 548 | label.frame = labelF; 549 | yPos += labelF.size.height; 550 | 551 | if (detailsLabelSize.height > 0.f && (indicatorF.size.height > 0.f || labelSize.height > 0.f)) { 552 | yPos += kPadding; 553 | } 554 | CGRect detailsLabelF; 555 | detailsLabelF.origin.y = yPos; 556 | detailsLabelF.origin.x = round((bounds.size.width - detailsLabelSize.width) / 2) + xPos; 557 | detailsLabelF.size = detailsLabelSize; 558 | detailsLabel.frame = detailsLabelF; 559 | 560 | // Enforce minsize and quare rules 561 | if (square) { 562 | CGFloat max = MAX(totalSize.width, totalSize.height); 563 | if (max <= bounds.size.width - 2 * margin) { 564 | totalSize.width = max; 565 | } 566 | if (max <= bounds.size.height - 2 * margin) { 567 | totalSize.height = max; 568 | } 569 | } 570 | if (totalSize.width < minSize.width) { 571 | totalSize.width = minSize.width; 572 | } 573 | if (totalSize.height < minSize.height) { 574 | totalSize.height = minSize.height; 575 | } 576 | 577 | self.size = totalSize; 578 | } 579 | 580 | #pragma mark BG Drawing 581 | 582 | - (void)drawRect:(CGRect)rect { 583 | 584 | CGContextRef context = UIGraphicsGetCurrentContext(); 585 | UIGraphicsPushContext(context); 586 | 587 | if (self.dimBackground) { 588 | //Gradient colours 589 | size_t gradLocationsNum = 2; 590 | CGFloat gradLocations[2] = {0.0f, 1.0f}; 591 | CGFloat gradColors[8] = {0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.75f}; 592 | CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 593 | CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, gradColors, gradLocations, gradLocationsNum); 594 | CGColorSpaceRelease(colorSpace); 595 | //Gradient center 596 | CGPoint gradCenter= CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2); 597 | //Gradient radius 598 | float gradRadius = MIN(self.bounds.size.width , self.bounds.size.height) ; 599 | //Gradient draw 600 | CGContextDrawRadialGradient (context, gradient, gradCenter, 601 | 0, gradCenter, gradRadius, 602 | kCGGradientDrawsAfterEndLocation); 603 | CGGradientRelease(gradient); 604 | } 605 | 606 | // Set background rect color 607 | if (self.color) { 608 | CGContextSetFillColorWithColor(context, self.color.CGColor); 609 | } else { 610 | CGContextSetGrayFillColor(context, 0.0f, self.opacity); 611 | } 612 | 613 | 614 | // Center HUD 615 | CGRect allRect = self.bounds; 616 | // Draw rounded HUD backgroud rect 617 | CGRect boxRect = CGRectMake(round((allRect.size.width - size.width) / 2) + self.xOffset, 618 | round((allRect.size.height - size.height) / 2) + self.yOffset, size.width, size.height); 619 | float radius = self.cornerRadius; 620 | CGContextBeginPath(context); 621 | CGContextMoveToPoint(context, CGRectGetMinX(boxRect) + radius, CGRectGetMinY(boxRect)); 622 | CGContextAddArc(context, CGRectGetMaxX(boxRect) - radius, CGRectGetMinY(boxRect) + radius, radius, 3 * (float)M_PI / 2, 0, 0); 623 | CGContextAddArc(context, CGRectGetMaxX(boxRect) - radius, CGRectGetMaxY(boxRect) - radius, radius, 0, (float)M_PI / 2, 0); 624 | CGContextAddArc(context, CGRectGetMinX(boxRect) + radius, CGRectGetMaxY(boxRect) - radius, radius, (float)M_PI / 2, (float)M_PI, 0); 625 | CGContextAddArc(context, CGRectGetMinX(boxRect) + radius, CGRectGetMinY(boxRect) + radius, radius, (float)M_PI, 3 * (float)M_PI / 2, 0); 626 | CGContextClosePath(context); 627 | CGContextFillPath(context); 628 | 629 | UIGraphicsPopContext(); 630 | } 631 | 632 | #pragma mark - KVO 633 | 634 | - (void)registerForKVO { 635 | for (NSString *keyPath in [self observableKeypaths]) { 636 | [self addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionNew context:NULL]; 637 | } 638 | } 639 | 640 | - (void)unregisterFromKVO { 641 | for (NSString *keyPath in [self observableKeypaths]) { 642 | [self removeObserver:self forKeyPath:keyPath]; 643 | } 644 | } 645 | 646 | - (NSArray *)observableKeypaths { 647 | return [NSArray arrayWithObjects:@"mode", @"customView", @"labelText", @"labelFont", @"labelColor", 648 | @"detailsLabelText", @"detailsLabelFont", @"detailsLabelColor", @"progress", nil]; 649 | } 650 | 651 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 652 | if (![NSThread isMainThread]) { 653 | [self performSelectorOnMainThread:@selector(updateUIForKeypath:) withObject:keyPath waitUntilDone:NO]; 654 | } else { 655 | [self updateUIForKeypath:keyPath]; 656 | } 657 | } 658 | 659 | - (void)updateUIForKeypath:(NSString *)keyPath { 660 | if ([keyPath isEqualToString:@"mode"] || [keyPath isEqualToString:@"customView"]) { 661 | [self updateIndicators]; 662 | } else if ([keyPath isEqualToString:@"labelText"]) { 663 | label.text = self.labelText; 664 | } else if ([keyPath isEqualToString:@"labelFont"]) { 665 | label.font = self.labelFont; 666 | } else if ([keyPath isEqualToString:@"labelColor"]) { 667 | label.textColor = self.labelColor; 668 | } else if ([keyPath isEqualToString:@"detailsLabelText"]) { 669 | detailsLabel.text = self.detailsLabelText; 670 | } else if ([keyPath isEqualToString:@"detailsLabelFont"]) { 671 | detailsLabel.font = self.detailsLabelFont; 672 | } else if ([keyPath isEqualToString:@"detailsLabelColor"]) { 673 | detailsLabel.textColor = self.detailsLabelColor; 674 | } else if ([keyPath isEqualToString:@"progress"]) { 675 | if ([indicator respondsToSelector:@selector(setProgress:)]) { 676 | [(id)indicator setValue:@(progress) forKey:@"progress"]; 677 | } 678 | return; 679 | } 680 | [self setNeedsLayout]; 681 | [self setNeedsDisplay]; 682 | } 683 | 684 | #pragma mark - Notifications 685 | 686 | - (void)registerForNotifications { 687 | NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; 688 | [nc addObserver:self selector:@selector(deviceOrientationDidChange:) 689 | name:UIDeviceOrientationDidChangeNotification object:nil]; 690 | } 691 | 692 | - (void)unregisterFromNotifications { 693 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 694 | } 695 | 696 | - (void)deviceOrientationDidChange:(NSNotification *)notification { 697 | UIView *superview = self.superview; 698 | if (!superview) { 699 | return; 700 | } else if ([superview isKindOfClass:[UIWindow class]]) { 701 | [self setTransformForCurrentOrientation:YES]; 702 | } else { 703 | self.frame = self.superview.bounds; 704 | [self setNeedsDisplay]; 705 | } 706 | } 707 | 708 | - (void)setTransformForCurrentOrientation:(BOOL)animated { 709 | // Stay in sync with the superview 710 | if (self.superview) { 711 | self.bounds = self.superview.bounds; 712 | [self setNeedsDisplay]; 713 | } 714 | 715 | UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; 716 | CGFloat radians = 0; 717 | if (UIInterfaceOrientationIsLandscape(orientation)) { 718 | if (orientation == UIInterfaceOrientationLandscapeLeft) { radians = -(CGFloat)M_PI_2; } 719 | else { radians = (CGFloat)M_PI_2; } 720 | // Window coordinates differ! 721 | self.bounds = CGRectMake(0, 0, self.bounds.size.height, self.bounds.size.width); 722 | } else { 723 | if (orientation == UIInterfaceOrientationPortraitUpsideDown) { radians = (CGFloat)M_PI; } 724 | else { radians = 0; } 725 | } 726 | rotationTransform = CGAffineTransformMakeRotation(radians); 727 | 728 | if (animated) { 729 | [UIView beginAnimations:nil context:nil]; 730 | } 731 | [self setTransform:rotationTransform]; 732 | if (animated) { 733 | [UIView commitAnimations]; 734 | } 735 | } 736 | 737 | @end 738 | 739 | 740 | @implementation RNRoundProgressView 741 | 742 | #pragma mark - Lifecycle 743 | 744 | - (id)init { 745 | return [self initWithFrame:CGRectMake(0.f, 0.f, 37.f, 37.f)]; 746 | } 747 | 748 | - (id)initWithFrame:(CGRect)frame { 749 | self = [super initWithFrame:frame]; 750 | if (self) { 751 | self.backgroundColor = [UIColor clearColor]; 752 | self.opaque = NO; 753 | _progress = 0.f; 754 | _annular = NO; 755 | _progressTintColor = [[UIColor alloc] initWithWhite:1.f alpha:1.f]; 756 | _backgroundTintColor = [[UIColor alloc] initWithWhite:1.f alpha:.1f]; 757 | [self registerForKVO]; 758 | } 759 | return self; 760 | } 761 | 762 | - (void)dealloc { 763 | [self unregisterFromKVO]; 764 | } 765 | 766 | #pragma mark - Drawing 767 | 768 | - (void)drawRect:(CGRect)rect { 769 | 770 | CGRect allRect = self.bounds; 771 | CGRect circleRect = CGRectInset(allRect, 2.0f, 2.0f); 772 | CGContextRef context = UIGraphicsGetCurrentContext(); 773 | 774 | if (_annular) { 775 | // Draw background 776 | CGFloat lineWidth = 5.f; 777 | UIBezierPath *processBackgroundPath = [UIBezierPath bezierPath]; 778 | processBackgroundPath.lineWidth = lineWidth; 779 | processBackgroundPath.lineCapStyle = kCGLineCapRound; 780 | CGPoint center = CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2); 781 | CGFloat radius = (self.bounds.size.width - lineWidth)/2; 782 | CGFloat startAngle = - ((float)M_PI / 2); // 90 degrees 783 | CGFloat endAngle = (2 * (float)M_PI) + startAngle; 784 | [processBackgroundPath addArcWithCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES]; 785 | [_backgroundTintColor set]; 786 | [processBackgroundPath stroke]; 787 | // Draw progress 788 | UIBezierPath *processPath = [UIBezierPath bezierPath]; 789 | processPath.lineCapStyle = kCGLineCapRound; 790 | processPath.lineWidth = lineWidth; 791 | endAngle = (self.progress * 2 * (float)M_PI) + startAngle; 792 | [processPath addArcWithCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES]; 793 | [_progressTintColor set]; 794 | [processPath stroke]; 795 | } else { 796 | // Draw background 797 | [_progressTintColor setStroke]; 798 | [_backgroundTintColor setFill]; 799 | CGContextSetLineWidth(context, 2.0f); 800 | CGContextFillEllipseInRect(context, circleRect); 801 | CGContextStrokeEllipseInRect(context, circleRect); 802 | // Draw progress 803 | CGPoint center = CGPointMake(allRect.size.width / 2, allRect.size.height / 2); 804 | CGFloat radius = (allRect.size.width - 4) / 2; 805 | CGFloat startAngle = - ((float)M_PI / 2); // 90 degrees 806 | CGFloat endAngle = (self.progress * 2 * (float)M_PI) + startAngle; 807 | CGContextSetRGBFillColor(context, 1.0f, 1.0f, 1.0f, 1.0f); // white 808 | CGContextMoveToPoint(context, center.x, center.y); 809 | CGContextAddArc(context, center.x, center.y, radius, startAngle, endAngle, 0); 810 | CGContextClosePath(context); 811 | CGContextFillPath(context); 812 | } 813 | } 814 | 815 | #pragma mark - KVO 816 | 817 | - (void)registerForKVO { 818 | for (NSString *keyPath in [self observableKeypaths]) { 819 | [self addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionNew context:NULL]; 820 | } 821 | } 822 | 823 | - (void)unregisterFromKVO { 824 | for (NSString *keyPath in [self observableKeypaths]) { 825 | [self removeObserver:self forKeyPath:keyPath]; 826 | } 827 | } 828 | 829 | - (NSArray *)observableKeypaths { 830 | return [NSArray arrayWithObjects:@"progressTintColor", @"backgroundTintColor", @"progress", @"annular", nil]; 831 | } 832 | 833 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 834 | [self setNeedsDisplay]; 835 | } 836 | 837 | @end 838 | 839 | 840 | @implementation RNBarProgressView 841 | 842 | #pragma mark - Lifecycle 843 | 844 | - (id)init { 845 | return [self initWithFrame:CGRectMake(.0f, .0f, 120.0f, 20.0f)]; 846 | } 847 | 848 | - (id)initWithFrame:(CGRect)frame { 849 | self = [super initWithFrame:frame]; 850 | if (self) { 851 | _progress = 0.f; 852 | _lineColor = [UIColor whiteColor]; 853 | _progressColor = [UIColor whiteColor]; 854 | _progressRemainingColor = [UIColor clearColor]; 855 | self.backgroundColor = [UIColor clearColor]; 856 | self.opaque = NO; 857 | [self registerForKVO]; 858 | } 859 | return self; 860 | } 861 | 862 | - (void)dealloc { 863 | [self unregisterFromKVO]; 864 | } 865 | 866 | #pragma mark - Drawing 867 | 868 | - (void)drawRect:(CGRect)rect { 869 | CGContextRef context = UIGraphicsGetCurrentContext(); 870 | 871 | CGContextSetLineWidth(context, 2); 872 | CGContextSetStrokeColorWithColor(context,[_lineColor CGColor]); 873 | CGContextSetFillColorWithColor(context, [_progressRemainingColor CGColor]); 874 | 875 | // Draw background 876 | float radius = (rect.size.height / 2) - 2; 877 | CGContextMoveToPoint(context, 2, rect.size.height/2); 878 | CGContextAddArcToPoint(context, 2, 2, radius + 2, 2, radius); 879 | CGContextAddLineToPoint(context, rect.size.width - radius - 2, 2); 880 | CGContextAddArcToPoint(context, rect.size.width - 2, 2, rect.size.width - 2, rect.size.height / 2, radius); 881 | CGContextAddArcToPoint(context, rect.size.width - 2, rect.size.height - 2, rect.size.width - radius - 2, rect.size.height - 2, radius); 882 | CGContextAddLineToPoint(context, radius + 2, rect.size.height - 2); 883 | CGContextAddArcToPoint(context, 2, rect.size.height - 2, 2, rect.size.height/2, radius); 884 | CGContextFillPath(context); 885 | 886 | // Draw border 887 | CGContextMoveToPoint(context, 2, rect.size.height/2); 888 | CGContextAddArcToPoint(context, 2, 2, radius + 2, 2, radius); 889 | CGContextAddLineToPoint(context, rect.size.width - radius - 2, 2); 890 | CGContextAddArcToPoint(context, rect.size.width - 2, 2, rect.size.width - 2, rect.size.height / 2, radius); 891 | CGContextAddArcToPoint(context, rect.size.width - 2, rect.size.height - 2, rect.size.width - radius - 2, rect.size.height - 2, radius); 892 | CGContextAddLineToPoint(context, radius + 2, rect.size.height - 2); 893 | CGContextAddArcToPoint(context, 2, rect.size.height - 2, 2, rect.size.height/2, radius); 894 | CGContextStrokePath(context); 895 | 896 | CGContextSetFillColorWithColor(context, [_progressColor CGColor]); 897 | radius = radius - 2; 898 | float amount = self.progress * rect.size.width; 899 | 900 | // Progress in the middle area 901 | if (amount >= radius + 4 && amount <= (rect.size.width - radius - 4)) { 902 | CGContextMoveToPoint(context, 4, rect.size.height/2); 903 | CGContextAddArcToPoint(context, 4, 4, radius + 4, 4, radius); 904 | CGContextAddLineToPoint(context, amount, 4); 905 | CGContextAddLineToPoint(context, amount, radius + 4); 906 | 907 | CGContextMoveToPoint(context, 4, rect.size.height/2); 908 | CGContextAddArcToPoint(context, 4, rect.size.height - 4, radius + 4, rect.size.height - 4, radius); 909 | CGContextAddLineToPoint(context, amount, rect.size.height - 4); 910 | CGContextAddLineToPoint(context, amount, radius + 4); 911 | 912 | CGContextFillPath(context); 913 | } 914 | 915 | // Progress in the right arc 916 | else if (amount > radius + 4) { 917 | float x = amount - (rect.size.width - radius - 4); 918 | 919 | CGContextMoveToPoint(context, 4, rect.size.height/2); 920 | CGContextAddArcToPoint(context, 4, 4, radius + 4, 4, radius); 921 | CGContextAddLineToPoint(context, rect.size.width - radius - 4, 4); 922 | float angle = -acos(x/radius); 923 | if (isnan(angle)) angle = 0; 924 | CGContextAddArc(context, rect.size.width - radius - 4, rect.size.height/2, radius, M_PI, angle, 0); 925 | CGContextAddLineToPoint(context, amount, rect.size.height/2); 926 | 927 | CGContextMoveToPoint(context, 4, rect.size.height/2); 928 | CGContextAddArcToPoint(context, 4, rect.size.height - 4, radius + 4, rect.size.height - 4, radius); 929 | CGContextAddLineToPoint(context, rect.size.width - radius - 4, rect.size.height - 4); 930 | angle = acos(x/radius); 931 | if (isnan(angle)) angle = 0; 932 | CGContextAddArc(context, rect.size.width - radius - 4, rect.size.height/2, radius, -M_PI, angle, 1); 933 | CGContextAddLineToPoint(context, amount, rect.size.height/2); 934 | 935 | CGContextFillPath(context); 936 | } 937 | 938 | // Progress is in the left arc 939 | else if (amount < radius + 4 && amount > 0) { 940 | CGContextMoveToPoint(context, 4, rect.size.height/2); 941 | CGContextAddArcToPoint(context, 4, 4, radius + 4, 4, radius); 942 | CGContextAddLineToPoint(context, radius + 4, rect.size.height/2); 943 | 944 | CGContextMoveToPoint(context, 4, rect.size.height/2); 945 | CGContextAddArcToPoint(context, 4, rect.size.height - 4, radius + 4, rect.size.height - 4, radius); 946 | CGContextAddLineToPoint(context, radius + 4, rect.size.height/2); 947 | 948 | CGContextFillPath(context); 949 | } 950 | } 951 | 952 | #pragma mark - KVO 953 | 954 | - (void)registerForKVO { 955 | for (NSString *keyPath in [self observableKeypaths]) { 956 | [self addObserver:self forKeyPath:keyPath options:NSKeyValueObservingOptionNew context:NULL]; 957 | } 958 | } 959 | 960 | - (void)unregisterFromKVO { 961 | for (NSString *keyPath in [self observableKeypaths]) { 962 | [self removeObserver:self forKeyPath:keyPath]; 963 | } 964 | } 965 | 966 | - (NSArray *)observableKeypaths { 967 | return [NSArray arrayWithObjects:@"lineColor", @"progressRemainingColor", @"progressColor", @"progress", nil]; 968 | } 969 | 970 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 971 | [self setNeedsDisplay]; 972 | } 973 | 974 | @end 975 | -------------------------------------------------------------------------------- /CustomImagePicker/UIView+RNActivityView.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+RNActivityView.h 3 | // HudDemo 4 | // 5 | // Created by Romilson Nunes on 09/07/14. 6 | // Copyright (c) 2014 Matej Bukovinski. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "RNActivityView.h" 11 | 12 | 13 | @interface UIView (RNActivityView) 14 | 15 | @property(nonatomic, readonly) RNActivityView * activityView; 16 | 17 | 18 | -(void)showActivityView; 19 | -(void)showActivityViewWithLabel:(NSString *)text; 20 | -(void)showActivityViewWithLabel:(NSString *)text detailLabel:(NSString *)detail; 21 | -(void)showActivityViewWithMode:(RNActivityViewMode)mode label:(NSString *)text detailLabel:(NSString *)detail; 22 | 23 | -(void)showActivityViewWithMode:(RNActivityViewMode)mode label:(NSString *)text detailLabel:(NSString *)detail whileExecuting:(SEL)method onTarget:(id)target; 24 | 25 | -(void)showActivityViewWithMode:(RNActivityViewMode)mode label:(NSString *)text detailLabel:(NSString *)detail whileExecutingBlock:(dispatch_block_t)block; 26 | 27 | 28 | - (void) hideActivityView; 29 | - (void) hideActivityViewWithAfterDelay:(NSTimeInterval)delay; 30 | 31 | - (void) showActivityViewWithLabel:(NSString *)text image:(UIImage *)image; 32 | - (void) showActivityViewWithLabel:(NSString *)text customView:(UIView *)view; 33 | 34 | 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /CustomImagePicker/UIView+RNActivityView.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+RNActivityView.m 3 | // HudDemo 4 | // 5 | // Created by Romilson Nunes on 09/07/14. 6 | // Copyright (c) 2014 Matej Bukovinski. All rights reserved. 7 | // 8 | 9 | #import "UIView+RNActivityView.h" 10 | 11 | #import 12 | #import 13 | 14 | #define RNLoadingHelperKey @"RNLoadingHelperKey" 15 | #define RNDateLastUpadaKey @"RNDateLastUpadaKey" 16 | 17 | @implementation UIView (RNActivityView) 18 | 19 | - (void)rn_dealloc { 20 | [self destroyActivityView]; 21 | 22 | //this calls original dealloc method 23 | [self rn_dealloc]; 24 | } 25 | 26 | 27 | - (void)rn_didMoveToSuperview { 28 | if (!self.superview || !self.window) { 29 | [self destroyActivityView]; 30 | } 31 | 32 | [self rn_didMoveToSuperview]; 33 | } 34 | 35 | - (void)rn_willMoveToSuperview:(UIView *)newSuperview { 36 | 37 | if (!self.window) { 38 | [self rn_activityView].delegate = nil; 39 | 40 | [self destroyActivityView]; 41 | } 42 | 43 | [self rn_willMoveToSuperview:newSuperview]; 44 | } 45 | 46 | - (void) destroyActivityView { 47 | @synchronized(self) { 48 | if (self.rn_activityView) { 49 | 50 | [NSObject cancelPreviousPerformRequestsWithTarget:self.rn_activityView]; 51 | self.rn_activityView.delegate = nil; 52 | 53 | @try { 54 | [self.rn_activityView removeFromSuperview]; 55 | } 56 | @catch (NSException *exception) { 57 | } 58 | 59 | [self setActivityView:nil]; 60 | } 61 | } 62 | } 63 | 64 | 65 | 66 | 67 | -(RNActivityView *)rn_activityView { 68 | return objc_getAssociatedObject(self, RNLoadingHelperKey); 69 | } 70 | 71 | - (void)swizzleMethod:(SEL)originalSelector withMethod:(SEL)swizzledSelector { 72 | 73 | Method originalMethod = class_getInstanceMethod([self class], originalSelector); 74 | Method swizzledMethod = class_getInstanceMethod([self class], swizzledSelector); 75 | 76 | BOOL didAddMethod = 77 | class_addMethod([self class], 78 | originalSelector, 79 | method_getImplementation(swizzledMethod), 80 | method_getTypeEncoding(swizzledMethod)); 81 | 82 | if (didAddMethod) { 83 | class_replaceMethod([self class], 84 | swizzledSelector, 85 | method_getImplementation(originalMethod), 86 | method_getTypeEncoding(originalMethod)); 87 | } else { 88 | method_exchangeImplementations(originalMethod, swizzledMethod); 89 | } 90 | 91 | } 92 | 93 | 94 | 95 | #pragma mark - Public Methods 96 | 97 | -(RNActivityView *)activityView { 98 | RNActivityView *activityView = objc_getAssociatedObject(self, RNLoadingHelperKey); 99 | 100 | if (!activityView) { 101 | activityView = [[RNActivityView alloc] initWithView:self]; 102 | activityView.delegate = self; 103 | [self setActivityView:activityView]; 104 | 105 | [self swizzleMethod:NSSelectorFromString(@"dealloc") withMethod:@selector(rn_dealloc)]; 106 | [self swizzleMethod:NSSelectorFromString(@"didMoveToSuperview") withMethod:@selector(rn_didMoveToSuperview)]; 107 | [self swizzleMethod:NSSelectorFromString(@"willMoveToSuperview") withMethod:@selector(rn_willMoveToSuperview:)]; 108 | 109 | 110 | 111 | } 112 | if (!activityView.superview) { 113 | [self addSubview:activityView]; 114 | } 115 | return activityView; 116 | } 117 | 118 | -(void)setActivityView:(RNActivityView *)activityView { 119 | objc_setAssociatedObject(self, RNLoadingHelperKey, activityView, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 120 | } 121 | 122 | -(void)showActivityView { 123 | [self.activityView show:YES]; 124 | } 125 | 126 | -(void)showActivityViewWithLabel:(NSString *)text { 127 | [self showActivityViewWithLabel:text detailLabel:nil]; 128 | } 129 | 130 | -(void)showActivityViewWithLabel:(NSString *)text detailLabel:(NSString *)detail { 131 | [self showActivityViewWithMode:self.activityView.mode label:text detailLabel:detail]; 132 | } 133 | 134 | -(void)showActivityViewWithMode:(RNActivityViewMode)mode label:(NSString *)text detailLabel:(NSString *)detail; { 135 | 136 | [self.activityView setupDefaultValues]; 137 | self.activityView.labelText = text; 138 | self.activityView.detailsLabelText = detail; 139 | self.activityView.mode = mode; 140 | self.activityView.dimBackground = NO; 141 | 142 | [self showActivityView]; 143 | } 144 | 145 | -(void)showActivityViewWithMode:(RNActivityViewMode)mode label:(NSString *)text detailLabel:(NSString *)detail whileExecuting:(SEL)method onTarget:(id)target { 146 | 147 | [self.activityView setupDefaultValues]; 148 | self.activityView.labelText = text; 149 | self.activityView.detailsLabelText = detail; 150 | self.activityView.mode = mode; 151 | self.activityView.dimBackground = YES; 152 | 153 | [self.activityView showWhileExecuting:method onTarget:target withObject:nil animated:YES]; 154 | } 155 | 156 | -(void)showActivityViewWithMode:(RNActivityViewMode)mode label:(NSString *)text detailLabel:(NSString *)detail whileExecutingBlock:(dispatch_block_t)block { 157 | 158 | [self.activityView setupDefaultValues]; 159 | self.activityView.labelText = text; 160 | self.activityView.detailsLabelText = detail; 161 | self.activityView.mode = mode; 162 | self.activityView.dimBackground = YES; 163 | 164 | [self.activityView showAnimated:YES whileExecutingBlock:block]; 165 | } 166 | 167 | 168 | - (void) showActivityViewWithLabel:(NSString *)text image:(UIImage *)image { 169 | UIImageView *imageView = [[UIImageView alloc] initWithImage:image]; 170 | [self showActivityViewWithLabel:text customView:imageView]; 171 | } 172 | 173 | 174 | - (void) showActivityViewWithLabel:(NSString *)text customView:(UIView *)view { 175 | [self.activityView setupDefaultValues]; 176 | self.activityView.customView = view; 177 | self.activityView.mode = RNActivityViewModeCustomView; 178 | self.activityView.labelText = text; 179 | 180 | [self showActivityView]; 181 | } 182 | 183 | 184 | - (void) hideActivityView { 185 | [self hideActivityViewWithAfterDelay:0]; 186 | } 187 | 188 | - (void) hideActivityViewWithAfterDelay:(NSTimeInterval)delay { 189 | [self.activityView hide:YES afterDelay:delay]; 190 | } 191 | 192 | 193 | 194 | #pragma mark - 195 | #pragma mark RNActivityViewDelegate methods 196 | 197 | - (void)hudWasHidden:(RNActivityView *)hud { 198 | // Remove HUD from screen when the HUD was hidded 199 | [hud removeFromSuperview]; 200 | self.activityView = nil; 201 | } 202 | 203 | 204 | 205 | @end 206 | -------------------------------------------------------------------------------- /CustomImagePicker/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // CustomImagePicker 4 | // 5 | // Created by C S P Nanda on 1/5/15. 6 | // Copyright (c) 2015 C S P Nanda. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CustomeImagePicker.h" 11 | @interface ViewController : UIViewController 12 | @property(nonatomic, weak) IBOutlet UIImageView *imageView1; 13 | @property(nonatomic, weak) IBOutlet UIImageView *imageView2; 14 | @property(nonatomic, weak) IBOutlet UIImageView *imageView3; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /CustomImagePicker/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // CustomImagePicker 4 | // 5 | // Created by C S P Nanda on 1/5/15. 6 | // Copyright (c) 2015 C S P Nanda. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "UIView+RNActivityView.h" 11 | @interface ViewController () 12 | 13 | @end 14 | 15 | @implementation ViewController 16 | @synthesize imageView1,imageView2,imageView3; 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | // Do any additional setup after loading the view from its nib. 20 | } 21 | 22 | - (void)didReceiveMemoryWarning { 23 | [super didReceiveMemoryWarning]; 24 | // Dispose of any resources that can be recreated. 25 | } 26 | 27 | -(IBAction)getPhoto:(id)sender 28 | { 29 | CustomeImagePicker *cip = [[CustomeImagePicker alloc] init]; 30 | cip.delegate = self; 31 | [cip setHideSkipButton:NO]; 32 | [cip setHideNextButton:NO]; 33 | [cip setMaxPhotos:MAX_ALLOWED_PICK]; 34 | [cip setShowOnlyPhotosWithGPS:NO]; 35 | 36 | [self presentViewController:cip animated:YES completion:^{ 37 | } 38 | ]; 39 | } 40 | 41 | -(void) imageSelected:(NSArray *)arrayOfImages 42 | { 43 | 44 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ // 1 45 | dispatch_async(dispatch_get_main_queue(), ^{ 46 | [self.view showActivityView]; 47 | }); // Main Queue to Display the Activity View 48 | int count = 0; 49 | for(NSString *imageURLString in arrayOfImages) 50 | { 51 | // Asset URLs 52 | ALAssetsLibrary *assetsLibrary = [[ALAssetsLibrary alloc] init]; 53 | [assetsLibrary assetForURL:[NSURL URLWithString:imageURLString] resultBlock:^(ALAsset *asset) { 54 | ALAssetRepresentation *representation = [asset defaultRepresentation]; 55 | CGImageRef imageRef = [representation fullScreenImage]; 56 | UIImage *image = [UIImage imageWithCGImage:imageRef]; 57 | if (imageRef) { 58 | dispatch_async(dispatch_get_main_queue(), ^{ 59 | if(count==0) 60 | { 61 | [imageView1 setImage:image]; 62 | } 63 | if(count==1) 64 | { 65 | [imageView2 setImage:image]; 66 | } 67 | if(count==2) 68 | { 69 | [imageView3 setImage:image]; 70 | } 71 | }); 72 | } // Valid Image URL 73 | } failureBlock:^(NSError *error) { 74 | }]; 75 | count++; 76 | } // All Images I got 77 | dispatch_async(dispatch_get_main_queue(), ^{ 78 | [self.view hideActivityView]; 79 | }); 80 | }); // Queue for reloading all images 81 | } 82 | -(void) imageSelectionCancelled 83 | { 84 | 85 | } 86 | 87 | 88 | 89 | @end 90 | -------------------------------------------------------------------------------- /CustomImagePicker/ViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /CustomImagePicker/YCameraViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // PhotoShapViewController.h 3 | // NoshedItStaging 4 | // 5 | // Created by yuvraj on 08/01/14. 6 | // Copyright (c) 2014 limbasiya.nirav@gmail.com. All rights reserved. 7 | // 8 | 9 | // 10 | // ARC Helper 11 | #ifndef ah_retain 12 | #if __has_feature(objc_arc) 13 | #define ah_retain self 14 | #define ah_dealloc self 15 | #define release self 16 | #define autorelease self 17 | #else 18 | #define ah_retain retain 19 | #define ah_dealloc dealloc 20 | #define __bridge 21 | #endif 22 | #endif 23 | 24 | // ARC Helper ends 25 | 26 | #import 27 | #import 28 | #import 29 | #import "CameraFocusSquare.h" 30 | #import "OLGhostAlertView.h" 31 | #import 32 | @protocol YCameraViewControllerDelegate; 33 | 34 | @interface YCameraViewController : UIViewController { 35 | 36 | UIImagePickerController *imgPicker; 37 | BOOL pickerDidShow; 38 | 39 | //Today Implementation 40 | BOOL FrontCamera; 41 | BOOL haveImage; 42 | BOOL initializeCamera, photoFromCam; 43 | AVCaptureSession *session; 44 | AVCaptureDeviceInput *input; 45 | AVCaptureVideoPreviewLayer *captureVideoPreviewLayer; 46 | AVCaptureStillImageOutput *stillImageOutput; 47 | UIImage *croppedImageWithoutOrientation; 48 | CameraFocusSquare *camFocus; 49 | NSURL *assetURLToSend; 50 | NSDictionary *metadata; 51 | } 52 | @property (nonatomic, readwrite) BOOL dontAllowResetRestaurant; 53 | @property (nonatomic, assign) id delegate; 54 | 55 | #pragma mark - 56 | @property (nonatomic, strong) IBOutlet UIButton *photoCaptureButton; 57 | @property (nonatomic, strong) IBOutlet UIButton *cancelButton; 58 | @property (nonatomic, strong) IBOutlet UIButton *cameraToggleButton; 59 | @property (nonatomic, strong) IBOutlet UIButton *libraryToggleButton; 60 | @property (nonatomic, strong) IBOutlet UIButton *flashToggleButton; 61 | @property (retain, nonatomic) IBOutlet UIImageView *ImgViewGrid; 62 | @property (nonatomic, strong) IBOutlet UIView *photoBar; 63 | @property (nonatomic, strong) IBOutlet UIView *topBar; 64 | @property (retain, nonatomic) IBOutlet UIView *imagePreview; 65 | @property (retain, nonatomic) IBOutlet UIImageView *captureImage; 66 | @property (nonatomic, weak) IBOutlet UISlider *zoomFactor; 67 | @property (nonatomic,strong) CLLocation *currentUserLocation; 68 | @end 69 | 70 | @protocol YCameraViewControllerDelegate 71 | - (void)didFinishPickingImage:(UIImage *)image metadata:(NSDictionary*)metadata; 72 | - (void)yCameraControllerDidCancel; 73 | - (void)yCameraControllerdidSkipped; 74 | @end 75 | -------------------------------------------------------------------------------- /CustomImagePicker/YCameraViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // PhotoShapViewController.m 3 | // NoshedItStaging 4 | // 5 | // Created by yuvraj on 08/01/14. 6 | // Copyright (c) 2014 limbasiya.nirav@gmail.com. All rights reserved. 7 | // 8 | 9 | #import "YCameraViewController.h" 10 | #import "AppDelegate.h" 11 | #import 12 | 13 | #define DegreesToRadians(x) ((x) * M_PI / 180.0) 14 | 15 | @interface YCameraViewController (){ 16 | UIInterfaceOrientation orientationLast, orientationAfterProcess; 17 | CMMotionManager *motionManager; 18 | } 19 | @end 20 | 21 | @implementation YCameraViewController 22 | @synthesize delegate,zoomFactor,currentUserLocation; 23 | 24 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 25 | { 26 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 27 | if (self) { 28 | // Custom initialization 29 | } 30 | return self; 31 | } 32 | 33 | - (void)viewDidLoad 34 | { 35 | [super viewDidLoad]; 36 | 37 | // if ([self respondsToSelector:@selector(edgesForExtendedLayout)]){ 38 | // self.edgesForExtendedLayout = UIRectEdgeNone; 39 | // } 40 | 41 | self.navigationController.navigationBarHidden = YES; 42 | [self.navigationController setNavigationBarHidden:YES]; 43 | 44 | // Do any additional setup after loading the view. 45 | pickerDidShow = NO; 46 | 47 | FrontCamera = NO; 48 | self.captureImage.hidden = YES; 49 | 50 | // Setup UIImagePicker Controller 51 | imgPicker = [[UIImagePickerController alloc] init]; 52 | imgPicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; 53 | imgPicker.delegate = self; 54 | imgPicker.allowsEditing = YES; 55 | 56 | croppedImageWithoutOrientation = [[UIImage alloc] init]; 57 | 58 | initializeCamera = YES; 59 | photoFromCam = YES; 60 | self.flashToggleButton.selected=NO; 61 | // Initialize Motion Manager 62 | [self initializeMotionManager]; 63 | camFocus = [[CameraFocusSquare alloc] init]; 64 | } 65 | 66 | - (void)viewWillAppear:(BOOL)animated{ 67 | [super viewWillAppear:animated]; 68 | [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide]; 69 | } 70 | 71 | - (void)viewDidAppear:(BOOL)animated{ 72 | [super viewDidAppear:animated]; 73 | 74 | if (initializeCamera){ 75 | initializeCamera = NO; 76 | 77 | // Initialize camera 78 | [self initializeCamera]; 79 | } 80 | 81 | } 82 | 83 | - (void)viewWillDisappear:(BOOL)animated{ 84 | [super viewWillDisappear:animated]; 85 | [session stopRunning]; 86 | [[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide]; 87 | [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]; 88 | } 89 | 90 | - (void)didReceiveMemoryWarning 91 | { 92 | [super didReceiveMemoryWarning]; 93 | // Dispose of any resources that can be recreated. 94 | } 95 | 96 | -(void) dealloc 97 | { 98 | [_imagePreview release]; 99 | [_captureImage release]; 100 | [imgPicker release]; 101 | imgPicker = nil; 102 | camFocus = Nil; 103 | if (session) 104 | [session release], session=nil; 105 | 106 | if (captureVideoPreviewLayer) 107 | [captureVideoPreviewLayer release], captureVideoPreviewLayer=nil; 108 | 109 | if (stillImageOutput) 110 | [stillImageOutput release], stillImageOutput=nil; 111 | } 112 | 113 | #pragma mark - CoreMotion Task 114 | - (void)initializeMotionManager{ 115 | motionManager = [[CMMotionManager alloc] init]; 116 | motionManager.accelerometerUpdateInterval = .2; 117 | motionManager.gyroUpdateInterval = .2; 118 | 119 | [motionManager startAccelerometerUpdatesToQueue:[NSOperationQueue currentQueue] 120 | withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) { 121 | if (!error) { 122 | [self outputAccelertionData:accelerometerData.acceleration]; 123 | } 124 | else{ 125 | NSLog(@"%@", error); 126 | } 127 | }]; 128 | } 129 | 130 | #pragma mark - UIAccelerometer callback 131 | 132 | - (void)outputAccelertionData:(CMAcceleration)acceleration{ 133 | UIInterfaceOrientation orientationNew; 134 | 135 | if (acceleration.x >= 0.75) { 136 | orientationNew = UIInterfaceOrientationLandscapeLeft; 137 | } 138 | else if (acceleration.x <= -0.75) { 139 | orientationNew = UIInterfaceOrientationLandscapeRight; 140 | } 141 | else if (acceleration.y <= -0.75) { 142 | orientationNew = UIInterfaceOrientationPortrait; 143 | } 144 | else if (acceleration.y >= 0.75) { 145 | orientationNew = UIInterfaceOrientationPortraitUpsideDown; 146 | } 147 | else { 148 | // Consider same as last time 149 | return; 150 | } 151 | 152 | if (orientationNew == orientationLast) 153 | return; 154 | 155 | // NSLog(@"Going from %@ to %@!", [[self class] orientationToText:orientationLast], [[self class] orientationToText:orientationNew]); 156 | 157 | orientationLast = orientationNew; 158 | } 159 | 160 | #ifdef DEBUG 161 | +(NSString*)orientationToText:(const UIInterfaceOrientation)ORIENTATION { 162 | switch (ORIENTATION) { 163 | case UIInterfaceOrientationPortrait: 164 | return @"UIInterfaceOrientationPortrait"; 165 | case UIInterfaceOrientationPortraitUpsideDown: 166 | return @"UIInterfaceOrientationPortraitUpsideDown"; 167 | case UIInterfaceOrientationLandscapeLeft: 168 | return @"UIInterfaceOrientationLandscapeLeft"; 169 | case UIInterfaceOrientationLandscapeRight: 170 | return @"UIInterfaceOrientationLandscapeRight"; 171 | } 172 | return @"Unknown orientation!"; 173 | } 174 | #endif 175 | 176 | #pragma mark - Camera Initialization 177 | 178 | //AVCaptureSession to show live video feed in view 179 | - (void) initializeCamera { 180 | if (session) 181 | [session release], session=nil; 182 | 183 | session = [[AVCaptureSession alloc] init]; 184 | // session.sessionPreset = AVCaptureSessionPresetPhoto; 185 | session.sessionPreset = AVCaptureSessionPreset1280x720; 186 | if (captureVideoPreviewLayer) 187 | [captureVideoPreviewLayer release], captureVideoPreviewLayer=nil; 188 | 189 | captureVideoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session]; 190 | [captureVideoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill]; 191 | 192 | captureVideoPreviewLayer.frame = self.imagePreview.bounds; 193 | [self.imagePreview.layer addSublayer:captureVideoPreviewLayer]; 194 | 195 | UIView *view = [self imagePreview]; 196 | CALayer *viewLayer = [view layer]; 197 | [viewLayer setMasksToBounds:YES]; 198 | 199 | CGRect bounds = [view bounds]; 200 | [captureVideoPreviewLayer setFrame:bounds]; 201 | 202 | NSArray *devices = [AVCaptureDevice devices]; 203 | AVCaptureDevice *frontCamera=nil; 204 | AVCaptureDevice *backCamera=nil; 205 | 206 | // check if device available 207 | if (devices.count==0) { 208 | NSLog(@"No Camera Available"); 209 | [self disableCameraDeviceControls]; 210 | return; 211 | } 212 | 213 | for (AVCaptureDevice *device in devices) { 214 | if ([device hasMediaType:AVMediaTypeVideo]) { 215 | 216 | if ([device position] == AVCaptureDevicePositionBack) { 217 | NSLog(@"Device position : back"); 218 | backCamera = device; 219 | } 220 | else { 221 | NSLog(@"Device position : front"); 222 | frontCamera = device; 223 | // if([device isFocusModeSupported:AVCaptureFocusModeAutoFocus]) 224 | // { 225 | // if([device lockForConfiguration:NULL]) 226 | // { 227 | // [device setFocusMode:AVCaptureFocusModeAutoFocus]; 228 | // [device unlockForConfiguration]; 229 | // } 230 | // } 231 | } 232 | } 233 | } 234 | 235 | if (!FrontCamera) { 236 | 237 | if ([backCamera hasFlash]){ 238 | [backCamera lockForConfiguration:nil]; 239 | if (self.flashToggleButton.selected) 240 | [backCamera setFlashMode:AVCaptureFlashModeOn]; 241 | else 242 | [backCamera setFlashMode:AVCaptureFlashModeOff]; 243 | [backCamera unlockForConfiguration]; 244 | 245 | [self.flashToggleButton setEnabled:YES]; 246 | } 247 | else{ 248 | if ([backCamera isFlashModeSupported:AVCaptureFlashModeOff]) { 249 | [backCamera lockForConfiguration:nil]; 250 | [backCamera setFlashMode:AVCaptureFlashModeOff]; 251 | [backCamera unlockForConfiguration]; 252 | } 253 | [self.flashToggleButton setEnabled:NO]; 254 | } 255 | 256 | NSError *error = nil; 257 | input = [AVCaptureDeviceInput deviceInputWithDevice:backCamera error:&error]; 258 | if (!input) { 259 | NSLog(@"ERROR: trying to open camera: %@", error); 260 | } 261 | else 262 | { 263 | [session addInput:input]; 264 | if (stillImageOutput) 265 | [stillImageOutput release], stillImageOutput=nil; 266 | 267 | stillImageOutput = [[AVCaptureStillImageOutput alloc] init]; 268 | [stillImageOutput setHighResolutionStillImageOutputEnabled:YES]; 269 | NSDictionary *outputSettings = [[[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey, nil] autorelease]; 270 | [stillImageOutput setOutputSettings:outputSettings]; 271 | 272 | [session addOutput:stillImageOutput]; 273 | 274 | [session startRunning]; 275 | } 276 | } 277 | 278 | if (FrontCamera) { 279 | [self.flashToggleButton setEnabled:NO]; 280 | NSError *error = nil; 281 | input = [AVCaptureDeviceInput deviceInputWithDevice:frontCamera error:&error]; 282 | if (!input) { 283 | NSLog(@"ERROR: trying to open camera: %@", error); 284 | } 285 | else 286 | { 287 | [session addInput:input]; 288 | if (stillImageOutput) 289 | [stillImageOutput release], stillImageOutput=nil; 290 | 291 | stillImageOutput = [[AVCaptureStillImageOutput alloc] init]; 292 | NSDictionary *outputSettings = [[[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey, nil] autorelease]; 293 | [stillImageOutput setOutputSettings:outputSettings]; 294 | 295 | [session addOutput:stillImageOutput]; 296 | 297 | [session startRunning]; 298 | } 299 | } 300 | 301 | for(UIGestureRecognizer *gesture in [self.imagePreview gestureRecognizers]) 302 | { 303 | [self.imagePreview removeGestureRecognizer:gesture]; 304 | } 305 | 306 | UITapGestureRecognizer *tapGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapToFocus:)]; 307 | [tapGR setNumberOfTapsRequired:1]; 308 | [tapGR setNumberOfTouchesRequired:1]; 309 | [tapGR setDelegate:self]; 310 | [self.imagePreview addGestureRecognizer:tapGR]; 311 | 312 | 313 | if (camFocus) 314 | { 315 | [camFocus removeFromSuperview]; 316 | } 317 | camFocus = [[CameraFocusSquare alloc]initWithFrame:CGRectMake(self.imagePreview.center.x-40, self.imagePreview.center.y-40, 80, 80)]; 318 | [camFocus setBackgroundColor:[UIColor clearColor]]; 319 | [self.imagePreview addSubview:camFocus]; 320 | [camFocus setNeedsDisplay]; 321 | 322 | [UIView beginAnimations:nil context:NULL]; 323 | [UIView setAnimationDuration:1.0]; 324 | [camFocus setAlpha:0.0]; 325 | [UIView commitAnimations]; 326 | 327 | } 328 | 329 | 330 | -(IBAction)zoomChanged:(UISlider*)sender 331 | { 332 | AVCaptureDevice *currentDevice = input.device; 333 | if(sender.value == 0) 334 | { 335 | if ([currentDevice lockForConfiguration:Nil]) { 336 | currentDevice.videoZoomFactor = 1.0; 337 | [currentDevice unlockForConfiguration]; 338 | } 339 | } 340 | else 341 | { 342 | if ([currentDevice lockForConfiguration:Nil]) { 343 | currentDevice.videoZoomFactor = 1.0 + sender.value; 344 | [currentDevice unlockForConfiguration]; 345 | } 346 | } 347 | } 348 | 349 | 350 | -(void)tapToFocus:(UITapGestureRecognizer *)singleTap{ 351 | CGPoint touchPoint = [singleTap locationInView:self.imagePreview]; 352 | CGPoint convertedPoint = [captureVideoPreviewLayer captureDevicePointOfInterestForPoint:touchPoint]; 353 | 354 | 355 | 356 | if (camFocus) 357 | { 358 | [camFocus removeFromSuperview]; 359 | } 360 | camFocus = [[CameraFocusSquare alloc]initWithFrame:CGRectMake(touchPoint.x-40, touchPoint.y-40, 80, 80)]; 361 | [camFocus setBackgroundColor:[UIColor clearColor]]; 362 | [self.imagePreview addSubview:camFocus]; 363 | [camFocus setNeedsDisplay]; 364 | 365 | [UIView beginAnimations:nil context:NULL]; 366 | [UIView setAnimationDuration:1.5]; 367 | [camFocus setAlpha:0.0]; 368 | [UIView commitAnimations]; 369 | 370 | 371 | AVCaptureDevice *currentDevice = input.device; 372 | 373 | 374 | 375 | if([currentDevice isFocusPointOfInterestSupported] && [currentDevice isFocusModeSupported:AVCaptureFocusModeAutoFocus]){ 376 | NSError *error = nil; 377 | [currentDevice lockForConfiguration:&error]; 378 | if(!error){ 379 | [currentDevice setFocusPointOfInterest:convertedPoint]; 380 | [currentDevice setFocusMode:AVCaptureFocusModeAutoFocus]; 381 | [currentDevice unlockForConfiguration]; 382 | NSLog(@"Changed Focus"); 383 | } 384 | } 385 | } 386 | 387 | - (IBAction)snapImage:(id)sender { 388 | [self.photoCaptureButton setEnabled:NO]; 389 | 390 | if (!haveImage) { 391 | self.captureImage.image = nil; //remove old image from view 392 | self.captureImage.hidden = NO; //show the captured image view 393 | self.imagePreview.hidden = YES; //hide the live video feed 394 | [self capImage]; 395 | } 396 | else { 397 | self.captureImage.hidden = YES; 398 | self.imagePreview.hidden = NO; 399 | haveImage = NO; 400 | } 401 | } 402 | 403 | - (void) capImage { //method to capture image from AVCaptureSession video feed 404 | AVCaptureConnection *videoConnection = nil; 405 | for (AVCaptureConnection *connection in stillImageOutput.connections) { 406 | 407 | for (AVCaptureInputPort *port in [connection inputPorts]) { 408 | 409 | if ([[port mediaType] isEqual:AVMediaTypeVideo] ) { 410 | videoConnection = connection; 411 | break; 412 | } 413 | } 414 | 415 | if (videoConnection) { 416 | break; 417 | } 418 | } 419 | 420 | [stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error) { 421 | 422 | if (imageSampleBuffer != NULL) { 423 | 424 | NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer]; 425 | CFDictionaryRef attachments = CMCopyDictionaryOfAttachments(kCFAllocatorDefault, 426 | imageSampleBuffer, 427 | kCMAttachmentMode_ShouldPropagate); 428 | metadata = (__bridge NSDictionary*)attachments; 429 | 430 | 431 | 432 | CFMutableDictionaryRef mutable = CFDictionaryCreateMutableCopy(NULL, 0, attachments); 433 | NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:@"UTC"]; 434 | NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; 435 | [formatter setTimeZone:timeZone]; 436 | [formatter setDateFormat:@"HH:mm:ss.SS"]; 437 | NSDictionary *gpsDict = [NSDictionary dictionaryWithObjectsAndKeys: 438 | [NSNumber numberWithFloat:fabs(currentUserLocation.coordinate.latitude)], kCGImagePropertyGPSLatitude 439 | , ((currentUserLocation.coordinate.latitude >= 0) ? @"N" : @"S"), kCGImagePropertyGPSLatitudeRef 440 | , [NSNumber numberWithFloat:fabs(currentUserLocation.coordinate.longitude)], kCGImagePropertyGPSLongitude 441 | , ((currentUserLocation.coordinate.longitude >= 0) ? @"E" : @"W"), kCGImagePropertyGPSLongitudeRef 442 | , [formatter stringFromDate:[currentUserLocation timestamp]], kCGImagePropertyGPSTimeStamp 443 | , [NSNumber numberWithFloat:fabs(currentUserLocation.altitude)], kCGImagePropertyGPSAltitude 444 | ,[NSNumber numberWithFloat:currentUserLocation.horizontalAccuracy],kCGImagePropertyGPSDOP 445 | 446 | , nil]; 447 | 448 | 449 | CFDictionarySetValue(mutable, kCGImagePropertyGPSDictionary, (__bridge void *)gpsDict); 450 | 451 | CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL); 452 | 453 | CFStringRef UTI = CGImageSourceGetType(source); //this is the type of image (e.g., public.jpeg) 454 | NSMutableData *dest_data = [NSMutableData data]; 455 | CGImageDestinationRef destination = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)dest_data,UTI,1,NULL); 456 | if(!destination) { 457 | NSLog(@"***Could not create image destination ***"); 458 | } 459 | CGImageDestinationAddImageFromSource(destination,source,0, (CFDictionaryRef) mutable); 460 | 461 | //tell the destination to write the image data and metadata into our data object. 462 | //It will return false if something goes wrong 463 | BOOL success = CGImageDestinationFinalize(destination); 464 | 465 | if(!success) { 466 | NSLog(@"***Could not create data from image destination ***"); 467 | } 468 | 469 | CFRelease(destination); 470 | CFRelease(source); 471 | imageData = NULL; 472 | metadata = (__bridge NSDictionary*)mutable; 473 | 474 | // [self processImage:[UIImage imageWithData:imageData]]; 475 | [self.captureImage setImage:[UIImage imageWithData:dest_data]]; 476 | 477 | [self setCapturedImage]; 478 | 479 | 480 | // CFDictionaryRef attachments = CMCopyDictionaryOfAttachments(kCFAllocatorDefault, 481 | // imageSampleBuffer, 482 | // kCMAttachmentMode_ShouldPropagate); 483 | // NSDictionary *andBack = (__bridge NSDictionary*)attachments; 484 | // ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; 485 | // [library writeImageDataToSavedPhotosAlbum:imageData metadata:andBack completionBlock:^(NSURL *assetURL, NSError *error) { 486 | // if (error) { 487 | // [self displayErrorOnMainQueue:error withMessage:@"Save to camera roll failed"]; 488 | // } 489 | // }]; 490 | // 491 | // if (attachments) 492 | // CFRelease(attachments); 493 | // [library release]; 494 | // 495 | // [self.captureImage setImage:[UIImage imageWithData:imageData]]; 496 | // 497 | // [self setCapturedImage]; 498 | } 499 | }]; 500 | } 501 | 502 | - (void)displayErrorOnMainQueue:(NSError *)error withMessage:(NSString *)message 503 | { 504 | dispatch_async(dispatch_get_main_queue(), ^(void) { 505 | UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:[NSString stringWithFormat:@"%@ (%d)", message, (int)[error code]] 506 | message:[error localizedDescription] 507 | delegate:nil 508 | cancelButtonTitle:@"Dismiss" 509 | otherButtonTitles:nil]; 510 | [alertView show]; 511 | [alertView release]; 512 | }); 513 | } 514 | 515 | - (UIImage*)imageWithImage:(UIImage *)sourceImage scaledToWidth:(float) i_width 516 | { 517 | float oldWidth = sourceImage.size.width; 518 | float scaleFactor = i_width / oldWidth; 519 | 520 | float newHeight = sourceImage.size.height * scaleFactor; 521 | float newWidth = oldWidth * scaleFactor; 522 | 523 | UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight)); 524 | [sourceImage drawInRect:CGRectMake(0, 0, newWidth, newHeight)]; 525 | UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 526 | UIGraphicsEndImageContext(); 527 | return newImage; 528 | } 529 | 530 | - (void) processImage:(UIImage *)image { //process captured image, crop, resize and rotate 531 | haveImage = YES; 532 | photoFromCam = YES; 533 | 534 | // Resize image to 640x640 535 | // Resize image 536 | // NSLog(@"Image size %f and %f",image.size.width,image.size.height); 537 | // 538 | // 539 | // CGRect screenRect = [[UIScreen mainScreen] bounds]; 540 | // CGFloat screenWidth = screenRect.size.width; 541 | // CGFloat screenHeight = screenRect.size.height; 542 | 543 | 544 | 545 | 546 | UIImage *smallImage = [self imageWithImage:image scaledToWidth:720]; //UIGraphicsGetImageFromCurrentImageContext(); 547 | CGRect cropRect = CGRectMake(0, 0, smallImage.size.width, smallImage.size.height); 548 | CGImageRef imageRef = CGImageCreateWithImageInRect([smallImage CGImage], cropRect); 549 | croppedImageWithoutOrientation = [[UIImage imageWithCGImage:imageRef] copy]; 550 | 551 | UIImage *croppedImage = nil; 552 | orientationAfterProcess = orientationLast; 553 | switch (orientationLast) { 554 | case UIInterfaceOrientationPortrait: 555 | NSLog(@"UIInterfaceOrientationPortrait"); 556 | croppedImage = [UIImage imageWithCGImage:imageRef]; 557 | break; 558 | 559 | case UIInterfaceOrientationPortraitUpsideDown: 560 | NSLog(@"UIInterfaceOrientationPortraitUpsideDown"); 561 | croppedImage = [[[UIImage alloc] initWithCGImage: imageRef 562 | scale: 1.0 563 | orientation: UIImageOrientationDown] autorelease]; 564 | break; 565 | 566 | case UIInterfaceOrientationLandscapeLeft: 567 | NSLog(@"UIInterfaceOrientationLandscapeLeft"); 568 | croppedImage = [[[UIImage alloc] initWithCGImage: imageRef 569 | scale: 1.0 570 | orientation: UIImageOrientationRight] autorelease]; 571 | break; 572 | 573 | case UIInterfaceOrientationLandscapeRight: 574 | NSLog(@"UIInterfaceOrientationLandscapeRight"); 575 | croppedImage = [[[UIImage alloc] initWithCGImage: imageRef 576 | scale: 1.0 577 | orientation: UIImageOrientationLeft] autorelease]; 578 | break; 579 | 580 | default: 581 | croppedImage = [UIImage imageWithCGImage:imageRef]; 582 | break; 583 | } 584 | 585 | CGImageRelease(imageRef); 586 | 587 | [self.captureImage setImage:croppedImage]; 588 | 589 | [self setCapturedImage]; 590 | } 591 | 592 | - (void)setCapturedImage{ 593 | // Stop capturing image 594 | [session stopRunning]; 595 | 596 | // Hide Top/Bottom controller after taking photo for editing 597 | [self hideControllers]; 598 | } 599 | 600 | #pragma mark - Device Availability Controls 601 | - (void)disableCameraDeviceControls{ 602 | self.cameraToggleButton.enabled = NO; 603 | self.flashToggleButton.enabled = NO; 604 | self.photoCaptureButton.enabled = NO; 605 | } 606 | 607 | //#pragma mark - UIImagePicker Delegate 608 | //- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{ 609 | // if (info) { 610 | // photoFromCam = NO; 611 | // 612 | // UIImage* outputImage = [info objectForKey:UIImagePickerControllerEditedImage]; 613 | // if (outputImage == nil) { 614 | // outputImage = [info objectForKey:UIImagePickerControllerOriginalImage]; 615 | // } 616 | // 617 | // if (outputImage) { 618 | // self.captureImage.hidden = NO; 619 | // self.captureImage.image=outputImage; 620 | // 621 | // [self dismissViewControllerAnimated:YES completion:nil]; 622 | // 623 | // // Hide Top/Bottom controller after taking photo for editing 624 | // [self hideControllers]; 625 | // } 626 | // } 627 | //} 628 | 629 | //- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker{ 630 | // initializeCamera = YES; 631 | // [picker dismissViewControllerAnimated:YES completion:nil]; 632 | //} 633 | 634 | #pragma mark - Button clicks 635 | - (IBAction)gridToogle:(UIButton *)sender{ 636 | if (sender.selected) { 637 | sender.selected = NO; 638 | [UIView animateWithDuration:0.2 delay:0.0 options:0 animations:^{ 639 | self.ImgViewGrid.alpha = 1.0f; 640 | } completion:nil]; 641 | } 642 | else{ 643 | sender.selected = YES; 644 | [UIView animateWithDuration:0.2 delay:0.0 options:0 animations:^{ 645 | self.ImgViewGrid.alpha = 0.0f; 646 | } completion:nil]; 647 | } 648 | } 649 | 650 | -(IBAction)switchToLibrary:(id)sender { 651 | 652 | if (session) { 653 | [session stopRunning]; 654 | } 655 | 656 | // self.captureImage = nil; 657 | 658 | // UIImagePickerController* imagePickerController = [[UIImagePickerController alloc] init]; 659 | // imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; 660 | // imagePickerController.delegate = self; 661 | // imagePickerController.allowsEditing = YES; 662 | [self presentViewController:imgPicker animated:YES completion:NULL]; 663 | } 664 | 665 | - (IBAction)skipped:(id)sender{ 666 | 667 | if ([delegate respondsToSelector:@selector(yCameraControllerdidSkipped)]) { 668 | [delegate yCameraControllerdidSkipped]; 669 | } 670 | 671 | // Dismiss self view controller 672 | [self dismissViewControllerAnimated:YES completion:nil]; 673 | } 674 | 675 | -(IBAction) cancel:(id)sender { 676 | if ([delegate respondsToSelector:@selector(yCameraControllerDidCancel)]) { 677 | [delegate yCameraControllerDidCancel]; 678 | } 679 | 680 | // Dismiss self view controller 681 | [self dismissViewControllerAnimated:YES completion:nil]; 682 | } 683 | 684 | - (IBAction)donePhotoCapture:(id)sender{ 685 | [session stopRunning]; 686 | [motionManager stopDeviceMotionUpdates]; 687 | imgPicker = Nil; 688 | session = Nil; 689 | motionManager = Nil; 690 | captureVideoPreviewLayer = Nil; 691 | stillImageOutput = Nil; 692 | if ([delegate respondsToSelector:@selector(didFinishPickingImage:metadata:)]) { 693 | [delegate didFinishPickingImage:self.captureImage.image metadata:metadata]; 694 | } 695 | // Dismiss self view controller 696 | [self dismissViewControllerAnimated:NO completion:^(void) 697 | { 698 | 699 | }]; 700 | } 701 | 702 | - (IBAction)retakePhoto:(id)sender{ 703 | [self.photoCaptureButton setEnabled:YES]; 704 | self.captureImage.image = nil; 705 | self.imagePreview.hidden = NO; 706 | // Show Camera device controls 707 | [self showControllers]; 708 | 709 | haveImage=NO; 710 | FrontCamera = NO; 711 | // [self performSelector:@selector(initializeCamera) withObject:nil afterDelay:0.001]; 712 | [session startRunning]; 713 | } 714 | 715 | - (IBAction)switchCamera:(UIButton *)sender { //switch cameras front and rear cameras 716 | // Stop current recording process 717 | [session stopRunning]; 718 | 719 | if (sender.selected) { // Switch to Back camera 720 | sender.selected = NO; 721 | FrontCamera = NO; 722 | [self performSelector:@selector(initializeCamera) withObject:nil afterDelay:0.001]; 723 | } 724 | else { // Switch to Front camera 725 | sender.selected = YES; 726 | FrontCamera = YES; 727 | [self performSelector:@selector(initializeCamera) withObject:nil afterDelay:0.001]; 728 | } 729 | } 730 | 731 | - (IBAction)toogleFlash:(UIButton *)sender{ 732 | if (!FrontCamera) { 733 | if (sender.selected) { // Set flash off 734 | [sender setSelected:NO]; 735 | 736 | NSArray *devices = [AVCaptureDevice devices]; 737 | for (AVCaptureDevice *device in devices) { 738 | if ([device hasMediaType:AVMediaTypeVideo]) { 739 | 740 | if ([device position] == AVCaptureDevicePositionBack) { 741 | NSLog(@"Device position : back"); 742 | if ([device hasFlash]){ 743 | 744 | [device lockForConfiguration:nil]; 745 | [device setFlashMode:AVCaptureFlashModeOff]; 746 | [device unlockForConfiguration]; 747 | 748 | break; 749 | } 750 | } 751 | } 752 | } 753 | 754 | } 755 | else{ // Set flash on 756 | [sender setSelected:YES]; 757 | 758 | NSArray *devices = [AVCaptureDevice devices]; 759 | for (AVCaptureDevice *device in devices) { 760 | if ([device hasMediaType:AVMediaTypeVideo]) { 761 | 762 | if ([device position] == AVCaptureDevicePositionBack) { 763 | NSLog(@"Device position : back"); 764 | if ([device hasFlash]){ 765 | 766 | [device lockForConfiguration:nil]; 767 | [device setFlashMode:AVCaptureFlashModeOn]; 768 | [device unlockForConfiguration]; 769 | 770 | break; 771 | } 772 | } 773 | } 774 | } 775 | 776 | } 777 | } 778 | } 779 | 780 | #pragma mark - UI Control Helpers 781 | - (void)hideControllers{ 782 | [UIView animateWithDuration:0.2 animations:^{ 783 | //1)animate them out of screen 784 | self.photoBar.center = CGPointMake(self.photoBar.center.x, self.photoBar.center.y+116.0); 785 | self.topBar.center = CGPointMake(self.topBar.center.x, self.topBar.center.y-44.0); 786 | 787 | //2)actually hide them 788 | self.photoBar.alpha = 0.0; 789 | self.topBar.alpha = 0.0; 790 | 791 | } completion:nil]; 792 | } 793 | 794 | - (void)showControllers{ 795 | [UIView animateWithDuration:0.2 animations:^{ 796 | //1)animate them into screen 797 | self.photoBar.center = CGPointMake(self.photoBar.center.x, self.photoBar.center.y-116.0); 798 | self.topBar.center = CGPointMake(self.topBar.center.x, self.topBar.center.y+44.0); 799 | 800 | //2)actually show them 801 | self.photoBar.alpha = 1.0; 802 | self.topBar.alpha = 1.0; 803 | 804 | } completion:nil]; 805 | } 806 | 807 | @end 808 | -------------------------------------------------------------------------------- /CustomImagePicker/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // CustomImagePicker 4 | // 5 | // Created by C S P Nanda on 1/5/15. 6 | // Copyright (c) 2015 C S P Nanda. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /CustomImagePickerTests/CustomImagePickerTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // CustomImagePickerTests.m 3 | // CustomImagePickerTests 4 | // 5 | // Created by Prasanna Nanda on 1/5/15. 6 | // Copyright (c) 2015 Prasanna Nanda. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface CustomImagePickerTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation CustomImagePickerTests 17 | 18 | - (void)setUp { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown { 24 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /CustomImagePickerTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | mompop.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Header.h 3 | // CustomImagePicker 4 | // 5 | // Created by Prasanna Nanda on 6/28/15. 6 | // Copyright (c) 2015 Prasanna Nanda. All rights reserved. 7 | // 8 | 9 | #ifndef CustomImagePicker_Header_h 10 | #define CustomImagePicker_Header_h 11 | 12 | #define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) 13 | #define IS_IPHONE (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) 14 | #define IS_RETINA ([[UIScreen mainScreen] scale] >= 2.0) 15 | 16 | #define SCREEN_WIDTH ([[UIScreen mainScreen] bounds].size.width) 17 | #define SCREEN_HEIGHT ([[UIScreen mainScreen] bounds].size.height) 18 | #define SCREEN_MAX_LENGTH (MAX(SCREEN_WIDTH, SCREEN_HEIGHT)) 19 | #define SCREEN_MIN_LENGTH (MIN(SCREEN_WIDTH, SCREEN_HEIGHT)) 20 | 21 | #define IS_IPHONE_4_OR_LESS (IS_IPHONE && SCREEN_MAX_LENGTH < 568.0) 22 | #define IS_IPHONE_5 (IS_IPHONE && SCREEN_MAX_LENGTH == 568.0) 23 | #define IS_IPHONE_6 (IS_IPHONE && SCREEN_MAX_LENGTH == 667.0) 24 | #define IS_IPHONE_6P (IS_IPHONE && SCREEN_MAX_LENGTH == 736.0) 25 | 26 | 27 | 28 | #define CELLCONTENTOFFSET 12.5 29 | #define MAX_ALLOWED_PICK 3 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 C S P Nanda 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CustomImagePicker 2 | An integrated Image Picker for iPhone like the one used in FB or twitter. 3 | All the images in your Camera Roll is shown as cells in a collection view. 4 | The Camera is shown as the first cell. Look at the attached screenshot.jpg. 5 | v2.0 adds the support for live camera feed. Read more about it at http://iosrecipe.blogspot.com/2015/06/integrated-image-picker-for-ios.html 6 | 7 | Branches 8 | -------- 9 | 1. Master branch uses the ALAssetLibrary to handle photos. 10 | 2. photokit branch uses the PHAsset or the new Photo framework to handle photos. All new 11 | functionality will be available by Apple in the photokit going forward. 12 | 13 | How to Use it 14 | ------------- 15 | 1. Add all files from the example project except the AppDelegate and 16 | ViewController to your project. 17 | 2. Import CustomImagePicker.h into your ViewController.h and implement the 18 | delegate CustomeImagePickerDelegate 19 | 3. Implement method -(void) imageSelected:(NSArray *)arrayOfImages in your 20 | ViewController to get the array containing AssetURLs. 21 | -------------------------------------------------------------------------------- /images/camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cspnanda/CustomImagePicker/72f140b66a91e8f09506e29912cf1e4c76119479/images/camera.png -------------------------------------------------------------------------------- /images/cameraorange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cspnanda/CustomImagePicker/72f140b66a91e8f09506e29912cf1e4c76119479/images/cameraorange.png -------------------------------------------------------------------------------- /images/discard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cspnanda/CustomImagePicker/72f140b66a91e8f09506e29912cf1e4c76119479/images/discard.png -------------------------------------------------------------------------------- /images/discard@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cspnanda/CustomImagePicker/72f140b66a91e8f09506e29912cf1e4c76119479/images/discard@2x.png -------------------------------------------------------------------------------- /images/flash-auto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cspnanda/CustomImagePicker/72f140b66a91e8f09506e29912cf1e4c76119479/images/flash-auto.png -------------------------------------------------------------------------------- /images/flash-auto@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cspnanda/CustomImagePicker/72f140b66a91e8f09506e29912cf1e4c76119479/images/flash-auto@2x.png -------------------------------------------------------------------------------- /images/flash-off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cspnanda/CustomImagePicker/72f140b66a91e8f09506e29912cf1e4c76119479/images/flash-off.png -------------------------------------------------------------------------------- /images/flash-off@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cspnanda/CustomImagePicker/72f140b66a91e8f09506e29912cf1e4c76119479/images/flash-off@2x.png -------------------------------------------------------------------------------- /images/flash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cspnanda/CustomImagePicker/72f140b66a91e8f09506e29912cf1e4c76119479/images/flash.png -------------------------------------------------------------------------------- /images/flash@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cspnanda/CustomImagePicker/72f140b66a91e8f09506e29912cf1e4c76119479/images/flash@2x.png -------------------------------------------------------------------------------- /images/focus-crosshair.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cspnanda/CustomImagePicker/72f140b66a91e8f09506e29912cf1e4c76119479/images/focus-crosshair.png -------------------------------------------------------------------------------- /images/focus-crosshair@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cspnanda/CustomImagePicker/72f140b66a91e8f09506e29912cf1e4c76119479/images/focus-crosshair@2x.png -------------------------------------------------------------------------------- /images/front-camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cspnanda/CustomImagePicker/72f140b66a91e8f09506e29912cf1e4c76119479/images/front-camera.png -------------------------------------------------------------------------------- /images/front-camera@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cspnanda/CustomImagePicker/72f140b66a91e8f09506e29912cf1e4c76119479/images/front-camera@2x.png -------------------------------------------------------------------------------- /images/screenshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cspnanda/CustomImagePicker/72f140b66a91e8f09506e29912cf1e4c76119479/images/screenshot.jpg -------------------------------------------------------------------------------- /images/take-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cspnanda/CustomImagePicker/72f140b66a91e8f09506e29912cf1e4c76119479/images/take-snap.png -------------------------------------------------------------------------------- /images/take-snap@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cspnanda/CustomImagePicker/72f140b66a91e8f09506e29912cf1e4c76119479/images/take-snap@2x.png -------------------------------------------------------------------------------- /images/tick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cspnanda/CustomImagePicker/72f140b66a91e8f09506e29912cf1e4c76119479/images/tick.png -------------------------------------------------------------------------------- /screenshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cspnanda/CustomImagePicker/72f140b66a91e8f09506e29912cf1e4c76119479/screenshot.jpg --------------------------------------------------------------------------------