Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
xcuserdata
12 changes: 12 additions & 0 deletions RSAvatarController.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,23 @@
@protocol RSAvatarControllerDelegate <UINavigationControllerDelegate>

- (void)avatarController:(RSAvatarController *)controller pickedAvatar:(UIImage *)avatar;

/* Supplies the view that will be overlaid atop the selected image as its being moved and scaled.
This view should include controls (i.e., UIButtons or gesture recognizers) that send "cancel"
and "choose" messages to the trait object, when the user has canceled or chosen their
move and scale transformation on the picked image.
*/
- (UIView *)avatarController:(RSAvatarController *)controller overlayForMoveAndScale:(id<RSMoveAndScaleTrait>)trait;

// Returns rect to be used for popover, on iPad
- (CGRect)popoverRectForAvatarController:(RSAvatarController *)controller;

// size to which selected image will be scaled
- (CGSize)destinationImageSizeForAvatarController:(RSAvatarController *)controller;

@optional

// Supplies overlay for the image picker
- (UIView *)overlayForAvatarControllerImagePicker:(RSAvatarController *)controller;

@end
61 changes: 34 additions & 27 deletions RSAvatarController.m
Original file line number Diff line number Diff line change
Expand Up @@ -100,49 +100,56 @@ - (void)switchFlashMode
}
}

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
#pragma mark UIPopoverControllerDelegate

- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
UIImage *originImage = [info objectForKey:UIImagePickerControllerOriginalImage];
RSMoveAndScaleController *moveAndScale = [[RSMoveAndScaleController alloc] init];
moveAndScale.originImage = originImage;
moveAndScale.destinationSize = [self.delegate destinationImageSizeForAvatarController:self];
moveAndScale.overlayView = [self.delegate avatarController:self overlayForMoveAndScale:moveAndScale];
moveAndScale.delegate = self;
[picker pushViewController:moveAndScale animated:NO];
popover = nil;
_imagePicker = nil;
}

- (void)moveAndScaleController:(RSMoveAndScaleController *)moveAndScale didFinishCropping:(UIImage *)destImage
#pragma mark UIImagePickerControllerDelegate

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
[self.delegate avatarController:self pickedAvatar:destImage];
[self.imagePicker popToRootViewControllerAnimated:NO];
[self imagePickerControllerDidCancel:self.imagePicker];
UIImage *originImage = [info objectForKey:UIImagePickerControllerOriginalImage];
RSMoveAndScaleController *moveAndScale = [[RSMoveAndScaleController alloc] init];
moveAndScale.originImage = originImage;
moveAndScale.destinationSize = [self.delegate destinationImageSizeForAvatarController:self];
moveAndScale.overlayView = [self.delegate avatarController:self overlayForMoveAndScale:moveAndScale];
moveAndScale.delegate = self;
[picker pushViewController:moveAndScale animated:NO];
}

- (void)moveAndScaleControllerDidCancel:(RSMoveAndScaleController *)moveAndScale
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[self.imagePicker popToRootViewControllerAnimated:NO];
[self imagePickerControllerDidCancel:self.imagePicker];
if (popover) {
[popover dismissPopoverAnimated:YES];
popover = nil;
} else {
[picker.presentingViewController dismissViewControllerAnimated:YES completion:^{
_imagePicker = nil;
}];
}
}

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
#pragma mark RSMoveAndScaleControllerDelegate

- (void)moveAndScaleController:(RSMoveAndScaleController *)moveAndScale didFinishCropping:(UIImage *)destImage
{
if (popover) {
[popover dismissPopoverAnimated:YES];
popover = nil;
} else {
[picker.presentingViewController dismissViewControllerAnimated:YES completion:^{
_imagePicker = nil;
}];
}
[self.delegate avatarController:self pickedAvatar:destImage];
[self.imagePicker popToRootViewControllerAnimated:NO];
[self imagePickerControllerDidCancel:self.imagePicker];
}

- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
- (void)moveAndScaleControllerDidCancel:(RSMoveAndScaleController *)moveAndScale
{
popover = nil;
_imagePicker = nil;
[self.imagePicker popToRootViewControllerAnimated:NO];
[self imagePickerControllerDidCancel:self.imagePicker];
}

#pragma mark - UINavigationControllerDelegate

- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if ([self.delegate respondsToSelector:@selector(navigationController:didShowViewController:animated:)])
Expand Down
6 changes: 6 additions & 0 deletions RSAvatarController.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
5E5614AE19DEFF9800D88C74 /* DemoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5E5614AD19DEFF9800D88C74 /* DemoViewController.m */; };
CF2886B9177AB26300B43887 /* RSAvatarController.m in Sources */ = {isa = PBXBuildFile; fileRef = CF2886B8177AB26300B43887 /* RSAvatarController.m */; };
CF2886BF177AB34A00B43887 /* RSMoveAndScaleController.m in Sources */ = {isa = PBXBuildFile; fileRef = CF2886BE177AB34A00B43887 /* RSMoveAndScaleController.m */; };
CF7B83AD17B8E34D00913E5B /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CF7B83AC17B8E34D00913E5B /* QuartzCore.framework */; };
Expand All @@ -22,6 +23,8 @@
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
5E5614AC19DEFF9800D88C74 /* DemoViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DemoViewController.h; sourceTree = "<group>"; };
5E5614AD19DEFF9800D88C74 /* DemoViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DemoViewController.m; sourceTree = "<group>"; };
CF2886B7177AB26300B43887 /* RSAvatarController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RSAvatarController.h; sourceTree = "<group>"; };
CF2886B8177AB26300B43887 /* RSAvatarController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RSAvatarController.m; sourceTree = "<group>"; };
CF2886BD177AB34A00B43887 /* RSMoveAndScaleController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RSMoveAndScaleController.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -103,6 +106,8 @@
CFA94345177AB13E005782D7 /* RSAppDelegate.h */,
CFA94346177AB13E005782D7 /* RSAppDelegate.m */,
CFA9433D177AB13E005782D7 /* Supporting Files */,
5E5614AC19DEFF9800D88C74 /* DemoViewController.h */,
5E5614AD19DEFF9800D88C74 /* DemoViewController.m */,
);
path = RSAvatarController;
sourceTree = "<group>";
Expand Down Expand Up @@ -190,6 +195,7 @@
CFA94343177AB13E005782D7 /* main.m in Sources */,
CF2886BF177AB34A00B43887 /* RSMoveAndScaleController.m in Sources */,
CF2886B9177AB26300B43887 /* RSAvatarController.m in Sources */,
5E5614AE19DEFF9800D88C74 /* DemoViewController.m in Sources */,
CFA94347177AB13E005782D7 /* RSAppDelegate.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDESourceControlProjectFavoriteDictionaryKey</key>
<false/>
<key>IDESourceControlProjectIdentifier</key>
<string>F78C5D8D-FEA8-4FD1-8CDF-628827FD99D7</string>
<key>IDESourceControlProjectName</key>
<string>RSAvatarController</string>
<key>IDESourceControlProjectOriginsDictionary</key>
<dict>
<key>8E6F39E93010B62143E7BF0514D25B452B518332</key>
<string>github.com:algal/RSAvatarController.git</string>
</dict>
<key>IDESourceControlProjectPath</key>
<string>RSAvatarController.xcodeproj</string>
<key>IDESourceControlProjectRelativeInstallPathDictionary</key>
<dict>
<key>8E6F39E93010B62143E7BF0514D25B452B518332</key>
<string>../..</string>
</dict>
<key>IDESourceControlProjectURL</key>
<string>github.com:algal/RSAvatarController.git</string>
<key>IDESourceControlProjectVersion</key>
<integer>111</integer>
<key>IDESourceControlProjectWCCIdentifier</key>
<string>8E6F39E93010B62143E7BF0514D25B452B518332</string>
<key>IDESourceControlProjectWCConfigurations</key>
<array>
<dict>
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
<string>public.vcs.git</string>
<key>IDESourceControlWCCIdentifierKey</key>
<string>8E6F39E93010B62143E7BF0514D25B452B518332</string>
<key>IDESourceControlWCCName</key>
<string>RSAvatarController</string>
</dict>
</array>
</dict>
</plist>
13 changes: 13 additions & 0 deletions RSAvatarController/DemoViewController.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// DemoViewController.h
// RSAvatarController
//
// Created by Alexis Gallagher on 2014-10-03.
// Copyright (c) 2014 Rex Sheng. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface DemoViewController : UIViewController

@end
142 changes: 142 additions & 0 deletions RSAvatarController/DemoViewController.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
//
// DemoViewController.m
// RSAvatarController
//
// Created by Alexis Gallagher on 2014-10-03.
// Copyright (c) 2014 Rex Sheng. All rights reserved.
//

#import "DemoViewController.h"
#import "RSAvatarController.h"

@interface DemoViewController ()
@property (strong,nonatomic) RSAvatarController * rsAvatarController;
@property (weak,nonatomic) UIImageView * pickedImageView;
@end

@interface DemoViewController (RSAvatarControllerDelegate) <RSAvatarControllerDelegate>
- (void)avatarController:(RSAvatarController *)controller pickedAvatar:(UIImage *)avatar;
- (UIView *)avatarController:(RSAvatarController *)controller overlayForMoveAndScale:(id<RSMoveAndScaleTrait>)trait;
- (CGRect)popoverRectForAvatarController:(RSAvatarController *)controller;
- (CGSize)destinationImageSizeForAvatarController:(RSAvatarController *)controller;

//@optional
- (UIView *)overlayForAvatarControllerImagePicker:(RSAvatarController *)controller;

@end

@implementation DemoViewController

- (void)viewDidLoad {
[super viewDidLoad];

self.view.backgroundColor = [UIColor whiteColor];

// add a button that launches the RSAvatarController
UIButton * button = [UIButton buttonWithType:UIButtonTypeSystem];
[button setTitle:@"LAUNCH RSAVATARCONTROLLER" forState:UIControlStateNormal];
[button addTarget:self action:@selector(handleTap:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];

// add a UIImageView beneath it.
UIImageView * imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
[self.view addSubview:imageView];
self.pickedImageView = imageView;

// center the button
button.translatesAutoresizingMaskIntoConstraints = NO;
imageView.translatesAutoresizingMaskIntoConstraints = NO;
UIView * superview = self.view;
NSDictionary * views = NSDictionaryOfVariableBindings(button,imageView,superview);
[@[@"V:|-(100)-[button]-(20)-[imageView]", // stack the views
@"V:[superview]-(>=0)-[button]"] // center them w/r/t/ superview
enumerateObjectsUsingBlock:
^(NSString * visualFormat, NSUInteger idx, BOOL *stop) {
[self.view addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:visualFormat
options:NSLayoutFormatAlignAllCenterX
metrics:nil views:views]];
}];
}

- (void) handleTap:(id)sender {
self.rsAvatarController = [[RSAvatarController alloc] init];
self.rsAvatarController.delegate = self;
[self.rsAvatarController openActionSheetInController:self];
}

- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

#pragma mark - RSAvatarControllerDelegate

- (void)avatarController:(RSAvatarController *)controller pickedAvatar:(UIImage *)avatar
{
NSLog(@"picked image=%@",avatar);
self.pickedImageView.image = avatar;
}

- (UIView *)avatarController:(RSAvatarController *)controller
overlayForMoveAndScale:(id<RSMoveAndScaleTrait>)trait
{
/*
setup a view holding a "cancel" and "choose" button
*/
UIView * moveAndScaleOverlay = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 200, 100)];

UIButton * cancelButton = [UIButton buttonWithType:UIButtonTypeSystem];
[cancelButton setTitle:@"cancel" forState:UIControlStateNormal];

UIButton * chooseButton = [UIButton buttonWithType:UIButtonTypeSystem];
[chooseButton setTitle:@"choose" forState:UIControlStateNormal];

// wire up the buttons to call the trait object
[cancelButton addTarget:trait action:@selector(cancel) forControlEvents:UIControlEventTouchUpInside];
[chooseButton addTarget:trait action:@selector(choose) forControlEvents:UIControlEventTouchUpInside];


// set up layout so the buttons are left to right with a bit of padding
[moveAndScaleOverlay addSubview:cancelButton];
[moveAndScaleOverlay addSubview:chooseButton];

NSDictionary * views = NSDictionaryOfVariableBindings(cancelButton,chooseButton);
NSMutableArray * constraints = [NSMutableArray array];
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[cancelButton]-(>=20)-[chooseButton]-|" options:NSLayoutFormatAlignAllCenterY metrics:nil views:views]];
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(>=0)-[cancelButton]-(>=0)-|" options:0 metrics:nil views:views]];
[constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(>=0)-[chooseButton]-(>=0)-|" options:0 metrics:nil views:views]];
cancelButton.translatesAutoresizingMaskIntoConstraints = NO;
chooseButton.translatesAutoresizingMaskIntoConstraints = NO;
[moveAndScaleOverlay addConstraints:constraints];

CGSize smallerSize = [moveAndScaleOverlay systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
moveAndScaleOverlay.frame = CGRectMake(moveAndScaleOverlay.frame.origin.x,moveAndScaleOverlay.frame.origin.y,
smallerSize.width,smallerSize.height);

return moveAndScaleOverlay;
}

- (CGRect)popoverRectForAvatarController:(RSAvatarController *)controller
{
// TODO: implement example for iPad
return CGRectMake(0, 0, 100, 100);
}

- (CGSize)destinationImageSizeForAvatarController:(RSAvatarController *)controller
{
return CGSizeMake(150, 150);
}

//@optional
//- (UIView *)overlayForAvatarControllerImagePicker:(RSAvatarController *)controller
//{
// return nil;
//}

#pragma mark debugging

-(void)logTap:(id)sender {
NSLog(@"tap on %@",sender);
}
@end
7 changes: 5 additions & 2 deletions RSAvatarController/RSAppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@
//

#import "RSAppDelegate.h"
#import "DemoViewController.h"

@implementation RSAppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];

// Override point for customization after application launch.
self.window.rootViewController = [[DemoViewController alloc] init];

[self.window makeKeyAndVisible];
return YES;
}
Expand Down
3 changes: 3 additions & 0 deletions RSMoveAndScaleController.m
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,9 @@ - (void)viewDidLoad
clippingView.clipsToBounds = YES;
if (_maximumZoomScale) clippingView.maximumZoomScale = _maximumZoomScale;
[self.view addSubview:_clippingView = clippingView];

// ensure the overlay is over the image
[self.view bringSubviewToFront:self.overlayView];
}

- (void)viewWillAppear:(BOOL)animated
Expand Down