¿Cómo hacer para reordenar el control de UITableViewCell en el lado izquierdo?

Estoy haciendo una aplicación de lector de noticias y quiero que el usuario pueda elegir mostrar / ocultar categorías de noticias (como noticias, negocios, tecnología, deportes, etc.) y reordenarlas como la aplicación de noticias de la BBC en Android.

Ver la imagen a continuación: enter image description here

Mi pregunta es:

  • ¿Cómo hacer el control de reordenar en el lado izquierdo de la celda? (Su posición predeterminada está en el lado derecho de la celda en el modo de edición)
  • He marcado checkbox de control personalizado, ¿cómo ponerlo en el lado derecho de la celda?

¡¡¡Gracias de antemano!!!

Respuesta [Si no está utilizando ningún accesorio (información detallada, & c)]

(0) Supongo que tiene configuradas sus tablas, & c.

(1) Esta solución solo funciona si sus celdas de tablas son siempre arrastrables. Agregue esto en su viewDidLoad a su archivo Table View Controller .m.

- (void)viewDidLoad { [super viewDidLoad]; [self setEditing:YES]; } 

(2) Para que sea posible reordenar sus celdas, agregue cell.showsReorderControl = YES; a su mesa Vista: cellForRowAtIndexPath :.

(3) Asegúrese de tener tableView: canMoveRowAtIndexPath: y tableView: moveRowAtIndexPath: toIndexPath: methods.

 - (BOOL)tableView:(UITableView *)tableview canMoveRowAtIndexPath:(NSIndexPath *)indexPath { return YES; } - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath { } 

(4) Debido a que desea el control de reorden de la izquierda, tenemos que quitar el círculo Eliminar que está allí y el método tableView: editingStyleForRowAtIndexPath: hace eso.

 - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath { return UITableViewCellEditingStyleNone; } 

(5) Último paso, donde sucede la magia: agregue el método tableView: willDisplayCell: forRowAtIndexPath: busque las subvistas de la celda, acórtela a la UITableViewCellReorderControl privada y finalmente anulela.

 - (void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { for(UIView* view in cell.subviews) { if([[[view class] description] isEqualToString:@"UITableViewCellReorderControl"]) { // Creates a new subview the size of the entire cell UIView *movedReorderControl = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetMaxX(view.frame), CGRectGetMaxY(view.frame))]; // Adds the reorder control view to our new subview [movedReorderControl addSubview:view]; // Adds our new subview to the cell [cell addSubview:movedReorderControl]; // CGStuff to move it to the left CGSize moveLeft = CGSizeMake(movedReorderControl.frame.size.width - view.frame.size.width, movedReorderControl.frame.size.height - view.frame.size.height); CGAffineTransform transform = CGAffineTransformIdentity; transform = CGAffineTransformTranslate(transform, -moveLeft.width, -moveLeft.height); // Performs the transform [movedReorderControl setTransform:transform]; } } } 

Pasé casi diez horas tratando de encontrar una solución para los accesorios y no pude hacerlo. Necesito más experiencia y conocimiento primero. Simplemente haciendo lo mismo con el control de reordenar en el botón de divulgación no funcionó. Así que espero que esto funcione por ahora; y si lo averiguo en el futuro, me aseguraré de actualizar esto.

Hola Hoang Van Ha, esta es mi primera respuesta, y solo comencé a aprender Objective-C hace un mes, así que todavía soy bastante novato.

He intentado hacer lo mismo con mi aplicación y he estado buscando horas de cómo hacerlo. La documentación de Apple no es de mucha ayuda cuando se trata de esto. Me pareció bastante frustrante cuando las personas simplemente se vinculan a la documentación. Yo quería gritarles. Espero que mi respuesta te haya ayudado.

Un montón de felicitaciones para b2Cloud porque utilicé parte de su código de este artículo y lo adapté para mis respuestas.

En lugar de buscar UITableViewCellReorderControl , que es una API no pública y podría cambiar en el futuro , recomiendo usar UILongPressGestureRecognizer en UITableView e implementar su propia lógica de reordenamiento.

Resolví el caso general (respondiendo a una pulsación larga en cualquier parte de la celda) en HPReorderTableView , un reemplazo directo de UITableView. Se puede modificar fácilmente para responder a toques en partes específicas de la celda, por ejemplo implementando gestureRecognizer:shouldReceiveTouch: del delegado reorderGestureRecognizer .

Ahora hay una solución mucho más fácil para iOS 9 y posterior

 tableView.semanticContentAttribute = .forceRightToLeft 

Editar :

Como mencionó Roland , debes notar que “si alineas las subvistas de tus celdas” con anclas leading y trailing lugar de hacia la left y hacia la right , esta configuración cambiará todo “.

Luke Dubert, tiene una buena respuesta para iOS 7, debería cambiarse un poco para:

 UIView *cellSubview = cell.subviews[0]; for(UIView* view in cellSubview.subviews) { if([[[view class] description] isEqualToString:@"UITableViewCellReorderControl"]) { 

Esta solución no funcionó para mí en iOS7, así que he creado una versión para ambos, espero que sea útil:

 - (void)moveReorderControl:(UITableViewCell *)cell subviewCell:(UIView *)subviewCell { if([[[subviewCell class] description] isEqualToString:@"UITableViewCellReorderControl"]) { static int TRANSLATION_REORDER_CONTROL_Y = -20; //Code to move the reorder control, you change change it for your code, this works for me UIView* resizedGripView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetMaxX(subviewCell.frame), CGRectGetMaxY(subviewCell.frame))]; [resizedGripView addSubview:subviewCell]; [cell addSubview:resizedGripView]; // Original transform const CGAffineTransform transform = CGAffineTransformMakeTranslation(subviewCell.frame.size.width - cell.frame.size.width, TRANSLATION_REORDER_CONTROL_Y); // Move custom view so the grip's top left aligns with the cell's top left [resizedGripView setTransform:transform]; } } //This method is due to the move cells icons is on right by default, we need to move it. - (void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { if (tableView.tag == MEETING_BLOCK_TABLE_TAG) { for(UIView* subviewCell in cell.subviews) { if ([ROCFunctions isIOS7]) { if([[[subviewCell class] description] isEqualToString:@"UITableViewCellScrollView"]) { for(UIView* subSubviewCell in subviewCell.subviews) { [self moveReorderControl:cell subviewCell:subSubviewCell]; } } } else{ [self moveReorderControl:cell subviewCell:subviewCell]; } } } } 

Gracias a todos. Aquí está mi solución. han probado en iOS7 y iOS9

 @implementation StoryPreviewCell -(void)layoutSubviews{ [super layoutSubviews]; //subviews contains first level and second level views. NSMutableArray *subviews = [NSMutableArray array]; [subviews addObjectsFromArray:self.subviews]; for (NSInteger i=0; i 

Para aquellos que usan Xamarin, aquí está mi solución basada en la respuesta de @ luke-dubert, pero teniendo cuidado de eliminar las vistas adicionales añadidas al reutilizar:

En TableViewSource:

 public override void WillDisplay(UITableView tableView, UITableViewCell cell, NSIndexPath indexPath) { (cell as GraphBarLineCell)?.SetEditionMode(tableView.Editing); } 

En la celda:

 private UIView _reorderControlContainer; public void SetEditionMode(bool editing) { _title.Frame = editing ? TitleFrameForEditing : TitleFrame; if (editing) { var reorderControl = Subviews.FirstOrDefault(x => x.Class.Name.Equals("UITableViewCellReorderControl")); if (reorderControl != null) { _reorderControlContainer?.RemoveFromSuperview(); // Creates a new subview the size of the entire cell _reorderControlContainer = new UIView(new CGRect(0, 0, reorderControl.Frame.GetMaxX(), reorderControl.Frame.GetMaxY())); // Adds the reorder control view to our new subview _reorderControlContainer.AddSubview(reorderControl); // Adds our new subview to the cell AddSubview(_reorderControlContainer); // CGStuff to move it to the left var moveLeft = new CGSize(_reorderControlContainer.Frame.Size.Width - reorderControl.Frame.Size.Width, _reorderControlContainer.Frame.Size.Height - reorderControl.Frame.Size.Height); var transform = CGAffineTransform.MakeIdentity(); transform = CGAffineTransform.Translate(transform, -moveLeft.Width, -moveLeft.Height); _reorderControlContainer.Transform = transform; // Align the icon with the title var icon = reorderControl.Subviews[0]; icon.Frame = new CGRect(10, 25, icon.Frame.Width, icon.Frame.Height); } } } 

Encontré una solución mucho más sencilla que no requiere un posicionamiento manual absoluto de nada, e incluso funciona con transiciones animadas desde / hasta el modo de edición. Debería funcionar para iOS6 y 7.

Defina esta categoría en UIView en algún lugar:

 @interface UIView (ClassSearch) - (instancetype)subviewOfClassMatching:(NSString*)partialName; @end @implementation UIView (ClassSearch) -(instancetype)subviewOfClassMatching:(NSString *)partialName { if ([[[self class] description] rangeOfString:partialName options:NSCaseInsensitiveSearch].location != NSNotFound) { return self; } for (UIView* v in self.subviews) { id match = [v subviewOfClassMatching:partialName]; if (match) { return match; } } return nil; } @end 

Luego, en su subclase UITableViewCell, anularáTransitionToState de la siguiente manera:

 -(void)willTransitionToState:(UITableViewCellStateMask)state { [super willTransitionToState:state]; if (state == UITableViewCellStateShowingEditControlMask) { UIView* reorderControl = [self subviewOfClassMatching:@"ReorderControl"]; UIView* reorderContainer = [[UIView alloc] initWithFrame:self.bounds]; CGAffineTransform t = CGAffineTransformMakeScale(-1, 1); reorderContainer.transform = t; [self addSubview:reorderContainer]; [reorderContainer addSubview:reorderControl]; } } 

Tenga en cuenta que la celda necesita configurarse para mostrar solo el control de reorden, de lo contrario, se necesita hacer más trabajo.