forked from shusta/ReorderingTableViewController
-
Notifications
You must be signed in to change notification settings - Fork 1
/
ATSDragToReorderTableView.h
166 lines (117 loc) · 6.57 KB
/
ATSDragToReorderTableView.h
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
// ATSDragToReorderTableView.h
//
// Created by Daniel Shusta on 11/28/10.
// Copyright 2010 Acacia Tree Software. All rights reserved.
//
// Permission is given to use this source code file, free of charge, in any
// project, commercial or otherwise, entirely at your risk, with the condition
// that any redistribution (in part or whole) of source code must retain
// this copyright and permission notice. Attribution in compiled projects is
// appreciated but not required.
//
// THIS 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.
/*
Interface Overview:
ATSDragToReorderTableViewController is a UITableViewController subclass
that incorporates a press-and-drag-to-reorder functionality into the
tableView.
Because it subclasses from UITableViewController, you can use existing
classes that subclass from UITableViewController and subclass from
ATSDragToReorderTableViewController instead. You only need to make a few
changes (listed below).
ATSDragToReorderTableViewControllerDelegate notifies upon change in
dragging state. This could be useful if the destination or source of the
reorder could change the content of the cell.
ATSDragToReorderTableViewControllerDraggableIndicators defines how to
customize the dragged cell to make it appear more "draggable". By
default this indicatorDelegate is self and the default implementation
adds shadows above and below the cell.
Requires iOS 4.0 or greater.
Steps for use:
0. If you aren't already, link against the QuartzCore framework.
In Xcode 3.2, right-click the group tree (sidebar thingy),
Add -> Existing Frameworks… -> QuartzCore.framework
In Xcode 4.0, go to the project file -> Build Phases and add to
Link Binary With Libraries.
1. Subclass from this instead of UITableViewController
2. UITableViewDataSource (almost certainly your subclass) should
implement -tableView:moveRowAtIndexPath:toIndexPath:
Other recommendations:
It is recommended that the tableView's dataSource -setReorderingEnabled:
to NO if there is only one row.
Rotation while dragging a cell is screwy and it's not clear to me how to
handle that situation. For now, recommendation is to not allow rotations
while dragging, maybe not at all.
Assumptions made by this code:
Subclass doesn't conform to UIGestureRecognizerDelegate. If it does,
you're going to have to figure out how to orchastrate it all. It's
likely not that difficult.
self.tableView is of type UITableViewStylePlain. It will technically
work with UITableViewStyleGrouped but it'll look ugly.
This code totally ignores self.tableView.delegate's
-tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath:
I have no idea what I would do with that.
The tableview's contents won't change while dragging. I'm pretty sure if
you do this, it will crash.
*/
#import <UIKit/UIKit.h>
#import <QuartzCore/CADisplayLink.h>
#import <QuartzCore/CALayer.h>
@class ATSDragToReorderTableView;
@protocol ATSDragToReorderTableViewDelegate
@optional
- (void)dragTableView:(ATSDragToReorderTableView *)dragTableView didBeginDraggingAtRow:(NSIndexPath *)dragRow;
- (void)dragTableView:(ATSDragToReorderTableView *)dragTableView willEndDraggingToRow:(NSIndexPath *)destinationIndexPath;
- (void)dragTableView:(ATSDragToReorderTableView *)dragTableView didEndDraggingToRow:(NSIndexPath *)destinationIndexPath;
- (BOOL)dragTableView:(ATSDragToReorderTableView *)dragTableView shouldHideDraggableIndicatorForDraggingToRow:(NSIndexPath *)destinationIndexPath;
@required
// hate this, required to fix an iOS 6 bug where cell is hidden when going through normal paths to get a cell
// you must make a new cell to return this (use reuseIdent == nil), do not use dequeueResable
- (UITableViewCell *)cellIdenticalToCellAtIndexPath:(NSIndexPath *)indexPath forDragTableView:(ATSDragToReorderTableView *)dragTableView;
@end
@protocol ATSDragToReorderTableViewDraggableIndicators
@required
/*******
*
* -addDraggableIndicatorsToCell:forIndexPath and -removeDraggableIndicatorsFromCell: are guaranteed to be called.
* -hideDraggableIndicatorsOfCell: is usually called, but might not be.
*
* These work in tandem, so if your subclass overrides any of them it should override the others as well.
*
*******/
// Customize cell to appear draggable. Will be called inside an animation block.
// Cell will have highlighted set to YES, animated NO. (changes are to the selectedBackgroundView if it exists)
- (void)dragTableView:(ATSDragToReorderTableView *)dragTableView addDraggableIndicatorsToCell:(UITableViewCell *)cell forIndexPath:(NSIndexPath *)indexPath;
// You should set alpha of adjustments to 0 and similar. Will be called inside an animation block.
// This should make the cell look like a normal cell, but is not expected to actually be one.
- (void)dragTableView:(ATSDragToReorderTableView *)dragTableView hideDraggableIndicatorsOfCell:(UITableViewCell *)cell;
// Removes all adjustments to prepare cell for reuse. Will not be animated.
// -hideDraggableIndicatorsOfCell: will probably be called before this, but not necessarily.
- (void)dragTableView:(ATSDragToReorderTableView *)dragTableView removeDraggableIndicatorsFromCell:(UITableViewCell *)cell;
@end
@interface ATSDragToReorderTableView : UITableView <UIGestureRecognizerDelegate, ATSDragToReorderTableViewDraggableIndicators> {
@protected
UIPanGestureRecognizer *dragGestureRecognizer;
UILongPressGestureRecognizer *longPressGestureRecognizer;
@private
// Use setter/getter, not even subclasses should adjust this directly.
CADisplayLink *timerToAutoscroll;
CGFloat distanceThresholdToAutoscroll;
CGFloat initialYOffsetOfDraggedCellCenter;
CGPoint veryInitialTouchPoint;
UITableViewCell *draggedCell;
NSIndexPath *indexPathBelowDraggedCell;
__weak id resignActiveObserver;
}
// default is YES. Removes or adds gesture recognizers to self.tableView.
@property (assign, getter=isReorderingEnabled) BOOL reorderingEnabled;
- (void)becomeReady:(BOOL)reorderingEnabled;
- (BOOL)isDraggingCell;
@property (weak) NSObject <ATSDragToReorderTableViewDelegate> *dragDelegate; // nil by default
@property (weak) NSObject <ATSDragToReorderTableViewDraggableIndicators> *indicatorDelegate; // self by default
@end