Поделиться через


Редактирование таблиц с помощью Xamarin.iOS

Функции редактирования таблиц включены путем переопределения методов в подклассе UITableViewSource . Самое простое поведение редактирования — жест прокрутки к удалению, который можно реализовать с помощью одного переопределения метода. Более сложное редактирование (включая перемещение строк) можно сделать с таблицей в режиме редактирования.

Проводите пальцем к удалению

Проводите пальцем, чтобы удалить функцию, является естественным жестом в iOS, который ожидает пользователи.

Пример прокрутки для удаления

Существует три переопределения метода, влияющие на жест прокрутки, чтобы отобразить кнопку "Удалить " в ячейке:

  • CommitEditingStyle — источник таблицы определяет, переопределяет ли этот метод и автоматически включает жест прокрутки для удаления. Реализация метода должна вызвать DeleteRowsUITableView причину исчезновения ячеек, а также удалить базовые данные из модели (например, массив, словарь или базу данных).
  • CanEditRow — если параметр CommitEditingStyle переопределен, предполагается, что все строки могут быть редактируемыми. Если этот метод реализован и возвращает значение false (для некоторых определенных строк или для всех строк), то жест прокрутки к удалению не будет доступен в этой ячейке.
  • TitleForDeleteConfirmation — необязательно указывает текст для кнопки "Удалить ". Если этот метод не реализован, текст кнопки будет "Удалить".

Эти методы реализуются в TableSource классе следующим образом:

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 + ")";
}

В этом примере UITableViewSource обновлено использование List<TableItem> (вместо строкового массива) в качестве источника данных, так как оно поддерживает добавление и удаление элементов из коллекции.

Режим правки

Когда таблица находится в режиме редактирования, пользователь видит красное мини-приложение stop на каждой строке, которое показывает кнопку "Удалить" при касании. В таблице также отображается значок дескриптора, указывающий, что строку можно перетащить, чтобы изменить порядок. Пример TableEditMode реализует эти функции, как показано ниже.

Пример TableEditMode реализует эти функции, как показано ниже.

Существует ряд различных методов, UITableViewSource влияющих на поведение режима редактирования таблицы:

  • CanEditRow — можно ли изменять каждую строку. Возвращает значение false, чтобы предотвратить удаление и удаление пальцем во время редактирования.
  • CanMoveRow — возвращает значение true, чтобы включить перемещение "handle" или false, чтобы предотвратить перемещение.
  • EditStyleForRow — если таблица находится в режиме редактирования, возвращаемое значение из этого метода определяет, отображается ли ячейка красный значок удаления или зеленый значок добавления. Возвращается UITableViewCellEditingStyle.None , если строка не должна быть редактируемой.
  • MoveRow — вызывается при перемещении строки таким образом, чтобы базовая структура данных была изменена, чтобы она соответствовала данным, отображаемым в таблице.

Реализация первых трех методов относительно прямая, если вы не хотите изменять indexPath поведение определенных строк, просто жестко закодируете возвращаемые значения для всей таблицы.

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
}

Реализация MoveRow немного сложнее, так как необходимо изменить базовую структуру данных, чтобы она соответствовала новому заказу. Так как данные реализуются в виде List кода, приведенного ниже, удаляет элемент данных в старом расположении и вставляет его в новое расположение. Если данные хранятся в таблице базы данных SQLite с столбцом order (например, этот метод должен выполнять некоторые операции SQL, чтобы изменить порядок чисел в этом столбце).

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);
}

Наконец, чтобы получить таблицу в режим редактирования, кнопка "Изменить " должна вызываться SetEditing следующим образом.

table.SetEditing (true, true);

и когда пользователь завершит редактирование, кнопка "Готово " должна отключить режим редактирования:

table.SetEditing (false, true);

Стиль редактирования вставки строк

Вставка строк из таблицы является необычным пользовательским интерфейсом— основным примером в стандартных приложениях iOS является экран "Изменить контакт ". На этом снимке экрана показано, как работает функция вставки строк. В режиме редактирования есть дополнительная строка, которая (при щелчке) вставляет дополнительные строки в данные. После завершения редактирования временная строка (добавление новой) удаляется.

После завершения редактирования временная добавление новой строки удаляется

Существует ряд различных методов, UITableViewSource влияющих на поведение режима редактирования таблицы. Эти методы реализованы следующим образом в примере кода:

  • EditingStyleForRow — возвращается UITableViewCellEditingStyle.Delete для строк, содержащих данные, и возвращается UITableViewCellEditingStyle.Insert для последней строки (которая будет добавлена специально для поведения в качестве кнопки вставки).
  • НастройкаMoveTarget — пока пользователь перемещает ячейку возвращаемого значения из этого необязательного метода, может переопределить выбор расположения. Это означает, что их можно запретить "удалить" ячейку в определенных позициях, например в этом примере, которая препятствует перемещению строк после строки (добавить новую).
  • CanMoveRow — возвращает значение true, чтобы включить перемещение "handle" или false, чтобы предотвратить перемещение. В примере последняя строка скрыта, так как она предназначена только для сервера в качестве кнопки вставки.

Мы также добавим два настраиваемых метода, чтобы добавить строку insert, а затем удалить ее снова, когда она больше не требуется. Они вызываются из кнопок "Изменить " и "Готово ":

  • WillBeginTableEditing — при нажатии кнопки "Изменить " вызывается SetEditing , чтобы поместить таблицу в режим редактирования. Это активирует метод WillBeginTableEditing, где в конце таблицы отображается строка (добавить новую) для действия в качестве кнопки вставки.
  • DidFinishTableEditing — при нажатии SetEditing кнопки "Готово" вызывается снова, чтобы отключить режим редактирования. Пример кода удаляет строку (добавить новую) из таблицы, когда редактирование больше не требуется.

Эти переопределения метода реализуются в примере файла 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;
}

Эти два пользовательских метода используются для добавления и удаления (добавления новой) строки при включении или отключении режима редактирования таблицы:

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
}

Наконец, этот код создает экземпляр кнопок "Изменить " и "Готово " с лямбда-лямбдами, которые позволяют включить или отключить режим редактирования при касании:

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;
});

Этот шаблон пользовательского интерфейса вставки строк не используется очень часто, однако вы также можете использовать UITableView.BeginUpdatesEndUpdates методы для анимации вставки или удаления ячеек в любой таблице. Правило использования этих методов заключается в том, что разница в значении, возвращаемом RowsInSection между EndUpdatesBeginUpdates вызовами, должна соответствовать чистому количеству ячеек, добавленных или удаленных с InsertRows помощью методов и DeleteRows методов. Если базовый источник данных не изменяется на соответствие вставкам или удалениям в представлении таблицы, возникнет ошибка.