Condividi tramite


Modifica di tabelle con Xamarin.iOS

Le funzionalità di modifica delle tabelle sono abilitate eseguendo l'override dei metodi in una UITableViewSource sottoclasse. Il comportamento di modifica più semplice è il movimento swipe-to-delete che può essere implementato con un unico override del metodo. La modifica più complessa (incluse le righe in movimento) può essere eseguita con la tabella in modalità di modifica.

Scorrimento rapido per eliminare

La funzionalità di scorrimento rapido per eliminare è un gesto naturale in iOS previsto dagli utenti.

Esempio di scorrimento rapido da eliminare

Esistono tre override del metodo che influiscono sul movimento di scorrimento rapido per visualizzare un pulsante Elimina in una cella:

  • CommitEditingStyle : l'origine della tabella rileva se questo metodo viene sottoposto a override e abilita automaticamente il movimento swipe-to-delete. L'implementazione del metodo deve chiamare DeleteRows su UITableView per far scomparire le celle e rimuovere anche i dati sottostanti dal modello, ad esempio una matrice, un dizionario o un database.
  • CanEditRow : se CommitEditingStyle è sottoposto a override, si presuppone che tutte le righe siano modificabili. Se questo metodo viene implementato e restituisce false (per alcune righe specifiche o per tutte le righe), il gesto swipe-to-delete non sarà disponibile in tale cella.
  • TitleForDeleteConfirmation : specifica facoltativamente il testo per il pulsante Elimina . Se questo metodo non viene implementato, il testo del pulsante sarà "Delete".

Questi metodi vengono implementati nella TableSource classe seguente:

public override void CommitEditingStyle (UITableView tableView, UITableViewCellEditingStyle editingStyle, Foundation.NSIndexPath indexPath)
{
    switch (editingStyle) {
        case UITableViewCellEditingStyle.Delete:
            // remove the item from the underlying data source
            tableItems.RemoveAt(indexPath.Row);
            // delete the row from the table
            tableView.DeleteRows (new NSIndexPath[] { indexPath }, UITableViewRowAnimation.Fade);
            break;
        case UITableViewCellEditingStyle.None:
            Console.WriteLine ("CommitEditingStyle:None called");
            break;
    }
}
public override bool CanEditRow (UITableView tableView, NSIndexPath indexPath)
{
    return true; // return false if you wish to disable editing for a specific indexPath or for all rows
}
public override string TitleForDeleteConfirmation (UITableView tableView, NSIndexPath indexPath)
{   // Optional - default text is 'Delete'
    return "Trash (" + tableItems[indexPath.Row].SubHeading + ")";
}

Per questo esempio l'oggetto UITableViewSource è stato aggiornato in modo da usare (anziché una List<TableItem> matrice di stringhe) come origine dati perché supporta l'aggiunta e l'eliminazione di elementi dalla raccolta.

Modalità Modifica

Quando una tabella è in modalità di modifica, l'utente vede un widget rosso "stop" su ogni riga, che rivela un pulsante Elimina quando viene toccato. Nella tabella viene inoltre visualizzata un'icona "handle" per indicare che la riga può essere trascinata per modificare l'ordine. L'esempio TableEditMode implementa queste funzionalità come illustrato.

L'esempio TableEditMode implementa queste funzionalità come illustrato

Esistono diversi metodi su UITableViewSource cui influiscono sul comportamento della modalità di modifica di una tabella:

  • CanEditRow : indica se ogni riga può essere modificata. Restituisce false per impedire l'eliminazione e l'eliminazione tramite scorrimento rapido durante la modalità di modifica.
  • CanMoveRow : restituisce true per abilitare lo spostamento 'handle' o false per impedire lo spostamento.
  • EditingStyleForRow : quando la tabella è in modalità di modifica, il valore restituito da questo metodo determina se la cella visualizza l'icona di eliminazione rossa o l'icona di aggiunta verde. Restituisce UITableViewCellEditingStyle.None se la riga non deve essere modificabile.
  • MoveRow : chiamato quando viene spostata una riga in modo che la struttura di dati sottostante possa essere modificata in modo che corrisponda ai dati visualizzati nella tabella.

L'implementazione per i primi tre metodi è relativamente semplice, a meno che non si voglia usare indexPath per modificare il comportamento di righe specifiche, è sufficiente impostare come hardcode i valori restituiti per l'intera tabella.

public override bool CanEditRow (UITableView tableView, NSIndexPath indexPath)
{
    return true; // return false if you wish to disable editing for a specific indexPath or for all rows
}
public override bool CanMoveRow (UITableView tableView, NSIndexPath indexPath)
{
    return true; // return false if you don't allow re-ordering
}
public override UITableViewCellEditingStyle EditingStyleForRow (UITableView tableView, NSIndexPath indexPath)
{
    return UITableViewCellEditingStyle.Delete; // this example doesn't support Insert
}

L'implementazione MoveRow è leggermente più complessa perché deve modificare la struttura dei dati sottostante in modo che corrisponda al nuovo ordine. Poiché i dati vengono implementati come List codice seguente elimina l'elemento di dati nella posizione precedente e lo inserisce nella nuova posizione. Se i dati sono stati archiviati in una tabella di database SQLite con una colonna "order", ad esempio, questo metodo dovrà eseguire alcune operazioni SQL per riordinare i numeri in tale colonna.

public override void MoveRow (UITableView tableView, NSIndexPath sourceIndexPath, NSIndexPath destinationIndexPath)
{
    var item = tableItems[sourceIndexPath.Row];
    var deleteAt = sourceIndexPath.Row;
    var insertAt = destinationIndexPath.Row;

    // are we inserting
    if (destinationIndexPath.Row < sourceIndexPath.Row) {
        // add one to where we delete, because we're increasing the index by inserting
        deleteAt += 1;
    } else {
        // add one to where we insert, because we haven't deleted the original yet
        insertAt += 1;
    }
    tableItems.Insert (insertAt, item);
    tableItems.RemoveAt (deleteAt);
}

Infine, per ottenere la tabella in modalità di modifica, il pulsante Modifica deve chiamare SetEditing come questo

table.SetEditing (true, true);

e al termine della modifica dell'utente, il pulsante Fine dovrebbe disattivare la modalità di modifica:

table.SetEditing (false, true);

Stile di modifica inserimento righe

L'inserimento di righe dall'interno della tabella è un'interfaccia utente non comune. L'esempio principale nelle app iOS standard è la schermata Modifica contatto . Questo screenshot mostra come funziona la funzionalità di inserimento delle righe, in modalità di modifica è presente una riga aggiuntiva che, quando si fa clic, inserisce righe aggiuntive nei dati. Al termine della modifica, la riga temporanea (aggiunta nuova) viene rimossa.

Al termine della modifica, l'aggiunta temporanea di una nuova riga viene rimossa

Esistono diversi metodi che influiscono sul UITableViewSource comportamento della modalità di modifica di una tabella. Questi metodi sono stati implementati come segue nel codice di esempio:

  • EditingStyleForRow : restituisce UITableViewCellEditingStyle.Delete per le righe contenenti dati e restituisce UITableViewCellEditingStyle.Insert per l'ultima riga (che verrà aggiunta specificamente per comportarsi come pulsante di inserimento).
  • CustomizeMoveTarget : mentre l'utente sta spostando una cella il valore restituito da questo metodo facoltativo può eseguire l'override della propria posizione. Ciò significa che è possibile impedirgli di eliminare la cella in determinate posizioni, ad esempio questo esempio che impedisce che qualsiasi riga venga spostata dopo la riga (aggiungi nuova).
  • CanMoveRow : restituisce true per abilitare lo spostamento 'handle' o false per impedire lo spostamento. Nell'esempio l'ultima riga ha nascosto lo spostamento 'handle' perché è destinato al server solo come pulsante di inserimento.

Vengono inoltre aggiunti due metodi personalizzati per aggiungere la riga 'insert' e quindi rimuoverla di nuovo quando non è più necessario. Vengono chiamati dai pulsanti Modifica e Fine :

  • WillBeginTableEditing : quando viene toccato il pulsante Modifica chiama SetEditing per mettere la tabella in modalità di modifica. In questo modo viene attivato il metodo WillBeginTableEditing in cui viene visualizzata la riga (aggiungi nuova) alla fine della tabella in modo da fungere da "pulsante di inserimento".
  • DidFinishTableEditing : quando viene toccato SetEditing il pulsante Fine viene chiamato di nuovo per disattivare la modalità di modifica. Il codice di esempio rimuove la riga (aggiungi nuova) dalla tabella quando la modifica non è più necessaria.

Questi override del metodo vengono implementati nel file di esempio TableEditModeAdd/Code/TableSource.cs:

public override UITableViewCellEditingStyle EditingStyleForRow (UITableView tableView, NSIndexPath indexPath)
{
    if (tableView.Editing) {
        if (indexPath.Row == tableView.NumberOfRowsInSection (0) - 1)
            return UITableViewCellEditingStyle.Insert;
        else
            return UITableViewCellEditingStyle.Delete;
    } else // not in editing mode, enable swipe-to-delete for all rows
        return UITableViewCellEditingStyle.Delete;
}
public override NSIndexPath CustomizeMoveTarget (UITableView tableView, NSIndexPath sourceIndexPath, NSIndexPath proposedIndexPath)
{
    var numRows = tableView.NumberOfRowsInSection (0) - 1; // less the (add new) one
    if (proposedIndexPath.Row >= numRows)
        return NSIndexPath.FromRowSection(numRows - 1, 0);
    else
        return proposedIndexPath;
}
public override bool CanMoveRow (UITableView tableView, NSIndexPath indexPath)
{
    return indexPath.Row < tableView.NumberOfRowsInSection (0) - 1;
}

Questi due metodi personalizzati vengono usati per aggiungere e rimuovere la riga (aggiungi nuovo) quando la modalità di modifica della tabella è abilitata o disabilitata:

public void WillBeginTableEditing (UITableView tableView)
{
    tableView.BeginUpdates ();
    // insert the 'ADD NEW' row at the end of table display
    tableView.InsertRows (new NSIndexPath[] {
            NSIndexPath.FromRowSection (tableView.NumberOfRowsInSection (0), 0)
        }, UITableViewRowAnimation.Fade);
    // create a new item and add it to our underlying data (it is not intended to be permanent)
    tableItems.Add (new TableItem ("(add new)"));
    tableView.EndUpdates (); // applies the changes
}
public void DidFinishTableEditing (UITableView tableView)
{
    tableView.BeginUpdates ();
    // remove our 'ADD NEW' row from the underlying data
    tableItems.RemoveAt ((int)tableView.NumberOfRowsInSection (0) - 1); // zero based :)
    // remove the row from the table display
    tableView.DeleteRows (new NSIndexPath[] { NSIndexPath.FromRowSection (tableView.NumberOfRowsInSection (0) - 1, 0) }, UITableViewRowAnimation.Fade);
    tableView.EndUpdates (); // applies the changes
}

Infine, questo codice crea un'istanza dei pulsanti Modifica e Fine , con espressioni lambda che abilitano o disabilitano la modalità di modifica quando vengono toccati:

done = new UIBarButtonItem(UIBarButtonSystemItem.Done, (s,e)=>{
    table.SetEditing (false, true);
    NavigationItem.RightBarButtonItem = edit;
    tableSource.DidFinishTableEditing(table);
});
edit = new UIBarButtonItem(UIBarButtonSystemItem.Edit, (s,e)=>{
    if (table.Editing)
        table.SetEditing (false, true); // if we've half-swiped a row
    tableSource.WillBeginTableEditing(table);
    table.SetEditing (true, true);
    NavigationItem.LeftBarButtonItem = null;
    NavigationItem.RightBarButtonItem = done;
});

Questo modello di interfaccia utente di inserimento di righe non viene usato molto spesso, ma è anche possibile usare i UITableView.BeginUpdates metodi e EndUpdates per animare l'inserimento o la rimozione di celle in qualsiasi tabella. La regola per l'uso di questi metodi è che la differenza nel valore restituito da RowsInSection tra le BeginUpdates chiamate e EndUpdates deve corrispondere al numero netto di celle aggiunte/eliminate con i InsertRows metodi e DeleteRows . Se l'origine dati sottostante non viene modificata in modo che corrisponda agli inserimenti/eliminazioni nella vista tabella si verificherà un errore.