다음을 통해 공유


Xamarin.iOS를 사용하여 테이블 편집

테이블 편집 기능은 서브클래스에서 메서드를 재정의 UITableViewSource 하여 사용하도록 설정됩니다. 가장 간단한 편집 동작은 단일 메서드 재정의로 구현할 수 있는 살짝 밀기-삭제 제스처입니다. 편집 모드에서 테이블을 사용하여 더 복잡한 편집(행 이동 포함)을 수행할 수 있습니다.

살짝 밀어 삭제

삭제할 살짝 밀기 기능은 사용자가 기대하는 iOS의 자연스러운 제스처입니다.

삭제할 살짝 밀기 예제

셀에 삭제 단추를 표시하기 위해 살짝 밀기 제스처에 영향을 주는 세 가지 메서드 재정의가 있습니다.

  • CommitEditingStyle – 테이블 원본은 이 메서드가 재정의되었는지 감지하고 살짝 밀기-삭제 제스처를 자동으로 사용하도록 설정합니다. 메서드의 구현은 셀이 사라지도록 하고 모델에서 기본 데이터(예: 배열, 사전 또는 데이터베이스)를 제거하도록 호출 DeleteRowsUITableView 해야 합니다.
  • CanEditRow – CommitEditingStyle이 재정의되면 모든 행을 편집할 수 있는 것으로 간주됩니다. 이 메서드가 구현되고 false를 반환하는 경우(일부 특정 행 또는 모든 행에 대해) 해당 셀에서 살짝 밀기-삭제 제스처를 사용할 수 없습니다.
  • TitleForDeleteConfirmation – 선택적으로 삭제 단추의 텍스트를 지정합니다. 이 메서드를 구현하지 않으면 단추 텍스트는 "Delete"가 됩니다.

이러한 메서드는 다음 클래스에서 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> 업데이트되었습니다.

편집 모드

테이블이 편집 모드인 경우 각 행에 빨간색 '중지' 위젯이 표시되며, 이 위젯은 터치 시 삭제 단추를 표시합니다. 표에는 행을 끌어 순서를 변경할 수 있음을 나타내는 '핸들' 아이콘도 표시됩니다. TableEditMode 샘플은 표시된 대로 이러한 기능을 구현합니다.

TableEditMode 샘플은 표시된 대로 이러한 기능을 구현합니다.

테이블의 편집 모드 동작에 UITableViewSource 영향을 주는 다양한 메서드가 있습니다.

  • CanEditRow – 각 행을 편집할 수 있는지 여부입니다. 편집 모드에서 삭제 및 삭제를 모두 방지하려면 false를 반환합니다.
  • CanMoveRow – 이동을 방지하기 위해 이동 '핸들' 또는 false를 사용하도록 설정하려면 true를 반환합니다.
  • EditingStyleForRow – 테이블이 편집 모드에 있는 경우 이 메서드의 반환 값은 셀에 빨간색 삭제 아이콘 또는 녹색 추가 아이콘이 표시되는지 여부를 결정합니다. 행을 편집할 수 없으면 반환 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 구현되므로 이전 위치에서 데이터 항목을 삭제하고 새 위치에 삽입합니다. 데이터가 'order' 열이 있는 SQLite 데이터베이스 테이블에 저장된 경우(예:) 이 메서드는 대신 해당 열의 숫자 순서를 다시 지정하기 위해 일부 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 합니다.
  • CustomizeMoveTarget – 사용자가 셀을 이동하는 동안 이 선택적 메서드의 반환 값이 선택한 위치를 재정의할 수 있습니다. 즉, 특정 위치에 있는 셀을 '삭제'하지 못하도록 할 수 있습니다. 예를 들어 (새 추가) 행 이후에 행이 이동되지 않도록 하는 예제입니다.
  • CanMoveRow – 이동을 방지하기 위해 이동 '핸들' 또는 false를 사용하도록 설정하려면 true를 반환합니다. 이 예제에서 마지막 행에는 삽입 단추로만 서버용이므로 이동 '핸들'이 숨겨집니다.

또한 두 개의 사용자 지정 메서드를 추가하여 '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;
});

이 행 삽입 UI 패턴은 자주 사용되지는 않습니다. 그러나 테이블의 셀 삽입 또는 제거에 애니메이션 효과를 줄 수 있는 메서드와 EndUpdates 메서드를 사용할 UITableView.BeginUpdates 수도 있습니다. 이러한 메서드를 사용하는 규칙은 호출 간에 BeginUpdates 반환되는 값의 차이가 추가/삭제된 RowsInSection 셀의 순 번호와 EndUpdatesDeleteRows 메서드와 InsertRows 일치해야 한다는 것입니다. 기본 데이터 원본이 테이블 뷰의 삽입/삭제와 일치하도록 변경되지 않으면 오류가 발생합니다.