Merge pull request #34 from dustin-graham/customize_ios

Make iOS scanner UI look the same as Android
This commit is contained in:
Matthew Smith 2018-08-29 21:55:57 -07:00 committed by GitHub
commit b830da7e84
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 161 additions and 37 deletions

View File

@ -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

View File

@ -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 = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
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 = "<group>"; };
3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
@ -48,7 +49,6 @@
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
9740EEB71CF902C7004384FC /* app.flx */ = {isa = PBXFileReference; lastKnownFileType = file; name = app.flx; path = Flutter/app.flx; sourceTree = "<group>"; };
9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = "<group>"; };
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 = "<group>"; };
@ -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)",

View File

@ -1,6 +1,11 @@
#import <Flutter/Flutter.h>
#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<FlutterPlugin, BarcodeScannerViewControllerDelegate>

View File

@ -6,11 +6,15 @@
#import <MTBBarcodeScanner/MTBBarcodeScanner.h>
#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<BarcodeScannerViewControllerDelegate> delegate;
@end
-(id) initWithOptions:(NSDictionary *) options;
@end

View File

@ -4,6 +4,7 @@
#import "BarcodeScannerViewController.h"
#import <MTBBarcodeScanner/MTBBarcodeScanner.h>
#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;
}

View File

@ -0,0 +1,8 @@
#import <UIKit/UIKit.h>
@interface ScannerOverlay : UIView
@property(nonatomic) CGRect scanLineRect;
- (void) startAnimating;
- (void) stopAnimating;
@end

View File

@ -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