diff --git a/MaterialShowcase.podspec b/MaterialShowcase.podspec index 2d3e32b..c231a80 100644 --- a/MaterialShowcase.podspec +++ b/MaterialShowcase.podspec @@ -13,7 +13,7 @@ s.author = { 'Quang Nguyen' => 'quangnguyen@aromajoin.com' } s.source = { :git => 'https://github.com/aromajoin/material-showcase-ios.git', :tag => s.version.to_s } s.swift_version = '5.0' -s.ios.deployment_target = '8.0' +s.ios.deployment_target = '10.0' s.source_files = 'MaterialShowcase/*.swift' end diff --git a/MaterialShowcase.xcodeproj/project.pbxproj b/MaterialShowcase.xcodeproj/project.pbxproj index 824872f..fbd4c42 100644 --- a/MaterialShowcase.xcodeproj/project.pbxproj +++ b/MaterialShowcase.xcodeproj/project.pbxproj @@ -178,11 +178,11 @@ }; buildConfigurationList = CE083A131EBACFEB0077666F /* Build configuration list for PBXProject "MaterialShowcase" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( - English, en, + Base, ); mainGroup = CE083A0F1EBACFEB0077666F; productRefGroup = CE083A1A1EBACFEB0077666F /* Products */; @@ -341,7 +341,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -398,7 +398,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; @@ -423,7 +423,7 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = MaterialShowcase/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MARKETING_VERSION = 0.7.1; ONLY_ACTIVE_ARCH = NO; @@ -449,7 +449,7 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = MaterialShowcase/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MARKETING_VERSION = 0.7.1; ONLY_ACTIVE_ARCH = NO; diff --git a/MaterialShowcase/MaterialShowcase+Calculations.swift b/MaterialShowcase/MaterialShowcase+Calculations.swift index da72227..fa29031 100644 --- a/MaterialShowcase/MaterialShowcase+Calculations.swift +++ b/MaterialShowcase/MaterialShowcase+Calculations.swift @@ -39,8 +39,8 @@ extension MaterialShowcase { let targetCenterY = targetBounds.midY let expandedRadius = 1.1 * TARGET_HOLDER_RADIUS - let expandedBounds = CGRect(x: targetCenterX, y: targetCenterY, width: 0, height: 0) - expandedBounds.insetBy(dx: -expandedRadius, dy: -expandedRadius); + var expandedBounds = CGRect(x: targetCenterX, y: targetCenterY, width: 0, height: 0) + expandedBounds = expandedBounds.insetBy(dx: -expandedRadius, dy: -expandedRadius); let textRadius = maxDistance(from: center, to: textBounds) let targetRadius = maxDistance(from: center, to: expandedBounds) diff --git a/MaterialShowcase/MaterialShowcase.swift b/MaterialShowcase/MaterialShowcase.swift index 296fab6..748027e 100644 --- a/MaterialShowcase/MaterialShowcase.swift +++ b/MaterialShowcase/MaterialShowcase.swift @@ -43,6 +43,8 @@ open class MaterialShowcase: UIView { var offsetThreshold: CGFloat = 88 // MARK: Private view properties + var closeButton : UIButton! + var containerView: UIView! var targetView: UIView! var backgroundView: UIView! @@ -52,9 +54,13 @@ open class MaterialShowcase: UIView { var targetCopyView: UIView! var instructionView: MaterialShowcaseInstructionView! + + public var skipButton: (() -> Void)? var onTapThrough: (() -> Void)? // MARK: Public Properties + // setSkipImage + public var skipImage = "HintClose" // Background @objc public var backgroundAlpha: CGFloat = 1.0 @@ -169,8 +175,22 @@ extension MaterialShowcase { targetHolderRadius = 0 } + + /// Sets a UICollectionViewCell as target + @objc public func setTargetView(collectionView: UICollectionView, section: Int, item: Int) { + let indexPath = IndexPath(item: item, section: section) + targetView = collectionView.cellForItem(at: indexPath) + // for table viewcell, we do not need target holder (circle view) + // therefore, set its radius = 0 + targetHolderRadius = 0 + } + + @objc func dismissTutorialButtonDidTouch() { + skipButton?() + } + /// Shows it over current screen after completing setup process - @objc public func show(animated: Bool = true, completion handler: (()-> Void)?) { + @objc public func show(animated: Bool = true,hasShadow: Bool = true, hasSkipButton: Bool = true, completion handler: (()-> Void)?) { initViews() alpha = 0.0 containerView.addSubview(self) @@ -181,6 +201,36 @@ extension MaterialShowcase { backgroundView.transform = CGAffineTransform(scaleX: scale, y: scale) // Initial set to support animation backgroundView.center = targetHolderView.center + + + + + + if hasSkipButton { + + closeButton = UIButton() + + closeButton.setImage(UIImage(named: skipImage), for: .normal) + addSubview(closeButton) + closeButton.addTarget(self, action: #selector(dismissTutorialButtonDidTouch), for: .touchUpInside) + + let margins = layoutMarginsGuide + closeButton.translatesAutoresizingMaskIntoConstraints = false + closeButton.topAnchor.constraint(equalTo: margins.topAnchor, constant: 0).isActive = true + closeButton.rightAnchor.constraint(equalTo: margins.rightAnchor, constant: -8).isActive = true + closeButton.widthAnchor.constraint(equalTo: widthAnchor, multiplier: 0.13).isActive = true + closeButton.heightAnchor.constraint(equalTo: closeButton.widthAnchor, multiplier: 1.0/1.0).isActive = true + } + + + if hasShadow { + backgroundView.layer.shadowColor = UIColor.black.cgColor + backgroundView.layer.shadowRadius = 5.0 + backgroundView.layer.shadowOpacity = 0.5 + backgroundView.layer.shadowOffset = .zero + backgroundView.clipsToBounds = false + } + if animated { UIView.animate(withDuration: aniComeInDuration, animations: { self.targetHolderView.transform = CGAffineTransform(scaleX: 1, y: 1) @@ -319,20 +369,24 @@ extension MaterialShowcase { } let center = targetRippleView.center - backgroundView = UIView(frame: CGRect(x: 0, y: 0, width: radius * 2,height: radius * 2)) backgroundView.center = center - backgroundView.asCircle() + + + case .full: backgroundView = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width,height: UIScreen.main.bounds.height)) } + + backgroundView.backgroundColor = backgroundPromptColor.withAlphaComponent(backgroundPromptColorAlpha) insertSubview(backgroundView, belowSubview: targetRippleView) - addBackgroundMask(with: targetHolderRadius, in: backgroundView) + +// addBackgroundMask(with: targetHolderRadius, in: backgroundView) } - private func getDefaultBackgroundRadius() -> CGFloat{ + private func getDefaultBackgroundRadius() -> CGFloat { var radius: CGFloat = 0.0 if UIDevice.current.userInterfaceIdiom == .pad { radius = 300.0 @@ -344,6 +398,7 @@ extension MaterialShowcase { private func addBackgroundMask(with radius: CGFloat, in view: UIView) { let center = backgroundViewType == .circle ? view.bounds.center : targetRippleView.center + let mutablePath = CGMutablePath() mutablePath.addRect(view.bounds) mutablePath.addArc(center: center, radius: radius, startAngle: 0.0, endAngle: 2 * .pi, clockwise: false) @@ -548,17 +603,20 @@ extension MaterialShowcase { /// Detects the position of target view relative to its container func getTargetPosition(target: UIView, container: UIView) -> TargetPosition { let center = calculateCenter(at: targetView, to: container) - if center.y < container.frame.height / 2{ + if center.y < container.frame.height / 2 { return .above } else { return .below } } + + // Calculates the center point based on targetview func calculateCenter(at targetView: UIView, to containerView: UIView) -> CGPoint { let targetRect = targetView.convert(targetView.bounds , to: containerView) return targetRect.center + } // Gets all UIView from TabBarItem. diff --git a/MaterialShowcase/MaterialShowcaseInstructionView.swift b/MaterialShowcase/MaterialShowcaseInstructionView.swift index 411c60f..d8ef849 100644 --- a/MaterialShowcase/MaterialShowcaseInstructionView.swift +++ b/MaterialShowcase/MaterialShowcaseInstructionView.swift @@ -82,6 +82,7 @@ public class MaterialShowcaseInstructionView: UIView { y: 0, width: getWidth(), height: 0) + primaryLabel.sizeToFitHeight() addSubview(primaryLabel) } @@ -114,7 +115,7 @@ public class MaterialShowcaseInstructionView: UIView { } //Calculate width per device - private func getWidth() -> CGFloat{ + private func getWidth() -> CGFloat { //superview was left side if (self.superview?.frame.origin.x)! < CGFloat(0) { return frame.width - (frame.minX/2) diff --git a/README.md b/README.md index 847086a..163198d 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ ## Requirement -* iOS 8.0+ +* iOS 10.0+ * Swift 4.2+ ## Installation diff --git a/Sample/MaterialShowcaseSample.xcodeproj/project.pbxproj b/Sample/MaterialShowcaseSample.xcodeproj/project.pbxproj index 8151b58..5f15680 100644 --- a/Sample/MaterialShowcaseSample.xcodeproj/project.pbxproj +++ b/Sample/MaterialShowcaseSample.xcodeproj/project.pbxproj @@ -14,6 +14,8 @@ CE9F24961EC2907700444781 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CE9F24941EC2907700444781 /* LaunchScreen.storyboard */; }; CE9F249E1EC2945300444781 /* MaterialShowcase.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CE9F249D1EC2945300444781 /* MaterialShowcase.framework */; }; CE9F249F1EC2945300444781 /* MaterialShowcase.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = CE9F249D1EC2945300444781 /* MaterialShowcase.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + E2F545EA23DB71F8009D9B77 /* CollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2F545E923DB71F8009D9B77 /* CollectionViewController.swift */; }; + E2F545EC23DB7251009D9B77 /* CollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2F545EB23DB7251009D9B77 /* CollectionViewCell.swift */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -39,6 +41,8 @@ CE9F24951EC2907700444781 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; CE9F24971EC2907700444781 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; CE9F249D1EC2945300444781 /* MaterialShowcase.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = MaterialShowcase.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + E2F545E923DB71F8009D9B77 /* CollectionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionViewController.swift; sourceTree = ""; }; + E2F545EB23DB7251009D9B77 /* CollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionViewCell.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -75,6 +79,8 @@ children = ( CE9F248B1EC2907700444781 /* AppDelegate.swift */, CE9F248D1EC2907700444781 /* ViewController.swift */, + E2F545E923DB71F8009D9B77 /* CollectionViewController.swift */, + E2F545EB23DB7251009D9B77 /* CollectionViewCell.swift */, CE9F248F1EC2907700444781 /* Main.storyboard */, CE9F24921EC2907700444781 /* Assets.xcassets */, CE9F24941EC2907700444781 /* LaunchScreen.storyboard */, @@ -158,7 +164,9 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + E2F545EA23DB71F8009D9B77 /* CollectionViewController.swift in Sources */, CE9F248E1EC2907700444781 /* ViewController.swift in Sources */, + E2F545EC23DB7251009D9B77 /* CollectionViewCell.swift in Sources */, CE9F248C1EC2907700444781 /* AppDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -304,7 +312,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; DEVELOPMENT_TEAM = 4V6HDFWSR4; INFOPLIST_FILE = MaterialShowcaseSample/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.aromajoin.MaterialShowcaseSample; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -318,7 +326,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; DEVELOPMENT_TEAM = 4V6HDFWSR4; INFOPLIST_FILE = MaterialShowcaseSample/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.aromajoin.MaterialShowcaseSample; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/Sample/MaterialShowcaseSample.xcodeproj/xcshareddata/xcschemes/MaterialShowcaseSample.xcscheme b/Sample/MaterialShowcaseSample.xcodeproj/xcshareddata/xcschemes/MaterialShowcaseSample.xcscheme new file mode 100644 index 0000000..3b94bc1 --- /dev/null +++ b/Sample/MaterialShowcaseSample.xcodeproj/xcshareddata/xcschemes/MaterialShowcaseSample.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sample/MaterialShowcaseSample/Assets.xcassets/HintClose.imageset/Contents.json b/Sample/MaterialShowcaseSample/Assets.xcassets/HintClose.imageset/Contents.json new file mode 100644 index 0000000..25aa132 --- /dev/null +++ b/Sample/MaterialShowcaseSample/Assets.xcassets/HintClose.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "HintClose.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Sample/MaterialShowcaseSample/Assets.xcassets/HintClose.imageset/HintClose.pdf b/Sample/MaterialShowcaseSample/Assets.xcassets/HintClose.imageset/HintClose.pdf new file mode 100644 index 0000000..683d931 Binary files /dev/null and b/Sample/MaterialShowcaseSample/Assets.xcassets/HintClose.imageset/HintClose.pdf differ diff --git a/Sample/MaterialShowcaseSample/Base.lproj/Main.storyboard b/Sample/MaterialShowcaseSample/Base.lproj/Main.storyboard index 55760e1..948d3ae 100644 --- a/Sample/MaterialShowcaseSample/Base.lproj/Main.storyboard +++ b/Sample/MaterialShowcaseSample/Base.lproj/Main.storyboard @@ -1,11 +1,10 @@ - - - - + + - + + @@ -33,35 +32,35 @@ - + @@ -71,11 +70,11 @@ - +