diff --git a/TZImagePickerController.xcodeproj/project.pbxproj b/TZImagePickerController.xcodeproj/project.pbxproj index 5d01d7c6..963a70bc 100644 --- a/TZImagePickerController.xcodeproj/project.pbxproj +++ b/TZImagePickerController.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 48C130DE2B6F41BF00D8827C /* TZPhotoPickerController+Custom.m in Sources */ = {isa = PBXBuildFile; fileRef = 48C130DD2B6F41BF00D8827C /* TZPhotoPickerController+Custom.m */; }; 570A348C26D7275C000EEF2E /* Photos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 570A348B26D7275C000EEF2E /* Photos.framework */; }; 570A348E26D72762000EEF2E /* PhotosUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 570A348D26D72762000EEF2E /* PhotosUI.framework */; }; 570A349026D72768000EEF2E /* PhotosUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 570A348F26D72768000EEF2E /* PhotosUI.framework */; }; @@ -122,6 +123,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 48C130DC2B6F41BF00D8827C /* TZPhotoPickerController+Custom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "TZPhotoPickerController+Custom.h"; sourceTree = ""; }; + 48C130DD2B6F41BF00D8827C /* TZPhotoPickerController+Custom.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "TZPhotoPickerController+Custom.m"; sourceTree = ""; }; 570A348B26D7275C000EEF2E /* Photos.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Photos.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk/System/Library/Frameworks/Photos.framework; sourceTree = DEVELOPER_DIR; }; 570A348D26D72762000EEF2E /* PhotosUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PhotosUI.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk/System/iOSSupport/System/Library/Frameworks/PhotosUI.framework; sourceTree = DEVELOPER_DIR; }; 570A348F26D72768000EEF2E /* PhotosUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PhotosUI.framework; path = System/Library/Frameworks/PhotosUI.framework; sourceTree = SDKROOT; }; @@ -281,6 +284,8 @@ 900E657E1C2BB8D5003D9A9E /* TZImagePickerController */ = { isa = PBXGroup; children = ( + 48C130DC2B6F41BF00D8827C /* TZPhotoPickerController+Custom.h */, + 48C130DD2B6F41BF00D8827C /* TZPhotoPickerController+Custom.m */, 5B7A0D4F288691E7002B2603 /* Location */, 901F228F215CABD600F604ED /* FLAnimatedImage */, 900EEFF51C2BBF7600EA709B /* TZImagePickerController */, @@ -525,7 +530,7 @@ TargetAttributes = { 900E657B1C2BB8D5003D9A9E = { CreatedOnToolsVersion = 7.2; - DevelopmentTeam = LTFQDC2QVX; + DevelopmentTeam = Z38FDTGA25; ProvisioningStyle = Automatic; }; 900E65941C2BB8D5003D9A9E = { @@ -615,6 +620,7 @@ B662C36F2662914D006A672A /* TZVideoEditedPreviewController.m in Sources */, 9038D5911C3974F0007DE549 /* TZTestCell.m in Sources */, 900EF00F1C2C0B1100EA709B /* TZAssetModel.m in Sources */, + 48C130DE2B6F41BF00D8827C /* TZPhotoPickerController+Custom.m in Sources */, 900EEFFE1C2BD58B00EA709B /* TZPhotoPickerController.m in Sources */, 900EF0021C2BD7E400EA709B /* TZAssetCell.m in Sources */, 6DD0502B1DF659ED0057C78D /* TZProgressView.m in Sources */, @@ -781,7 +787,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.2; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -829,7 +835,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.2; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; @@ -844,13 +850,13 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = LTFQDC2QVX; + DEVELOPMENT_TEAM = Z38FDTGA25; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/TZImagePickerController", ); INFOPLIST_FILE = TZImagePickerController/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; MARKETING_VERSION = 3.8.4; PRODUCT_BUNDLE_IDENTIFIER = tanzhenios2022.TZImagePickerController.www; @@ -869,13 +875,13 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = LTFQDC2QVX; + DEVELOPMENT_TEAM = Z38FDTGA25; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/TZImagePickerController", ); INFOPLIST_FILE = TZImagePickerController/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; MARKETING_VERSION = 3.8.4; PRODUCT_BUNDLE_IDENTIFIER = tanzhenios2022.TZImagePickerController.www; @@ -962,7 +968,7 @@ GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = TZImagePickerControllerFramework/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MARKETING_VERSION = 3.8.3; OTHER_LDFLAGS = "-all_load"; @@ -1003,7 +1009,7 @@ GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = TZImagePickerControllerFramework/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MARKETING_VERSION = 3.8.3; OTHER_LDFLAGS = "-all_load"; diff --git a/TZImagePickerController/TZImagePickerController/TZPhotoPreviewCell.m b/TZImagePickerController/TZImagePickerController/TZPhotoPreviewCell.m index 81d0b5ee..10bfd5f7 100644 --- a/TZImagePickerController/TZImagePickerController/TZPhotoPreviewCell.m +++ b/TZImagePickerController/TZImagePickerController/TZPhotoPreviewCell.m @@ -237,11 +237,13 @@ - (void)setAsset:(PHAsset *)asset { [self resizeSubviews]; if (self.imageView.tz_height && self.allowCrop) { CGFloat scale = MAX(self.cropRect.size.width / self.imageView.tz_width, self.cropRect.size.height / self.imageView.tz_height); - if (self.scaleAspectFillCrop && scale > 1) { // 如果设置图片缩放裁剪并且图片需要缩放 + if (self.scaleAspectFillCrop) { // 如果设置图片缩放裁剪并且图片需要缩放 CGFloat multiple = self.scrollView.maximumZoomScale / self.scrollView.minimumZoomScale; self.scrollView.minimumZoomScale = scale; self.scrollView.maximumZoomScale = scale * MAX(multiple, 2); - [self.scrollView setZoomScale:scale animated:YES]; + if (scale > 1) { // 自动放大与框同宽,如果是缩小,等用户手动操作 + [self.scrollView setZoomScale:scale animated:YES]; + } } } diff --git a/TZImagePickerController/TZPhotoPickerController+Custom.h b/TZImagePickerController/TZPhotoPickerController+Custom.h new file mode 100644 index 00000000..898b3b9b --- /dev/null +++ b/TZImagePickerController/TZPhotoPickerController+Custom.h @@ -0,0 +1,17 @@ +// +// TZPhotoPickerController+Custom.h +// yxqls +// +// Created by mac17 on 2021/8/24. +// + +#import "TZPhotoPickerController.h" +#import "TZImagePickerController.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TZPhotoPickerController (Custom) + +@end + +NS_ASSUME_NONNULL_END diff --git a/TZImagePickerController/TZPhotoPickerController+Custom.m b/TZImagePickerController/TZPhotoPickerController+Custom.m new file mode 100644 index 00000000..4ed80c0e --- /dev/null +++ b/TZImagePickerController/TZPhotoPickerController+Custom.m @@ -0,0 +1,162 @@ +// +// TZPhotoPickerController+Custom.m +// yxqls +// +// Created by mac17 on 2021/8/24. +// + +#import "TZPhotoPickerController+Custom.h" +#import +#import +#import "TZAssetCell.h" +#import + +@implementation TZPhotoPickerController (Custom) + ++ (void)load { + [self swizzleSEL:NSSelectorFromString(@"initSubviews") withSEL:@selector(sw_initSubviews)]; +} + ++ (void)swizzleSEL:(SEL)originalSEL withSEL:(SEL)swizzledSEL { + Class class = [self class]; + + Method originalMethod = class_getInstanceMethod(class, originalSEL); + Method swizzledMethod = class_getInstanceMethod(class, swizzledSEL); + + BOOL didAddMethod = + class_addMethod(class, + originalSEL, + method_getImplementation(swizzledMethod), + method_getTypeEncoding(swizzledMethod)); + + if (didAddMethod) { + class_replaceMethod(class, + swizzledSEL, + method_getImplementation(originalMethod), + method_getTypeEncoding(originalMethod)); + } else { + method_exchangeImplementations(originalMethod, swizzledMethod); + } +} + +- (void)sw_initSubviews { + [self sw_initSubviews]; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + TZImagePickerController *imgPicker = (TZImagePickerController *)self.navigationController; + if (imgPicker.maxImagesCount == 1 || imgPicker.allowPickingVideo) { + return;//只能选择一个或者能选视频,不启用多选 + } + UIPanGestureRecognizer *ges = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(multiSelectAction:)]; + [self.view addGestureRecognizer:ges]; + }); +} + +//@property (nonatomic, strong) TZCollectionView *collectionView;UICollectionViewFlowLayout *layout +- (TZCollectionView *)collView { + return [self valueForKey:@"collectionView"]; +} +- (UICollectionViewFlowLayout *)collLayout { + return [self valueForKey:@"layout"]; +} + +static CGFloat itemMargin = 5;//这个变量直接复制自原文件,如果原文件改了这个需要也改一下 +- (void)multiSelectAction:(UIGestureRecognizer *)ges { + static NSInteger beginIdx = -1; + CGPoint lc = [ges locationInView:self.collView]; + NSInteger h = self.collLayout.itemSize.height + itemMargin; + NSInteger w = self.collLayout.itemSize.width + itemMargin; + NSInteger line = (NSInteger)lc.y / h; + NSInteger column = (NSInteger)lc.x / w; + NSInteger idx = line * self.columnNumber + column; + if (beginIdx == -1) { + beginIdx = idx; + } + [self selectIdx:beginIdx toIdx2:idx]; + if (self.collView.contentOffset.y + self.collView.bounds.size.height - lc.y < 40) { + selectingTopEdge = NO; + [self dpLink]; + } else if (lc.y - self.collView.contentOffset.y < 40) { + selectingTopEdge = YES; + [self dpLink]; + } else { + [dpLink invalidate]; + dpLink = nil; + } + if (ges.state == UIGestureRecognizerStateEnded || ges.state == UIGestureRecognizerStateCancelled) { + beginIdx = -1; + isCancel = -1; + previousEndIdx = -1; + currEndIdx = -1; + [dpLink invalidate]; + dpLink = nil; + } +} + +- (void)selectingEdge { + CGPoint off = self.collView.contentOffset; + off.y += selectingTopEdge ? -5 : 5; + off.y = MAX(- itemMargin, off.y); + off.y = MIN(self.collView.contentSize.height - self.collView.frame.size.height + itemMargin, off.y); + self.collView.contentOffset = off; +} + +- (CADisplayLink *)dpLink { + if (!dpLink) { + dpLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(selectingEdge)]; + [dpLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; + } + return dpLink; +} + +static CADisplayLink *dpLink; +static BOOL selectingTopEdge; +static NSInteger isCancel = -1; +static NSInteger previousEndIdx = -1;//选过的最大index +static NSInteger currEndIdx = -1; +- (void)selectIdx:(NSInteger)idx toIdx2:(NSInteger)idx2 { + if (currEndIdx == idx2) { + return;//手指在同一个cell上多次触发 + } + currEndIdx = idx2; + if (previousEndIdx != -1) { + BOOL preBigger = previousEndIdx > idx2 && previousEndIdx > idx; + BOOL preSmaller = previousEndIdx < idx2 && previousEndIdx < idx; + if (preBigger || preSmaller) {//选则过程中往回滑动 + //是否反转了方向(例:本来向下滑选择,往回滑动越过了起点变成了向上滑选择) + BOOL isReverse = (idx2 > idx && idx > previousEndIdx) || (idx2 < idx && idx < previousEndIdx); + for (NSInteger i = previousEndIdx; (preBigger && i > MAX(idx, idx2)) || (preSmaller && i < MIN(idx, idx2)); preBigger ? i-- : i++) { + NSIndexPath *idxp = [NSIndexPath indexPathForItem:i inSection:0]; + TZAssetCell *cell = (TZAssetCell *)[self.collView cellForItemAtIndexPath:idxp]; + [self selectCell:cell isBack:YES]; + } + previousEndIdx = idx2; + if (!isReverse) { + return;//之前的已经选中/取消选中,不再走下面的逻辑 + } + } + } + BOOL idx2Bigger = idx2 > idx; + for (NSInteger i = idx; (idx2Bigger && i <= idx2) || (!idx2Bigger && i >= idx2); idx2Bigger ? i++ : i--) { + NSIndexPath *idxp = [NSIndexPath indexPathForItem:i inSection:0]; + TZAssetCell *cell = (TZAssetCell *)[self.collView cellForItemAtIndexPath:idxp]; + if (isCancel == -1 && i == idx) {//如果第一个选择的是已选中状态,则全体都是取消选中,反之为选中 + isCancel = cell.selectPhotoButton.selected; + } + [self selectCell:cell isBack:NO]; + } + previousEndIdx = idx2; + NSLog(@"%@选择至%ld", isCancel ? @"取消" : @"", (long)idx2); +} + +- (void)selectCell:(TZAssetCell *)cell isBack:(BOOL)isBack { + BOOL select = isBack ? !isCancel : isCancel; + SEL selectSel = NSSelectorFromString(@"selectPhotoButtonClick:"); + if ([cell respondsToSelector:selectSel] && cell.selectPhotoButton.selected == select) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + [cell performSelector:selectSel withObject:cell.selectPhotoButton]; +#pragma clang diagnostic pop + } +} + +@end