Partager via


Glisser-déplacer dans Xamarin.iOS

Implémentation du glisser-déplacer pour iOS 11

iOS 11 inclut la prise en charge des glisser-déplacer pour copier des données entre les applications sur iPad. Les utilisateurs peuvent sélectionner et faire glisser tous les types de contenu à partir d’applications positionnées côte à côte, ou en faisant glisser sur une icône d’application qui déclenchera l’ouverture de l’application et permet de supprimer les données :

Exemple de glisser-déplacer de l’application personnalisée dans l’application Notes

Remarque

Avant iOS 15, le glisser-déplacer est disponible uniquement dans la même application sur i Téléphone. iOS 15 introduit le glisser-déplacer entre applications.

Envisagez de prendre en charge les opérations de glisser-déplacer partout où le contenu peut être créé ou modifié :

  • Les contrôles de texte prennent en charge le glisser-déplacer pour toutes les applications créées sur iOS 11, sans aucun travail supplémentaire.
  • Les vues de table et les vues de collection incluent des améliorations apportées à iOS 11 qui simplifient l’ajout d’un comportement de glisser-déplacer.
  • Toute autre vue peut être effectuée pour prendre en charge le glisser-déplacer avec une personnalisation supplémentaire.

Lorsque vous ajoutez la prise en charge du glisser-déplacer à vos applications, vous pouvez fournir différents niveaux de fidélité de contenu ; Par exemple, vous pouvez fournir à la fois un texte mis en forme et une version de texte brut des données afin que l’application de réception puisse choisir ce qui convient le mieux à la cible glisser. Il est également possible de personnaliser la visualisation de glissement et d’activer le glissement de plusieurs éléments à la fois.

Glisser-déplacer avec des contrôles de texte

UITextView et UITextField prennent automatiquement en charge le glissement du texte sélectionné et la suppression de contenu de texte.

Glisser-déplacer avec UITableView

UITableView a une gestion intégrée des interactions de glisser-déplacer avec des lignes de table, nécessitant seulement quelques méthodes pour activer le comportement par défaut.

Il existe deux interfaces impliquées :

  • IUITableViewDragDelegate : empaquette les informations lorsqu’un glisser-déplacer est lancé dans la vue table.
  • IUITableViewDropDelegate : traite les informations lorsqu’une suppression est tentée et terminée.

Dans l’exemple, ces deux interfaces sont implémentées sur la UITableViewController classe, ainsi que sur la source de données et le délégué. Ils sont affectés dans la ViewDidLoad méthode :

this.TableView.DragDelegate = this;
this.TableView.DropDelegate = this;

Le code minimal requis pour ces deux interfaces est expliqué ci-dessous.

Faire glisser le délégué en mode Tableau

La seule méthode requise pour prendre en charge le glissement d’une ligne à partir d’une vue de table est GetItemsForBeginningDragSession. Si l’utilisateur commence à faire glisser une ligne, cette méthode est appelée.

Une implémentation est illustrée ci-dessous. Il récupère les données associées à la ligne déplacée, l’encode et configure un NSItemProvider qui détermine la façon dont les applications gèrent la partie « drop » de l’opération (par exemple, s’ils peuvent gérer le type de données, PlainTextdans l’exemple) :

public UIDragItem[] GetItemsForBeginningDragSession (UITableView tableView,
  IUIDragSession session, NSIndexPath indexPath)
{
  // gets the 'information' to be dragged
  var placeName = model.PlaceNames[indexPath.Row];
  // convert to NSData representation
  var data = NSData.FromString(placeName, NSStringEncoding.UTF8);
  // create an NSItemProvider to describe the data
  var itemProvider = new NSItemProvider();
  itemProvider.RegisterDataRepresentation(UTType.PlainText,
                                NSItemProviderRepresentationVisibility.All,
                                (completion) =>
  {
    completion(data, null);
    return null;
  });
  // wrap in a UIDragItem
  return new UIDragItem[] { new UIDragItem(itemProvider) };
}

Il existe de nombreuses méthodes facultatives sur le délégué glisser qui peuvent être implémentées pour personnaliser le comportement de glissement, telles que la fourniture de plusieurs représentations de données qui peuvent être utilisées dans les applications cibles (telles que le texte mis en forme, ainsi que le texte brut ou une version vectorielle et bitmap d’un dessin). Vous pouvez également fournir des représentations de données personnalisées à utiliser lors du glisser-déplacer dans la même application.

Délégué de suppression d’affichage de table

Les méthodes du délégué de déplacement sont appelées lorsqu’une opération de glissement se produit sur une vue de table ou se termine au-dessus de celle-ci. Les méthodes requises déterminent si les données sont autorisées à être supprimées et quelles actions sont effectuées si la suppression est terminée :

  • CanHandleDropSession : pendant qu’un glisser-déplacer est en cours et qu’il est potentiellement supprimé sur l’application, cette méthode détermine si les données déplacées sont autorisées à être supprimées.
  • DropSessionDidUpdate : pendant que le glisser est en cours, cette méthode est appelée pour déterminer l’action prévue. Les informations de la vue de table déplacées, la session de glissement et le chemin d’index possible peuvent tous être utilisées pour déterminer le comportement et les commentaires visuels fournis à l’utilisateur.
  • PerformDrop : lorsque l’utilisateur termine la suppression (en levant son doigt), cette méthode extrait les données déplacées et modifie la vue de table pour ajouter les données dans une nouvelle ligne (ou lignes).

CanHandleDropSession

CanHandleDropSession indique si la vue de table peut accepter les données déplacées. Dans cet extrait de code, CanLoadObjects est utilisé pour confirmer que cette vue de table peut accepter des données de chaîne.

public bool CanHandleDropSession(UITableView tableView, IUIDropSession session)
{
  return session.CanLoadObjects(typeof(NSString));
}

DropSessionDidUpdate

La DropSessionDidUpdate méthode est appelée à plusieurs reprises pendant que l’opération de glisser est en cours, pour fournir des indications visuelles à l’utilisateur.

Dans le code ci-dessous, HasActiveDrag permet de déterminer si l’opération provient de la vue de table actuelle. Dans ce cas, seules les lignes uniques sont autorisées à être déplacées. Si le glisser provient d’une autre source, une opération de copie est indiquée :

public UITableViewDropProposal DropSessionDidUpdate(UITableView tableView, IUIDropSession session, NSIndexPath destinationIndexPath)
{
  // The UIDropOperation.Move operation is available only for dragging within a single app.
  if (tableView.HasActiveDrag)
  {
    if (session.Items.Length > 1)
    {
        return new UITableViewDropProposal(UIDropOperation.Cancel);
    } else {
        return new UITableViewDropProposal(UIDropOperation.Move, UITableViewDropIntent.InsertAtDestinationIndexPath);
    }
  } else {
    return new UITableViewDropProposal(UIDropOperation.Copy, UITableViewDropIntent.InsertAtDestinationIndexPath);
  }
}

L’opération de suppression peut être l’une des Cancelopérations de suppression ou MoveCopy.

L’intention de suppression peut être d’insérer une nouvelle ligne ou d’ajouter/ajouter des données à une ligne existante.

PerformDrop

La PerformDrop méthode est appelée lorsque l’utilisateur termine l’opération et modifie la vue de table et la source de données pour refléter les données supprimées.

public void PerformDrop(UITableView tableView, IUITableViewDropCoordinator coordinator)
{
  NSIndexPath indexPath, destinationIndexPath;
  if (coordinator.DestinationIndexPath != null)
  {
    indexPath = coordinator.DestinationIndexPath;
    destinationIndexPath = indexPath;
  }
  else
  {
    // Get last index path of table view
    var section = tableView.NumberOfSections() - 1;
    var row = tableView.NumberOfRowsInSection(section);
    destinationIndexPath = NSIndexPath.FromRowSection(row, section);
  }
  coordinator.Session.LoadObjects(typeof(NSString), (items) =>
  {
    // Consume drag items
    List<string> stringItems = new List<string>();
    foreach (var i in items)
    {
      var q = NSString.FromHandle(i.Handle);
      stringItems.Add(q.ToString());
    }
    var indexPaths = new List<NSIndexPath>();
    for (var j = 0; j < stringItems.Count; j++)
    {
      var indexPath1 = NSIndexPath.FromRowSection(destinationIndexPath.Row + j, destinationIndexPath.Section);
      model.AddItem(stringItems[j], indexPath1.Row);
      indexPaths.Add(indexPath1);
    }
    tableView.InsertRows(indexPaths.ToArray(), UITableViewRowAnimation.Automatic);
  });
}

Vous pouvez ajouter du code supplémentaire pour charger de manière asynchrone des objets de données volumineux.