Cómo crear un botón «más» cuando el usuario desliza el dedo de una celda en la vista de tabla (como la aplicación de correo en ios 7)

He estado buscando esta información, tanto aquí como en el Cocoa Touch foro, pero me parece no puede encontrar la respuesta y yo estoy esperando que alguien más inteligente que yo, me puede dar una solución.

Me gustaría que cuando el usuario pasa la vista de la tabla de la célula, para mostrar más de un botón de edición (que por defecto es el botón eliminar).
En la aplicación de Correo para iOS 7 se puede deslizar el dedo para eliminar, pero hay un botón «MÁS» que se muestra arriba.

Pase a Eliminar y el botón

  • Intente siguiente URL: HHPanningTableViewCell LRSlidingTableViewCell TISwipeableTableView RMSwipeTableViewCell
  • Para agregar el botón «Eliminar» implementar las siguientes dos funciones. – (BOOL)en formato tableview:(UITableView *)en formato tableview canEditRowAtIndexPath:(NSIndexPath *)indexPath; – (void)formato tableview:(UITableView *)en formato tableview commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath; Y quiero agregar el botón «Más» junto a él.
  • Bansal se Parece a alguien en este hilo (devforums.apple.com/message/860459#860459 en el foro de desarrolladores de Apple) siguió adelante y se construyó su propia implementación. Usted puede encontrar un proyecto que hace lo que quiere en GitHub:github.com/daria-kopaliani/DAContextMenuTableViewController
  • gracias por la solución funciona como un encanto. Esta es la pregunta Nº 1 resultado en muchas de las búsquedas de google, y la gente está obligada a intercambiar sus conocimientos con los comentarios, porque un chico decidido que es más útil para cerrar la pregunta y predicar la democracia en su lugar. Este lugar claramente mejor las necesidades de los mods.
  • Comprobar esto : teehanlax.com/blog/reproducing-the-ios-7-mail-apps-interface y mi aplicación con el diseño automático github.com/Jafared/JASwipeCellExperiment
  • Creo que este tutorial puede ayudar a: raywenderlich.com/62435/…
  • Si usted puede hacer objetivo a iOS 8, mi respuesta será lo que usted quiera.
  • como de iOS 11 esto es posible sin necesidad de código de terceros. desplácese hacia abajo de mi respuesta
  • Cómo ajustar el ancho de los botones de rowEditActionButtons

InformationsquelleAutor Guy Kahlon | 2013-06-22

20 Comentarios

  1. 125

    Cómo Implementar

    Parece que iOS 8 se abre esta API. Sugerencias de tales funciones están presentes en la versión Beta 2.

    Para conseguir algo de trabajo, aplicar los dos métodos siguientes en su UITableView del delegado para conseguir el efecto deseado (véase esencial para un ejemplo).

    - tableView:editActionsForRowAtIndexPath:
    - tableView:commitEditingStyle:forRowAtIndexPath:

    Problemas Conocidos

    La documentación dice formato tableview:commitEditingStyle:forRowAtIndexPath es:

    «No se llama para editar las acciones utilizando UITableViewRowAction – la acción del controlador será invocada en su lugar.»

    Sin embargo, el deslizar no funciona sin él. Incluso si el código auxiliar del método está en blanco, es preciso que, por ahora. Esto es más evidente un error en la versión beta 2.

    Fuentes

    https://twitter.com/marksands/status/481642991745265664
    https://gist.github.com/marksands/76558707f583dbb8f870

    Original Respuesta: https://stackoverflow.com/a/24540538/870028

    Actualización:

    Código de ejemplo de este trabajo (En Swift): http://dropbox.com/s/0fvxosft2mq2v5m/DeleteRowExampleSwift.zip

    El código de ejemplo que contiene este fácil de seguir el método en MasterViewController.swift, y sólo con este método de obtener el comportamiento que se muestra en la OP captura de pantalla:

    override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [AnyObject]? {
    
        var moreRowAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "More", handler:{action, indexpath in
            println("MORE•ACTION");
        });
        moreRowAction.backgroundColor = UIColor(red: 0.298, green: 0.851, blue: 0.3922, alpha: 1.0);
    
        var deleteRowAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "Delete", handler:{action, indexpath in
            println("DELETE•ACTION");
        });
    
        return [deleteRowAction, moreRowAction];
    }
    • Esta parece ser la correcta, pero en Xcode 6 GM el gesto no parece funcionar. El editActions todavía se puede acceder al poner a la vista de la tabla en modo de edición. Nadie encuentra que pase no está funcionando?
    • ¿Has probado la aplicación (incluso si se deja vacío) en formato tableview:commitEditingStyle:forRowAtIndexPath:?
    • No he trabajado en objective c.. el Mismo código que he escrito. por favor, sugiera algunas pistas.
    • ¿Tienes un proyecto de ejemplo que se podía mirar? Yo podría ser capaz de ayudar a una mejor de esa manera.
    • han hizo. Pero no estoy seguro de por qué sucedió esto. Trabaja conmigo en UITableViewController no en UITableView que está dentro de UIViewController.
    • Esto puede sonar demasiado simple, pero sólo quiero para asegurarse de que las bases están cubiertas. ¿Su UIViewController se ajustan a la UITableViewDelegate protocolo? Si es así, la asignación de la misma con el auto.formato tableview.delegado = auto; (o lo que sea)?
    • Perdón, se me olvidó etiqueta.
    • Sí, he mencionado. Trabajando ahora he de heredar con UITableViewController y trabajado. Gracias por su apoyo.
    • Parece que los controladores se llama, pero la célula no está «cerrada» después. Me estoy perdiendo una manera obvia de hacer eso? Llamar endEditing: en el formato tableview no parece hacer nada.
    • Para responder a mi propio comentario. Llame tableView.editing = false (NO en objc) y la celda de «cerrar».
    • Cómo agregar el icono en lugar de texto ? No quiero borrar texto, sólo quiero un icono de eliminar. Cómo lograr esto en swift? Por favor ayuda
    • Buena información
    • Muchas gracias. 🙂 Tu respuesta me ha ayudado mucho
    • Si sólo pudiera ver esta respuesta antes de entrar en la difícil aplicación antes de iOS 8!

  2. 121

    He creado una nueva biblioteca para implementar swippable botones que soporta una variedad de transiciones y ampliable botones como los de iOS 8 aplicación de correo.

    https://github.com/MortimerGoro/MGSwipeTableCell

    Esta biblioteca es compatible con todas las diferentes maneras de crear un UITableViewCell y su probado en iOS 5, iOS 6, iOS 7 y iOS 8.

    Aquí una muestra de algunas de las transiciones:

    Frontera de transición:

    Pase a Eliminar y el botón

    Clip de transición

    Pase a Eliminar y el botón

    De Transición 3D:

    Pase a Eliminar y el botón

    • Wow, en serio impresionante trabajo!
    • Gran Trabajo! Sería estupendo que las devoluciones de llamada para personalizar las animaciones.
    • Increíble!!! Acaba de pasar, pero no puede ayudar a la votación de las fantásticas animaciones!!!
    • Buen trabajo de hombre. Se ve buena. Estoy tratando de implementar efecto similar en uno de mis Proyecto Android. Por favor, dime cómo puedo lograr esto en Android?
    • Gran trabajo bro! Esto me ayuda mucho y salvó un montón de tiempo.
    • en iOS 8 + iPad, simplemente no estoy recibiendo el pase a suceder.
    • Esta es una increíble biblioteca y lo que es muy bueno es que todavía ha de apoyo.
    • Esto es bastante badass de la yema.. Simplemente genial, gracias!
    • He probado con «MGSwipeTableCel»l marco, pero el problema es cuando puedo recargar mi mesa, a continuación, deslice el botón está oculto. Cualquier trabajo en torno a este problema.
    • También hay algunos problemas con VoiceOver con esta configuración. Es una increíble pieza de trabajo lo contrario!

  3. 70

    De Johnny respuesta es la correcta para upvote. Yo soy sólo la adición de este a continuación en objective-c para hacer más claro para los principiantes (y a aquellos que se niegan a aprender Swift sintaxis 🙂

    Asegúrese de declarar la uitableviewdelegate y tiene los siguientes métodos:

     -(NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {
     UITableViewRowAction *button = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"Button 1" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath)
        {
            NSLog(@"Action to perform with Button 1");
        }];
        button.backgroundColor = [UIColor greenColor]; //arbitrary color
        UITableViewRowAction *button2 = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"Button 2" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath)
                                        {
                                            NSLog(@"Action to perform with Button2!");
                                        }];
        button2.backgroundColor = [UIColor blueColor]; //arbitrary color
    
        return @[button, button2]; //array with all the buttons you want. 1,2,3, etc...
    }
    
    - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    //you need to implement this method too or nothing will work:
    
    }
     - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
        {
            return YES; //tableview must be editable or nothing will work...
        }
    • importante mencionar canEditRowAtIndexPath
    • Si puedo volver a cargar la tabla tras deslizar la celda, y luego los pase botones son visibles u ocultas?
  4. 25

    Esto es (bastante ridículo) una API privada.

    Los siguientes dos métodos son privadas y se envía a la UITableView delegado:

    -(NSString *)tableView:(UITableView *)tableView titleForSwipeAccessoryButtonForRowAtIndexPath:(NSIndexPath *)indexPath;
    -(void)tableView:(UITableView *)tableView swipeAccessoryButtonPushedForRowAtIndexPath:(NSIndexPath *)indexPath;

    Son bastante auto explicativo.

    • Apple ha abierto esta característica con iOS 8. Ver Johnny respuesta a continuación.
  5. 23

    Para mejorar Johnny respuesta, esto ahora se puede hacer uso de la API pública de la siguiente manera :

    func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
    
        let moreRowAction = UITableViewRowAction(style: UITableViewRowActionStyle.default, title: "More", handler:{action, indexpath in
            print("MORE•ACTION");
        });
        moreRowAction.backgroundColor = UIColor(red: 0.298, green: 0.851, blue: 0.3922, alpha: 1.0);
    
        let deleteRowAction = UITableViewRowAction(style: UITableViewRowActionStyle.default, title: "Delete", handler:{action, indexpath in
            print("DELETE•ACTION");
        });
    
        return [deleteRowAction, moreRowAction];
    }
    • Podría usted por favor, actualice el código Swift 3? Gracias
    • gracias funcionando bien.
  6. 17

    Espero que usted no puede esperar hasta que apple le da lo que necesita? Así que aquí es mi opción.

    Crear una costumbre de la célula. Tiene dos uiviews en ella

    1. upper
    2. lower

    En la vista inferior, añadir lo que nunca botones que usted necesita. Trato de sus acciones
    como cualquier otro IBActions. usted puede decidir el tiempo de la animación, el estilo y la nada.

    ahora agregue un uiswipegesture a la vista superior y revelar su vista inferior en gesto de barrido. He hecho esto antes y es la opción más simple como lo que me refiero.

    La esperanza de que la ayuda.

  7. 7

    Esto no es posible con el estándar del SDK. Sin embargo, hay varios 3ª parte de las soluciones que más o menos imitar el comportamiento en el Correo.app. Algunos de ellos (por ejemplo,MCSwipeTableViewCell, DAContextMenuTableViewController, RMSwipeTableViewCell) detectar golpes con gestos reconocedores, algunos de ellos (por ejemplo,SWTableViewCell) poner una segunda UISScrollView por debajo del estándar UITableViewCellScrollView (privado subvista de UITableViewCell) y algunos de ellos modificar el comportamiento de UITableViewCellScrollView.

    Me gusta el último enfoque más desde el manejo táctil se siente más natural. Específicamente, MSCMoreOptionTableViewCell es bueno. Su elección puede variar dependiendo de sus necesidades específicas (si usted necesita una izquierda a derecha pan, también, si usted necesita iOS 6 de compatibilidad, etc.). También ser conscientes de que la mayoría de estos enfoques vienen con una carga: se pueden romper fácilmente en una futura versión de iOS si Apple hace que los cambios en la UITableViewCell subvista jerarquía.

  8. 7

    Swift 3 código de la versión sin utilizar cualquier biblioteca:

    import UIKit
    class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    @IBOutlet weak var tableView: UITableView!
    override func viewDidLoad() {
    super.viewDidLoad()
    //Do any additional setup after loading the view, typically from a nib.
    tableView.tableFooterView = UIView(frame: CGRect.zero) //Hiding blank cells.
    tableView.separatorInset = UIEdgeInsets.zero
    tableView.dataSource = self
    tableView.delegate = self
    }
    override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    //Dispose of any resources that can be recreated.
    }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 4
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath)
    return cell
    }
    //Enable cell editing methods.
    func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
    return true
    }
    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
    }
    func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
    let more = UITableViewRowAction(style: .normal, title: "More") { action, index in
    //self.isEditing = false
    print("more button tapped")
    }
    more.backgroundColor = UIColor.lightGray
    let favorite = UITableViewRowAction(style: .normal, title: "Favorite") { action, index in
    //self.isEditing = false
    print("favorite button tapped")
    }
    favorite.backgroundColor = UIColor.orange
    let share = UITableViewRowAction(style: .normal, title: "Share") { action, index in
    //self.isEditing = false
    print("share button tapped")
    }
    share.backgroundColor = UIColor.blue
    return [share, favorite, more]
    }
    }
  9. 6

    Deberá subclase UITableViewCell y método de subclase willTransitionToState:(UITableViewCellStateMask)state que es llamado cada vez que el usuario golpes de la célula. El state banderas le permitirá saber si el botón Eliminar que se muestra, y mostrar/ocultar el botón Más allá.

    Por desgracia, este método da ni el ancho del botón Borrar ni el tiempo de la animación. Por lo que necesita para observer & duro-código de tu botón Más de la trama y de tiempo de la animación en el código (yo personalmente creo que Apple tiene que hacer algo acerca de esto).

    • «Yo personalmente creo que Apple tiene que hacer algo acerca de esto». Estoy de acuerdo. ¿Ya les escribe un informe de error / función de solicitud?
  10. 4

    De programación swift

    func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
    if editingStyle == UITableViewCellEditingStyle.Delete {
    deleteModelAt(indexPath.row)
    self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
    }
    else if editingStyle == UITableViewCellEditingStyle.Insert {
    println("insert editing action")
    }
    }
    func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [AnyObject]? {
    var archiveAction = UITableViewRowAction(style: .Default, title: "Archive",handler: { (action: UITableViewRowAction!, indexPath: NSIndexPath!) in
    //maybe show an action sheet with more options
    self.tableView.setEditing(false, animated: false)
    }
    )
    archiveAction.backgroundColor = UIColor.lightGrayColor()
    var deleteAction = UITableViewRowAction(style: .Normal, title: "Delete",
    handler: { (action: UITableViewRowAction!, indexPath: NSIndexPath!) in
    self.deleteModelAt(indexPath.row)
    self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic);
    }
    );
    deleteAction.backgroundColor = UIColor.redColor()
    return [deleteAction, archiveAction]
    }
    func deleteModelAt(index: Int) {
    //... delete logic for model
    }
    • Podría usted por favor actualizar el código para el Swift 3?
    • usted es bienvenido para sugerir una edición. No he utilizado swift en un tiempo no tan seguro de lo que la sintaxis correcta es
  11. 3

    ESTO PODRÍA AYUDARLE.

    -(NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewRowAction *button = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"Button 1" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath)
    {
    NSLog(@"Action to perform with Button 1");
    }];
    button.backgroundColor = [UIColor greenColor]; //arbitrary color
    UITableViewRowAction *button2 = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"Button 2" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath)
    {
    NSLog(@"Action to perform with Button2!");
    }];
    button2.backgroundColor = [UIColor blueColor]; //arbitrary color
    return @[button, button2]; //array with all the buttons you want. 1,2,3, etc...
    }
    - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    //you need to implement this method too or nothing will work:
    }
    - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
    {
    return YES; //tableview must be editable or nothing will work...
    }
  12. 3

    Yo estaba mirando para agregar a la misma funcionalidad a mi aplicación, y después de pasar a través de tantos tutoriales (raywenderlich ser la mejor solución de BRICOLAJE), me enteré de que Apple tiene su propio UITableViewRowActionclase, que es muy práctico.

    Tienes que cambiar el formato tableview del boilerpoint método a esto:

    override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [AnyObject]?  {
    //1   
    var shareAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "Share" , handler: { (action:UITableViewRowAction!, indexPath:NSIndexPath!) -> Void in
    //2
    let shareMenu = UIAlertController(title: nil, message: "Share using", preferredStyle: .ActionSheet)
    let twitterAction = UIAlertAction(title: "Twitter", style: UIAlertActionStyle.Default, handler: nil)
    let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil)
    shareMenu.addAction(twitterAction)
    shareMenu.addAction(cancelAction)
    self.presentViewController(shareMenu, animated: true, completion: nil)
    })
    //3
    var rateAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "Rate" , handler: { (action:UITableViewRowAction!, indexPath:NSIndexPath!) -> Void in
    //4
    let rateMenu = UIAlertController(title: nil, message: "Rate this App", preferredStyle: .ActionSheet)
    let appRateAction = UIAlertAction(title: "Rate", style: UIAlertActionStyle.Default, handler: nil)
    let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil)
    rateMenu.addAction(appRateAction)
    rateMenu.addAction(cancelAction)
    self.presentViewController(rateMenu, animated: true, completion: nil)
    })
    //5
    return [shareAction,rateAction]
    }

    Usted puede averiguar más acerca de esto en Este Sitio. Apple propia documentación es realmente útil para cambiar el color de fondo:

    El color de fondo del botón de acción.

    Declaración de OBJECTIVE-C @property(nonatomic, copia) UIColor
    *backgroundColor Discusión Utilice esta propiedad para especificar el color de fondo para el botón. Si no especifica un valor para
    esta propiedad, UIKit asigna un color predeterminado basado en el valor de la
    propiedad de estilo.

    Disponibilidad Disponible en iOS 8.0 y versiones posteriores.

    Si quieres cambiar la fuente del botón, es un poco más complicado. He visto otro post en TAN. Por el bien de proporcionar el código así como el enlace, este es el código que se usa allí. Tendrías que cambiar la apariencia del botón. Tendrías que hacer una referencia específica a tableviewcell, de lo contrario se tendría el botón cambiar la apariencia de toda la aplicación (yo no quiero eso, pero quizás, no lo sé 🙂 )

    Objetivo C:

    + (void)setupDeleteRowActionStyleForUserCell {
    UIFont *font = [UIFont fontWithName:@"AvenirNext-Regular" size:19];
    NSDictionary *attributes = @{NSFontAttributeName: font,
    NSForegroundColorAttributeName: [UIColor whiteColor]};
    NSAttributedString *attributedTitle = [[NSAttributedString alloc] initWithString: @"DELETE"
    attributes: attributes];
    /*
    * We include UIView in the containment hierarchy because there is another button in UserCell that is a direct descendant of UserCell that we don't want this to affect.
    */
    [[UIButton appearanceWhenContainedIn:[UIView class], [UserCell class], nil] setAttributedTitle: attributedTitle
    forState: UIControlStateNormal];
    }

    Swift:

        //create your attributes however you want to
    let attributes = [NSFontAttributeName: UIFont.systemFontOfSize(UIFont.systemFontSize())] as Dictionary!            
    //Add more view controller types in the []
    UIButton.appearanceWhenContainedInInstancesOfClasses([ViewController.self])

    Esta es la más fácil, y la mayoría de corriente alineada versión en mi humilde opinión. Espero que ayude.

    Actualización: Aquí está el Swift de la versión 3.0:

    func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
    var shareAction:UITableViewRowAction = UITableViewRowAction(style: .default, title: "Share", handler: {(action, cellIndexpath) -> Void in
    let shareMenu = UIAlertController(title: nil, message: "Share using", preferredStyle: .actionSheet)
    let twitterAction = UIAlertAction(title: "Twitter", style: .default, handler: nil)
    let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
    shareMenu.addAction(twitterAction)
    shareMenu.addAction(cancelAction)
    self.present(shareMenu,animated: true, completion: nil)
    })
    var rateAction:UITableViewRowAction = UITableViewRowAction(style: .default, title: "Rate" , handler: {(action, cellIndexpath) -> Void in
    //4
    let rateMenu = UIAlertController(title: nil, message: "Rate this App", preferredStyle: .actionSheet)
    let appRateAction = UIAlertAction(title: "Rate", style: .default, handler: nil)
    let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
    rateMenu.addAction(appRateAction)
    rateMenu.addAction(cancelAction)
    self.present(rateMenu, animated: true, completion: nil)
    })
    //5
    return [shareAction,rateAction]
    }
    • Gracias por tu respuesta, estoy seguro que será de ayuda para muchos de los desarrolladores. Sí, tienes razón, en realidad Apple ofrece esta solución de iOS 8. Pero desafortunadamente, esta solución nativa no proporciona la funcionalidad completa. Por ejemplo, en la Manzana de la aplicación de Correo tienes los botones de los dos lados (Un botón de la izquierda lado, y tres de la derecha) con el API actual de Apple no se pueden agregar botones a ambos lados, y también el de la API actual no admite la acción por defecto cuando el usuario pase de largo a cada lado. La mejor solución por ahora, en mi humilde opinión es que el open source MGSwipeTableCell.
    • sí, tienes toda la razón en lo que respecta a la izquierda y a la derecha, pase el dedo problema, y estoy de acuerdo en que para más personalización, la MGSwipeTableCell es la mejor. La propia Apple no es la más sofisticada opción, pero me pareció más sencillos para tareas sencillas.
    • Podría usted por favor, actualice el código Swift 3? shareMenu. no tomar una addAction método. Gracias
    • He añadido el swift versión. ¿Necesita poco para el atributo así? sharemenu es sólo un UIAlertController, por lo que se debe de tomar la acción. Pruébalo y dime si hay suerte 🙂
  13. 3

    Real Swift 3 Respuesta

    Esta es la ÚNICA función que usted necesita. Usted no necesita CanEdit o CommitEditingStyle funciones para acciones personalizadas.

    func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
    let action1 = UITableViewRowAction(style: .default, title: "Action1", handler: {
    (action, indexPath) in
    print("Action1")
    })
    action1.backgroundColor = UIColor.lightGray
    let action2 = UITableViewRowAction(style: .default, title: "Action2", handler: {
    (action, indexPath) in
    print("Action2")
    })
    return [action1, action2]
    }
  14. 3

    Como de iOS 11 esté a disposición del público en UITableViewDelegate. He aquí algunos ejemplos de código:

    - (UISwipeActionsConfiguration *)tableView:(UITableView *)tableView trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath {
    UIContextualAction *delete = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleDestructive
    title:@"DELETE"
    handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) {
    NSLog(@"index path of delete: %@", indexPath);
    completionHandler(YES);
    }];
    UIContextualAction *rename = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleNormal
    title:@"RENAME"
    handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) {
    NSLog(@"index path of rename: %@", indexPath);
    completionHandler(YES);
    }];
    UISwipeActionsConfiguration *swipeActionConfig = [UISwipeActionsConfiguration configurationWithActions:@[rename, delete]];
    swipeActionConfig.performsFirstActionWithFullSwipe = NO;
    return swipeActionConfig;
    }

    También disponible:

    - (UISwipeActionsConfiguration *)tableView:(UITableView *)tableView leadingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath;

    Docs: https://developer.apple.com/documentation/uikit/uitableviewdelegate/2902367-tableview?language=objc

  15. 3

    Swift 4 & iOs 11+

    @available(iOS 11.0, *)
    override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
    let delete = UIContextualAction(style: .destructive, title: "Delete") { _, _, handler in
    handler(true)
    //handle deletion here
    }
    let more = UIContextualAction(style: .normal, title: "More") { _, _, handler in
    handler(true)
    //handle more here
    }
    return UISwipeActionsConfiguration(actions: [delete, more])
    }
  16. 2

    He utilizado tableViewCell para mostrar varios datos, después de deslizar el dedo () de derecha a izquierda en una celda se muestran dos botones de Aprobar Y rechazar, hay dos métodos, el primero es ApproveFunc que toma un argumento, y el otro es RejectFunc que también toma un argumento.

    Pase a Eliminar y el botón

    func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
    let Approve = UITableViewRowAction(style: .normal, title: "Approve") { action, index in
    self.ApproveFunc(indexPath: indexPath)
    }
    Approve.backgroundColor = .green
    let Reject = UITableViewRowAction(style: .normal, title: "Reject") { action, index in
    self.rejectFunc(indexPath: indexPath)
    }
    Reject.backgroundColor = .red
    return [Reject, Approve]
    }
    func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
    return true
    }
    func ApproveFunc(indexPath: IndexPath) {
    print(indexPath.row)
    }
    func rejectFunc(indexPath: IndexPath) {
    print(indexPath.row)
    }
    • Se puede añadir alguna explicación a su respuesta de tal manera que un lector puede aprender de él?
    • Gracias por este fragmento de código, que podría proporcionar cierta ayuda inmediata. explicación adecuada mejoraría en gran medida su valor de largo plazo mostrando porque esta es una buena solución para el problema y que sea más útil para los lectores futuros con otras preguntas similares. Por favor, editar su respuesta a añadir alguna explicación, incluyendo las suposiciones que hemos hecho.
  17. 1

    Aquí una frágil forma de hacerlo que no implica privado Api o de la construcción de su propio sistema. Estás cubrir sus apuestas de que Apple no romper con eso y que esperemos que liberar una API que puede reemplazar estas pocas líneas de código.

    1. KVO auto.contentView.superview.la capa.la subcapa. Hacer esto en init. Este es el UIScrollView de la capa. Usted no puede KVO ‘subvistas’.
    2. Cuando subvistas cambios, encontrar la confirmación de eliminación de la vista dentro de scrollview.subvistas. Esto se realiza en el observar de devolución de llamada.
    3. Doble que el tamaño de la vista y agregar un UIButton a la izquierda de su único subvista. Esto también se hace en el observar de devolución de llamada. La única subvista de la confirmación de eliminación de la vista es el botón eliminar.
    4. (opcional) El UIButton evento debe buscar el auto.superview hasta que encuentra un UITableView y, a continuación, llamar a un origen de datos o delegado método de crear, como en formato tableview:commitCustomEditingStyle:forRowAtIndexPath:. Usted puede encontrar el indexPath de la célula mediante el uso de [formato tableview indexPathForCell:auto].

    Esto también requiere que implemente el estándar de la tabla de la vista de edición de delegar las devoluciones de llamada.

    static char kObserveContext = 0;
    @implementation KZTableViewCell {
    UIScrollView *_contentScrollView;
    UIView *_confirmationView;
    UIButton *_editButton;
    UIButton *_deleteButton;
    }
    - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
    _contentScrollView = (id)self.contentView.superview;
    [_contentScrollView.layer addObserver:self
    forKeyPath:@"sublayers"
    options:0
    context:&kObserveContext];
    _editButton = [UIButton new];
    _editButton.backgroundColor = [UIColor lightGrayColor];
    [_editButton setTitle:@"Edit" forState:UIControlStateNormal];
    [_editButton addTarget:self
    action:@selector(_editTap)
    forControlEvents:UIControlEventTouchUpInside];
    }
    return self;
    }
    -(void)dealloc {
    [_contentScrollView.layer removeObserver:self forKeyPath:@"sublayers" context:&kObserveContext];
    }
    -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if(context != &kObserveContext) {
    [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    return;
    }
    if(object == _contentScrollView.layer) {
    for(UIView * view in _contentScrollView.subviews) {
    if([NSStringFromClass(view.class) hasSuffix:@"ConfirmationView"]) {
    _confirmationView = view;
    _deleteButton = [view.subviews objectAtIndex:0];
    CGRect frame = _confirmationView.frame;
    CGRect frame2 = frame;
    frame.origin.x -= frame.size.width;
    frame.size.width *= 2;
    _confirmationView.frame = frame;
    frame2.origin = CGPointZero;
    _editButton.frame = frame2;
    frame2.origin.x += frame2.size.width;
    _deleteButton.frame = frame2;
    [_confirmationView addSubview:_editButton];
    break;
    }
    }
    return;
    }
    }
    -(void)_editTap {
    UITableView *tv = (id)self.superview;
    while(tv && ![tv isKindOfClass:[UITableView class]]) {
    tv = (id)tv.superview;
    }
    id<UITableViewDelegate> delegate = tv.delegate;
    if([delegate respondsToSelector:@selector(tableView:editTappedForRowWithIndexPath:)]) {
    NSIndexPath *ip = [tv indexPathForCell:self];
    //define this in your own protocol
    [delegate tableView:tv editTappedForRowWithIndexPath:ip];
    }
    }
    @end
    • Estoy realmente feliz si usted puede proporcionar ejemplos de código, Gracias
    • Hecho. Podría haber un error o dos, pero la esencia.
    • Gracias por la ayuda
  18. 1

    Hay una increíble biblioteca llamada SwipeCellKit, debería ganar más reconocimiento. En mi opinión es más frío que MGSwipeTableCell. El último no completamente replicar el comportamiento de la aplicación de Correo de las células, mientras que SwipeCellKit hace. Eche un vistazo

    • Traté de salir SwipeCellKit y quedó impresionado… hasta que me dieron una de esas Excepciones debido a que el número de filas antes de la vista de la tabla de actualización no fue el mismo después de la actualización de +/- el cambio en las filas. La cosa es que nunca he cambiado mi conjunto de datos. Así que si eso no es preocupante, no sé lo que es. Así que me decidí en contra de su uso y sólo utiliza el nuevo UITableViewDelegate métodos. Si usted necesita más personalización, siempre se pueden reemplazar willBeginEditingRowAt: ....
    • eso es raro. Nunca me he topado con alguna excepción cuando se utiliza SwipeCellKit. Después de todo ¿qué tipo de relación puede una célula tienen a una excepción de este tipo que ocurre debido al origen de los cambios?
  19. 1

    Swift 4

    func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
    let delete = UIContextualAction(style: .destructive, title: "Delete") { (action, sourceView, completionHandler) in
    print("index path of delete: \(indexPath)")
    completionHandler(true)
    }
    let rename = UIContextualAction(style: .normal, title: "Edit") { (action, sourceView, completionHandler) in
    print("index path of edit: \(indexPath)")
    completionHandler(true)
    }
    let swipeActionConfig = UISwipeActionsConfiguration(actions: [rename, delete])
    swipeActionConfig.performsFirstActionWithFullSwipe = false
    return swipeActionConfig
    }
    • ¿cuál es la fuente de la vista en sus códigos? es el Icono o la Imagen ?
    • es «La vista en la que la acción se ha mostrado.» Para obtener más información, busque «UIContextualAction.El controlador».
  20. 0

    Aquí es una solución simple. Es capaz de mostrar y ocultar personalizado UIView dentro de UITableViewCell.
    Mostrar la lógica está contenida dentro de la clase extendida de UITableViewCell, BaseTableViewCell.

    BaseTableViewCell.h

    #import <UIKit/UIKit.h>
    @interface BaseTableViewCell : UITableViewCell
    @property(nonatomic,strong)UIView* customView;
    -(void)showCustomView;
    -(void)hideCustomView;
    @end

    BaseTableViewCell.M

    #import "BaseTableViewCell.h"
    @interface BaseTableViewCell()
    {
    BOOL _isCustomViewVisible;
    }
    @end
    @implementation BaseTableViewCell
    - (void)awakeFromNib {
    //Initialization code
    }
    -(void)prepareForReuse
    {
    self.customView = nil;
    _isCustomViewVisible = NO;
    }
    - (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    [super setSelected:selected animated:animated];
    //Configure the view for the selected state
    }
    -(void)showCustomView
    {
    if(nil != self.customView)
    {
    if(!_isCustomViewVisible)
    {
    _isCustomViewVisible = YES;
    if(!self.customView.superview)
    {
    CGRect frame = self.customView.frame;
    frame.origin.x = self.contentView.frame.size.width;
    self.customView.frame = frame;
    [self.customView willMoveToSuperview:self.contentView];
    [self.contentView addSubview:self.customView];
    [self.customView didMoveToSuperview];
    }
    __weak BaseTableViewCell* blockSelf = self;
    [UIView animateWithDuration:.5 animations:^(){
    for(UIView* view in blockSelf.contentView.subviews)
    {
    CGRect frame = view.frame;
    frame.origin.x = frame.origin.x - blockSelf.customView.frame.size.width;
    view.frame = frame;
    }
    }];
    }
    }
    }
    -(void)hideCustomView
    {
    if(nil != self.customView)
    {
    if(_isCustomViewVisible)
    {
    __weak BaseTableViewCell* blockSelf = self;
    _isCustomViewVisible = NO;
    [UIView animateWithDuration:.5 animations:^(){
    for(UIView* view in blockSelf.contentView.subviews)
    {
    CGRect frame = view.frame;
    frame.origin.x = frame.origin.x + blockSelf.customView.frame.size.width;
    view.frame = frame;
    }
    }];
    }
    }
    }
    @end

    Para obtener esta funcionalidad, simple extender su vista de tabla de células de BaseTableViewCell.

    Siguiente,
    Dentro de UIViewController, que implementan UITableViewDelegate, crear dos gesto reconocedores de manejar a la izquierda y a la derecha pasadas.

    - (void)viewDidLoad {
    [super viewDidLoad];
    //Do any additional setup after loading the view, typically from a nib.
    [self.tableView registerNib:[UINib nibWithNibName:CUSTOM_CELL_NIB_NAME bundle:nil] forCellReuseIdentifier:CUSTOM_CELL_ID];
    UISwipeGestureRecognizer* leftSwipeRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleLeftSwipe:)];
    leftSwipeRecognizer.direction = UISwipeGestureRecognizerDirectionLeft;
    [self.tableView addGestureRecognizer:leftSwipeRecognizer];
    UISwipeGestureRecognizer* rightSwipeRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleRightSwipe:)];
    rightSwipeRecognizer.direction = UISwipeGestureRecognizerDirectionRight;
    [self.tableView addGestureRecognizer:rightSwipeRecognizer];
    }

    Que añadir dos deslizar los controladores de

    - (void)handleLeftSwipe:(UISwipeGestureRecognizer*)recognizer
    {
    CGPoint point = [recognizer locationInView:self.tableView];
    NSIndexPath* index = [self.tableView indexPathForRowAtPoint:point];
    UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:index];
    if([cell respondsToSelector:@selector(showCustomView)])
    {
    [cell performSelector:@selector(showCustomView)];
    }
    }
    - (void)handleRightSwipe:(UISwipeGestureRecognizer*)recognizer
    {
    CGPoint point = [recognizer locationInView:self.tableView];
    NSIndexPath* index = [self.tableView indexPathForRowAtPoint:point];
    UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:index];
    if([cell respondsToSelector:@selector(hideCustomView)])
    {
    [cell performSelector:@selector(hideCustomView)];
    }
    }

    Ahora, dentro de cellForRowAtIndexPath, de UITableViewDelegate, puede crear personalizado UIView y adjuntarlo a la descargados de la célula.

    -(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
    CustomCellTableViewCell* cell = (CustomCellTableViewCell*)[tableView dequeueReusableCellWithIdentifier:@"CustomCellTableViewCell" forIndexPath:indexPath];
    NSArray* nibViews = [[NSBundle mainBundle] loadNibNamed:@"CellCustomView"
    owner:nil
    options:nil];
    CellCustomView* customView = (CellCustomView*)[ nibViews objectAtIndex: 0];
    cell.customView = customView;
    return cell;
    }

    Por supuesto, esta forma de carga de personalizado UIView es sólo para este ejemplo. Administrar como desee.

Dejar respuesta

Please enter your comment!
Please enter your name here