2010-10-25 15 views
6

Me pregunto si alguien tiene un enlace a un buen tutorial o puede indicarme la dirección correcta para recrear las celdas 'arrastrar para reordenar' en una aplicación UITableView como Epic Win. La idea básica es que toque y mantenga presionado un elemento de la lista y luego arrastre hacia donde desea que esté el elemento. Cualquier ayuda sería muy apreciada.Reordenación UITableView personalizada

+0

cómo lograr esto, si tenemos varias secciones con una fila para cada sección ??? Por favor ayúdame! – ravoorinandan

Respuesta

7

Es bastante sencillo, lo que probablemente sea el motivo por el que no hay un tutorial explícito al respecto.

Simplemente cree el UITableView normalmente, pero configure el showsReorderControl de cada celda en VERDADERO. Cuando ingresa al modo de edición (normalmente presionando el botón "editar" y configurando el valor "Editing" de UITableView en TRUE), las barras de reordenación aparecerán en las celdas.

Nota:

Si el origen de datos implementa tableView:canMoveRowAtIndexPath: - y vuelve "NO" - no aparecerá las barras de nuevo pedido.

También necesitará implementar –tableView:moveRowAtIndexPath:toIndexPath: en el delegado de la fuente de datos.

+5

Lo único que me gustaría poder hacer es reemplazar el botón y hacer que la celda completa sea el botón. Entonces puedes arrastrar la celda. ¿Conoces alguna forma de cómo hacer eso? ¿O un trampolín de cómo hacer eso? – Pudgeball

+0

Es muy fácil subclasificar UITableCellView en cualquier cosa que desee, por lo que solo sería cuestión de hacer suya la suya con su propio botón/área de la barra de reordenación. – Brad

+0

De acuerdo, gracias por la ayuda :) – Pudgeball

13

La forma más sencilla, utilizando los métodos incorporados, es el siguiente:

En primer lugar, establecer su celda de la tabla para tener programas de reordenar el control sobre. ejemplo más simple (utilizando ARC):

Esto es suponiendo NSMutableArray *things se ha creado en otro lugar en esta clase

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"do not leak me"]; 
    if (!cell) { 
     cell = [[UITableViewCell alloc] init]; 
     cell.showsReorderControl = YES; 
    } 
    cell.textLabel.text = [things objectAtIndex:indexPath.row]; 
    return cell; 
} 

poner en práctica sus dos UITableViewDelegate métodos, como esto:

Este método le dice al tableView se permitido ser reordenado

-(BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { 
    return YES; 
} 

Aquí es donde el reordenamiento tableView realmente sucede

-(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath { 
    id thing = [things objectAtIndex:sourceIndexPath.row]; 
    [things removeObjectAtIndex:sourceIndexPath.row]; 
    [things insertObject:thing atIndex:destinationIndexPath.row]; 

} 

y de alguna manera, en algún lugar, establezca la edición en verdadero. Este es un ejemplo de cómo puedes hacer esto. TableView debe estar en modo de edición para poder reordenarlo.

- (IBAction)doSomething:(id)sender { 
    self.table.editing = YES; 
} 

Espero que sirva como un ejemplo concreto.

+0

La pregunta claramente establecida para dar una opción de reorden personalizado, no la predeterminada. – Unome

+0

@Unome No. El OP eligió la Respuesta Aceptada, que es básicamente una versión más resumida de mi respuesta. Gracias. –

+0

La respuesta aceptada como usted dijo es una versión diluida de lo que la pregunta solicitó. He publicado una subclase de trabajo de UITableView. – Unome

3

Esta solución aquí funcionará de manera similar a la aplicación Recordatorios en OSX que le permite reordenar celdas al mantener y arrastrar en cualquier lugar.

He creado una subclase de UITableView que le permite arrastrar y reordenar las celdas sin tener que tener editing o usar los controladores estándar de reorden.

La idea básica es que utilizo los toques iniciados y toques terminados para obtener la celda que se tocó, luego creo una vista falsa que es solo una captura de pantalla de la vista que tocó y la mueve de un lado a otro, intercambiando las celdas en el fondo. Cuando el usuario lo suelta, yo saco la vista original.

class ReorderTableView: UITableView { 

var customView:UIImageView? 
var oldIndexPath:NSIndexPath? 

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { 
    guard let touch1 = touches.first else{ 
     return 
    } 

    oldIndexPath = self.indexPathForRowAtPoint(touch1.locationInView(self)) 
    guard (oldIndexPath != nil) else{ 
     return 
    } 
    let oldCell = self.cellForRowAtIndexPath(self.oldIndexPath!) 

    customView = UIImageView(frame: CGRectMake(0, touch1.locationInView(self).y - 20, self.frame.width, 40)) 
    customView?.image = screenShotView(oldCell!) 
    customView?.layer.shadowColor = UIColor.blackColor().CGColor 
    customView?.layer.shadowOpacity = 0.5 
    customView?.layer.shadowOffset = CGSizeMake(1, 1) 

    self.addSubview(customView!) 
    oldCell?.alpha = 0 
} 

override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) { 

    guard let touch1 = touches.first else{ 
     return 
    } 
    let newIndexPath = self.indexPathForRowAtPoint(touch1.locationInView(self)) 
    guard newIndexPath != nil else{ 
     return 
    } 
    guard oldIndexPath != nil else{ 
     return 
    } 
    if newIndexPath != oldIndexPath{ 
     self.moveRowAtIndexPath(oldIndexPath!, toIndexPath: newIndexPath!) 
     oldIndexPath = newIndexPath 
     self.cellForRowAtIndexPath(self.oldIndexPath!)!.alpha = 0 
    } 
    self.customView!.frame.origin = CGPointMake(0, touch1.locationInView(self).y - 20) 
} 

override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) { 
    self.customView?.removeFromSuperview() 
    self.customView = nil 
    guard (oldIndexPath != nil) else{ 
     return 
    } 
    self.cellForRowAtIndexPath(self.oldIndexPath!)!.alpha = 1 
} 

func screenShotView(view: UIView) -> UIImage? { 

    let rect = view.bounds 
    UIGraphicsBeginImageContextWithOptions(rect.size,true,0.0) 
    let context = UIGraphicsGetCurrentContext() 

    CGContextTranslateCTM(context, 0, -view.frame.origin.y); 
    self.layer.renderInContext(context!) 
    let capturedImage = UIGraphicsGetImageFromCurrentImageContext() 
    UIGraphicsEndImageContext() 
    return capturedImage 
} 

} 

Al final puede reordenar las celdas sin tener que utilizar las asas. Esto puede ampliarse para diferentes gestos o modos dependiendo del caso de uso, pero lo dejé como una versión estándar.Hazme saber si tienes alguna pregunta.

Actualización:

Algunas advertencias que he encontrado. Es muy importante que descubra cómo desea utilizar el desplazamiento y modifique esto en consecuencia. Por ejemplo, cuando lo ridiculicé, configuré scrollingEnabled = false. A la larga, quería desplazarme, así que cambié el código para que solo ejecutara esta funcionalidad en una prensa de más de 0,25 (utilicé algunos temporizadores para hacerlo). Deshabilitaría temporalmente el desplazamiento durante este período y volveré a habilitar al finalizar.

+0

¿Qué te hace pensar que el OP quiere esto? La respuesta aceptada usa identificadores. Gracias. –

+1

su pregunta: "La idea básica es que toque y mantenga presionado un elemento de la lista y luego arrastre hacia donde desea que esté el elemento" no especificó que quería usar identificadores, y el título "Reordenar personalizado" implica no usar el métodos predeterminados Tuve un problema similar, y ninguna de las respuestas aquí me ayudó. Traté de contribuir con una respuesta que ayudaría a aquellos que tienen problemas similares. Una respuesta aceptada no = respuesta correcta. Gracias. – Unome

+0

Todo bien. Si desea agregar otra respuesta que muestre otro enfoque, es perfecto. No es necesario criticar las otras respuestas para promocionar el suyo +1 –

Cuestiones relacionadas