Wie funktioniert das Drag’n’Drop-Feature in LeadHound?

Das Drag’n’Drop-Feature in LeadHound soll Nutzern bei der Bearbeitung von Leads helfen. Mit Hilfe von Drag’n’Drop können einzelne Wörter eine Property innerhalb ihrer Property umsortiert werden. Außerdem können Wörter auch in eine andere Property verschoben werden. Die neue Position des Wortes wird dem Nutzer angezeigt.

Wer macht was beim Drag’n’Drop?

Für das Drag’n’Drop- Feature werden Custom-Klassen verwendet, deren Aufgaben im Folgenden beschrieben werden:

Z7DragAndDropTableView:UITableView
Z7DragAndDropRow:UIView
Z7DragAndDropTouchElement:NSObject
Z7DragAndDropTouchView:UIView

dragAndDrop

Z7DragAndDropTableView

//public properties
var wasDragging = false
var dragAndDropRows:[Z7DragAndDropRow] = []
var selectedDragAndDropView:Z7DragAndDropTouchView?
var motherRow:Z7DragAndDropRow?
var touchingRow:Z7DragAndDropRow?

Die TableView ist das DragAndDrop-Hirn. Sie kennt alle DragAndDropRows und weiß, welche TouchView gerade bewegt wird.

Sie weiß außerdem, welches die AusgangsRow ist (motherRow) und über welcher Row sich die TouchView gerade befindet (selectedDragAndDropRow).

Bei ihr kommen alle Touches an, die dann verwaltet werden. Die TableView markiert und bewegt die selektierte TouchView. Außerdem deaktiviert sie bei aktivem Dragging das Scrollen der ScrollView.

Sie aktualisiert regelmäßig alle notwendigen Variablen und verwaltet/bearbeitet auch das Verschieben einer TouchView in einen ungültigen Bereich.

Die Unterscheidung, ob eine TouchView nur angeklickt oder ob sie bewegt wurde, wird in der

touchesMoved(touches: Set, withEvent event: UIEvent?)

geprüft und in der delegate-Funktion der TableView

(-(NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath)

über

wasDragging

weiterverarbeitet. Hier wird entschieden, ob der Touch an

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

weitergegeben wird.

Implementierung der Z7DragAndDropTableView

Die DragAndDropTableView funktioniert aktuell nur in Verbindung mit einem TableViewController. Die TableView wird per Storyboard mit dem TVC verbunden und ein Outlet wird erstellt.

In der

-(void)viewWillAppear:(BOOL)animated

des TVC wird zuerst reloadData auf dem tableView-Outlet aufgerufen. Anschließend wird die öffentliche Funktion

updateDragAndDropRows()

auf der Z7DragAndDropTableView ausgeführt.

Diese Funktion holt sich aus allen visibleCells alle Zellen, die DragAndDropRows enthalten und speichert diese in der Property

dragAndDropRows

Z7DragAndDropRow

//public properties
var property:BusinessCardProperty?
var textField:UITextField?
var currentPropertyName = ""
var newPositionView:UIView?

Für die DragAndDropRow gibt es zwei Phasen: Init-Phase und Dragging-Phase.

 

Init-Phase

Die DragAndDropRow ist eine Subview der TableView-Zelle.

dragAndDropRow = [[Z7DragAndDropRow alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
[cellView addSubview:dragAndDropRow];

Sobald der Zelle Text zugewiesen wird, wird die DragAndDropRow gefüllt. Außerdem werden delegate, das textField und der currentPropertyName gesetzt.

Auf Basis des Texts werden in der DragAndDropRow mit Hilfe der TouchElemente die TouchViews generiert und angeordnet.

Ändert sich der Text wiederholt sich dieser Prozess.

 

Dragging-Phase

Während der Dragging-Phase gibt es drei Fälle, die per HitTest unterschieden werden:
„Abmelden“, „Anmelden“ und „Verschieben innerhalb einer DragAndDropRow“

 

– Fall A: Abmelden

Beim Abmelden wird die TouchView aus dem Array „touchViews“ entfernt und der propertyText angepasst. Unterscheidet sich der propertyText, wird per delegate der Text in CoreData gespeichert.

Die restlichen TouchViews der DragAndDropRow werden neu ausgerichtet.

Anschließend wird über das TouchElement der selektierten TouchView

oldProperty

gesetzt und

currentProperty

entfernt.

 

– Fall B: Anmelden

Hat sich eine TouchView bei einer DragAndDropRow abgemeldet, muss sie sich sofort danach bei einer anderen DragAndDropRow anmelden. Dazu wird zuerst per delegate validiert, ob die neue DragAndDropRow nicht vom Property-Typ „gender“ oder eine „AddNewProperty“-Zelle ist.

Damit die neue TouchView weiß, an welcher Position sie sich in der neuen DragAndDropRow einfügen muss, wird über den x-Wert die nächste TouchView gesucht. Die TouchView wird eingefügt und der Text der neuen DragAndDropRow geändert und gespeichert.

Befinden sich rechts neben der selektierten TouchView noch andere TouchViews, werden diese nach rechts geschoben. Die neue Position wird markiert (newPositionView).

Die Property

currentProperty

des touchElements wird entsprechend gesetzt.

 

– Fall C: Verschieben innerhalb einer DragAndDropRow

Wird eine TouchView nur innerhalb einer Row verschoben, wird per hitTest überprüft wie sich die TouchViews der DragAndDropRow verhalten/ausrichten sollen.

Die neue Position wird mit der newPositionView angezeigt. Ändern sich die Positionen, wird das Array der TouchViews angepasst und der Text aktualisiert, was immer wieder eine Speicherung der Property in CoreData mit sich bringt.

Nachdem die selektierte TouchView losgelassen wird, geht sie an ihre entsprechende Stelle in der DragAndDropRow.

Z7DragAndDropTouchElement

// public properties
var text:String?
var currentProperty:String?
var oldProperty:String?

Ein TouchElement wird beim Anlegen der DragAndDropRow generiert und mit einem Wort und dem currentPropertyName der DragAndDropRow initialisiert.

Das TouchElement ist immer als Property einer TouchView gesetzt. Ändert sich die DragAndDropRow der TouchView, werden die currentProperty und die oldProperty aktualisiert.

Z7DragAndDropTouchView

// public properties
var title:String?
var touchElement:Z7DragAndDropTouchElement?
var label:UILabel?

Die TouchView wird per DragAndDrop verschoben. Initialisiert wird sie durch das TouchElement.

init(text:String?, currentProperty:String?) {
    super.init()
    self.text = text
    self.currentProperty = currentProperty
}

Beim Wechsel in eine andere Row ändern sich die Properties des TouchElements.