Может ли стандартное вспомогательное представление быть в другом положении в UITableViewCell? - PullRequest
30 голосов
/ 20 мая 2010

Я хочу, чтобы мой аксессуар находился немного в другом месте, чем обычно. Является ли это возможным? Этот код не имеет никакого эффекта:

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

Ответы [ 10 ]

26 голосов
/ 20 мая 2010

Нет, вы не можете двигаться там, где вид аксессуара. В качестве альтернативы вы можете добавить подпредставление наподобие следующего:

[cell.contentView addSubview:aView];

Кроме того, устанавливая свойство accessoryView равным чему-либо, значение accessoryType игнорируется.

20 голосов
/ 27 мая 2011

Есть способ переместить accessoryView по умолчанию, но он довольно хакерский. Так что он может перестать работать в один прекрасный день, когда появится новый SDK.

Используйте на свой страх и риск (этот фрагмент кода перемещается на accessoryView 8 пикселей влево. Вставьте его в метод -(void)layoutSubviews нужного подкласса UITableViewCell):

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;
}
15 голосов
/ 24 сентября 2013

Мне удалось изменить рамку вспомогательного вида, просто сделав это в моем подклассе пользовательской ячейки.

CGRect adjustedFrame = self.accessoryView.frame;
adjustedFrame.origin.x += 10.0f;
self.accessoryView.frame = adjustedFrame;
3 голосов
/ 15 января 2014

Другой способ сделать это - встроить свой пользовательский вид аксессуара в другой вид, который устанавливается как вид аксессуара ячейки, и управлять заполнением с помощью рамки.

Вот пример с изображением в качестве пользовательского аксессуара:

// 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;
2 голосов
/ 16 марта 2017

Простой способ установить пользовательскую позицию для accessoryView , который * сохраняется в любом состоянии ячейки , состоит в размещении accessoryView в layoutSubViews:

- (void)layoutSubviews
{
    [super layoutSubviews];
    self.accessoryView.center = CGPointMake($yourX, $yourY);
}
2 голосов
/ 02 августа 2013

Приведенные выше ответы не работали для меня под IOS 6.1. Поэтому я попытался использовать UIEdgeInsets, потому что DetailDisclosure - это UIButton. И теперь работает нормально. Вот источник:

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 голосов
/ 05 мая 2013

Следуя решению, предоставленному Ана, я попытался лучше определить вспомогательный вид, и смотрю на правую сторону ячейки.

Создайте собственный класс, расширяющий UITableViewCell, и добавьте этот метод:

- (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;
            }
        }
    } 
}
1 голос
/ 11 августа 2017

улучшений других ответов

Для Джеймса Куанга, Kappe, accessoryView - ноль для дополнительного вида по умолчанию.

Для Matjan, subviews.lastObject - это просто неправильное представление, как UITableViewCellSeparatorView.

Для Алексея, Ана, Томаш, перечисление подпредставлений, пока мы не найдем неизвестное, которое пока работает. Но это трудоемко и может быть легко сломано в будущих версиях, если, скажем, Apple добавит backgroundAccessoryView.

Для larshaeuser перечислять подпредставления до тех пор, пока мы не найдем UIButton, это хорошая идея, но contentEdgeInsets недостаточно заметно меняет вид аксессуара.

решение для Swift 3.x и 4.0

Мы будем перечислять и искать последний 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
        }
    }
}

для Swift 4.1 и новее

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 голос
/ 27 июня 2013

Может быть, вам этого будет достаточно:

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;

Таким образом, я добавил отступ справа, поэтому вспомогательная кнопка выглядит смещенной влево. У него более широкая область, которая реагирует на прикосновения, это единственный побочный эффект.

1 голос
/ 14 августа 2012

Я работал с ios5, и решение, данное Алексеем, не работало полностью. Я обнаружил, что когда accessoryType установлен для таблицы, accessoryView является нулевым, поэтому первое «если» не работало. Я немного изменил код:

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;

}

и это решение работает на меня. Как сказал Алексей, я не знаю, что произойдет с будущими версиями, но по крайней мере в ios 4 работает.

...