Je veux que mon accessoire soit dans un endroit légèrement différent de la normale. C'est possible? Ce code n'a aucun effet:
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.accessoryView.frame = CGRectMake(5.0, 5.0, 5.0, 5.0);
Non, vous ne pouvez pas vous déplacer là où se trouve la vue accessoire. Vous pouvez également ajouter une sous-vue, comme suit:
[cell.contentView addSubview:aView];
De même, en définissant la propriété accessoryView
sur quelque chose, la valeur accessoryType
est ignorée.
Il y a un moyen de déplacer accessoireView par défaut, mais c'est assez hacky. Il est donc possible qu’il cesse de fonctionner un jour à l’arrivée d’un nouveau SDK.
Utilisez-le à vos risques et périls (cet extrait de code déplace la variable accessoryView
de 8 pixels vers la gauche. Insérez-la dans la méthode -(void)layoutSubviews
de la sous-classe UITableViewCell
souhaitée):
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;
}
J'ai pu modifier le cadre de la vue des accessoires en le faisant simplement dans ma sous-classe de cellules personnalisée.
CGRect adjustedFrame = self.accessoryView.frame;
adjustedFrame.Origin.x += 10.0f;
self.accessoryView.frame = adjustedFrame;
Une autre façon de procéder consiste à incorporer votre vue d'accessoire personnalisée dans une autre vue, définie comme vue d'accessoire de la cellule et à contrôler le remplissage à l'aide du cadre.
Voici un exemple avec une vue d'image en tant que vue accessoire personnalisée:
// 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;
Le moyen simple de définir une position personnalisée pour le accessoriesView qui est est conservé dans l'état de la cellule consiste à mettre en page l'accessoireView dans layoutSubViews:
- (void)layoutSubviews
{
[super layoutSubviews];
self.accessoryView.center = CGPointMake($yourX, $yourY);
}
Suite à la solution donnée par Ana, j'ai essayé de mieux détecter la vue accessoire, je regarde du côté droit de la cellule.
Créez une classe personnalisée qui étend UITableViewCell et ajoutez cette méthode:
- (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;
}
}
}
}
Les réponses ci-dessus ne fonctionnaient pas pour moi sous iOS 6.1. J'ai donc essayé d'utiliser UIEdgeInsets, car DetailDisclosure est un UIButton. Et cela fonctionne bien maintenant. Voici la source:
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);
}
}
Je travaillais avec iOS 5 et la solution proposée par Alexey ne fonctionnait pas entièrement. J'ai découvert que, quand un type d'accessoire est défini sur une table, la valeur de l'accessoire est nulle et le premier "si" ne fonctionne pas. J'ai juste changé un peu le code:
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;
}
et cette solution fonctionne pour moi. Comme Alexey l'a dit, je ne sais pas ce qui va se passer avec les futures versions, mais au moins dans iOS 4, cela fonctionne.
Peut-être que cela vous suffira:
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;
De cette façon, j'ai ajouté un rembourrage à droite, le bouton accessoire a donc l'air décalé vers la gauche. Il a une zone plus large qui répond aux contacts, c'est le seul effet secondaire.
Pour James Kuang, Kappe, accessoryView
est nil pour la vue des accessoires par défaut.
Pour Matjan, subviews.lastObject
est facilement une vue erronée, comme un UITableViewCellSeparatorView.
Pour Alexey, Ana, Tomasz, énumérant les sous-vues jusqu'à ce que nous trouvions un inconnu fonctionne pour le moment. Mais c’est laborieux et pourrait être facilement supprimé dans les versions futures si, disons, Apple ajoute un backgroundAccessoryView
.
Pour larshaeuser, il est judicieux d'énumérer les sous-vues jusqu'à ce que nous trouvions un bouton UIB, mais contentEdgeInsets
ne modifie pas de manière adéquate la vue accessoire.
Nous allons énumérer et rechercher le dernier UIButton.
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
}
}
}
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
}
}
}