如何在左侧对UITableViewCell进行重新sorting控制?

我正在做一个新闻阅读器的应用程序,我希望用户可以select显示/隐藏新闻类别(如最新新闻,商业,科技,体育等),并重新sorting他们像在BBC的新闻应用程序。

见下图: 在这里输入图像说明

我的问题是:

  • 如何在单元格的左侧进行重新sorting控制? (在编辑模式下,其默认位置在单元的右侧)
  • 我有checkbox自定义控件,如何把它放在单元格的右侧?

预先感谢!!!

答案[如果您没有使用任何附件(详细披露,&c)]

(0)我假设你有你的表设置,&C。

(1)此解决scheme仅适用于您的表单元格始终可拖动的情况。 在你的viewDidLoad中添加这个到你的Table View Controller .m文件。

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

(2)为了让你可以重新sorting你的单元格,添加cell.showsReorderControl = YES; 到你的tableView:cellForRowAtIndexPath :.

(3)确保你有tableView:canMoveRowAtIndexPath:和tableView:moveRowAtIndexPath:toIndexPath:methods。

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

(4)因为你想在左边的重新sorting控制,我们必须去掉通常在那里的删除圆,tableView:editingStyleForRowAtIndexPath:方法。

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

(5)最后一步,发生奇迹 – 添加tableView:willDisplayCell:forRowAtIndexPath:方法,search单元格的子视图,将其缩小到专用的UITableViewCellReorderControl,最后覆盖它。

 - (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]; } } } 

我花了近十个小时试图找出配件的解决scheme,我无法做到这一点。 我需要更多的经验和知识。 简单地对披露button上的重新sorting控制做同样的事情是行不通的。 所以我希望这会现在起作用; 如果我在将来想出来,我一定会更新这个。

嗨黄凡哈,这是我有史以来的第一个答案,一个月前我才开始学习Objective-C,所以我还是个不错的select。

我一直在试图用我的应用程序做同样的事情,并一直在寻找如何做到这一点。 当涉及到这个时,苹果的文档不是很有帮助。 当人们简单地链接到文档时,我感到非常沮丧。 我想吼他们。 我希望我的回答对你有所帮助。

很多b2Cloud的荣誉,因为我使用了这篇文章中的一些代码,并将其用于我的答案。

而不是寻找UITableViewCellReorderControl它是非公开的API,将来可能会改变 ,我推荐使用UITableViewUILongPressGestureRecognizer并实现自己的重新sorting逻辑。

我在HPReorderTableView解决了一般情况(在单元的任何部分响应长按), HPReorderTableView是一个UITableView的替代scheme。 它可以很容易地修改,以响应单元gestureRecognizer:shouldReceiveTouch:定部分的触摸,例如通过实现reorderGestureRecognizer委托的gestureRecognizer:shouldReceiveTouch: reorderGestureRecognizer

现在对于iOS 9及更高版本,有一个更简单的解决scheme

 tableView.semanticContentAttribute = .forceRightToLeft 

卢克Dubert,有很酷的答案iOS 7应该改变一点点:

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

这个解决scheme在iOS7中不适合我,所以我为这两个版本创build了一个版本,我希望这个版本有用:

 - (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]; } } } } 

谢谢大家以上。这是我的解决scheme。 已经在iOS7和iOS9上进行了testing

 @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<self.subviews.count; i++) { UIView *firstLevelView = self.subviews[i]; if(firstLevelView.subviews.count) [subviews addObjectsFromArray:firstLevelView.subviews]; } for(UIView* view in subviews) { if([[[view class] description] isEqualToString:@"UITableViewCellReorderControl"]) { UIView *reorderControl = view; CGFloat leftMoveDistance = 100;//can customize CGAffineTransform transform = CGAffineTransformTranslate(CGAffineTransformIdentity, -leftMoveDistance, 0); reorderControl.transform = transform; } } } @end 

对于那些使用Xamarin的人来说,这里是基于@ luke-dubert答案的解决scheme,但是在重用时要注意删除附加的视图:

在TableViewSource上:

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

在单元格上:

 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); } } } 

我发现一个更简单的解决scheme,不需要绝对的手动定位任何东西,甚至可以使用从/到编辑模式的animation过渡。 应该适用于iOS6和7。

在UIView某处定义这个类别:

 @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 

然后,在您的UITableViewCell子类中,重写willTransitionToState,如下所示:

 -(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]; } } 

请注意,单元格需要configuration为只显示重新sorting控件,否则需要做更多的工作。