diff --git a/.gitignore b/.gitignore index 1e502dc..b6590b2 100755 --- a/.gitignore +++ b/.gitignore @@ -2,9 +2,15 @@ # .DS_Store -# Xcode + +# Build generated # build/ +DerivedData + + +# Various settings +# *.pbxuser !default.pbxuser *.mode1v3 @@ -14,15 +20,37 @@ build/ *.perspectivev3 !default.perspectivev3 xcuserdata + + +# Other +# *.xccheckout *.moved-aside -DerivedData +*.xcuserstate +*.xcscmblueprint + + +# Obj-C/Swift specific +# *.hmap *.ipa -*.xcuserstate *.gcno *.gcda + +# Binaries +# +*.zip + + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build + + # CocoaPods # # We recommend against adding the Pods directory to your .gitignore. However diff --git a/Example/RSKImageCropperExample/RSKImageCropperExample-Info.plist b/Example/RSKImageCropperExample/RSKImageCropperExample-Info.plist index bfb557b..ae4d14d 100755 --- a/Example/RSKImageCropperExample/RSKImageCropperExample-Info.plist +++ b/Example/RSKImageCropperExample/RSKImageCropperExample-Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.4.1 + 1.5.0 CFBundleSignature ???? CFBundleVersion diff --git a/Framework/Info.plist b/Framework/Info.plist index 07b3f7e..beed82a 100755 --- a/Framework/Info.plist +++ b/Framework/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.4.1 + 1.5.0 CFBundleSignature ???? CFBundleVersion diff --git a/RSKImageCropper.podspec b/RSKImageCropper.podspec index 3c6120d..0327889 100644 --- a/RSKImageCropper.podspec +++ b/RSKImageCropper.podspec @@ -1,14 +1,19 @@ Pod::Spec.new do |s| - s.name = 'RSKImageCropper' - s.version = '1.4.1' - s.summary = 'An image cropper for iOS like in the Contacts app with support for landscape orientation.' - s.homepage = 'https://github.com/ruslanskorb/RSKImageCropper' - s.license = { :type => 'MIT', :file => 'LICENSE' } - s.authors = { 'Ruslan Skorb' => 'ruslan.skorb@gmail.com' } - s.source = { :git => 'https://github.com/ruslanskorb/RSKImageCropper.git', :tag => s.version.to_s } - s.platform = :ios, '6.0' - s.source_files = 'RSKImageCropper/*.{h,m}' - s.resources = 'RSKImageCropper/RSKImageCropperStrings.bundle' - s.frameworks = 'QuartzCore', 'UIKit' - s.requires_arc = true + s.name = 'RSKImageCropper' + s.version = '1.5.0' + s.summary = 'An image cropper for iOS like in the Contacts app with support for landscape orientation.' + s.homepage = 'https://github.com/ruslanskorb/RSKImageCropper' + s.license = { :type => 'MIT', :file => 'LICENSE' } + s.authors = { 'Ruslan Skorb' => 'ruslan.skorb@gmail.com' } + s.source = { :git => 'https://github.com/ruslanskorb/RSKImageCropper.git', :tag => s.version.to_s } + s.platform = :ios, '6.0' + s.source_files = 'RSKImageCropper/*.{h,m}' + s.resources = 'RSKImageCropper/RSKImageCropperStrings.bundle' + s.frameworks = 'QuartzCore', 'UIKit' + s.requires_arc = true + s.public_header_files = [ + 'RSKImageCropper/RSKImageCropper.h', + 'RSKImageCropper/RSKImageCropViewController.h', + 'RSKImageCropper/RSKImageCropViewController+Protected.h' + ] end diff --git a/RSKImageCropper.xcodeproj/project.pbxproj b/RSKImageCropper.xcodeproj/project.pbxproj index 1868a6e..cf9ef90 100755 --- a/RSKImageCropper.xcodeproj/project.pbxproj +++ b/RSKImageCropper.xcodeproj/project.pbxproj @@ -226,7 +226,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1.4.1; + CURRENT_PROJECT_VERSION = 1.5.0; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; @@ -274,7 +274,7 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1.4.1; + CURRENT_PROJECT_VERSION = 1.5.0; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -300,8 +300,8 @@ isa = XCBuildConfiguration; buildSettings = { DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1.4.1; - DYLIB_CURRENT_VERSION = 1.4.1; + DYLIB_COMPATIBILITY_VERSION = 1.5.0; + DYLIB_CURRENT_VERSION = 1.5.0; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = Framework/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -316,8 +316,8 @@ isa = XCBuildConfiguration; buildSettings = { DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1.4.1; - DYLIB_CURRENT_VERSION = 1.4.1; + DYLIB_COMPATIBILITY_VERSION = 1.5.0; + DYLIB_CURRENT_VERSION = 1.5.0; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = Framework/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; diff --git a/RSKImageCropper/RSKImageCropViewController+Protected.h b/RSKImageCropper/RSKImageCropViewController+Protected.h index 3573507..25dbd52 100644 --- a/RSKImageCropper/RSKImageCropViewController+Protected.h +++ b/RSKImageCropper/RSKImageCropViewController+Protected.h @@ -48,6 +48,20 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)reset:(BOOL)animated; +/** + Sets the current rotation angle of the image in radians. + + @param rotationAngle The rotation angle of the image in radians. + */ +- (void)setRotationAngle:(CGFloat)rotationAngle; + +/** + Sets the current scale factor for the image. + + @param zoomScale The scale factor for the image. + */ +- (void)setZoomScale:(CGFloat)zoomScale; + @end NS_ASSUME_NONNULL_END diff --git a/RSKImageCropper/RSKImageCropViewController.h b/RSKImageCropper/RSKImageCropViewController.h index a645800..29ce823 100755 --- a/RSKImageCropper/RSKImageCropViewController.h +++ b/RSKImageCropper/RSKImageCropViewController.h @@ -192,6 +192,80 @@ typedef NS_ENUM(NSUInteger, RSKImageCropMode) { */ - (BOOL)isPortraitInterfaceOrientation; +/// ------------------------------------- +/// @name Accessing the Layout Attributes +/// ------------------------------------- + +/** + The inset of the circle mask rect's area within the crop view's area in portrait orientation. Default value is `15.0f`. + */ +@property (assign, nonatomic) CGFloat portraitCircleMaskRectInnerEdgeInset; + +/** + The inset of the square mask rect's area within the crop view's area in portrait orientation. Default value is `20.0f`. + */ +@property (assign, nonatomic) CGFloat portraitSquareMaskRectInnerEdgeInset; + +/** + The vertical space between the top of the 'Move and Scale' label and the top of the crop view in portrait orientation. Default value is `64.0f`. + */ +@property (assign, nonatomic) CGFloat portraitMoveAndScaleLabelTopAndCropViewTopVerticalSpace; + +/** + The vertical space between the bottom of the crop view and the bottom of the 'Cancel' button in portrait orientation. Default value is `21.0f`. + */ +@property (assign, nonatomic) CGFloat portraitCropViewBottomAndCancelButtonBottomVerticalSpace; + +/** + The vertical space between the bottom of the crop view and the bottom of the 'Choose' button in portrait orientation. Default value is `21.0f`. + */ +@property (assign, nonatomic) CGFloat portraitCropViewBottomAndChooseButtonBottomVerticalSpace; + +/** + The horizontal space between the leading of the 'Cancel' button and the leading of the crop view in portrait orientation. Default value is `13.0f`. + */ +@property (assign, nonatomic) CGFloat portraitCancelButtonLeadingAndCropViewLeadingHorizontalSpace; + +/** + The horizontal space between the trailing of the crop view and the trailing of the 'Choose' button in portrait orientation. Default value is `13.0f`. + */ +@property (assign, nonatomic) CGFloat portraitCropViewTrailingAndChooseButtonTrailingHorizontalSpace; + +/** + The inset of the circle mask rect's area within the crop view's area in landscape orientation. Default value is `45.0f`. + */ +@property (assign, nonatomic) CGFloat landscapeCircleMaskRectInnerEdgeInset; + +/** + The inset of the square mask rect's area within the crop view's area in landscape orientation. Default value is `45.0f`. + */ +@property (assign, nonatomic) CGFloat landscapeSquareMaskRectInnerEdgeInset; + +/** + The vertical space between the top of the 'Move and Scale' label and the top of the crop view in landscape orientation. Default value is `12.0f`. + */ +@property (assign, nonatomic) CGFloat landscapeMoveAndScaleLabelTopAndCropViewTopVerticalSpace; + +/** + The vertical space between the bottom of the crop view and the bottom of the 'Cancel' button in landscape orientation. Default value is `12.0f`. + */ +@property (assign, nonatomic) CGFloat landscapeCropViewBottomAndCancelButtonBottomVerticalSpace; + +/** + The vertical space between the bottom of the crop view and the bottom of the 'Choose' button in landscape orientation. Default value is `12.0f`. + */ +@property (assign, nonatomic) CGFloat landscapeCropViewBottomAndChooseButtonBottomVerticalSpace; + +/** + The horizontal space between the leading of the 'Cancel' button and the leading of the crop view in landscape orientation. Default value is `13.0f`. + */ +@property (assign, nonatomic) CGFloat landscapeCancelButtonLeadingAndCropViewLeadingHorizontalSpace; + +/** + The horizontal space between the trailing of the crop view and the trailing of the 'Choose' button in landscape orientation. Default value is `13.0f`. + */ +@property (assign, nonatomic) CGFloat landscapeCropViewTrailingAndChooseButtonTrailingHorizontalSpace; + @end /** diff --git a/RSKImageCropper/RSKImageCropViewController.m b/RSKImageCropper/RSKImageCropViewController.m index 31230c9..27c780d 100644 --- a/RSKImageCropper/RSKImageCropViewController.m +++ b/RSKImageCropper/RSKImageCropViewController.m @@ -30,17 +30,6 @@ #import "CGGeometry+RSKImageCropper.h" #import "UIApplication+RSKImageCropper.h" -static const CGFloat kPortraitCircleMaskRectInnerEdgeInset = 15.0f; -static const CGFloat kPortraitSquareMaskRectInnerEdgeInset = 20.0f; -static const CGFloat kPortraitMoveAndScaleLabelVerticalMargin = 64.0f; -static const CGFloat kPortraitCancelAndChooseButtonsHorizontalMargin = 13.0f; -static const CGFloat kPortraitCancelAndChooseButtonsVerticalMargin = 21.0f; - -static const CGFloat kLandscapeCircleMaskRectInnerEdgeInset = 45.0f; -static const CGFloat kLandscapeSquareMaskRectInnerEdgeInset = 45.0f; -static const CGFloat kLandscapeMoveAndScaleLabelVerticalMargin = 12.0f; -static const CGFloat kLandscapeCancelAndChooseButtonsVerticalMargin = 12.0f; - static const CGFloat kResetAnimationDuration = 0.4; static const CGFloat kLayoutImageScrollViewAnimationDuration = 0.25; @@ -78,7 +67,9 @@ @interface RSKImageCropViewController () @property (assign, nonatomic) BOOL didSetupConstraints; @property (strong, nonatomic) NSLayoutConstraint *moveAndScaleLabelTopConstraint; @property (strong, nonatomic) NSLayoutConstraint *cancelButtonBottomConstraint; +@property (strong, nonatomic) NSLayoutConstraint *cancelButtonLeadingConstraint; @property (strong, nonatomic) NSLayoutConstraint *chooseButtonBottomConstraint; +@property (strong, nonatomic) NSLayoutConstraint *chooseButtonTrailingConstraint; @end @@ -95,6 +86,22 @@ - (instancetype)init _maskLayerLineWidth = 1.0; _rotationEnabled = NO; _cropMode = RSKImageCropModeCircle; + + _portraitCircleMaskRectInnerEdgeInset = 15.0f; + _portraitSquareMaskRectInnerEdgeInset = 20.0f; + _portraitMoveAndScaleLabelTopAndCropViewTopVerticalSpace = 64.0f; + _portraitCropViewBottomAndCancelButtonBottomVerticalSpace = 21.0f; + _portraitCropViewBottomAndChooseButtonBottomVerticalSpace = 21.0f; + _portraitCancelButtonLeadingAndCropViewLeadingHorizontalSpace = 13.0f; + _portraitCropViewTrailingAndChooseButtonTrailingHorizontalSpace = 13.0; + + _landscapeCircleMaskRectInnerEdgeInset = 45.0f; + _landscapeSquareMaskRectInnerEdgeInset = 45.0f; + _landscapeMoveAndScaleLabelTopAndCropViewTopVerticalSpace = 12.0f; + _landscapeCropViewBottomAndCancelButtonBottomVerticalSpace = 12.0f; + _landscapeCropViewBottomAndChooseButtonBottomVerticalSpace = 12.0f; + _landscapeCancelButtonLeadingAndCropViewLeadingHorizontalSpace = 13.0; + _landscapeCropViewTrailingAndChooseButtonTrailingHorizontalSpace = 13.0; } return self; } @@ -217,7 +224,7 @@ - (void)updateViewConstraints constant:0.0f]; [self.view addConstraint:constraint]; - CGFloat constant = kPortraitMoveAndScaleLabelVerticalMargin; + CGFloat constant = self.portraitMoveAndScaleLabelTopAndCropViewTopVerticalSpace; self.moveAndScaleLabelTopConstraint = [NSLayoutConstraint constraintWithItem:self.moveAndScaleLabel attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0f constant:constant]; @@ -227,15 +234,15 @@ - (void)updateViewConstraints // The button "Cancel". // -------------------- - constant = kPortraitCancelAndChooseButtonsHorizontalMargin; - constraint = [NSLayoutConstraint constraintWithItem:self.cancelButton attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual - toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0f - constant:constant]; - [self.view addConstraint:constraint]; + constant = self.portraitCancelButtonLeadingAndCropViewLeadingHorizontalSpace; + self.cancelButtonLeadingConstraint = [NSLayoutConstraint constraintWithItem:self.cancelButton attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual + toItem:self.view attribute:NSLayoutAttributeLeading multiplier:1.0f + constant:constant]; + [self.view addConstraint:self.cancelButtonLeadingConstraint]; - constant = -kPortraitCancelAndChooseButtonsVerticalMargin; - self.cancelButtonBottomConstraint = [NSLayoutConstraint constraintWithItem:self.cancelButton attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual - toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0f + constant = self.portraitCropViewBottomAndCancelButtonBottomVerticalSpace; + self.cancelButtonBottomConstraint = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual + toItem:self.cancelButton attribute:NSLayoutAttributeBottom multiplier:1.0f constant:constant]; [self.view addConstraint:self.cancelButtonBottomConstraint]; @@ -243,28 +250,32 @@ - (void)updateViewConstraints // The button "Choose". // -------------------- - constant = -kPortraitCancelAndChooseButtonsHorizontalMargin; - constraint = [NSLayoutConstraint constraintWithItem:self.chooseButton attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual - toItem:self.view attribute:NSLayoutAttributeRight multiplier:1.0f - constant:constant]; - [self.view addConstraint:constraint]; + constant = self.portraitCropViewTrailingAndChooseButtonTrailingHorizontalSpace; + self.chooseButtonTrailingConstraint = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual + toItem:self.chooseButton attribute:NSLayoutAttributeTrailing multiplier:1.0f + constant:constant]; + [self.view addConstraint:self.chooseButtonTrailingConstraint]; - constant = -kPortraitCancelAndChooseButtonsVerticalMargin; - self.chooseButtonBottomConstraint = [NSLayoutConstraint constraintWithItem:self.chooseButton attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual - toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0f + constant = self.portraitCropViewBottomAndChooseButtonBottomVerticalSpace; + self.chooseButtonBottomConstraint = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual + toItem:self.chooseButton attribute:NSLayoutAttributeBottom multiplier:1.0f constant:constant]; [self.view addConstraint:self.chooseButtonBottomConstraint]; self.didSetupConstraints = YES; } else { if ([self isPortraitInterfaceOrientation]) { - self.moveAndScaleLabelTopConstraint.constant = kPortraitMoveAndScaleLabelVerticalMargin; - self.cancelButtonBottomConstraint.constant = -kPortraitCancelAndChooseButtonsVerticalMargin; - self.chooseButtonBottomConstraint.constant = -kPortraitCancelAndChooseButtonsVerticalMargin; + self.moveAndScaleLabelTopConstraint.constant = self.portraitMoveAndScaleLabelTopAndCropViewTopVerticalSpace; + self.cancelButtonBottomConstraint.constant = self.portraitCropViewBottomAndCancelButtonBottomVerticalSpace; + self.cancelButtonLeadingConstraint.constant = self.portraitCancelButtonLeadingAndCropViewLeadingHorizontalSpace; + self.chooseButtonBottomConstraint.constant = self.portraitCropViewBottomAndChooseButtonBottomVerticalSpace; + self.chooseButtonTrailingConstraint.constant = self.portraitCropViewTrailingAndChooseButtonTrailingHorizontalSpace; } else { - self.moveAndScaleLabelTopConstraint.constant = kLandscapeMoveAndScaleLabelVerticalMargin; - self.cancelButtonBottomConstraint.constant = -kLandscapeCancelAndChooseButtonsVerticalMargin; - self.chooseButtonBottomConstraint.constant = -kLandscapeCancelAndChooseButtonsVerticalMargin; + self.moveAndScaleLabelTopConstraint.constant = self.landscapeMoveAndScaleLabelTopAndCropViewTopVerticalSpace; + self.cancelButtonBottomConstraint.constant = self.landscapeCropViewBottomAndCancelButtonBottomVerticalSpace; + self.cancelButtonLeadingConstraint.constant = self.landscapeCancelButtonLeadingAndCropViewLeadingHorizontalSpace; + self.chooseButtonBottomConstraint.constant = self.landscapeCropViewBottomAndChooseButtonBottomVerticalSpace; + self.chooseButtonTrailingConstraint.constant = self.landscapeCropViewTrailingAndChooseButtonTrailingHorizontalSpace; } } } @@ -496,6 +507,11 @@ - (void)setRotationEnabled:(BOOL)rotationEnabled } } +- (void)setZoomScale:(CGFloat)zoomScale +{ + self.imageScrollView.zoomScale = zoomScale; +} + #pragma mark - Action handling - (void)onCancelButtonTouch:(UIBarButtonItem *)sender @@ -742,9 +758,9 @@ - (void)updateMaskRect CGFloat diameter; if ([self isPortraitInterfaceOrientation]) { - diameter = MIN(viewWidth, viewHeight) - kPortraitCircleMaskRectInnerEdgeInset * 2; + diameter = MIN(viewWidth, viewHeight) - self.portraitCircleMaskRectInnerEdgeInset * 2; } else { - diameter = MIN(viewWidth, viewHeight) - kLandscapeCircleMaskRectInnerEdgeInset * 2; + diameter = MIN(viewWidth, viewHeight) - self.landscapeCircleMaskRectInnerEdgeInset * 2; } CGSize maskSize = CGSizeMake(diameter, diameter); @@ -761,9 +777,9 @@ - (void)updateMaskRect CGFloat length; if ([self isPortraitInterfaceOrientation]) { - length = MIN(viewWidth, viewHeight) - kPortraitSquareMaskRectInnerEdgeInset * 2; + length = MIN(viewWidth, viewHeight) - self.portraitSquareMaskRectInnerEdgeInset * 2; } else { - length = MIN(viewWidth, viewHeight) - kLandscapeSquareMaskRectInnerEdgeInset * 2; + length = MIN(viewWidth, viewHeight) - self.landscapeSquareMaskRectInnerEdgeInset * 2; } CGSize maskSize = CGSizeMake(length, length);