Úpravy tabulek pomocí Xamarin.iOS
Funkce pro úpravy tabulek jsou povoleny přepsáním metod v podtřídě UITableViewSource
. Nejjednodušším chováním při úpravách je gesto potáhnutí prstem na odstranění, které lze implementovat s jedním přepsáním metody.
Složitější úpravy (včetně přesouvání řádků) je možné provádět s tabulkou v režimu úprav.
Potáhnutím prstem na odstranění
Funkce odstranění potáhnutím prstem je přirozené gesto v iOSu, které uživatelé očekávají.
Existují tři přepsání metod, které ovlivňují gesto potáhnutí prstem, aby se v buňce zobrazilo tlačítko Odstranit :
- CommitEditingStyle – Zdroj tabulky zjistí, jestli je tato metoda přepsána a automaticky povolí gesto potáhnutí prstem na odstranění. Implementace metody by měla volat
DeleteRows
UITableView
, aby buňky zmizely, a také odebrat podkladová data z modelu (například pole, slovník nebo databáze). - CanEditRow – Pokud CommitEditingStyle je přepsán, předpokládá se, že všechny řádky budou upravitelné. Pokud je tato metoda implementována a vrací false (pro některé konkrétní řádky nebo pro všechny řádky), gesto potáhnutí prstem na odstranění nebude v této buňce k dispozici.
- TitleForDeleteConfirmation – Volitelně určuje text tlačítka Odstranit . Pokud tato metoda není implementována, text tlačítka bude "Delete".
Tyto metody jsou implementovány ve TableSource
třídě:
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 + ")";
}
V tomto příkladu byl aktualizován tak UITableViewSource
, aby jako zdroj dat používal ( List<TableItem>
místo pole řetězců), protože podporuje přidávání a odstraňování položek z kolekce.
Režim Úpravy
Když je tabulka v režimu úprav, zobrazí se uživateli na každém řádku červený widget Stop, který při dotyku odhalí tlačítko Odstranit. Tabulka také zobrazí ikonu úchytu, která označuje, že řádek lze přetáhnout a změnit pořadí. Ukázka TableEditMode implementuje tyto funkce, jak je znázorněno.
Existuje několik různých metod UITableViewSource
, které ovlivňují chování režimu úprav tabulky:
- CanEditRow – zda lze každý řádek upravit. Vrátí hodnotu false, aby se zabránilo odstranění potažením prstem a odstraněním v režimu úprav.
- CanMoveRow – vrátí hodnotu true, aby bylo možné povolit přesunutí popisovač nebo false, aby se zabránilo přesunutí.
- EditingStyleForRow – pokud je tabulka v režimu úprav, návratová hodnota z této metody určuje, zda buňka zobrazuje červenou ikonu odstranění nebo zelenou ikonu přidat. Pokud by řádek neměl být upravitelný, vraťte
UITableViewCellEditingStyle.None
se. - MoveRow – volá se při přesunutí řádku tak, aby byla podkladová datová struktura upravena tak, aby odpovídala datům zobrazeným v tabulce.
Implementace prvních tří metod je relativně jednoduchá – pokud nechcete použít indexPath
ke změně chování konkrétních řádků, stačí pevně zakódovat návratové hodnoty pro celou tabulku.
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
}
Implementace MoveRow
je trochu složitější, protože potřebuje změnit podkladovou datovou strukturu tak, aby odpovídala novému pořadí. Vzhledem k tomu, že se data implementují jako List
kód níže, odstraní položku dat ve starém umístění a vloží je do nového umístění. Pokud byla data uložená v tabulce databáze SQLite se sloupcem order (například), tato metoda by místo toho potřebovala provést některé operace SQL, aby se čísla v tomto sloupci přeuspořádala.
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);
}
Nakonec, aby se tabulka dostala do režimu úprav, musí tlačítko Upravit volat SetEditing
takto:
table.SetEditing (true, true);
a po dokončení úprav by mělo být vypnuto tlačítko Hotovo :
table.SetEditing (false, true);
Styl úprav vložení řádku
Vložení řádku z tabulky je neobvyklé uživatelské rozhraní – hlavním příkladem standardních aplikací pro iOS je obrazovka Upravit kontakt . Tento snímek obrazovky ukazuje, jak funguje funkce vložení řádku – v režimu úprav je další řádek, který (po kliknutí) vloží do dat další řádky. Po dokončení úprav se odebere dočasný (přidat nový) řádek.
Existuje řada různých metod UITableViewSource
, které ovlivňují chování režimu úprav tabulky. Tyto metody byly v ukázkovém kódu implementovány následujícím způsobem:
- EditingStyleForRow – vrátí řádky
UITableViewCellEditingStyle.Delete
obsahující data a vrátíUITableViewCellEditingStyle.Insert
se pro poslední řádek (který se přidá speciálně pro chování jako tlačítko vložení). - CustomizeMoveTarget – Zatímco uživatel přesouvá buňku návratovou hodnotu z této volitelné metody může přepsat svou volbu umístění. To znamená, že můžete zabránit tomu, aby buňky v určitých pozicích vyřadily – například v tomto příkladu, které brání přesunutí libovolného řádku za řádkem (přidat nový).
- CanMoveRow – vrátí hodnotu true, aby bylo možné povolit přesunutí popisovač nebo false, aby se zabránilo přesunutí. V tomto příkladu má poslední řádek skrytý popisovač, protože je určený jenom jako tlačítko pro vložení.
Přidáme také dvě vlastní metody pro přidání řádku Insert a potom ho znovu odebereme, pokud už není potřeba. Volají se z tlačítek Upravit a Hotovo :
- WillBeginTableEditing – Když se dotknete tlačítka Upravit , zavolá
SetEditing
se tabulka do režimu úprav. Tím se aktivuje Metoda WillBeginTableEditing, kde na konci tabulky zobrazíme (přidat nový) řádek, který bude fungovat jako tlačítko vložit. - DidFinishTableEditing – Po stisknutí
SetEditing
tlačítka Hotovo se znovu zavolá, aby se vypnul režim úprav. Ukázkový kód odebere řádek (přidat nový) z tabulky, když už není potřeba upravovat.
Tyto přepsání metod se implementují v ukázkovém souboru 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;
}
Tyto dvě vlastní metody slouží k přidání a odebrání řádku (přidání nového) řádku, když je režim úprav tabulky povolený nebo zakázaný:
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
}
Nakonec tento kód vytvoří instanci tlačítek Upravit a Hotovo s lambdami, které povolí nebo zakáže režim úprav, když se dotknete:
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;
});
Tento vzor uživatelského rozhraní pro vložení řádku se moc často nepoužívá, ale můžete je použít UITableView.BeginUpdates
EndUpdates
také k animaci vložení nebo odebrání buněk v libovolné tabulce. Pravidlo pro použití těchto metod spočívá v tom, že rozdíl v hodnotě vrácené mezi voláními RowsInSection
a EndUpdates
volání musí odpovídat čistému počtu buněk přidaných nebo odstraněných pomocí InsertRows
metod a DeleteRows
metod.BeginUpdates
Pokud se podkladový zdroj dat nezmění tak, aby odpovídal vložením nebo odstraněním v zobrazení tabulky, dojde k chybě.