AJWDraggableDroppable provides a rich drag and drop API for iOS apps.
💀
AJWDraggableDroppable
is an Objective-C project and is longer maintained. I'd orginally built it for a side project that never got released (seen in the video).
A draggable view can be moved with user interaction. A droppable view provides an area in which a draggable view can be dropped. AJWDraggableDroppable allows you to identify a view as a draggable or droppable, and provides a mechanism for responding to events involving the two.
Features:
- Identify a view as draggable or droppable in a single line.
- Add draggable behaviour to a view without having to go through the routine
UIPanGestureRecognizer
rigmarole. - Respond to events involving draggable and droppable views (example: a draggable was dropped on a droppable).
- Apply visual states to draggable and droppable views during the different phases of a drag and drop gesture.
- Animate a draggable view back to it's starting location, or a defined drop location with UIKitDynamics snap behaviours.
- Manage separate collections of draggable and droppable views.
I'm still writing this component so a CocoaPod hasn't yet been released due to the code being subject to change.
The API consists of the following components:
-
AJWDraggableDroppable
- Instances ofAJWDraggableDroppable
are responsible for managing a collection of draggable views, a collection of droppable views, and notifying other components of your application about any events that happen involving the two. -
<AJWDraggableDroppableDelegate>
- Thedelegate
of aAJWDraggableDroppable
object should adopt theAJWDraggableDroppableDelegate
protocol to be notified of any drag and drop events involving any views identified as draggable or droppable. -
<AJWDraggableView>
- TheAJWDraggableView
protocol is adopted byUIView
subclasses to be registered as draggable. It's methods allow behaviour and appearance customisation during user drag and drop interaction. -
<AJWDroppableView>
- TheAJWDroppableView
protocol is adopted byUIView
subclasses to be registered as droppable. It's methods allow behaviour and appearance customisation during user drag and drop interaction.
#import "AJWDraggableDroppable.h"
#import "ViewController.h"
@interface ViewController () <AJWDraggableDroppableDelegate>
@property (strong, nonatomic) AJWDraggableDroppable *dragDropController;
@end
@implementation ViewController
#pragma mark View Lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Note: the next 6 lines of code would typically be achieved in Interface Builder with defined outlets. Code given here for demonstrative purpose.
self.dragDropController = [AJWDraggableDroppable controllerWithReferenceView:self.view];
self.dragDropController.delegate = self;
UIView *draggable = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 50, 50)];
UIView *droppable = [[UIView alloc] initWithFrame:CGRectMake(0, 100, 200, 200)];
[self.view addSubView:draggable];
[self.view addSubView:droppable];
[self.dragDropController registerDraggableView:draggable];
[self.dragDropController registerDroppableView:droppable];
}
- (void)draggableDroppable:(AJWDraggableDroppable *)draggableDroppable draggable:(UIView *)draggable didDropIntoDroppable:(UIView *)droppable gesture:(UIPanGestureRecognizer *)gestureRecognizer
{
NSLog(@"Draggable (%@) was dropped into droppable (%@)", draggable, droppable);
}
To register a view as draggable:
[self.dragDropController registerDraggableView:view];
This adds a UIPanGestureRecognizer
to the view that allows a user to drag the view around the screen with touch. The method returns the gesture recognizer should you wish to set your class as it's delegate
or define additional actions.
To deregister a draggable view:
[self.dragDropController deregisterDraggableView:view];
Similarly:
[self.dragDropController registerDroppableView:view];
[self.dragDropController deregisterDroppableView:view];
Respond to drag and drop events by adopting the AJWDraggableDroppableDelegate
protocol and setting the AJWDraggableDroppable
delegate to the conforming class.
Respond to a draggable drag start:
- (void)draggableDroppable:(AJWDraggableDroppable *)draggableDroppable draggableGestureDidBegin:(UIPanGestureRecognizer *)gestureRecognizer draggable:(UIView *)draggable
{
NSLog(@"Draggable drag gesture started: %@", log);
}
Respond to a draggable drag end (and a drop into a droppable):
- (void)draggableDroppable:(AJWDraggableDroppable *)draggableDroppable draggableGestureDidEnd:(UIPanGestureRecognizer *)gestureRecognizer draggable:(UIView *)draggable droppable:(UIView *)droppable
{
if (droppable) {
NSLog(@"Dropped!");
}
else {
NSLog(@"Missed!");
}
}
By subclassing UIView and adopting the AJWDraggableView
protocol it's possible to customise the appearance of a draggable throughout the phases of a drag gesture.
@interface DraggableView <AJWDraggableView>
@end
Customise the draggable's appearance during a drag state:
- (void)draggableViewApplyAppearanceStateDragging
{
self.backgroundColor = [UIColor orangeColor];
}
Customise the draggable's appearance during a drag state while the center is hovering over a droppable bounds:
- (void)draggableViewApplyAppearanceStateHovering
{
self.backgroundColor = [UIColor redColor];
}
Resetting the draggable's appearance back to a regular state on gesture completion:
- (void)draggableViewApplyAppearanceStateRegular
{
self.backgroundColor = [UIColor yellowColor];
}
Similarly, a droppable's appearance can be customised throughout the phases of a gesture by adopting the AJWDroppableView
protocol.
@interface DroppableView <AJWDroppableView>
@end
Customise the droppable's appearance when a draggable is in motion but not over the droppable bounds:
- (void)droppableViewApplyAppearanceStatePending
{
self.backgroundColor = [self blueColor];
}
Customise the droppable's appearance when a draggable's center is hovering above it's bounds:
- (void)droppableViewApplyAppearanceStatePendingDrop
{
self.backgroundColor = [self purpleColor];
}
Resetting the droppable's appearance back to a regular state on gesture completion:
- (void)droppableViewApplyAppearanceStateRegular
{
self.backgroundColor = [self cyanColor];
}
The UISnapBehaviour class in UIKitDynamics has been used throughout AJWDraggableDroppable to animate draggables to a defined location on gesture completion (when the user lets go of the draggable).
To snap draggables back to their starting location on miss (defaults to NO
):
self.dragDropController.snapsDraggablesBackToDragStartOnMiss = YES;
To snap draggables to a point inside a droppable on hit (defaults to YES
):
self.dragDropController.snapsDraggablesToDroppableSnapPointOnHit = YES;
The snap point defaults to the droppable's center but can be set by implementing:
droppableViewSnapPoint
defined in <AJWDroppableView>
in your droppable view class:
- (CGPoint)droppableViewSnapPoint
{
return CGPointMake(5.0f, 5.0f);
}
An Xcode project is included with this repository to demonstrate the features of this component and to provide an indication of how the API is meant to be used.
The library is still in early stages of development. New functionality will be added as requirements are encountered.
Contribution welcome. Please keep the README up to date.
Copyright (c) 2014 Adam Waite. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.