提问人:devgeek 提问时间:12/22/2011 最后编辑:Baby Grootdevgeek 更新时间:10/13/2023 访问量:27743
更改 UITableView 中移动单元格的默认图标
Change default icon for moving cells in UITableView
答:
这是一个非常棘手的解决方案,可能不会长期有效,但可能会给你一个起点。重新排序控件是一个 ,但这是一个私有类,因此您不能直接访问它。但是,您可以查看子视图的层次结构并找到其 imageView。UITableViewCellReorderControl
您可以通过子类化和重写其方法来执行此操作,如下所示:UITableViewCell
setEditing:animated:
- (void) setEditing:(BOOL)editing animated:(BOOL)animated
{
[super setEditing: editing animated: YES];
if (editing) {
for (UIView * view in self.subviews) {
if ([NSStringFromClass([view class]) rangeOfString: @"Reorder"].location != NSNotFound) {
for (UIView * subview in view.subviews) {
if ([subview isKindOfClass: [UIImageView class]]) {
((UIImageView *)subview).image = [UIImage imageNamed: @"yourimage.png"];
}
}
}
}
}
}
或者在 Swift 中
override func setEditing(_ editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated)
if editing {
for view in subviews where view.description.contains("Reorder") {
for case let subview as UIImageView in view.subviews {
subview.image = UIImage(named: "yourimage.png")
}
}
}
}
不过要注意......这可能不是一个长期的解决方案,因为苹果可以随时改变视图层次结构。
评论
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
for (UIControl *control in cell.subviews)
{
if ([control isMemberOfClass:NSClassFromString(@"UITableViewCellReorderControl")] && [control.subviews count] > 0)
{
for (UIControl *someObj in control.subviews)
{
if ([someObj isMemberOfClass:[UIImageView class]])
{
UIImage *img = [UIImage imageNamed:@"reorder_icon.png"];
((UIImageView*)someObj).frame = CGRectMake(0.0, 0.0, 43.0, 43.0);
((UIImageView*)someObj).image = img;
}
}
}
}
}
评论
您也可以简单地将自己的自定义重新排序视图添加到单元格内的所有其他视图之上。
您所要做的就是确保此自定义视图始终高于其他视图,可以签入[UITableViewDelegate tableView: willDisplayCell: forRowAtIndexPath: indexPath:].
为了允许标准重新排序控件交互,自定义视图必须将其设置为 NO。userInteractionEnabled
根据单元格的外观,您可能需要或多或少复杂的自定义重新排序视图(以模拟单元格背景)。
评论
Ashley Mills的更新解决方案(适用于iOS 7.x)
if (editing) {
UIView *scrollView = self.subviews[0];
for (UIView * view in scrollView.subviews) {
NSLog(@"Class: %@", NSStringFromClass([view class]));
if ([NSStringFromClass([view class]) rangeOfString: @"Reorder"].location != NSNotFound) {
for (UIView * subview in view.subviews) {
if ([subview isKindOfClass: [UIImageView class]]) {
((UIImageView *)subview).image = [UIImage imageNamed: @"moveCellIcon"];
}
}
}
}
}
Ashley Mills 的回答在提供时非常出色,但正如其他人在评论中指出的那样,视图层次结构因 iOS 版本而异。为了正确找到重新排序控件,我使用了一种遍历整个视图层次结构的方法;希望这将使该方法有机会继续工作,即使 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;
}
这是我用来覆盖子类中方法的代码:-(void) setEditing:animated:
-(void) setEditing:(BOOL)editing animated:(BOOL)animated
{
[super setEditing:editing animated:animated];
if (editing)
{
// I'm assuming the findReorderView method noted above is either
// in the code for your subclassed UITableViewCell, or defined
// in a category for UIView somewhere
UIView *reorderView = [self findReorderView:self];
if (reorderView)
{
// I'm setting the background color of the control
// to match my cell's background color
// you might need to do this if you override the
// default background color for the cell
reorderView.backgroundColor = self.contentView.backgroundColor;
for (UIView *sv in reorderView.subviews)
{
// now we find the UIImageView for the reorder control
if ([sv isKindOfClass:[UIImageView class]])
{
// and replace it with the image we want
((UIImageView *)sv).image = [UIImage imageNamed:@"yourImage.png"];
// note: I have had to manually change the image's frame
// size to get it to display correctly
// also, for me the origin of the frame doesn't seem to
// matter, because the reorder control will center it
sv.frame = CGRectMake(0, 0, 48.0, 48.0);
}
}
}
}
}
评论
我使用 editingAccessoryView 替换重新排序图标。
- 创建 UITableViewCell 的子类。
- 覆盖 setEditing。只需隐藏重新排序控件,并将 editingAccessoryView 设置为包含重新排序图像的 uiimageview。
- (void) setEditing:(BOOL)editing animated:(BOOL)animated { [super setEditing: editing animated: YES]; self.showsReorderControl = NO; self.editingAccessoryView = editing ? [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"yourReorderIcon"]] : nil; }
如果您不使用编辑附件视图,这可能是一个不错的选择。
评论
Rick 回答的 Swift 版本,略有改进:
override func setEditing(editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated)
if editing {
if let reorderView = findReorderViewInView(self),
imageView = reorderView.subviews.filter({ $0 is UIImageView }).first as? UIImageView {
imageView.image = UIImage(named: "yourImage")
}
}
}
func findReorderViewInView(view: UIView) -> UIView? {
for subview in view.subviews {
if String(subview).rangeOfString("Reorder") != nil {
return subview
}
else {
findReorderViewInView(subview)
}
}
return nil
}
斯威夫特 4
// Change default icon (hamburger) for moving cells in UITableView
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
let imageView = cell.subviews.first(where: { $0.description.contains("Reorder") })?.subviews.first(where: { $0 is UIImageView }) as? UIImageView
imageView?.image = #imageLiteral(resourceName: "new_hamburger_icon") // give here your's new image
imageView?.contentMode = .center
imageView?.frame.size.width = cell.bounds.height
imageView?.frame.size.height = cell.bounds.height
}
评论
我在 iOS 12 上使用 swift 4.2 做到了这一点
我希望这能有所帮助:
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
for view in cell.subviews {
if view.self.description.contains("UITableViewCellReorderControl") {
for sv in view.subviews {
if (sv is UIImageView) {
(sv as? UIImageView)?.image = UIImage(named: "your_image")
(sv as? UIImageView)?.contentMode = .center
sv.frame = CGRect(x: 0, y: 0, width: 25, height: 25)
}
}
}
}
}
调试 UITableViewCell 后,可以使用 UITableViewCell 子类中的 KVC 来更改它。
// key
static NSString * const kReorderControlImageKey = @"reorderControlImage";
// setting when cellForRow calling
UIImage *customImage;
[self setValue:customImage forKeyPath:kReorderControlImageKey];
// to prevent crash
- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
if ([key isEqualToString:kReorderControlImageKey]) return;
else [super setValue:value forUndefinedKey:key];
}
我无法获得任何其他答案来为我工作,但我找到了解决方案。
Grzegorz R. Kulesza 的回答几乎对我有用,但我不得不做出一些改变。
这适用于 Swift 5 和 iOS 13:
// Change default reorder icon in UITableViewCell
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
let imageView = cell.subviews.first(where: { $0.description.contains("Reorder") })?.subviews.first(where: { $0 is UIImageView }) as? UIImageView
imageView?.image = UIImage(named: "your_custom_reorder_icon.png")
let size = cell.bounds.height * 0.6 // scaled for padding between cells
imageView?.frame.size.width = size
imageView?.frame.size.height = size
}
Swift 5 解决方案:
子类 UITableViewCell 并重写 didAddSubview 方法:
override func didAddSubview(_ subview: UIView) {
if !subview.description.contains("Reorder") { return }
(subview.subviews.first as? UIImageView)?.removeFromSuperview()
let imageView = UIImageView()
imageView.image = UIImage()
subview.addSubview(imageView)
imageView.snp.makeConstraints { make in
make.height.width.equalTo(24)
make.centerX.equalTo(subview.snp.centerX)
make.centerY.equalTo(subview.snp.centerY)
}
}
我使用 SnapKit 来设置约束,您可以按照自己的方式进行设置。
请注意,它可能是按Apple更新顺序排列的临时解决方案。
使用 iOS 16 和 Swift 5
我尝试了上述解决方案,但有时我的自定义图像未显示在某些单元格中。
这段代码对我来说在子类中工作得很好:UITableViewCell
private lazy var customReorderImgVw: UIImageView = {
let img = UIImage(named: "imgCustomReorder")!
let imgVw = UIImageView(image: img)
imgVw.contentMode = .center
imgVw.frame = CGRect(origin: .zero, size: img.size)
imgVw.alpha = 0
return imgVw
}()
override func setEditing(_ editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated)
if editing {
for subVw in subviews {
if "\(subVw.classForCoder)" == "UITableViewCellReorderControl" {
subVw.subviews.forEach { $0.removeFromSuperview() }
customReorderImgVw.center.y = subVw.center.y
subVw.addSubview(customReorderImgVw)
break
}
}
}
showOrHideCustomReorderView(isToShow: editing)
}
private func showOrHideCustomReorderView(isToShow: Bool) {
let newAlpha: CGFloat = (isToShow ? 1 : 0)
UIView.animate(withDuration: 0.25) {
self.customReorderImgVw.alpha = newAlpha
}
}
前面的 hack 是实现此目的的一种方法,但有一种非 hacky 方法可以做到这一点。这对我来说使用 Xcode 15 很好,但这些方法是在iOS 8.0
在您的 :UITableViewDelegate
func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {
false
}
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
.none
}
然后在你的 :UITableViewCell
override func setEditing(_ editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated)
showsReorderControl = false
}
评论