iPhone UITableView – Botón Eliminar

Estoy usando la funcionalidad ‘deslizar para eliminar’ de UITableView .

El problema es que estoy usando una UITableViewCell personalizada que se crea por elemento en

 - (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 

Necesito modificar la posición del botón Eliminar (simplemente moverlo alrededor de 10px a la izquierda), ¿cómo voy a hacer esto?

Aquí está mi código existente para crear la celda:

 - (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSLog(@"cellForRowAtIndexPath"); #if USE_CUSTOM_DRAWING const NSInteger TOP_LABEL_TAG = 1001; const NSInteger BOTTOM_LABEL_TAG = 1002; UILabel *topLabel; UILabel *bottomLabel; #endif static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { // // Create the cell. // cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease]; #if USE_CUSTOM_DRAWING const CGFloat LABEL_HEIGHT = 20; UIImage *image = [UIImage imageNamed:@"trans_clock.png"]; // // Create the label for the top row of text // topLabel = [[[UILabel alloc] initWithFrame: CGRectMake( image.size.width + 2.0 * cell.indentationWidth, 0.5 * (aTableView.rowHeight - 2 * LABEL_HEIGHT), aTableView.bounds.size.width - image.size.width - 4.0 * cell.indentationWidth , LABEL_HEIGHT)] autorelease]; [cell.contentView addSubview:topLabel]; // // Configure the properties for the text that are the same on every row // topLabel.tag = TOP_LABEL_TAG; topLabel.backgroundColor = [UIColor clearColor]; topLabel.textColor = fontColor; topLabel.highlightedTextColor = [UIColor colorWithRed:1.0 green:1.0 blue:0.9 alpha:1.0]; topLabel.font = [UIFont systemFontOfSize:[UIFont labelFontSize]]; // // Create the label for the top row of text // bottomLabel = [[[UILabel alloc] initWithFrame: CGRectMake( image.size.width + 2.0 * cell.indentationWidth, 0.5 * (aTableView.rowHeight - 2 * LABEL_HEIGHT) + LABEL_HEIGHT, aTableView.bounds.size.width - image.size.width - 4.0 * cell.indentationWidth , LABEL_HEIGHT)] autorelease]; [cell.contentView addSubview:bottomLabel]; // // Configure the properties for the text that are the same on every row // bottomLabel.tag = BOTTOM_LABEL_TAG; bottomLabel.backgroundColor = [UIColor clearColor]; bottomLabel.textColor = fontColor; bottomLabel.highlightedTextColor = [UIColor colorWithRed:1.0 green:1.0 blue:0.9 alpha:1.0]; bottomLabel.font = [UIFont systemFontOfSize:[UIFont labelFontSize] - 2]; // // Create a background image view. // cell.backgroundView = [[[UIImageView alloc] init] autorelease]; cell.selectedBackgroundView = [[[UIImageView alloc] init] autorelease]; #endif } #if USE_CUSTOM_DRAWING else { topLabel = (UILabel *)[cell viewWithTag:TOP_LABEL_TAG]; bottomLabel = (UILabel *)[cell viewWithTag:BOTTOM_LABEL_TAG]; } topLabel.text = @"Example Text"; topLabel.textColor = fontColor; bottomLabel.text = @"More Example Text"; bottomLabel.textColor = fontColor; // // Set the background and selected background images for the text. // Since we will round the corners at the top and bottom of sections, we // need to conditionally choose the images based on the row index and the // number of rows in the section. // UIImage *rowBackground; UIImage *selectionBackground; NSInteger sectionRows = [aTableView numberOfRowsInSection:[indexPath section]]; NSInteger row = [indexPath row]; if (row == 0 && row == sectionRows - 1) { rowBackground = [UIImage imageNamed:@"topAndBottomRow.png"]; selectionBackground = [UIImage imageNamed:@"topAndBottomRowSelected.png"]; } else if (row == 0) { rowBackground = [UIImage imageNamed:@"topRow.png"]; selectionBackground = [UIImage imageNamed:@"topRowSelected.png"]; } else if (row == sectionRows - 1) { rowBackground = [UIImage imageNamed:@"bottomRow.png"]; selectionBackground = [UIImage imageNamed:@"bottomRowSelected.png"]; } else { rowBackground = [UIImage imageNamed:@"middleRow.png"]; selectionBackground = [UIImage imageNamed:@"middleRowSelected.png"]; } ((UIImageView *)cell.backgroundView).image = rowBackground; ((UIImageView *)cell.selectedBackgroundView).image = selectionBackground; cell.imageView.image = [UIImage imageNamed:@"Example_Image.png"]; #else cell.text = @"Example"; #endif return cell; } 

El código de Iwat no funciona para mí. Pero esto funciona

  - (void) willTransitionToState: (UITableViewCellStateMask) state {

     [super willTransitionToState: estado];

     if ((estado y UITableViewellStateShowingDeleteConfirmationMask) == UITableViewCellStateShowingDeleteConfirmationMask) {

         para (subvista UIView * en self.subviews) {

             if ([NSStringFromClass ([subview class]) isEqualToString: @ "UITableViewCellDeleteConfirmationControl"]) {             

                 subview.hidden = YES;
                 subview.alpha = 0.0;
             }
         }
     }
 }

 - (void) didTransitionToState: (UITableViewCellStateMask) state {

     [super didTransitionToState: estado];

     if ( state == UITableViewCellStateShowingDeleteConfirmationMask || state == UITableViewCellStateDefaultMask ) {
         para (subvista UIView * en self.subviews) {

             if ([NSStringFromClass ([subview class]) isEqualToString: @ "UITableViewCellDeleteConfirmationControl"]) {

                 UIView * deleteButtonView = (UIView *) [subview.subviews objectAtIndex: 0]; 
                  CGRect f = deleteButtonView.frame; 
                  f.origin.x - = 20; 
                  deleteButtonView.frame = f;

                 subview.hidden = NO;

                 [UIView beginAnimations: @ "anim" context: nil];
                 subview.alpha = 1.0;
                 [UIView commitAnimations];
             }
         }
     }
 } 

Para mí, la mejor manera de resolver esto fue anular -(void)layoutSubviews en MyCell:UITableViewCell

Aquí puede ver no solo la posición personalizada del botón Eliminar, sino también el reposicionamiento de los controles Editar y Reordenar para el modo Edición

 - (void)layoutSubviews { [super layoutSubviews]; [UIView beginAnimations:nil context:NULL]; [UIView setAnimationBeginsFromCurrentState:YES]; [UIView setAnimationDuration:0.0f]; for (UIView *subview in self.subviews) { if ([NSStringFromClass([subview class]) isEqualToString:@"UITableViewCellDeleteConfirmationControl"]) { CGRect newFrame = subview.frame; newFrame.origin.x = 200; subview.frame = newFrame; } else if ([NSStringFromClass([subview class]) isEqualToString:@"UITableViewCellEditControl"]) { CGRect newFrame = subview.frame; newFrame.origin.x = 100; subview.frame = newFrame; } else if ([NSStringFromClass([subview class]) isEqualToString:@"UITableViewCellReorderControl"]) { CGRect newFrame = subview.frame; newFrame.origin.x = 200; subview.frame = newFrame; } } [UIView commitAnimations]; } 

No he podido cambiar el aspecto real del botón Eliminar, pero puede cambiar el texto. Tal vez puedas usar esto para obtener el efecto que estás buscando?

Consulte el siguiente miembro del protocolo UITableViewDelegate :

 - (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath 

Además, puede detectar cuándo se muestra el botón Eliminar subclasificando UITableViewCell y anulando lo siguiente:

 - (void)willTransitionToState:(UITableViewCellStateMask)state - (void)didTransitionToState:(UITableViewCellStateMask)state 

Para cualquiera de estos, la máscara de estado será UITableViewCellStateShowingDeleteConfirmationMask cuando se UITableViewCellStateShowingDeleteConfirmationMask el botón Eliminar.

Es de esperar que estas pistas te dirijan en la dirección correcta.

Utilizo una solución que, a primera vista, parece bastante hacky, pero funciona y no confía en las apis indocumentadas:

 /** * Transition to state */ -(void)willTransitionToState:(UITableViewCellStateMask)state { if(state & UITableViewCellStateShowingDeleteConfirmationMask) _deleting = YES; else if(!(state & UITableViewCellStateShowingDeleteConfirmationMask)) _deleting = NO; [super willTransitionToState:state]; } /** * Reset cell transformations */ -(void)resetCellTransform { self.transform = CGAffineTransformIdentity; _background.transform = CGAffineTransformIdentity; _content.transform = CGAffineTransformIdentity; } /** * Move cell around if we are currently in delete mode */ -(void)updateWithCurrentState { if(_deleting) { float x = -20; float y = 0; self.transform = CGAffineTransformMakeTranslation(x, y); _background.transform = CGAffineTransformMakeTranslation(-x, -y); _content.transform = CGAffineTransformMakeTranslation(-x, -y); } } -(void)setFrame:(CGRect)frame { [self resetCellTransform]; [super setFrame:frame]; [self updateWithCurrentState]; } -(void)layoutSubviews { [self resetCellTransform]; [super layoutSubviews]; [self updateWithCurrentState]; } 

Básicamente, esto cambia la posición de la celda y reajusta las porciones visibles. WillTransitionToState simplemente establece una variable de instancia que indica si la celda está en modo de eliminación. Reemplazar setFrame fue necesario para apoyar la rotación del teléfono al paisaje y viceversa. Donde _background es la vista de fondo de mi celda y _content es una vista agregada al contentView de la celda, con todas las tags, etc.

No sé de ninguna manera “mover el botón eliminar 10px hacia la izquierda”. Sin embargo, puede animar los contenidos personalizados de su celda de tabla alrededor de la posición estática del botón de eliminación inamovible escuchando el mensaje willTransitionToState: de una UITableViewCell , consulte aquí .

Para citar los documentos:

Las subclases de UITableViewCell pueden implementar este método para animar cambios adicionales en una celda cuando está cambiando de estado. UITableViewCell llama a este método cada vez que una celda realiza una transición entre estados, como desde un estado normal (predeterminado) hasta el modo de edición. La celda personalizada puede configurar y posicionar las vistas nuevas que aparecen con el nuevo estado. Luego, la celda recibe un mensaje layoutSubviews (UIView) en el que puede ubicar estas nuevas vistas en sus ubicaciones finales para el nuevo estado. Las subclases siempre deben llamar a super cuando anula este método.

Lo que está buscando es el valor UITableViewCellStateShowingDeleteConfirmationMask . Este es uno de esos momentos en los que la creación de la subclase UITableViewCell podría ser mejor, por lo que desde el controlador solo está creando una instancia de su celda personalizada. Luego, la célula puede ajustarse como animateLeft y animateRight y manejar el funcionamiento interno de ajustar sus propias subvistas.

No conozco la solución final, pero por lo que he intentado, el siguiente código podría ser útil.

 // subclass UITableViewCell - (void)willTransitionToState:(UITableViewCellStateMask)state { [super willTransitionToState:state]; if ((state & UITableViewCellStateShowingDeleteConfirmationMask) == UITableCellStateShowingDeleteConfirmationMask) { for (UIView *subview in self.subviews) { if ([NSStringFromClass([subview class]) isEqualToString:@"UITableViewCellDeleteConfirmationControl"]) { subview.hidden = YES; subview.alpha = 0; } } } } - (void)didTransitionToState:(UITableViewCellStateMask)state { [super willTransitionToState:state]; if ((state & UITableViewCellStateShowingDeleteConfirmationMask) == UITableCellStateShowingDeleteConfirmationMask) { for (UIView *subview in self.subviews) { if ([NSStringFromClass([subview class]) isEqualToString:@"UITableViewCellDeleteConfirmationControl"]) { subview.frame = CGRectMake(subview.frame.origin.x - 10, subview.frame.origin.y, subview.frame.size.width, subview.frame.size.height); subview.hidden = NO; [UIView beginAnimations:@"anim" context:nil]; subview.alpha = 1; [UIView commitAnimations]; } } } }