UITableViewCell 自定义重新排序控件
Posted
技术标签:
【中文标题】UITableViewCell 自定义重新排序控件【英文标题】:UITableViewCell custom reorder control 【发布时间】:2010-08-23 11:45:07 【问题描述】:有什么方法可以改变 UITableView 处于编辑模式时显示的重新排序控件的图像?我想显示一个 UIImage,而不是通常的灰色条。
我是否必须继承 UITableViewCell 才能做到这一点?
【问题讨论】:
我的回答可能对你有所帮助:***.com/questions/8603359/…> 【参考方案1】:我猜你现在已经过了很长一段路,但这已经出现在一个新问题中。
在这里查看我的答案:
Change default icon for moving cells in UITableView
【讨论】:
谢谢。当新的解决方案出现时,让老问题保持活力真是太好了,以防有人搜索这个问题! @RaphaelSchweikert,这正是我刚刚发生的事情。 这个问题在发布数年后仍然有用。干得好。【参考方案2】:我最近遇到了更改重新排序控件的图像的需要,因为我将UITableViewCell
子类化以提供我自己的自定义表格单元格。作为这项工作的一部分,我将单元格的背景更改为默认颜色以外的其他颜色。
一切正常,但是当我将UITableView
置于编辑模式时,将出现重新排序控件,其背景为白色 - 而不是我用于单元格的背景颜色。这看起来不太好,我希望背景匹配。
在 ios 的各个版本的过程中,UITableViewCell
中的视图层次结构发生了变化。我采取了一种遍历整个视图集的方法,直到找到UITableViewCellReorderControl
私有类。我相信这将适用于 iOS 5 和所有后续 iOS 版本。请注意,虽然 UITableViewCellReorderControl
类本身是私有的,但我没有使用任何私有 API 来查找它。
首先,这里是扫描重新排序控件的代码;我假设文本“重新排序”将出现在类名中——Apple 将来可能会更改:
-(UIView *) findReorderView:(UIView *) view
UIView *reorderView = nil;
for (UIView *subview in view.subviews)
if ([[[subview class] description] rangeOfString:@"Reorder"].location != NSNotFound)
reorderView = subview;
break;
else
reorderView = [self findReorderView:subview];
if (reorderView != nil)
break;
return reorderView;
在您的自定义 UITableViewCell 子类中,您将覆盖 -(void) setEditing:animated:
并在此处找到重新排序控件。如果您在表格未处于编辑模式时尝试查找此控件,则重新排序控件将不在单元格的视图层次结构中:
-(void) setEditing:(BOOL)editing animated:(BOOL)animated
[super setEditing:editing animated:animated];
if (editing)
// find the reorder view here
// place the previous method either directly in your
// subclassed UITableViewCell, or in a category
// defined on UIView
UIView *reorderView = [self findReorderView:self];
if (reorderView)
// here, I am changing the background color to match my custom cell
// you may not want or need to do this
reorderView.backgroundColor = self.contentView.backgroundColor;
// now scan the reorder control's subviews for the reorder image
for (UIView *sv in reorderView.subviews)
if ([sv isKindOfClass:[UIImageView class]])
// and replace the image with one that you want
((UIImageView *)sv).image = [UIImage imageNamed:@"yourImage.png"];
// it may be necessary to properly size the image's frame
// for your new image - in my experience, this was necessary
// the upper left position of the UIImageView's frame
// does not seem to matter - the parent reorder control
// will center it properly for you
sv.frame = CGRectMake(0, 0, 48.0, 48.0);
您的里程可能会有所不同;我希望这对你有用。
【讨论】:
【参考方案3】:这是我基于 Rick Morgan 回答的 Swift 解决方案:
func adjustSize()
// we're trying to leverage the existing reordering controls, however that means the table must be kept in editing mode,
// which shrinks the content area to less than full width to make room for editing controls
let cellBounds = bounds
let contentFrame = contentView.convert(contentView.bounds, to: self)
let leftPadding = contentFrame.minX - cellBounds.minX
let rightPadding = cellBounds.maxX - contentFrame.maxX
// adjust actual content so that it still covers the full length of the cell
contentLeadingEdge.constant = -leftPadding
// this should pull our custom reorder button in line with the system button
contentTrailingEdge.constant = -rightPadding
// make sure we can still see and interact with the content that overhangs
contentView.clipsToBounds = false
// recursive search of the view tree for a reorder control
func findReorderControl(_ view: UIView) -> UIView?
// this is depending on a private API, retest on every new iPad OS version
if String(describing: type(of: view)).contains("Reorder")
return view
for subview in view.subviews
if let v = findReorderControl(subview)
return v
return nil
// hunt down the system reorder button and make it invisible but still operable
findReorderControl(self)?.alpha = 0.05 // don't go too close to alpha 0, or it will be considered hidden
这工作得很好。 contentLeadingEdge
和 contentTrailingEdge
是我在 Interface Builder 中设置的 contentView
和实际内容之间的布局约束。我的代码从tableView(_:, willDisplay:, forRowAt:)
委托方法调用此adjustSize
方法。
不过,我最终还是同意了 Clifton 的建议,即仅涵盖重新排序控制。我在awakeFromNib
的单元格(不是contentView
)中直接添加了一个UIImageView,将其定位,当adjustSize
被调用时,我只需将图像视图放在前面,它覆盖了重新排序控件而不必依赖任何私有 API。
【讨论】:
【参考方案4】:我最近在这方面做了一些工作,但没有完成。我尝试设置自己的editingAccesoryView,但无法更改重新排序控件。奇怪的。
我的猜测是它与 UITableviewCell 文档中的以下评论有关:showsReorderControl:
如果值为 YES ,则重新排序 控制暂时取代任何 附件视图。
换句话说,editingAccessoryView 正在被重新排序控件视图所取代,这可能是我们无法覆盖重新排序控件的原因。希望有人能找到解决方法。
【讨论】:
【参考方案5】:您将单元格的editingAccessoryView
属性设置为包含所需图像的图像视图。
顺便说一句,我会提醒您在执行此操作时要小心。当您将自定义图形替换为系统标准(例如重新排序图形)时,您将面临使用户感到困惑的严重风险。标准 UI 语法告诉他们在重新排序时期待标准图形,他们可能不理解您的自定义图形的重要性。
【讨论】:
和默认视图没什么区别;线条是波浪形的,而不是直线的…… 我需要在哪里执行此操作?如果我在实例化单元格时这样做,我唯一得到的是默认重新排序视图左侧的附加视图。拖动新图像时,我也无法重新排列单元格。我尝试设置cell.editingAccessoryType = UITableViewCellEditingStyleNone;
,但无济于事。
文档说使用UITableViewCellAccessoryDetailDisclosureButton
或编辑附件视图永远不会出现或响应。阅读 UITableView 文档了解详细信息。【参考方案6】:
也许我们都想多了。 :)
只需将自定义 UIImageView
放在默认移动附件的顶部,以便将其覆盖。完成。
【讨论】:
以上是关于UITableViewCell 自定义重新排序控件的主要内容,如果未能解决你的问题,请参考以下文章
进入编辑/重新排序模式时的 UITableViewCell 自定义绘图和动画
编辑自定义 UITableViewCell 时不出现插入/删除编辑控件