diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 74572eb..d3536f1 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -3,23 +3,27 @@ PODS: - Flutter - MTBBarcodeScanner - Flutter (1.0.0) - - MTBBarcodeScanner (5.0.1) + - MTBBarcodeScanner (5.0.6) DEPENDENCIES: - - barcode_scan (from `/Users/matthew/Projects/AppTree/barcode_scan/ios`) - - Flutter (from `/Users/matthew/flutter/bin/cache/artifacts/engine/ios`) + - barcode_scan (from `/Users/dustin/Documents/workspace_flutter/flutter_barcode_reader/ios`) + - Flutter (from `/Users/dustin/flutter/bin/cache/artifacts/engine/ios`) + +SPEC REPOS: + https://github.com/cocoapods/specs.git: + - MTBBarcodeScanner EXTERNAL SOURCES: barcode_scan: - :path: /Users/matthew/Projects/AppTree/barcode_scan/ios + :path: "/Users/dustin/Documents/workspace_flutter/flutter_barcode_reader/ios" Flutter: - :path: /Users/matthew/flutter/bin/cache/artifacts/engine/ios + :path: "/Users/dustin/flutter/bin/cache/artifacts/engine/ios" SPEC CHECKSUMS: - barcode_scan: 33f586d02270046fc6559135038b34b5754eaa4f - Flutter: d674e78c937094a75ac71dd77e921e840bea3dbf - MTBBarcodeScanner: 66c75f40cbac5986c97634a0775bfe7f92243e7c + barcode_scan: 8288e70cb430072003bce2c794a1431e7adbcb4d + Flutter: 9d0fac939486c9aba2809b7982dfdbb47a7b0296 + MTBBarcodeScanner: bb0bb62e18b57f8a571a482248adc20722b70a91 PODFILE CHECKSUM: 407db753d18e8726329521f96a8fa0bebaef3f42 -COCOAPODS: 1.3.1 +COCOAPODS: 1.5.3 diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 36e6cfc..e4f7c6e 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */ = {isa = PBXBuildFile; fileRef = 2D5378251FAA1A9400D5DBA9 /* flutter_assets */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; @@ -17,7 +18,6 @@ 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; 9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB31CF90195004384FC /* Generated.xcconfig */; }; - 9740EEBB1CF902C7004384FC /* app.flx in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB71CF902C7004384FC /* app.flx */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; @@ -41,6 +41,7 @@ /* Begin PBXFileReference section */ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; @@ -48,7 +49,6 @@ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; - 9740EEB71CF902C7004384FC /* app.flx */ = {isa = PBXFileReference; lastKnownFileType = file; name = app.flx; path = Flutter/app.flx; sourceTree = ""; }; 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; @@ -83,9 +83,9 @@ 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( - 9740EEB71CF902C7004384FC /* app.flx */, 3B80C3931E831B6300D905FE /* App.framework */, 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 2D5378251FAA1A9400D5DBA9 /* flutter_assets */, 9740EEBA1CF902C7004384FC /* Flutter.framework */, 9740EEB21CF90195004384FC /* Debug.xcconfig */, 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, @@ -158,7 +158,6 @@ 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 9B898C697EA984FE43747B57 /* [CP] Embed Pods Frameworks */, - 146C1B61A1B6B49623A4CD5B /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -180,7 +179,7 @@ TargetAttributes = { 97C146ED1CF9000F007C117D = { CreatedOnToolsVersion = 7.3.1; - DevelopmentTeam = RTZBJSE8E8; + DevelopmentTeam = XPX9B2R9P6; LastSwiftMigration = 0830; }; }; @@ -208,10 +207,10 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 9740EEBB1CF902C7004384FC /* app.flx in Resources */, 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */, 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */, 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, @@ -221,24 +220,6 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 146C1B61A1B6B49623A4CD5B /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-resources.sh", - "${PODS_ROOT}/GoogleMaps/Maps/Frameworks/GoogleMaps.framework/Versions/A/Resources/GoogleMaps.bundle", - ); - name = "[CP] Copy Pods Resources"; - outputPaths = ( - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -434,7 +415,7 @@ ARCHS = arm64; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - DEVELOPMENT_TEAM = RTZBJSE8E8; + DEVELOPMENT_TEAM = XPX9B2R9P6; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -461,7 +442,7 @@ ARCHS = arm64; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - DEVELOPMENT_TEAM = RTZBJSE8E8; + DEVELOPMENT_TEAM = XPX9B2R9P6; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", diff --git a/ios/Classes/BarcodeScanPlugin.h b/ios/Classes/BarcodeScanPlugin.h index 88e38f7..197399e 100644 --- a/ios/Classes/BarcodeScanPlugin.h +++ b/ios/Classes/BarcodeScanPlugin.h @@ -1,6 +1,11 @@ #import #import "BarcodeScannerViewControllerDelegate.h" +#define UIColorFromRGB(rgbValue) \ +[UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 \ + green:((float)((rgbValue & 0x00FF00) >> 8))/255.0 \ + blue:((float)((rgbValue & 0x0000FF) >> 0))/255.0 \ + alpha:1.0] @interface BarcodeScanPlugin : NSObject diff --git a/ios/Classes/BarcodeScannerViewController.h b/ios/Classes/BarcodeScannerViewController.h index 6ee6a59..9d80ace 100644 --- a/ios/Classes/BarcodeScannerViewController.h +++ b/ios/Classes/BarcodeScannerViewController.h @@ -6,11 +6,15 @@ #import #import "BarcodeScannerViewControllerDelegate.h" +#import "ScannerOverlay.h" @interface BarcodeScannerViewController : UIViewController @property(nonatomic, retain) UIView *previewView; + @property(nonatomic, retain) ScannerOverlay *scanRect; @property(nonatomic, retain) MTBBarcodeScanner *scanner; @property(nonatomic, weak) id delegate; -@end \ No newline at end of file + + -(id) initWithOptions:(NSDictionary *) options; +@end diff --git a/ios/Classes/BarcodeScannerViewController.m b/ios/Classes/BarcodeScannerViewController.m index 3ca4745..770bde1 100644 --- a/ios/Classes/BarcodeScannerViewController.m +++ b/ios/Classes/BarcodeScannerViewController.m @@ -4,6 +4,7 @@ #import "BarcodeScannerViewController.h" #import +#import "ScannerOverlay.h" @implementation BarcodeScannerViewController { @@ -25,8 +26,28 @@ options:NSLayoutFormatAlignAllBottom metrics:nil views:@{@"previewView": _previewView}]]; + self.scanRect = [[ScannerOverlay alloc] initWithFrame:self.view.bounds]; + self.scanRect.translatesAutoresizingMaskIntoConstraints = NO; + self.scanRect.backgroundColor = UIColor.clearColor; + [self.view addSubview:_scanRect]; + [self.view addConstraints:[NSLayoutConstraint + constraintsWithVisualFormat:@"V:[scanRect]" + options:NSLayoutFormatAlignAllBottom + metrics:nil + views:@{@"scanRect": _scanRect}]]; + [self.view addConstraints:[NSLayoutConstraint + constraintsWithVisualFormat:@"H:[scanRect]" + options:NSLayoutFormatAlignAllBottom + metrics:nil + views:@{@"scanRect": _scanRect}]]; + [_scanRect startAnimating]; self.scanner = [[MTBBarcodeScanner alloc] initWithPreviewView:_previewView]; + __weak BarcodeScannerViewController *weakSelf = self; + self.scanner.didStartScanningBlock = ^{ + weakSelf.scanner.scanRect = weakSelf.scanRect.scanLineRect; + }; self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancel)]; + [self updateFlashButton]; } - (void)viewDidAppear:(BOOL)animated { @@ -90,7 +111,7 @@ - (BOOL)isFlashOn { AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; if (device) { - return device.torchMode == AVCaptureFlashModeOn || AVCaptureTorchModeOn; + return device.torchMode == AVCaptureFlashModeOn || device.torchMode == AVCaptureTorchModeOn; } return NO; } diff --git a/ios/Classes/ScannerOverlay.h b/ios/Classes/ScannerOverlay.h new file mode 100644 index 0000000..2067a95 --- /dev/null +++ b/ios/Classes/ScannerOverlay.h @@ -0,0 +1,8 @@ +#import + +@interface ScannerOverlay : UIView + @property(nonatomic) CGRect scanLineRect; + + - (void) startAnimating; + - (void) stopAnimating; +@end diff --git a/ios/Classes/ScannerOverlay.m b/ios/Classes/ScannerOverlay.m new file mode 100644 index 0000000..ab4c121 --- /dev/null +++ b/ios/Classes/ScannerOverlay.m @@ -0,0 +1,101 @@ +#import "ScannerOverlay.h" + +@interface ScannerOverlay() + @property(nonatomic, retain) UIView *line; +@end + +@implementation ScannerOverlay + + - (instancetype)initWithFrame:(CGRect)frame + { + self = [super initWithFrame:frame]; + if (self) { + _line = [[UIView alloc] init]; + _line.backgroundColor = UIColor.redColor; + _line.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_line]; + } + return self; + } + +- (void)drawRect:(CGRect)rect { + CGContextRef context = UIGraphicsGetCurrentContext(); + + UIColor * overlayColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.55]; + UIColor *scanLineColor = UIColor.redColor; + + CGContextSetFillColorWithColor(context, overlayColor.CGColor); + CGContextFillRect(context, self.bounds); + + // make a hole for the scanner + CGRect holeRect = [self scanRect]; + CGRect holeRectIntersection = CGRectIntersection( holeRect, rect ); + [[UIColor clearColor] setFill]; + UIRectFill(holeRectIntersection); + + // draw a horizontal line over the middle + CGRect lineRect = [self scanLineRect]; + _line.frame = lineRect; + + // drw the green corners + CGFloat cornerSize = 30; + UIBezierPath *path = [UIBezierPath bezierPath]; + //top left corner + [path moveToPoint:CGPointMake(holeRect.origin.x, holeRect.origin.y + cornerSize)]; + [path addLineToPoint:CGPointMake(holeRect.origin.x, holeRect.origin.y)]; + [path addLineToPoint:CGPointMake(holeRect.origin.x + cornerSize, holeRect.origin.y)]; + + //top right corner + CGFloat rightHoleX = holeRect.origin.x + holeRect.size.width; + [path moveToPoint:CGPointMake(rightHoleX - cornerSize, holeRect.origin.y)]; + [path addLineToPoint:CGPointMake(rightHoleX, holeRect.origin.y)]; + [path addLineToPoint:CGPointMake(rightHoleX, holeRect.origin.y + cornerSize)]; + + // bottom right corner + CGFloat bottomHoleY = holeRect.origin.y + holeRect.size.height; + [path moveToPoint:CGPointMake(rightHoleX, bottomHoleY - cornerSize)]; + [path addLineToPoint:CGPointMake(rightHoleX, bottomHoleY)]; + [path addLineToPoint:CGPointMake(rightHoleX - cornerSize, bottomHoleY)]; + + // bottom left corner + [path moveToPoint:CGPointMake(holeRect.origin.x + cornerSize, bottomHoleY)]; + [path addLineToPoint:CGPointMake(holeRect.origin.x, bottomHoleY)]; + [path addLineToPoint:CGPointMake(holeRect.origin.x, bottomHoleY - cornerSize)]; + + path.lineWidth = 2; + [[UIColor greenColor] setStroke]; + [path stroke]; + +} + + - (void)startAnimating { + CABasicAnimation *flash = [CABasicAnimation animationWithKeyPath:@"opacity"]; + flash.fromValue = [NSNumber numberWithFloat:0.0]; + flash.toValue = [NSNumber numberWithFloat:1.0]; + flash.duration = 0.25; + flash.autoreverses = YES; + flash.repeatCount = HUGE_VALF; + [_line.layer addAnimation:flash forKey:@"flashAnimation"]; + } + + - (void)stopAnimating { + [self.layer removeAnimationForKey:@"flashAnimation"]; + } + + - (CGRect)scanRect { + CGRect rect = self.frame; + CGFloat heightMultiplier = 3.0/4.0; // 4:3 aspect ratio + CGFloat scanRectWidth = rect.size.width * 0.8f; + CGFloat scanRectHeight = scanRectWidth * heightMultiplier; + CGFloat scanRectOriginX = (rect.size.width / 2) - (scanRectWidth / 2); + CGFloat scanRectOriginY = (rect.size.height / 2) - (scanRectHeight / 2); + return CGRectMake(scanRectOriginX, scanRectOriginY, scanRectWidth, scanRectHeight); + } + + - (CGRect)scanLineRect { + CGRect scanRect = [self scanRect]; + CGRect rect = self.frame; + return CGRectMake(scanRect.origin.x, rect.size.height / 2, scanRect.size.width, 1); + } + +@end