iphone - source - uitableviewcell types




¿Puede una vista de accesorio estándar estar en una posición diferente dentro de una UITableViewCell? (7)

Quiero que mi accesorio esté en un lugar ligeramente diferente de lo normal. ¿Es posible? Este código no tiene efecto:

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

mejoras en otras respuestas

Para James Kuang, Kappe, accessView es nulo para la vista de accesorios predeterminada.

Para Matjan, subviews.lastObject es una vista incorrecta, como una UITableViewCellSeparatorView.

Para Alexey, Ana, Tomasz, enumerar las subvistas hasta que encontremos una desconocida funciona por ahora. Pero es laborioso y podría romperse fácilmente en futuras versiones si, digamos, Apple agrega un backgroundAccessoryView .

Para larshaeuser, enumerar las subvistas hasta que encontremos un UIButton es una buena idea, pero contentEdgeInsets no está cambiando visiblemente de forma adecuada la vista de accesorios.

solución para Swift 3.xy 4.0

Enumeraremos y buscaremos el último 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
        }
    }
}

para Swift 4.1 y posterior

class AccessoryTableViewCell: UITableViewCell {
    override func layoutSubviews() {
        super.layoutSubviews()
        // https://.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
        }
    }
}

Estaba trabajando con el ios5 y la solución dada por Alexey no funcionaba por completo. Descubrí que cuando se configura un tipo de accesorio sobre una mesa, el accesorioView es nulo, por lo que el primer "si" no funcionaba. He cambiado el código solo un poco:

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;

}

y esta solución está funcionando para mí. Como dijo Alexey, no sé qué va a pasar con las versiones futuras, pero al menos en iOS 4 está funcionando.


La forma más sencilla de establecer una posición personalizada para el accesorioView que persiste en cualquier estado de celda es distribuir la vista de accesorio en layoutSubViews:

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

Las respuestas anteriores no funcionaron para mí bajo ios 6.1. Así que traté de usar UIEdgeInsets, porque DetailDisclosure es un UIButton. Y funciona bien ahora. Aquí la fuente:

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

Otra forma de hacerlo es insertar su vista de accesorios personalizada en otra vista, que se establece como la vista de accesorios de la celda y controlar el relleno usando el marco.

Aquí hay un ejemplo con una vista de imagen como vista de accesorios personalizada:

// 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;

Pude cambiar el marco de la vista accesoria simplemente haciendo esto en mi subclase de celda personalizada.

CGRect adjustedFrame = self.accessoryView.frame;
adjustedFrame.origin.x += 10.0f;
self.accessoryView.frame = adjustedFrame;

Tal vez esto sea suficiente para ti:

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 esta forma, agregué el relleno a la derecha, por lo que el botón de accesorios se ve desplazado hacia la izquierda. Tiene un área más amplia que responde a los toques, ese es el único efecto secundario.





uitableview