├── Example ├── VisualExample.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── naturaln0va.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── naturaln0va.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ └── xcschememanagement.plist └── VisualExample │ ├── AppDelegate.swift │ ├── ButtonsViewController.swift │ ├── ButtonsViewController.xib │ └── Supporting Files │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ ├── LaunchImage.launchimage │ │ └── Contents.json │ └── dog.imageset │ │ ├── Contents.json │ │ └── dog.jpg │ ├── Base.lproj │ └── LaunchScreen.storyboard │ └── Info.plist ├── LICENSE ├── README.md ├── VisualActivityViewController.swift └── readme-resources ├── vavc-header-logo.png └── vavc-preview.gif /Example/VisualExample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 48488A1D20B5210F002ADD30 /* VisualActivityViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48488A1C20B5210F002ADD30 /* VisualActivityViewController.swift */; }; 11 | 48F3BD5820B10A4C0060C777 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48F3BD5720B10A4C0060C777 /* AppDelegate.swift */; }; 12 | 48F3BD5F20B10A4F0060C777 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 48F3BD5E20B10A4F0060C777 /* Assets.xcassets */; }; 13 | 48F3BD6220B10A4F0060C777 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 48F3BD6020B10A4F0060C777 /* LaunchScreen.storyboard */; }; 14 | 48F3BD6C20B10A8B0060C777 /* ButtonsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 48F3BD6A20B10A8B0060C777 /* ButtonsViewController.swift */; }; 15 | 48F3BD6D20B10A8B0060C777 /* ButtonsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 48F3BD6B20B10A8B0060C777 /* ButtonsViewController.xib */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXFileReference section */ 19 | 48488A1C20B5210F002ADD30 /* VisualActivityViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = VisualActivityViewController.swift; path = ../../VisualActivityViewController.swift; sourceTree = ""; }; 20 | 48F3BD5420B10A4C0060C777 /* VisualExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = VisualExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 21 | 48F3BD5720B10A4C0060C777 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 22 | 48F3BD5E20B10A4F0060C777 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 23 | 48F3BD6120B10A4F0060C777 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 24 | 48F3BD6320B10A4F0060C777 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 25 | 48F3BD6A20B10A8B0060C777 /* ButtonsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonsViewController.swift; sourceTree = ""; }; 26 | 48F3BD6B20B10A8B0060C777 /* ButtonsViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ButtonsViewController.xib; sourceTree = ""; }; 27 | /* End PBXFileReference section */ 28 | 29 | /* Begin PBXFrameworksBuildPhase section */ 30 | 48F3BD5120B10A4C0060C777 /* Frameworks */ = { 31 | isa = PBXFrameworksBuildPhase; 32 | buildActionMask = 2147483647; 33 | files = ( 34 | ); 35 | runOnlyForDeploymentPostprocessing = 0; 36 | }; 37 | /* End PBXFrameworksBuildPhase section */ 38 | 39 | /* Begin PBXGroup section */ 40 | 48F3BD4B20B10A4C0060C777 = { 41 | isa = PBXGroup; 42 | children = ( 43 | 48F3BD5620B10A4C0060C777 /* VisualExample */, 44 | 48F3BD5520B10A4C0060C777 /* Products */, 45 | ); 46 | sourceTree = ""; 47 | }; 48 | 48F3BD5520B10A4C0060C777 /* Products */ = { 49 | isa = PBXGroup; 50 | children = ( 51 | 48F3BD5420B10A4C0060C777 /* VisualExample.app */, 52 | ); 53 | name = Products; 54 | sourceTree = ""; 55 | }; 56 | 48F3BD5620B10A4C0060C777 /* VisualExample */ = { 57 | isa = PBXGroup; 58 | children = ( 59 | 48F3BD5720B10A4C0060C777 /* AppDelegate.swift */, 60 | 48F3BD6A20B10A8B0060C777 /* ButtonsViewController.swift */, 61 | 48F3BD6B20B10A8B0060C777 /* ButtonsViewController.xib */, 62 | 48488A1C20B5210F002ADD30 /* VisualActivityViewController.swift */, 63 | 48F3BD6920B10A6B0060C777 /* Supporting Files */, 64 | ); 65 | path = VisualExample; 66 | sourceTree = ""; 67 | }; 68 | 48F3BD6920B10A6B0060C777 /* Supporting Files */ = { 69 | isa = PBXGroup; 70 | children = ( 71 | 48F3BD5E20B10A4F0060C777 /* Assets.xcassets */, 72 | 48F3BD6020B10A4F0060C777 /* LaunchScreen.storyboard */, 73 | 48F3BD6320B10A4F0060C777 /* Info.plist */, 74 | ); 75 | path = "Supporting Files"; 76 | sourceTree = ""; 77 | }; 78 | /* End PBXGroup section */ 79 | 80 | /* Begin PBXNativeTarget section */ 81 | 48F3BD5320B10A4C0060C777 /* VisualExample */ = { 82 | isa = PBXNativeTarget; 83 | buildConfigurationList = 48F3BD6620B10A4F0060C777 /* Build configuration list for PBXNativeTarget "VisualExample" */; 84 | buildPhases = ( 85 | 48F3BD5020B10A4C0060C777 /* Sources */, 86 | 48F3BD5120B10A4C0060C777 /* Frameworks */, 87 | 48F3BD5220B10A4C0060C777 /* Resources */, 88 | ); 89 | buildRules = ( 90 | ); 91 | dependencies = ( 92 | ); 93 | name = VisualExample; 94 | productName = VisualExample; 95 | productReference = 48F3BD5420B10A4C0060C777 /* VisualExample.app */; 96 | productType = "com.apple.product-type.application"; 97 | }; 98 | /* End PBXNativeTarget section */ 99 | 100 | /* Begin PBXProject section */ 101 | 48F3BD4C20B10A4C0060C777 /* Project object */ = { 102 | isa = PBXProject; 103 | attributes = { 104 | LastSwiftUpdateCheck = 0930; 105 | LastUpgradeCheck = 0930; 106 | ORGANIZATIONNAME = "Ryan Ackermann"; 107 | TargetAttributes = { 108 | 48F3BD5320B10A4C0060C777 = { 109 | CreatedOnToolsVersion = 9.3; 110 | LastSwiftMigration = 1010; 111 | }; 112 | }; 113 | }; 114 | buildConfigurationList = 48F3BD4F20B10A4C0060C777 /* Build configuration list for PBXProject "VisualExample" */; 115 | compatibilityVersion = "Xcode 9.3"; 116 | developmentRegion = en; 117 | hasScannedForEncodings = 0; 118 | knownRegions = ( 119 | en, 120 | Base, 121 | ); 122 | mainGroup = 48F3BD4B20B10A4C0060C777; 123 | productRefGroup = 48F3BD5520B10A4C0060C777 /* Products */; 124 | projectDirPath = ""; 125 | projectRoot = ""; 126 | targets = ( 127 | 48F3BD5320B10A4C0060C777 /* VisualExample */, 128 | ); 129 | }; 130 | /* End PBXProject section */ 131 | 132 | /* Begin PBXResourcesBuildPhase section */ 133 | 48F3BD5220B10A4C0060C777 /* Resources */ = { 134 | isa = PBXResourcesBuildPhase; 135 | buildActionMask = 2147483647; 136 | files = ( 137 | 48F3BD6220B10A4F0060C777 /* LaunchScreen.storyboard in Resources */, 138 | 48F3BD6D20B10A8B0060C777 /* ButtonsViewController.xib in Resources */, 139 | 48F3BD5F20B10A4F0060C777 /* Assets.xcassets in Resources */, 140 | ); 141 | runOnlyForDeploymentPostprocessing = 0; 142 | }; 143 | /* End PBXResourcesBuildPhase section */ 144 | 145 | /* Begin PBXSourcesBuildPhase section */ 146 | 48F3BD5020B10A4C0060C777 /* Sources */ = { 147 | isa = PBXSourcesBuildPhase; 148 | buildActionMask = 2147483647; 149 | files = ( 150 | 48F3BD6C20B10A8B0060C777 /* ButtonsViewController.swift in Sources */, 151 | 48488A1D20B5210F002ADD30 /* VisualActivityViewController.swift in Sources */, 152 | 48F3BD5820B10A4C0060C777 /* AppDelegate.swift in Sources */, 153 | ); 154 | runOnlyForDeploymentPostprocessing = 0; 155 | }; 156 | /* End PBXSourcesBuildPhase section */ 157 | 158 | /* Begin PBXVariantGroup section */ 159 | 48F3BD6020B10A4F0060C777 /* LaunchScreen.storyboard */ = { 160 | isa = PBXVariantGroup; 161 | children = ( 162 | 48F3BD6120B10A4F0060C777 /* Base */, 163 | ); 164 | name = LaunchScreen.storyboard; 165 | sourceTree = ""; 166 | }; 167 | /* End PBXVariantGroup section */ 168 | 169 | /* Begin XCBuildConfiguration section */ 170 | 48F3BD6420B10A4F0060C777 /* Debug */ = { 171 | isa = XCBuildConfiguration; 172 | buildSettings = { 173 | ALWAYS_SEARCH_USER_PATHS = NO; 174 | CLANG_ANALYZER_NONNULL = YES; 175 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 176 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 177 | CLANG_CXX_LIBRARY = "libc++"; 178 | CLANG_ENABLE_MODULES = YES; 179 | CLANG_ENABLE_OBJC_ARC = YES; 180 | CLANG_ENABLE_OBJC_WEAK = YES; 181 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 182 | CLANG_WARN_BOOL_CONVERSION = YES; 183 | CLANG_WARN_COMMA = YES; 184 | CLANG_WARN_CONSTANT_CONVERSION = YES; 185 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 186 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 187 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 188 | CLANG_WARN_EMPTY_BODY = YES; 189 | CLANG_WARN_ENUM_CONVERSION = YES; 190 | CLANG_WARN_INFINITE_RECURSION = YES; 191 | CLANG_WARN_INT_CONVERSION = YES; 192 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 193 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 194 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 195 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 196 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 197 | CLANG_WARN_STRICT_PROTOTYPES = YES; 198 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 199 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 200 | CLANG_WARN_UNREACHABLE_CODE = YES; 201 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 202 | CODE_SIGN_IDENTITY = "iPhone Developer"; 203 | COPY_PHASE_STRIP = NO; 204 | DEBUG_INFORMATION_FORMAT = dwarf; 205 | ENABLE_STRICT_OBJC_MSGSEND = YES; 206 | ENABLE_TESTABILITY = YES; 207 | GCC_C_LANGUAGE_STANDARD = gnu11; 208 | GCC_DYNAMIC_NO_PIC = NO; 209 | GCC_NO_COMMON_BLOCKS = YES; 210 | GCC_OPTIMIZATION_LEVEL = 0; 211 | GCC_PREPROCESSOR_DEFINITIONS = ( 212 | "DEBUG=1", 213 | "$(inherited)", 214 | ); 215 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 216 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 217 | GCC_WARN_UNDECLARED_SELECTOR = YES; 218 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 219 | GCC_WARN_UNUSED_FUNCTION = YES; 220 | GCC_WARN_UNUSED_VARIABLE = YES; 221 | IPHONEOS_DEPLOYMENT_TARGET = 11.3; 222 | MTL_ENABLE_DEBUG_INFO = YES; 223 | ONLY_ACTIVE_ARCH = YES; 224 | SDKROOT = iphoneos; 225 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 226 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 227 | }; 228 | name = Debug; 229 | }; 230 | 48F3BD6520B10A4F0060C777 /* Release */ = { 231 | isa = XCBuildConfiguration; 232 | buildSettings = { 233 | ALWAYS_SEARCH_USER_PATHS = NO; 234 | CLANG_ANALYZER_NONNULL = YES; 235 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 236 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 237 | CLANG_CXX_LIBRARY = "libc++"; 238 | CLANG_ENABLE_MODULES = YES; 239 | CLANG_ENABLE_OBJC_ARC = YES; 240 | CLANG_ENABLE_OBJC_WEAK = YES; 241 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 242 | CLANG_WARN_BOOL_CONVERSION = YES; 243 | CLANG_WARN_COMMA = YES; 244 | CLANG_WARN_CONSTANT_CONVERSION = YES; 245 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 246 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 247 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 248 | CLANG_WARN_EMPTY_BODY = YES; 249 | CLANG_WARN_ENUM_CONVERSION = YES; 250 | CLANG_WARN_INFINITE_RECURSION = YES; 251 | CLANG_WARN_INT_CONVERSION = YES; 252 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 253 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 254 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 255 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 256 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 257 | CLANG_WARN_STRICT_PROTOTYPES = YES; 258 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 259 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 260 | CLANG_WARN_UNREACHABLE_CODE = YES; 261 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 262 | CODE_SIGN_IDENTITY = "iPhone Developer"; 263 | COPY_PHASE_STRIP = NO; 264 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 265 | ENABLE_NS_ASSERTIONS = NO; 266 | ENABLE_STRICT_OBJC_MSGSEND = YES; 267 | GCC_C_LANGUAGE_STANDARD = gnu11; 268 | GCC_NO_COMMON_BLOCKS = YES; 269 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 270 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 271 | GCC_WARN_UNDECLARED_SELECTOR = YES; 272 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 273 | GCC_WARN_UNUSED_FUNCTION = YES; 274 | GCC_WARN_UNUSED_VARIABLE = YES; 275 | IPHONEOS_DEPLOYMENT_TARGET = 11.3; 276 | MTL_ENABLE_DEBUG_INFO = NO; 277 | SDKROOT = iphoneos; 278 | SWIFT_COMPILATION_MODE = wholemodule; 279 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 280 | VALIDATE_PRODUCT = YES; 281 | }; 282 | name = Release; 283 | }; 284 | 48F3BD6720B10A4F0060C777 /* Debug */ = { 285 | isa = XCBuildConfiguration; 286 | buildSettings = { 287 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 288 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 289 | CODE_SIGN_STYLE = Automatic; 290 | DEVELOPMENT_TEAM = WK4Y48HVH2; 291 | INFOPLIST_FILE = "$(SRCROOT)/VisualExample/Supporting Files/Info.plist"; 292 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 293 | LD_RUNPATH_SEARCH_PATHS = ( 294 | "$(inherited)", 295 | "@executable_path/Frameworks", 296 | ); 297 | PRODUCT_BUNDLE_IDENTIFIER = io.ackermann.VisualExample; 298 | PRODUCT_NAME = "$(TARGET_NAME)"; 299 | SWIFT_VERSION = 4.2; 300 | TARGETED_DEVICE_FAMILY = "1,2"; 301 | }; 302 | name = Debug; 303 | }; 304 | 48F3BD6820B10A4F0060C777 /* Release */ = { 305 | isa = XCBuildConfiguration; 306 | buildSettings = { 307 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 308 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 309 | CODE_SIGN_STYLE = Automatic; 310 | DEVELOPMENT_TEAM = WK4Y48HVH2; 311 | INFOPLIST_FILE = "$(SRCROOT)/VisualExample/Supporting Files/Info.plist"; 312 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 313 | LD_RUNPATH_SEARCH_PATHS = ( 314 | "$(inherited)", 315 | "@executable_path/Frameworks", 316 | ); 317 | PRODUCT_BUNDLE_IDENTIFIER = io.ackermann.VisualExample; 318 | PRODUCT_NAME = "$(TARGET_NAME)"; 319 | SWIFT_VERSION = 4.2; 320 | TARGETED_DEVICE_FAMILY = "1,2"; 321 | }; 322 | name = Release; 323 | }; 324 | /* End XCBuildConfiguration section */ 325 | 326 | /* Begin XCConfigurationList section */ 327 | 48F3BD4F20B10A4C0060C777 /* Build configuration list for PBXProject "VisualExample" */ = { 328 | isa = XCConfigurationList; 329 | buildConfigurations = ( 330 | 48F3BD6420B10A4F0060C777 /* Debug */, 331 | 48F3BD6520B10A4F0060C777 /* Release */, 332 | ); 333 | defaultConfigurationIsVisible = 0; 334 | defaultConfigurationName = Release; 335 | }; 336 | 48F3BD6620B10A4F0060C777 /* Build configuration list for PBXNativeTarget "VisualExample" */ = { 337 | isa = XCConfigurationList; 338 | buildConfigurations = ( 339 | 48F3BD6720B10A4F0060C777 /* Debug */, 340 | 48F3BD6820B10A4F0060C777 /* Release */, 341 | ); 342 | defaultConfigurationIsVisible = 0; 343 | defaultConfigurationName = Release; 344 | }; 345 | /* End XCConfigurationList section */ 346 | }; 347 | rootObject = 48F3BD4C20B10A4C0060C777 /* Project object */; 348 | } 349 | -------------------------------------------------------------------------------- /Example/VisualExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/VisualExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/VisualExample.xcodeproj/project.xcworkspace/xcuserdata/naturaln0va.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naturaln0va/VisualActivityViewController/275f5b756e213d3c97222ffc33edbaeca7347b4e/Example/VisualExample.xcodeproj/project.xcworkspace/xcuserdata/naturaln0va.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Example/VisualExample.xcodeproj/xcuserdata/naturaln0va.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /Example/VisualExample.xcodeproj/xcuserdata/naturaln0va.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | VisualExample.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Example/VisualExample/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // VisualExample 4 | // 5 | // Created by Ryan Ackermann on 5/19/18. 6 | // Copyright © 2018 Ryan Ackermann. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | window = UIWindow(frame: UIScreen.main.bounds) 18 | 19 | window?.rootViewController = ButtonsViewController() 20 | window?.makeKeyAndVisible() 21 | 22 | return true 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /Example/VisualExample/ButtonsViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ButtonsViewController.swift 3 | // VisualExample 4 | // 5 | // Created by Ryan Ackermann on 5/19/18. 6 | // Copyright © 2018 Ryan Ackermann. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | final class ButtonsViewController: UIViewController { 12 | 13 | private let shareText = "Lorem ipsum dolor sit amet, usu an fugit expetendis referrentur. Assum fuisset volumus duo te, ei ubique inimicus eum, nostrum mandamus mel in. Platonem quaerendum comprehensam et nam, at per exerci aliquip persius." 14 | private let shareURLString = "https://ackermann.io/about" 15 | 16 | @IBAction func textShareButtonPressed(_ sender: UIButton) { 17 | let vc = VisualActivityViewController(text: shareText) 18 | vc.previewNumberOfLines = 10 19 | 20 | presentActionSheet(vc, from: sender) 21 | } 22 | 23 | @IBAction func urlShareButtonPressed(_ sender: UIButton) { 24 | guard let url = URL(string: shareURLString) else { 25 | return 26 | } 27 | 28 | let vc = VisualActivityViewController(url: url) 29 | vc.previewLinkColor = .magenta 30 | 31 | presentActionSheet(vc, from: sender) 32 | } 33 | 34 | @IBAction func imageShareButtonPressed(_ sender: UIButton) { 35 | let vc = VisualActivityViewController(image: #imageLiteral(resourceName: "dog")) 36 | vc.previewImageSideLength = 160 37 | 38 | presentActionSheet(vc, from: sender) 39 | } 40 | 41 | @IBAction func allShareButtonPressed(_ sender: UIButton) { 42 | guard let url = URL(string: shareURLString) else { 43 | return 44 | } 45 | 46 | let items: [Any] = [shareText, url, #imageLiteral(resourceName: "dog")] 47 | let vc = VisualActivityViewController(activityItems: items, applicationActivities: nil) 48 | vc.previewNumberOfLines = 10 49 | 50 | presentActionSheet(vc, from: sender) 51 | } 52 | 53 | private func presentActionSheet(_ vc: VisualActivityViewController, from view: UIView) { 54 | if UIDevice.current.userInterfaceIdiom == .pad { 55 | vc.popoverPresentationController?.sourceView = view 56 | vc.popoverPresentationController?.sourceRect = view.bounds 57 | vc.popoverPresentationController?.permittedArrowDirections = [.right, .left] 58 | } 59 | 60 | present(vc, animated: true, completion: nil) 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /Example/VisualExample/ButtonsViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 29 | 30 | 31 | 32 | 39 | 46 | 53 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /Example/VisualExample/Supporting Files/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /Example/VisualExample/Supporting Files/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example/VisualExample/Supporting Files/Assets.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "11.0", 8 | "subtype" : "2436h", 9 | "scale" : "3x" 10 | }, 11 | { 12 | "orientation" : "landscape", 13 | "idiom" : "iphone", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "11.0", 16 | "subtype" : "2436h", 17 | "scale" : "3x" 18 | }, 19 | { 20 | "orientation" : "portrait", 21 | "idiom" : "iphone", 22 | "extent" : "full-screen", 23 | "minimum-system-version" : "8.0", 24 | "subtype" : "736h", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "orientation" : "landscape", 29 | "idiom" : "iphone", 30 | "extent" : "full-screen", 31 | "minimum-system-version" : "8.0", 32 | "subtype" : "736h", 33 | "scale" : "3x" 34 | }, 35 | { 36 | "orientation" : "portrait", 37 | "idiom" : "iphone", 38 | "extent" : "full-screen", 39 | "minimum-system-version" : "8.0", 40 | "subtype" : "667h", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "orientation" : "portrait", 45 | "idiom" : "iphone", 46 | "extent" : "full-screen", 47 | "minimum-system-version" : "7.0", 48 | "scale" : "2x" 49 | }, 50 | { 51 | "orientation" : "portrait", 52 | "idiom" : "iphone", 53 | "extent" : "full-screen", 54 | "minimum-system-version" : "7.0", 55 | "subtype" : "retina4", 56 | "scale" : "2x" 57 | }, 58 | { 59 | "orientation" : "portrait", 60 | "idiom" : "ipad", 61 | "extent" : "full-screen", 62 | "minimum-system-version" : "7.0", 63 | "scale" : "1x" 64 | }, 65 | { 66 | "orientation" : "landscape", 67 | "idiom" : "ipad", 68 | "extent" : "full-screen", 69 | "minimum-system-version" : "7.0", 70 | "scale" : "1x" 71 | }, 72 | { 73 | "orientation" : "portrait", 74 | "idiom" : "ipad", 75 | "extent" : "full-screen", 76 | "minimum-system-version" : "7.0", 77 | "scale" : "2x" 78 | }, 79 | { 80 | "orientation" : "landscape", 81 | "idiom" : "ipad", 82 | "extent" : "full-screen", 83 | "minimum-system-version" : "7.0", 84 | "scale" : "2x" 85 | }, 86 | { 87 | "orientation" : "portrait", 88 | "idiom" : "iphone", 89 | "extent" : "full-screen", 90 | "scale" : "1x" 91 | }, 92 | { 93 | "orientation" : "portrait", 94 | "idiom" : "iphone", 95 | "extent" : "full-screen", 96 | "scale" : "2x" 97 | }, 98 | { 99 | "orientation" : "portrait", 100 | "idiom" : "iphone", 101 | "extent" : "full-screen", 102 | "subtype" : "retina4", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "orientation" : "portrait", 107 | "idiom" : "ipad", 108 | "extent" : "to-status-bar", 109 | "scale" : "1x" 110 | }, 111 | { 112 | "orientation" : "portrait", 113 | "idiom" : "ipad", 114 | "extent" : "full-screen", 115 | "scale" : "1x" 116 | }, 117 | { 118 | "orientation" : "landscape", 119 | "idiom" : "ipad", 120 | "extent" : "to-status-bar", 121 | "scale" : "1x" 122 | }, 123 | { 124 | "orientation" : "landscape", 125 | "idiom" : "ipad", 126 | "extent" : "full-screen", 127 | "scale" : "1x" 128 | }, 129 | { 130 | "orientation" : "portrait", 131 | "idiom" : "ipad", 132 | "extent" : "to-status-bar", 133 | "scale" : "2x" 134 | }, 135 | { 136 | "orientation" : "portrait", 137 | "idiom" : "ipad", 138 | "extent" : "full-screen", 139 | "scale" : "2x" 140 | }, 141 | { 142 | "orientation" : "landscape", 143 | "idiom" : "ipad", 144 | "extent" : "to-status-bar", 145 | "scale" : "2x" 146 | }, 147 | { 148 | "orientation" : "landscape", 149 | "idiom" : "ipad", 150 | "extent" : "full-screen", 151 | "scale" : "2x" 152 | } 153 | ], 154 | "info" : { 155 | "version" : 1, 156 | "author" : "xcode" 157 | } 158 | } -------------------------------------------------------------------------------- /Example/VisualExample/Supporting Files/Assets.xcassets/dog.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "dog.jpg" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Example/VisualExample/Supporting Files/Assets.xcassets/dog.imageset/dog.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naturaln0va/VisualActivityViewController/275f5b756e213d3c97222ffc33edbaeca7347b4e/Example/VisualExample/Supporting Files/Assets.xcassets/dog.imageset/dog.jpg -------------------------------------------------------------------------------- /Example/VisualExample/Supporting Files/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Example/VisualExample/Supporting Files/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIRequiredDeviceCapabilities 26 | 27 | armv7 28 | 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Ryan Ackermann 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | VisualActivityViewController 3 |

4 | 5 |

6 | Swift 7 |
8 | Twitter 9 |

10 | 11 |

12 | VisualActivityViewController Preview 13 |

14 | 15 | ## About 16 | 17 | This project provides a preview of items being shared via `UIActivityViewController`. Example: 18 | 19 | ```swift 20 | // standard activity view controller 21 | let vc = UIActivityViewController(activityItems: [shareText]) 22 | 23 | // custom activity view controller with a preview 24 | let vc = VisualActivityViewController(text: shareText) 25 | ``` 26 | 27 | ## Features 28 | * Text, Image, and URL previewing 29 | * Swipe gesture to dismiss the share sheet 30 | * Easy customization (match your app’s style) 31 | 32 | ## Requirements 33 | 34 | * iOS 9.0+ 35 | * Xcode 9.0+ 36 | 37 | ## Installation 38 | 39 | To install, simply add the `VisualActivityViewController.swift` file to your project. 40 | 41 | ## Advanced Usage 42 | 43 | There are quite a few different options to customize the appearance of the preview. Check out the example project to see how some of these options work. 44 | 45 | ```swift 46 | /// The duration for the preview fading in 47 | var fadeInDuration: TimeInterval = 0.3 48 | 49 | /// The duration for the preview fading out 50 | var fadeOutDuration: TimeInterval = 0.3 51 | 52 | /// The corner radius of the preview 53 | var previewCornerRadius: CGFloat = 12 54 | 55 | /// The corner radius of the preview image 56 | var previewImageCornerRadius: CGFloat = 3 57 | 58 | /// The side length of the preview image 59 | var previewImageSideLength: CGFloat = 80 60 | 61 | /// The padding around the preview 62 | var previewPadding: CGFloat = 12 63 | 64 | /// The number of lines to preview 65 | var previewNumberOfLines: Int = 5 66 | 67 | /// The preview color for URL activity items 68 | var previewLinkColor: UIColor = UIColor(red: 0, green: 0.47, blue: 1, alpha: 1) 69 | 70 | /// The font for the preview label 71 | var previewFont: UIFont = UIFont.systemFont(ofSize: 18) 72 | 73 | /// The margin from the top of the viewController's window 74 | var previewTopMargin: CGFloat = 8 75 | 76 | /// The margin from the top of the viewController's view 77 | var previewBottomMargin: CGFloat = 8 78 | ``` 79 | 80 | ## License 81 | 82 | This project is available under the MIT license. See the LICENSE file for more info. 83 | -------------------------------------------------------------------------------- /VisualActivityViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VisualActivityViewController.swift 3 | // VisualExample 4 | // 5 | // Created by Ryan Ackermann on 5/19/18. 6 | // Copyright © 2018 Ryan Ackermann. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @objcMembers final class VisualActivityViewController: UIActivityViewController { 12 | 13 | /// The preview container view 14 | private var preview: UIVisualEffectView! 15 | 16 | /// Internal storage of the activity items 17 | private let activityItems: [Any] 18 | 19 | // MARK: - Configuration 20 | 21 | /// The duration for the preview fading in 22 | var fadeInDuration: TimeInterval = 0.3 23 | 24 | /// The duration for the preview fading out 25 | var fadeOutDuration: TimeInterval = 0.3 26 | 27 | /// The corner radius of the preview 28 | var previewCornerRadius: CGFloat = 12 29 | 30 | /// The corner radius of the preview image 31 | var previewImageCornerRadius: CGFloat = 3 32 | 33 | /// The side length of the preview image 34 | var previewImageSideLength: CGFloat = 80 35 | 36 | /// The padding around the preview 37 | var previewPadding: CGFloat = 12 38 | 39 | /// The number of lines to preview 40 | var previewNumberOfLines: Int = 5 41 | 42 | /// The preview color for URL activity items 43 | var previewLinkColor: UIColor = UIColor(red: 0, green: 0.47, blue: 1, alpha: 1) 44 | 45 | /// The font for the preview label 46 | var previewFont: UIFont = UIFont.systemFont(ofSize: 18) 47 | 48 | /// The margin from the top of the viewController's superview 49 | var previewTopMargin: CGFloat = 8 50 | 51 | /// The margin from the top of the viewController's view 52 | var previewBottomMargin: CGFloat = 8 53 | 54 | // MARK: - Init 55 | 56 | convenience init(activityItems: [Any]) { 57 | self.init(activityItems: activityItems, applicationActivities: nil) 58 | } 59 | 60 | convenience init(text: String, activities: [UIActivity]? = nil) { 61 | self.init(activityItems: [text], applicationActivities: activities) 62 | } 63 | 64 | convenience init(image: UIImage, activities: [UIActivity]? = nil) { 65 | self.init(activityItems: [image], applicationActivities: activities) 66 | } 67 | 68 | convenience init(url: URL, activities: [UIActivity]? = nil) { 69 | self.init(activityItems: [url], applicationActivities: activities) 70 | } 71 | 72 | override init(activityItems: [Any], applicationActivities: [UIActivity]?) { 73 | self.activityItems = activityItems 74 | 75 | super.init(activityItems: activityItems, applicationActivities: applicationActivities) 76 | } 77 | 78 | // MARK: - View Lifecycle 79 | 80 | override func viewDidLoad() { 81 | super.viewDidLoad() 82 | 83 | preview = UIVisualEffectView(effect: UIBlurEffect(style: .extraLight)) 84 | preview.translatesAutoresizingMaskIntoConstraints = false 85 | preview.layer.cornerRadius = previewCornerRadius 86 | preview.clipsToBounds = true 87 | preview.alpha = 0 88 | 89 | let previewLabel = UILabel() 90 | previewLabel.translatesAutoresizingMaskIntoConstraints = false 91 | previewLabel.numberOfLines = previewNumberOfLines 92 | 93 | let attributedString = NSMutableAttributedString() 94 | let baseAttributes: [NSAttributedString.Key: Any] = [.font: previewFont] 95 | 96 | for (index, item) in activityItems.enumerated() { 97 | if index > 0 && attributedString.length > 0 && (item is String || item is URL) { 98 | attributedString.append(NSAttributedString(string: "\n")) 99 | } 100 | 101 | if let url = item as? URL { 102 | var urlAttributes = baseAttributes 103 | urlAttributes[.foregroundColor] = previewLinkColor 104 | attributedString.append(NSAttributedString(string: url.absoluteString, attributes: urlAttributes)) 105 | } 106 | else if let text = item as? String { 107 | attributedString.append(NSAttributedString(string: text, attributes: baseAttributes)) 108 | } 109 | } 110 | 111 | previewLabel.attributedText = attributedString 112 | 113 | preview.contentView.addSubview(previewLabel) 114 | var constraints = [ 115 | previewLabel.topAnchor.constraint(equalTo: preview.topAnchor, constant: previewPadding), 116 | previewLabel.trailingAnchor.constraint(equalTo: preview.trailingAnchor, constant: -previewPadding), 117 | previewLabel.bottomAnchor.constraint(equalTo: preview.bottomAnchor, constant: -previewPadding) 118 | ] 119 | 120 | if let previewImage = activityItems.first(where: { $0 is UIImage }) as? UIImage { 121 | let previewImageView = UIImageView(image: previewImage) 122 | previewImageView.translatesAutoresizingMaskIntoConstraints = false 123 | previewImageView.layer.cornerRadius = previewImageCornerRadius 124 | previewImageView.contentMode = .scaleAspectFill 125 | previewImageView.clipsToBounds = true 126 | 127 | if #available(iOS 11.0, *) { 128 | previewImageView.accessibilityIgnoresInvertColors = true 129 | } 130 | 131 | preview.contentView.addSubview(previewImageView) 132 | constraints.append(contentsOf: [ 133 | previewImageView.widthAnchor.constraint(equalTo: previewImageView.heightAnchor), 134 | previewImageView.heightAnchor.constraint(lessThanOrEqualToConstant: previewImageSideLength), 135 | previewImageView.topAnchor.constraint(equalTo: preview.topAnchor, constant: previewPadding), 136 | previewImageView.leadingAnchor.constraint(equalTo: preview.leadingAnchor, constant: previewPadding), 137 | previewLabel.leadingAnchor.constraint(equalTo: previewImageView.trailingAnchor, constant: previewPadding), 138 | previewImageView.bottomAnchor.constraint(lessThanOrEqualTo: preview.bottomAnchor, constant: -previewPadding) 139 | ]) 140 | } 141 | else { 142 | constraints.append(previewLabel.leadingAnchor.constraint(equalTo: preview.leadingAnchor, constant: previewPadding)) 143 | } 144 | 145 | NSLayoutConstraint.activate(constraints) 146 | 147 | let swipeGesture = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipe(_:))) 148 | swipeGesture.direction = .down 149 | preview.addGestureRecognizer(swipeGesture) 150 | } 151 | 152 | override func viewDidAppear(_ animated: Bool) { 153 | super.viewDidAppear(animated) 154 | 155 | let isPad = UIDevice.current.userInterfaceIdiom == .pad 156 | guard let superview = isPad ? presentingViewController?.view : view.superview else { 157 | return 158 | } 159 | 160 | superview.addSubview(preview) 161 | 162 | let topAnchor: NSLayoutYAxisAnchor 163 | if #available(iOS 11.0, *) { 164 | topAnchor = superview.safeAreaLayoutGuide.topAnchor 165 | } 166 | else { 167 | topAnchor = superview.topAnchor 168 | } 169 | 170 | let constraints = [ 171 | preview.leadingAnchor.constraint(equalTo: view.leadingAnchor), 172 | preview.trailingAnchor.constraint(equalTo: view.trailingAnchor), 173 | preview.bottomAnchor.constraint(equalTo: view.topAnchor, constant: -previewBottomMargin), 174 | preview.topAnchor.constraint(greaterThanOrEqualTo: topAnchor, constant: previewTopMargin) 175 | ] 176 | NSLayoutConstraint.activate(constraints) 177 | 178 | UIView.animate(withDuration: fadeInDuration) { 179 | self.preview.alpha = 1 180 | } 181 | } 182 | 183 | override func viewWillDisappear(_ animated: Bool) { 184 | super.viewWillDisappear(animated) 185 | 186 | UIView.animate(withDuration: fadeOutDuration, animations: { 187 | self.preview?.alpha = 0 188 | }) { _ in 189 | self.preview?.removeFromSuperview() 190 | } 191 | } 192 | 193 | // MARK: - Actions 194 | 195 | @objc private func handleSwipe(_ gesture: UISwipeGestureRecognizer) { 196 | dismiss(animated: true, completion: nil) 197 | } 198 | 199 | } 200 | -------------------------------------------------------------------------------- /readme-resources/vavc-header-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naturaln0va/VisualActivityViewController/275f5b756e213d3c97222ffc33edbaeca7347b4e/readme-resources/vavc-header-logo.png -------------------------------------------------------------------------------- /readme-resources/vavc-preview.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/naturaln0va/VisualActivityViewController/275f5b756e213d3c97222ffc33edbaeca7347b4e/readme-resources/vavc-preview.gif --------------------------------------------------------------------------------