Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Adds support for dragging between subviews.

When placing TKDragView objects in different children (eg. scrollview
with objects) set the parentContainer property to the common ancestor.
It will be used to transform positions through the hierarchies.

This change required updating TKCGRectValue into a real object with a
parent UIView property so that different good rectangles can be in
different children.
  • Loading branch information...
commit a3a0f36d9924e6312fbc03fe5a0bb8c0c9966e17 1 parent 8173929
@gradha gradha authored
View
13 TKDragViewDemo/TKDragView.h
@@ -15,14 +15,18 @@ typedef BOOL TKVelocity;
#define kTKDragConstantSpeed NO
/**
- Creates NSValue object holding given CGRect
+ Holds a rectangle position along with the parent container view.
*/
-NSValue * TKCGRectValue(CGRect rect);
+@interface TKCGRect : NSObject
+@property (nonatomic, weak) UIView *parent;
+@property (nonatomic, assign) CGRect rect;
++ (TKCGRect*)from:(CGRect)rect forView:(UIView*)view;
+
+@end
-CGRect TKCGRectFromValue(NSValue *value);
/**
Returns the distance between centers of the two frames
@@ -231,6 +235,9 @@ inline CGPoint TKCGRectCenter(CGRect rect);
@property (nonatomic, weak) id<TKDragViewDelegate> delegate;
+// Adds option to specify a different parent than the normal superview.
+@property (nonatomic, weak) UIView *parentContainer;
+
/**
@discusion Initializer for drag views with only one end frame
*/
View
127 TKDragViewDemo/TKDragView.m
@@ -17,14 +17,18 @@
#define VELOCITY_PARAMETER 1000.0f
-NSValue * TKCGRectValue(CGRect rect){
- return [NSValue valueWithCGRect:rect];
-}
+@implementation TKCGRect
-CGRect TKCGRectFromValue(NSValue *value){
- return [value CGRectValue];
++ (TKCGRect*)from:(CGRect)rect forView:(UIView*)view
+{
+ TKCGRect *r = [TKCGRect new];
+ r.rect = rect;
+ r.parent = view;
+ return r;
}
+@end
+
CGPoint TKCGRectCenter(CGRect rect){
return CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));
}
@@ -61,6 +65,8 @@ - (NSTimeInterval)swapToStartAnimationDuration;
- (NSTimeInterval)swapToEndAnimationDurationWithFrame:(CGRect)endFrame;
+@property (nonatomic, weak) UIView *startView;
+
@end
@@ -227,6 +233,11 @@ - (void)setDelegate:(id<TKDragViewDelegate>)delegate{
}
}
+- (UIView*)parentContainer
+{
+ return _parentContainer ? _parentContainer : [self superview];
+}
+
- (void)setCanUseSameEndFrameManyTimes:(BOOL)canUseSameEndFrameManyTimes{
canUseSameEndFrameManyTimes_ = canUseSameEndFrameManyTimes;
@@ -284,17 +295,25 @@ - (void)panBegan:(UIPanGestureRecognizer*)gestureRecognizer{
isDragging_ = YES;
- CGPoint pt = [gestureRecognizer locationInView:self];
-
+ const CGPoint pt = [gestureRecognizer locationInView:self];
+
startLocation = pt;
-
- [[self superview] bringSubviewToFront:self];
+
+ self.startView = [self superview];
+ self.startFrame = self.frame;
// Displace view to match point as center.
if (self.dragsAtCenter)
[self setCenter:CGPointMake(self.frame.origin.x + startLocation.x,
self.frame.origin.y + startLocation.y)];
+ if (self.startView != [self parentContainer]) {
+ self.frame = [[self superview] convertRect:self.frame toView:[self parentContainer]];
+ [self.parentContainer addSubview:self];
+ }
+
+ [[self parentContainer] bringSubviewToFront:self];
+
if (delegateFlags_.dragViewDidStartDragging) {
[self.delegate dragViewDidStartDragging:self];
}
@@ -308,10 +327,11 @@ - (void)panMoved:(UIPanGestureRecognizer*)gestureRecognizer{
return;
- CGPoint pt = [gestureRecognizer locationInView:self];
- CGPoint translation = [gestureRecognizer translationInView:[self superview]];
- [self setCenter:CGPointMake([self center].x + translation.x, [self center].y + translation.y)];
- [gestureRecognizer setTranslation:CGPointZero inView:[self superview]];
+ CGPoint pt = [gestureRecognizer locationInView:[self parentContainer]];
+ CGPoint translation = [gestureRecognizer translationInView:[self parentContainer]];
+ [self setCenter:CGPointMake([self center].x + translation.x,
+ [self center].y + translation.y)];
+ [gestureRecognizer setTranslation:CGPointZero inView:[self parentContainer]];
// Is over start frame
@@ -359,7 +379,8 @@ - (void)panMoved:(UIPanGestureRecognizer*)gestureRecognizer{
}
if(!canUseSameEndFrameManyTimes_){
- CGRect goodFrame = TKCGRectFromValue([self.goodFramesArray objectAtIndex:currentGoodFrameIndex_]);
+ TKCGRect *r = self.goodFramesArray[currentGoodFrameIndex_];
+ CGRect goodFrame = r.rect;
[[TKDragManager manager] dragView:self didLeaveEndFrame:goodFrame];
}
@@ -379,7 +400,8 @@ - (void)panMoved:(UIPanGestureRecognizer*)gestureRecognizer{
}
if (!canUseSameEndFrameManyTimes_ && isAtEndFrame_) {
- CGRect rect = TKCGRectFromValue([self.goodFramesArray objectAtIndex:currentGoodFrameIndex_]);
+ TKCGRect *r = self.goodFramesArray[currentGoodFrameIndex_];
+ CGRect rect = r.rect;
[[TKDragManager manager] dragView:self didLeaveEndFrame:rect];
}
@@ -455,7 +477,8 @@ - (void)panEnded:(UIPanGestureRecognizer*)gestureRecognizer{
if (isAtEndFrame_ && !shouldStickToEndFrame_) {
if(!canUseSameEndFrameManyTimes_) {
- CGRect goodFrame = TKCGRectFromValue([self.goodFramesArray objectAtIndex:currentGoodFrameIndex_]);
+ TKCGRect *r = self.goodFramesArray[currentGoodFrameIndex_];
+ CGRect goodFrame = r.rect;
[[TKDragManager manager] dragView:self didLeaveEndFrame:goodFrame];
}
@@ -476,7 +499,8 @@ - (void)panEnded:(UIPanGestureRecognizer*)gestureRecognizer{
}
else{
if (isOverEndFrame_ && !canUseSameEndFrameManyTimes_) {
- CGRect goodFrame = TKCGRectFromValue([self.goodFramesArray objectAtIndex:currentGoodFrameIndex_]);
+ TKCGRect *r = self.goodFramesArray[currentGoodFrameIndex_];
+ CGRect goodFrame = r.rect;
[[TKDragManager manager] dragView:self didLeaveEndFrame:goodFrame];
}
@@ -515,42 +539,33 @@ - (BOOL)didEnterBadFrameWithPoint:(CGPoint)point {
- (BOOL)didEnterStartFrameWithPoint:(CGPoint)point {
- CGPoint touchInSuperview = [self convertPoint:point toView:[self superview]];
+ CGPoint touchInSuperview = [self convertPoint:point toView:[self parentContainer]];
return CGRectContainsPoint(startFrame_,touchInSuperview);
}
- (NSInteger)badFrameIndexWithPoint:(CGPoint)point{
-
- CGPoint touchInSuperview = [self convertPoint:point toView:[self superview]];
-
- NSInteger index = -1;
-
-
-
+
for (int i=0;i<[self.badFramesArray count];i++) {
- CGRect badFrame = [[self.badFramesArray objectAtIndex:i] CGRectValue];
- if (CGRectContainsPoint(badFrame, touchInSuperview))
- index = i;
+ TKCGRect *r = self.badFramesArray[i];
+ const CGRect goodFrame = [[self parentContainer] convertRect:r.rect fromView:r.parent];
+ if (CGRectContainsPoint(goodFrame, point))
+ return i;
}
-
- return index;
+ return -1;
}
- (NSInteger)goodFrameIndexWithPoint:(CGPoint)point{
-
- CGPoint touchInSuperview = [self convertPoint:point toView:[self superview]];
-
- NSInteger index = -1;
-
+
for (int i=0;i<[self.goodFramesArray count];i++) {
- CGRect goodFrame = [[self.goodFramesArray objectAtIndex:i] CGRectValue];
- if (CGRectContainsPoint(goodFrame, touchInSuperview))
- index = i;
+ TKCGRect *r = self.goodFramesArray[i];
+ const CGRect goodFrame = [[self parentContainer] convertRect:r.rect fromView:r.parent];
+ if (CGRectContainsPoint(goodFrame, point))
+ return i;
}
- return index;
+ return -1;
}
- (NSTimeInterval)swapToStartAnimationDuration{
@@ -578,6 +593,8 @@ - (NSTimeInterval)swapToEndAnimationDurationWithFrame:(CGRect)endFrame{
- (void)swapToStartPosition{
+ self.frame = [[self parentContainer] convertRect:self.frame toView:self.startView];
+ [self.startView addSubview:self];
isAnimating_ = YES;
if (delegateFlags_.dragViewWillSwapToStartFrame)
@@ -606,11 +623,21 @@ - (void)swapToStartPosition{
}
- (void)swapToEndPositionAtIndex:(NSInteger)index{
+
+ // Define a common action performed when the swap can not happen.
+ void (^abort_swap)(void) = ^{
+ self.frame = [[self parentContainer]
+ convertRect:self.frame toView:self.startView];
+ [self.startView addSubview:self];
+ };
- if (![self.goodFramesArray count]) return;
-
- CGRect endFrame = [[self.goodFramesArray objectAtIndex:index] CGRectValue];
+ if (![self.goodFramesArray count]) {
+ abort_swap();
+ return;
+ }
+ TKCGRect *r = self.goodFramesArray[index];
+ CGRect endFrame = r.rect;
if (!isAtEndFrame_) {
if (!canUseSameEndFrameManyTimes_) {
@@ -619,14 +646,17 @@ - (void)swapToEndPositionAtIndex:(NSInteger)index{
if(delegateFlags_.dragViewDidLeaveGoodFrame){
[self.delegate dragViewDidLeaveGoodFrame:self atIndex:index];
}
+ abort_swap();
return;
}
}
}
-
isAnimating_ = YES;
+ self.frame = [[self parentContainer] convertRect:self.frame toView:r.parent];
+ [r.parent addSubview:self];
+
if (delegateFlags_.dragViewWillSwapToEndFrame)
[self.delegate dragViewWillSwapToEndFrame:self atIndex:index];
@@ -699,8 +729,8 @@ - (void)addDragView:(TKDragView *)dragView{
if ([self.managerArray count]) {
- for (NSValue *dragViewValue in dragView.goodFramesArray) {
- CGRect dragViewRect = TKCGRectFromValue(dragViewValue);
+ for (TKCGRect *dragViewValue in dragView.goodFramesArray) {
+ CGRect dragViewRect = dragViewValue.rect;
BOOL isInTheArray = NO;
for (TKOccupancyIndicator *ind in self.managerArray) {
@@ -728,7 +758,8 @@ - (void)addDragView:(TKDragView *)dragView{
for (int i = 0;i < [framesToAdd count]; i++) {
- CGRect frame = TKCGRectFromValue([framesToAdd objectAtIndex:i]);
+ TKCGRect *r = framesToAdd[i];
+ CGRect frame = r.rect;
TKOccupancyIndicator *ind = [TKOccupancyIndicator indicatorWithFrame:frame];
@@ -745,9 +776,9 @@ - (void)removeDragView:(TKDragView *)dragView{
CGRect rect = ind.frame;
- for (NSValue *value in dragView.goodFramesArray) {
+ for (TKCGRect *value in dragView.goodFramesArray) {
- CGRect endFrame = TKCGRectFromValue(value);
+ CGRect endFrame = value.rect;
if (CGRectEqualToRect(rect, endFrame)) {
ind.count--;
View
6 TKDragViewDemo/TKViewController.m
@@ -57,8 +57,8 @@ - (void)viewDidLoad{
CGRect badFrame = CGRectMake(6 + i * 103, 290, 100, 100);
- [goodFrames addObject:TKCGRectValue(endFrame)];
- [badFrames addObject:TKCGRectValue(badFrame)];
+ [goodFrames addObject:[TKCGRect from:endFrame forView:self.view]];
+ [badFrames addObject:[TKCGRect from:badFrame forView:self.view]];
UIView *endView = [[UIView alloc] initWithFrame:endFrame];
endView.layer.borderColor = [UIColor greenColor].CGColor;
@@ -92,7 +92,7 @@ - (void)viewDidLoad{
andDelegate:self];
- dragView.dragsAtCenter = YES;
+ //dragView.dragsAtCenter = YES;
dragView.canDragMultipleDragViewsAtOnce = NO;
dragView.canUseSameEndFrameManyTimes = NO;
Please sign in to comment.
Something went wrong with that request. Please try again.