web-dev-qa-db-fra.com

Changer l'icône par défaut pour le déplacement de cellules dans UITableView

J'ai besoin de changer l'icône par défaut pour déplacer des cellules dans UITableView.

Celui-là: 

enter image description here

C'est possible?

31
devgeek

C’est une solution vraiment déconcertante qui risque de ne pas fonctionner à long terme, mais qui peut vous donner un point de départ. Le contrôle de réorganisation est une UITableViewCellReorderControl, mais c'est une classe privée, vous ne pouvez donc pas y accéder directement. Cependant, vous pouvez simplement parcourir la hiérarchie des sous-vues et trouver son imageView. 

Vous pouvez le faire en sous-classant UITableViewCell et en surchargeant sa méthode setEditing:animated: comme suit:

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

Ou à Swift

override func setEditing(editing: Bool, animated: Bool) {
    super.setEditing(editing, animated: animated)

    if (editing) {

        for view in subviews as [UIView] {
            if view.dynamicType.description().rangeOfString("Reorder") != nil {
                for subview in view.subviews as [UIImageView] {
                    if subview.isKindOfClass(UIImageView) {
                        subview.image = UIImage(named: "yourimage.png")
                    }
                }
            }
        }
    }
}

Soyez averti cependant ... cela pourrait ne pas être une solution à long terme, car Apple pourrait changer la hiérarchie des vues à tout moment.

49
Ashley Mills

La réponse d'Ashley Mills était excellente au moment où elle a été proposée, mais comme d'autres l'ont noté dans les commentaires, la hiérarchie des vues a changé d'une version à l'autre d'iOS. Afin de trouver correctement le contrôle de réorganisation, j'utilise une approche qui traverse toute la hiérarchie de vues. J'espère que cela donnera à l'approche une opportunité de continuer à fonctionner même si Apple change la hiérarchie des vues.

Voici le code que j'utilise pour trouver le contrôle de réorganisation:

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

Et voici le code que j'utilise pour remplacer la méthode -(void) setEditing:animated: dans ma sous-classe:

-(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);
                }
            }
        }
    }
}
11
Rick Morgan

J'utilise éditionAccessoryView pour remplacer l'icône de réorganisation.

  1. Créez une sous-classe de UITableViewCell.
  2. Remplacez setEditing. Il vous suffit de masquer le contrôle de réorganisation et de définir éditionAccessoryView sur uiimageview avec votre nouvelle image.
 - (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;

}

Si vous n'utilisez pas la vue des accessoires de montage, cela peut être un bon choix.

5
Hubert Wang

Mise à jour de la solution Ashley Mills (pour 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"];
                }
            }
        }
    }
}
5
OgreSwamp

Swift version de la réponse de Rick avec quelques améliorations:

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
}
5
Andrey Gordeev
- (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;
                }
            }
        }
    }   
}
4
Padavan

Swift 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
    }
3
Grzegorz R. Kulesza

Vous pouvez également simplement ajouter votre propre vue de réorganisation personnalisée au-dessus de toutes les autres à l'intérieur de votre cellule.

Tout ce que vous avez à faire est de vous assurer que cet affichage personnalisé est toujours supérieur aux autres, ce qui peut être vérifié dans [UITableViewDelegate tableView: willDisplayCell: forRowAtIndexPath: indexPath:].

Afin de permettre l'interaction de contrôle de réorganisation standard, votre vue personnalisée doit avoir sa userInteractionEnabled définie sur NO.

Selon l'apparence de votre cellule, vous aurez peut-être besoin d'une vue de réorganisation personnalisée plus ou moins complexe (pour imiter l'arrière-plan de la cellule, par exemple).

0
Phil