web-dev-qa-db-de.com

Kann sich eine Standard-Zubehöransicht in einer anderen Position innerhalb einer UITableViewCell befinden?

Ich möchte, dass sich mein Accessoire an einem anderen Ort als normal befindet. Ist es möglich? Dieser Code hat keine Auswirkungen:

cell.accessoryType =  UITableViewCellAccessoryDisclosureIndicator;
cell.accessoryView.frame = CGRectMake(5.0, 5.0, 5.0, 5.0);
28
cannyboy

Nein, Sie können sich nicht in die Zubehöransicht bewegen. Als Alternative können Sie eine Unteransicht wie die folgende hinzufügen;

[cell.contentView addSubview:aView];

Durch Festlegen der accessoryView-Eigenschaft auf etwas wird der accessoryType-Wert ignoriert.

26
rickharrison

Es gibt eine Möglichkeit, die Standard-Zubehöransicht zu verschieben, aber sie ist ziemlich hackig. Daher könnte es eines Tages aufhören zu arbeiten, wenn ein neues SDK ankommt. 

Verwendung auf eigene Gefahr (dieses Code-Snippet verschiebt alle accessoryView 8 Pixel nach links. Fügen Sie es in die -(void)layoutSubviews-Methode der gewünschten UITableViewCell-Unterklasse ein)

if (self.accessoryView) {
    r = self.accessoryView.frame;
    r.Origin.x -= 8;
    self.accessoryView.frame = r;
} else {
    UIView *defaultAccessoryView = nil;
    for (UIView *subview in self.subviews) {
        if (subview != self.textLabel && 
            subview != self.detailTextLabel && 
            subview != self.backgroundView && 
            subview != self.contentView &&
            subview != self.selectedBackgroundView &&
            subview != self.imageView) {
            defaultAccessoryView = subview;
            break;
        }
    }

    r = defaultAccessoryView.frame;
    r.Origin.x -= 8;
    defaultAccessoryView.frame = r;
}
20
Alexey

Ich konnte den Rahmen der Zubehöransicht ändern, indem ich dies einfach in meiner benutzerdefinierten Zellunterklasse durchführte.

CGRect adjustedFrame = self.accessoryView.frame;
adjustedFrame.Origin.x += 10.0f;
self.accessoryView.frame = adjustedFrame;
14
James Kuang

Sie können dies auch tun, indem Sie Ihre benutzerdefinierte Zubehöransicht in eine andere Ansicht einbetten, die als Zubehöransicht der Zelle festgelegt ist, und die Auffüllung mit dem Rahmen steuern.

Hier ist ein Beispiel mit einer Bildansicht als benutzerdefinierte Zubehöransicht: 

// Use insets to define the padding on each side within the wrapper view
UIEdgeInsets insets = UIEdgeInsetsMake(24, 0, 0, 0);

// Create custom accessory view, in this case an image view
UIImage *customImage = [UIImage imageNamed:@"customImage.png"];
UIImageView *accessoryView = [[UIImageView alloc] initWithImage:customImage];

// Create wrapper view with size that takes the insets into account 
UIView *accessoryWrapperView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, customImage.size.width+insets.left+insets.right, customImage.size.height+insets.top+insets.bottom)];

// Add custom accessory view into wrapper view
[accessoryWrapperView addSubview:accessoryView];

// Use inset's left and top values to position the custom accessory view inside the wrapper view
accessoryView.frame = CGRectMake(insets.left, insets.top, customImage.size.width, customImage.size.height);

// Set accessory view of cell (in this case this code is called from within the cell)
self.accessoryView = accessoryWrapperView;
3
Ole

Die einfache Einstellung einer benutzerdefinierten Position für die AccessoryView , die in jedem Zellenstatus beibehalten wird ist das Layout der AccessoryView in layoutSubViews:

- (void)layoutSubviews
{
    [super layoutSubviews];
    self.accessoryView.center = CGPointMake($yourX, $yourY);
}
2
Kappe

Nach der von Ana gegebenen Lösung habe ich versucht, die Zubehöransicht besser zu erkennen.

Erstellen Sie eine benutzerdefinierte Klasse, die UITableViewCell erweitert, und fügen Sie diese Methode hinzu:

- (void)layoutSubviews {
    [super layoutSubviews];

    if (self.accessoryType != UITableViewCellAccessoryNone) {
        float estimatedAccesoryX = MAX(self.textLabel.frame.Origin.x + self.textLabel.frame.size.width, self.detailTextLabel.frame.Origin.x + self.detailTextLabel.frame.size.width);

        for (UIView *subview in self.subviews) {
            if (subview != self.textLabel &&
                subview != self.detailTextLabel &&
                subview != self.backgroundView &&
                subview != self.contentView &&
                subview != self.selectedBackgroundView &&
                subview != self.imageView &&
                subview.frame.Origin.x > estimatedAccesoryX) {

                // This subview should be the accessory view, change its frame
                frame = subview.frame;
                frame.Origin.x -= 10;
                subview.frame = frame;
                break;
            }
        }
    } 
}
2
Tomasz

Die obigen Antworten haben für mich unter Ios 6.1 nicht funktioniert. Also habe ich versucht, UIEdgeInsets zu verwenden, weil die DetailDisclosure ein UIButton ist. Und es funktioniert jetzt gut. Hier die Quelle:

if (cell.accessoryType == UITableViewCellAccessoryDetailDisclosureButton) {
    UIView* defaultAccessoryView = [cell.subviews lastObject];
    if ([defaultAccessoryView isKindOfClass:[UIButton class]]){
        UIButton *bt = (UIButton*)defaultAccessoryView;            
        bt.contentEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 10);
    }
}
2
larshaeuser

Ich arbeitete mit dem ios5 und die von Alexey angebotene Lösung funktionierte nicht vollständig. Ich entdeckte, dass, wenn ein AccessoryType für eine Tabelle festgelegt ist, die AccessoryView null ist, sodass das erste "if" nicht funktioniert. Ich habe den Code nur ein wenig geändert:

if (self.accessoryType != UITableViewCellAccessoryNone) {
    UIView* defaultAccessoryView = nil;

    for (UIView* subview in self.subviews) {
        if (subview != self.textLabel && 
            subview != self.detailTextLabel && 
            subview != self.backgroundView && 
            subview != self.contentView &&
            subview != self.selectedBackgroundView &&
            subview != self.imageView &&
            subview != self.explanationButton && // Own button
            subview.frame.Origin.x > 0 // Assumption: the checkmark will always have an x position over 0. 
            ) {
            defaultAccessoryView = subview;
            break;
        }
    }
    r = defaultAccessoryView.frame;
    r.Origin.x -= 8;
    defaultAccessoryView.frame = r;

}

und diese Lösung funktioniert für mich. Wie Alexey sagte, ich weiß nicht, was mit zukünftigen Versionen passieren wird, aber zumindest in iOS 4 funktioniert es.

1
Ana

verbesserungen bei anderen Antworten

Für James Kuang, Kappe ist accessoryView für die Standardzubehöransicht gleich Null.

Für Matjan subviews.lastObject ist leicht die falsche Ansicht, wie eine UITableViewCellSeparatorView.

Für Alexey, Ana, Tomasz funktioniert die Aufzählung der Unteransichten, bis wir eine unbekannte finden, im Moment. Aber es ist mühsam und könnte in zukünftigen Versionen leicht kaputt gehen, wenn zB Apple fügt ein backgroundAccessoryView hinzu.

Für larshaeuser ist es eine gute Idee, die Unteransichten aufzulisten, bis wir einen UIButton finden, aber contentEdgeInsets ändert die Zubehöransicht nicht ausreichend sichtbar.

lösung für Swift 3.x und 4.0

Wir werden den letzten UIButton aufzählen und suchen.

class AccessoryTableViewCell: UITableViewCell {
    override func layoutSubviews() {
        super.layoutSubviews()
        if let lastButton = subviews.reversed().lazy.flatMap({ $0 as? UIButton }).first {
            // This subview should be the accessory view, change its Origin
            lastButton.frame.Origin.x = bounds.size.width - lastButton.frame.size.width - 5
        }
    }
}

für Swift 4.1 und neuer

class AccessoryTableViewCell: UITableViewCell {
    override func layoutSubviews() {
        super.layoutSubviews()
        // https://stackoverflow.com/a/45625959/1033581
        if let lastButton = subviews.reversed().lazy.compactMap({ $0 as? UIButton }).first {
            // This subview should be the accessory view, change its Origin
            lastButton.frame.Origin.x = bounds.size.width - lastButton.frame.size.width - 5
        }
    }
}
1
Cœur

Vielleicht reicht das für Sie aus:

UIImageView* accessoryImageView = [[UIImageView alloc] initWithFrame:
        CGRectMake(0, 0, accessoryImage.size.width + MARGIN_RIGHT, accessoryImage.size.height)];
accessoryImageView.contentMode = UIViewContentModeLeft;
accessoryImageView.image = accessoryImage;

self.accessoryView = accessoryImageView;

Auf diese Weise fügte ich rechts eine Polsterung hinzu, so dass der Zubehörknopf nach links verschoben erscheint. Es hat einen breiteren Bereich, der auf Berührungen reagiert, das ist die einzige Nebenwirkung.

1
ancajic