I have a drag and drop function (code below) for my table that works great. Except, I can't drag a cell to a location not showing on screen / in view.
In other words, I haven't figured out how to make it autoscroll.
Is anyone able to look at my code and know where to add code that enables autoscrolling when the user drags the cell towards the top or bottom of the view?
func animateCellDrag (gestureRecognizer: UIGestureRecognizer, tableView: UITableView, whichList: String) {
let longPress = gestureRecognizer as! UILongPressGestureRecognizer
let state = longPress.state
var locationInView = longPress.locationInView(tableView)
var indexPath = tableView.indexPathForRowAtPoint(locationInView)
var count = 0
struct My {
static var cellSnapshot : UIView? = nil
}
struct Path {
static var initialIndexPath : NSIndexPath? = nil
}
if indexPath != nil {
//Steps to take a cell snapshot. Function to be called in switch statement
func snapshotOfCell(inputView: UIView) -> UIView {
UIGraphicsBeginImageContextWithOptions(inputView.bounds.size, false, 0.0)
inputView.layer.renderInContext(UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext() as UIImage
UIGraphicsEndImageContext()
let cellSnapshot : UIView = UIImageView(image: image)
cellSnapshot.layer.masksToBounds = false
cellSnapshot.layer.cornerRadius = 0.0
cellSnapshot.layer.shadowOffset = CGSizeMake(-5.0, 0.0)
cellSnapshot.layer.shadowRadius = 5.0
cellSnapshot.layer.shadowOpacity = 0.4
return cellSnapshot
}
switch state {
case UIGestureRecognizerState.Began:
//Calls above function to take snapshot of held cell, animate pop out
//Run when a long-press gesture begins on a cell
if indexPath != nil {
Path.initialIndexPath = indexPath
let cell = tableView.cellForRowAtIndexPath(indexPath!) as UITableViewCell!
My.cellSnapshot = snapshotOfCell(cell)
var center = cell.center
My.cellSnapshot!.center = center
My.cellSnapshot!.alpha = 0.0
tableView.addSubview(My.cellSnapshot!)
UIView.animateWithDuration(0.25, animations: { () -> Void in
center.y = locationInView.y
My.cellSnapshot!.center = center
My.cellSnapshot!.transform = CGAffineTransformMakeScale(1.05, 1.05)
My.cellSnapshot!.alpha = 0.98
cell.alpha = 0.0
}, completion: { (finished) -> Void in
if finished {
cell.hidden = true
}
})
}
case UIGestureRecognizerState.Changed:
if My.cellSnapshot != nil || indexPath != nil {
//Runs when the user "lets go" of the cell
//Sets CG Y-Coordinate of snapshot cell to center of current location in table (snaps into place)
var center = My.cellSnapshot!.center
center.y = locationInView.y
My.cellSnapshot!.center = center
let appDel: AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
let context: NSManagedObjectContext = appDel.managedObjectContext!
let fetchRequest = NSFetchRequest(entityName: whichList)
let sortDescriptor = NSSortDescriptor(key: "displayOrder", ascending: true )
fetchRequest.sortDescriptors = [ sortDescriptor ]
//If the indexPath is not 0 AND is not the same as it began (didn't move): Update array and table row order
if ((indexPath != nil) && (indexPath != Path.initialIndexPath) && (indexPath?.row < taskList_Cntxt.count)) {
switch whichList {
case "TodayTask", "TomTask", "TBDTask", "FinTask":
swap(&taskList_Cntxt[indexPath!.row], &taskList_Cntxt[Path.initialIndexPath!.row])
tableView.moveRowAtIndexPath(Path.initialIndexPath!, toIndexPath: indexPath!)
toolBox.updateDisplayOrder()
default:
swap(&curLifeList_Context[indexPath!.row], &curLifeList_Context[Path.initialIndexPath!.row])
tableView.moveRowAtIndexPath(Path.initialIndexPath!, toIndexPath: indexPath!)
toolBox.llvc_updateDisplayOrder()
}
do {
try context.save()
} catch _ { print("Drag and drop error. State: Changed")}
Path.initialIndexPath = indexPath
}
}
default:
if My.cellSnapshot != nil || indexPath != nil {
//Runs continuously while a long press is recognized / Animates cell movement
let cell = tableView.cellForRowAtIndexPath(Path.initialIndexPath!) as UITableViewCell!
cell.hidden = false
cell.alpha = 0.0
UIView.animateWithDuration(0.25, animations: { () -> Void in
My.cellSnapshot!.center = cell.center
My.cellSnapshot!.transform = CGAffineTransformIdentity
My.cellSnapshot!.alpha = 0.0
cell.alpha = 1.0
}, completion: { (finished) -> Void in
if finished {
//Completion block removes snapshot of cell, cleans everything up
Path.initialIndexPath = nil
My.cellSnapshot!.removeFromSuperview()
My.cellSnapshot = nil
}
})//End of competion block & end of animation
}//End of 'if nil'
}//End of switch
}//End of longPress if-nil
}//End of longPressGestureRecognized
I was able to resolve it using this code:
if locationOnScreen.y < 200 && indexPath!.row > 1 {
let indexPath = NSIndexPath(forRow: indexPath!.row-1, inSection: 0)
tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: UITableViewScrollPosition.Top, animated: false)
} else if locationOnScreen.y > 550 && indexPath!.row < listCount {
let indexPath = NSIndexPath(forRow: indexPath!.row+1, inSection: 0)
tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: UITableViewScrollPosition.Bottom, animated: false)
}
Where:
var locationOnScreen = longPress.locationInView(tableView.superview)
listCount = listArrayOrContext.count
Inserted in the switch case:
case UIGestureRecognizerState.Changed:
I set animate to false because otherwise I got very jerky, messy scrolling. If anyone figures out how to get a slow, gradual scroll, please post it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With