Mat
Mat

Reputation: 6324

Drag and drop - UIGestureRecognizer - View added not where I want to

I have this 2 tableViews (All Services available and service offered) in a splitViewController. The idea is that then the cell is moved across the center of the screen, it moves to the service offered table view. Everything works except then the touch `.began, the cell is being added to the top of the tableView covering the navBar. enter image description here

On .changed it follows my finger enter image description here

I would like the view/cell to be added where the touch began, on top of the "ServiceCell" I am touching. I tried adding it to the splitViewController.view but I think there is something wrong with my logic.

Here the code:

func didLongPressCell (gr: UILongPressGestureRecognizer) {
    let serviceCell:ServiceCell =  gr.view as! ServiceCell
    switch gr.state {
    case .began:

        let touchOffsetInCell = gr.location(in: gr.view)
        let dragEvent = DragganbleServiceCell()
        mDraggableServiceCell = dragEvent.makeWithServiceCell(serviceCell: serviceCell, offset: self.tableView.contentOffset, touchOffset: touchOffsetInCell)
        self.splitViewController?.view.addSubview(mDraggableServiceCell!)

    case .changed:
        let cp:CGPoint = gr.location(in: self.view)
        let newOrigin = CGPoint(x: (cp.x), y: (cp.y) - (mDraggableServiceCell?.touchOffset?.y)!)
        UIView.animate(withDuration: 0.1, animations: {
            self.mDraggableServiceCell?.frame = CGRect(origin: newOrigin, size: (self.mDraggableServiceCell?.frame.size)!)  
        })

    case .ended:
        let detailViewNC = self.splitViewController?.viewControllers[1] as! UINavigationController
        let detailView = detailViewNC.topViewController as! ServiceOfferedTableViewController
        if (mDraggableServiceCell?.frame.intersects(detailView.tableView.frame))! {

        onDragEnded(serviceCell:serviceCell)
        }else{

        mDraggableServiceCell?.removeFromSuperview()

        }
    default:
        print("Any other action?")
    }
}

In DraggableServiceCell:

class DragganbleServiceCell: ServiceCell {

    var originalPosition:CGPoint?
    var touchOffset:CGPoint?

    func makeWithServiceCell(serviceCell:ServiceCell, offset:CGPoint, touchOffset:CGPoint)->DragganbleServiceCell{

        let newFrame =  CGRect(x: serviceCell.frame.origin.x, y: serviceCell.frame.origin.y, width: serviceCell.frame.size.width, height: serviceCell.frame.size.height)
        let dragCell = DragganbleServiceCell(frame: newFrame)
       dragCell.touchOffset = touchOffset
        dragCell.service = serviceCell.service
        dragCell.serviceName.text = serviceCell.service?.service_description
        return dragCell
    }

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        self.containingView.backgroundColor = UIColor.rgb(230, green: 32, blue: 31)
        self.serviceName.textColor = .white
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

Upvotes: 5

Views: 261

Answers (2)

Mahesh Agrawal
Mahesh Agrawal

Reputation: 3358

I would suggest adding the gesture to self.splitViewController?.view instead of self.viewif you are not doing and changing this part of the code.

case .changed:
    let cp:CGPoint = gr.location(in: self.view)
    let newOrigin = CGPoint(x: (cp.x), y: (cp.y) - (mDraggableServiceCell?.touchOffset?.y)!)
    UIView.animate(withDuration: 0.1, animations: {
        self.mDraggableServiceCell?.frame = CGRect(origin: newOrigin, size: (self.mDraggableServiceCell?.frame.size)!)  
    })

to this

case .changed:
    let cp:CGPoint = gr.location(in: self.splitViewController?.view)
    UIView.animate(withDuration: 0.1, animations: {
        self.mDraggableServiceCell?.center = cp  
    })

try once.

Upvotes: 0

Mihai Fratu
Mihai Fratu

Reputation: 7663

Your problem is in makeWithServiceCell(serviceCell:ServiceCell, offset:CGPoint, touchOffset:CGPoint) -> DragganbleServiceCell. The frame of your serviceCell is relative to the tableView that contains it instead of UISplitViewController's view and you are never using the offset or touchOffset values to correct that. So try adjusting the frame in the same way you are doing it in the .changed event.

You might even find that the convert(_:to:) method on UIView might be useful to do CGPoint transformations between two views. See more details here.

Upvotes: 3

Related Questions