如何在左侧对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,将来可能会改变 ,我推荐使用UITableView
的UILongPressGestureRecognizer
并实现自己的重新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控件,否则需要做更多的工作。