diff --git a/DragAndDrop.xcodeproj/project.pbxproj b/DragAndDrop.xcodeproj/project.pbxproj index 4bafdca..f66709a 100644 --- a/DragAndDrop.xcodeproj/project.pbxproj +++ b/DragAndDrop.xcodeproj/project.pbxproj @@ -9,10 +9,11 @@ /* Begin PBXBuildFile section */ 52C3B2371C7CD0BA00F3151C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52C3B2361C7CD0BA00F3151C /* AppDelegate.swift */; }; 52C3B2391C7CD0BA00F3151C /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52C3B2381C7CD0BA00F3151C /* ViewController.swift */; }; - 52C3B23C1C7CD0BA00F3151C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 52C3B23A1C7CD0BA00F3151C /* Main.storyboard */; }; 52C3B23E1C7CD0BA00F3151C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 52C3B23D1C7CD0BA00F3151C /* Assets.xcassets */; }; 52C3B2411C7CD0BA00F3151C /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 52C3B23F1C7CD0BA00F3151C /* LaunchScreen.storyboard */; }; 52C3B24C1C7CD0BA00F3151C /* DragAndDropTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52C3B24B1C7CD0BA00F3151C /* DragAndDropTests.swift */; }; + F6BAF15C1C8CC49200B6BD66 /* DraggableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6BAF15B1C8CC49200B6BD66 /* DraggableView.swift */; }; + F6DCCAED1C8CBAE0005A8A4E /* View.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6DCCAEC1C8CBAE0005A8A4E /* View.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -29,13 +30,14 @@ 52C3B2331C7CD0BA00F3151C /* DragAndDrop.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DragAndDrop.app; sourceTree = BUILT_PRODUCTS_DIR; }; 52C3B2361C7CD0BA00F3151C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 52C3B2381C7CD0BA00F3151C /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; - 52C3B23B1C7CD0BA00F3151C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 52C3B23D1C7CD0BA00F3151C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 52C3B2401C7CD0BA00F3151C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 52C3B2421C7CD0BA00F3151C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 52C3B2471C7CD0BA00F3151C /* DragAndDropTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DragAndDropTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 52C3B24B1C7CD0BA00F3151C /* DragAndDropTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DragAndDropTests.swift; sourceTree = ""; }; 52C3B24D1C7CD0BA00F3151C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + F6BAF15B1C8CC49200B6BD66 /* DraggableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DraggableView.swift; sourceTree = ""; }; + F6DCCAEC1C8CBAE0005A8A4E /* View.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = View.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -79,7 +81,8 @@ children = ( 52C3B2361C7CD0BA00F3151C /* AppDelegate.swift */, 52C3B2381C7CD0BA00F3151C /* ViewController.swift */, - 52C3B23A1C7CD0BA00F3151C /* Main.storyboard */, + F6BAF15B1C8CC49200B6BD66 /* DraggableView.swift */, + F6DCCAEC1C8CBAE0005A8A4E /* View.swift */, 52C3B23D1C7CD0BA00F3151C /* Assets.xcassets */, 52C3B23F1C7CD0BA00F3151C /* LaunchScreen.storyboard */, 52C3B2421C7CD0BA00F3151C /* Info.plist */, @@ -179,7 +182,6 @@ files = ( 52C3B2411C7CD0BA00F3151C /* LaunchScreen.storyboard in Resources */, 52C3B23E1C7CD0BA00F3151C /* Assets.xcassets in Resources */, - 52C3B23C1C7CD0BA00F3151C /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -199,6 +201,8 @@ files = ( 52C3B2391C7CD0BA00F3151C /* ViewController.swift in Sources */, 52C3B2371C7CD0BA00F3151C /* AppDelegate.swift in Sources */, + F6DCCAED1C8CBAE0005A8A4E /* View.swift in Sources */, + F6BAF15C1C8CC49200B6BD66 /* DraggableView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -221,14 +225,6 @@ /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ - 52C3B23A1C7CD0BA00F3151C /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 52C3B23B1C7CD0BA00F3151C /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; 52C3B23F1C7CD0BA00F3151C /* LaunchScreen.storyboard */ = { isa = PBXVariantGroup; children = ( @@ -388,6 +384,7 @@ 52C3B2521C7CD0BA00F3151C /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; 52C3B2531C7CD0BA00F3151C /* Build configuration list for PBXNativeTarget "DragAndDropTests" */ = { isa = XCConfigurationList; @@ -396,6 +393,7 @@ 52C3B2551C7CD0BA00F3151C /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; diff --git a/DragAndDrop/AppDelegate.swift b/DragAndDrop/AppDelegate.swift index 4357155..a52c550 100644 --- a/DragAndDrop/AppDelegate.swift +++ b/DragAndDrop/AppDelegate.swift @@ -16,6 +16,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { // Override point for customization after application launch. + window = UIWindow(frame: UIScreen.mainScreen().bounds) + window?.rootViewController = ViewController() + window?.makeKeyAndVisible() return true } diff --git a/DragAndDrop/Base.lproj/LaunchScreen.storyboard b/DragAndDrop/Base.lproj/LaunchScreen.storyboard index 2e721e1..716eb56 100644 --- a/DragAndDrop/Base.lproj/LaunchScreen.storyboard +++ b/DragAndDrop/Base.lproj/LaunchScreen.storyboard @@ -1,7 +1,8 @@ - + - + + @@ -15,7 +16,6 @@ - diff --git a/DragAndDrop/Base.lproj/Main.storyboard b/DragAndDrop/Base.lproj/Main.storyboard deleted file mode 100644 index 3a2a49b..0000000 --- a/DragAndDrop/Base.lproj/Main.storyboard +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/DragAndDrop/DraggableView.swift b/DragAndDrop/DraggableView.swift new file mode 100644 index 0000000..99bbcb4 --- /dev/null +++ b/DragAndDrop/DraggableView.swift @@ -0,0 +1,73 @@ +// +// Drag.swift +// DragAndDrop +// +// Created by Stanley Chiang on 3/6/16. +// Copyright © 2016 SantaClaraiOSConnect. All rights reserved. +// + +import UIKit + +protocol draggableViewDelegate { + func didDragToTrash() -> Bool +} + +class DraggableView: UIView { + + var panGestureRecognizer:UIPanGestureRecognizer! + var initialPosition:CGPoint! + + var delegate:draggableViewDelegate! + + override init(frame: CGRect) { + super.init(frame: frame) + initialPosition = frame.origin + panGestureRecognizer = UIPanGestureRecognizer() + panGestureRecognizer.addTarget(self, action: "updatePosition:") + addGestureRecognizer(panGestureRecognizer) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func updatePosition(sender: UIPanGestureRecognizer) { + let translation = sender.translationInView(self) + + frame.origin.x = initialPosition.x + translation.x + frame.origin.y = initialPosition.y + translation.y + + let willTrash: Bool = delegate.didDragToTrash() + + if willTrash { + layer.borderColor = UIColor.redColor().CGColor + layer.borderWidth = 3 + } else { + layer.borderWidth = 0 + } + + if panGestureRecognizer.state == UIGestureRecognizerState.Ended { + if !willTrash { + snapToOriginAnimation() + } else { + trashActionAnimation() + } + } + } + + func snapToOriginAnimation() { + UIView.animateWithDuration(0.2) { () -> Void in + self.frame.origin = self.initialPosition + } + } + + func trashActionAnimation() { + UIView.animateWithDuration(0.1, animations: { () -> Void in + self.alpha = 0 + }) { (complete) -> Void in + if complete { + self.removeFromSuperview() + } + } + } +} \ No newline at end of file diff --git a/DragAndDrop/Info.plist b/DragAndDrop/Info.plist index 40c6215..eabb3ae 100644 --- a/DragAndDrop/Info.plist +++ b/DragAndDrop/Info.plist @@ -24,8 +24,6 @@ UILaunchStoryboardName LaunchScreen - UIMainStoryboardFile - Main UIRequiredDeviceCapabilities armv7 diff --git a/DragAndDrop/View.swift b/DragAndDrop/View.swift new file mode 100644 index 0000000..3a6f8b5 --- /dev/null +++ b/DragAndDrop/View.swift @@ -0,0 +1,72 @@ +// +// View.swift +// DragAndDrop +// +// Created by Stanley Chiang on 3/6/16. +// Copyright © 2016 SantaClaraiOSConnect. All rights reserved. +// + +import UIKit + +protocol ViewDelegate { + func reset() +} + +class View: UIView, draggableViewDelegate { + + var draggableView:DraggableView! + var trashArea:UIView! + var resetButton:UIButton! + + var delegate:ViewDelegate! + + override init(frame: CGRect) { + super.init(frame: frame) + + trashArea = initTrashArea() + addSubview(trashArea) + + resetButton = initResetButton() + addSubview(resetButton) + + draggableView = initDraggableView() + addSubview(draggableView) + + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func initDraggableView() -> DraggableView { + let view = DraggableView(frame: CGRectMake(100,100,100,100)) + view.delegate = self + view.backgroundColor = UIColor.orangeColor() + return view + } + + func initTrashArea() -> UIView { + let view = UIView(frame: CGRectMake(0, frame.height * 2 / 3,frame.width,frame.height / 3 - 50)) + view.backgroundColor = UIColor.lightGrayColor() + return view + } + + func initResetButton() -> UIButton { + let button = UIButton(frame: CGRectMake(0,frame.height - 50,frame.width, 50)) + button.setTitle("Reset", forState: UIControlState.Normal) + button.setTitleColor(UIColor.lightTextColor(), forState: UIControlState.Normal) + button.backgroundColor = UIColor.darkGrayColor() + +// TODO: learn more about what it means to pass target as self all the time + button.addTarget(self, action: "resetAction:", forControlEvents: UIControlEvents.TouchUpInside) + return button + } + + func resetAction(sender: UIButton){ + delegate.reset() + } + + func didDragToTrash() -> Bool { + return draggableView.frame.intersects(trashArea.frame) + } +} diff --git a/DragAndDrop/ViewController.swift b/DragAndDrop/ViewController.swift index 824f5f5..e9f9913 100644 --- a/DragAndDrop/ViewController.swift +++ b/DragAndDrop/ViewController.swift @@ -8,11 +8,16 @@ import UIKit -class ViewController: UIViewController { +class ViewController: UIViewController, ViewDelegate { + var mainView:View! + override func viewDidLoad() { super.viewDidLoad() - // Do any additional setup after loading the view, typically from a nib. + self.view.backgroundColor = UIColor.whiteColor() + mainView = View(frame: self.view.frame) + mainView.delegate = self + self.view.addSubview(mainView) } override func didReceiveMemoryWarning() { @@ -20,6 +25,13 @@ class ViewController: UIViewController { // Dispose of any resources that can be recreated. } + func reset() { + mainView.removeFromSuperview() + + mainView = View(frame: self.view.frame) + mainView.delegate = self + self.view.addSubview(mainView) + } }