'How to rotate the Drag&Drop preview in Swift
I have a problem rotating the preview when I drag a button. In this project I drag a button that represents a street that you can rotate, so when the user rotates the button I save the number of rotations in the button tag. I tried to use the UITargetedDragPreview methods and the drag item's preview provider, but it doesn't work. Is my approach wrong?
This is the code (in the lasts three methods there are the approaches that I tried:
func dragInteraction(_ interaction: UIDragInteraction, itemsForBeginning session: UIDragSession) -> [UIDragItem] {
if let btn=self.cardsStack.hitTest(session.location(in: self.cardsStack), with: nil) as? UIButton{
let touchedImage=btn.currentBackgroundImage ?? UIImage()
selectedCard = (touchedImage, btn.tag)
let itemProvider=NSItemProvider(object: touchedImage)
let dragItem=UIDragItem(itemProvider: itemProvider)
selectedBtn=btn
return [dragItem]
}
else{
return []
}
}
func dropInteraction(_ interaction: UIDropInteraction, sessionDidUpdate session: UIDropSession) -> UIDropProposal {
return UIDropProposal(operation: .copy)
}
func dropInteraction(_ interaction: UIDropInteraction, performDrop session: UIDropSession) {
for dragItem in session.items {
dragItem.itemProvider.loadObject(ofClass: UIImage.self, completionHandler: {object,error in
DispatchQueue.main.async {
if let btn=self.outerStack.hitTest(session.location(in: self.outerStack), with: nil) as? UIButton{
btn.setTitle("", for: .normal)
btn.setBackgroundImage(self.selectedCard.0, for: .normal)
btn.transform=CGAffineTransform(rotationAngle: (.pi/2)*CGFloat(self.selectedCard.1))
let result=self.handler.addCard(at: self.buttonAt(btn: btn)!, to: self.directions(for: self.selectedCard.0, rotations: self.selectedCard.1), in: self.structure(for: self.selectedCard.0), for: self.selectedCard.1)
self.selectedCard=(UIImage(),0)
self.selectedBtn.transform=CGAffineTransform(rotationAngle: 0)
UIView.animate(withDuration: 0.5, animations: {
self.selectedBtn.transform=self.selectedBtn.transform.translatedBy(x: 0, y: self.outerStack.frame.maxY)
}, completion: {_ in
UIView.animate(withDuration: 1, animations: {
self.selectedBtn.transform=CGAffineTransform.identity
self.selectedBtn.setBackgroundImage(UIImage(named: self.cardsDeck[0]), for: .normal)
})
self.selectedBtn.tag=0
self.cardsDeck.removeFirst()
})
self.handler.indexActivePlayer = self.handler.indexActivePlayer>=self.handler.players.count-1 ? 0 : self.handler.indexActivePlayer+1
let index=self.handler.indexActivePlayer
self.turnButton.tintColor=self.handler.players[index].exitColor
self.turnButton.title=self.handler.players[index].nickname
if let exit = result{
self.win=true
self.winnerExit=exit
self.performSegue(withIdentifier: "result", sender: nil)
}
}
}
})
}
}
func canDrop(for btn:UIButton)->Bool{
let image=selectedCard.0
let rotations=selectedCard.1
let position=buttonAt(btn: btn)!
if btn.currentBackgroundImage != nil{
return false
}
else{
let directions=directions(for: image, rotations: rotations)
var index=0 //punti in cui la strada si può collegare
var t=false //valore che segnala se è posizionabile in tutte le direzioni in cui c'è qualcosa
let dir:[Direction]=[.left, .right, .top, .bottom]
for d in dir{
switch d {
case .left:
if directions.contains(.left){
if handler.streetsTable[position.section][position.row-1].structure[2]>0{
t=true
index+=1
}
else if handler.streetsTable[position.section][position.row-1].structure.allSatisfy({$0<0}){
index+=1
}
}
else if handler.streetsTable[position.section][position.row-1].structure[2]<0{
index+=1 //rileva se la strada a sinistra non è vuota
}
case .top:
if directions.contains(.top){
if handler.streetsTable[position.section-1][position.row].structure[3]>0{
t=true
index+=1
}
else if handler.streetsTable[position.section-1][position.row].structure.allSatisfy({$0<0}){
index+=1
}
}
else if handler.streetsTable[position.section-1][position.row].structure[3]<0{
index+=1
}
case .right:
if directions.contains(.right){
if handler.streetsTable[position.section][position.row+1].structure[0]>0{
t=true
index+=1
}
else if handler.streetsTable[position.section][position.row+1].structure.allSatisfy({$0<0}){
index+=1
}
}
else if handler.streetsTable[position.section][position.row+1].structure[0]<0{
index+=1
}
case .bottom:
if directions.contains(.bottom){
if handler.streetsTable[position.section+1][position.row].structure[1]>0{
t=true
index+=1
}
else if handler.streetsTable[position.section+1][position.row].structure.allSatisfy({$0<0}){
index+=1
}
}
else if handler.streetsTable[position.section+1][position.row].structure[1]<0{
index+=1
}
}
}
t=t&&index==4
return t
}
}
func dragInteraction(_ interaction: UIDragInteraction, sessionIsRestrictedToDraggingApplication session: UIDragSession) -> Bool {
return true
}
func dragInteraction(_ interaction: UIDragInteraction, prefersFullSizePreviewsFor session: UIDragSession) -> Bool {
return false
}
func dropInteraction(_ interaction: UIDropInteraction, canHandle session: UIDropSession) -> Bool {
if let btn=outerStack.hitTest(session.location(in: outerStack), with: nil) as? UIButton{
return session.canLoadObjects(ofClass: UIImage.self) && canDrop(for: btn)
}
else{
return false
}
}
func dragInteraction(_ interaction: UIDragInteraction, sessionDidMove session: UIDragSession) {
session.items[0].previewProvider = {
let imageView = UIImageView(frame: self.selectedBtn.frame)
imageView.transform = CGAffineTransform(rotationAngle: .pi/2 * CGFloat(self.selectedCard.1))
imageView.image=self.selectedCard.0
return UIDragPreview(view: imageView)
}
}
func dropInteraction(_ interaction: UIDropInteraction, previewForDropping item: UIDragItem, withDefault defaultPreview: UITargetedDragPreview) -> UITargetedDragPreview? {let parameters=UIPreviewParameters()
parameters.visiblePath=UIBezierPath(rect: selectedBtn.frame)
parameters.shadowPath=UIBezierPath(rect: selectedBtn.frame)
let target=UIPreviewTarget(container: selectedBtn, center: selectedBtn.center, transform: selectedBtn.transform)
return UITargetedDragPreview(view: selectedBtn, parameters: parameters, target: target)
}
func dragInteraction(_ interaction: UIDragInteraction, previewForLifting item: UIDragItem, session: UIDragSession) -> UITargetedDragPreview? {
let parameters=UIPreviewParameters()
let w=selectedBtn.frame.width/2
let h=selectedBtn.frame.height/2
let x=selectedBtn.frame.midX
let y=selectedBtn.frame.midY
parameters.visiblePath=UIBezierPath(rect: CGRect(x: x, y: y, width: w, height: h) )
selectedBtn.adjustsImageSizeForAccessibilityContentSizeCategory=true
let target=UIPreviewTarget(container: cardsStack, center: selectedBtn.center)
return UITargetedDragPreview(view: selectedBtn, parameters: parameters, target: target)
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|