it-swarm.com.ru

Может ли стандартное вспомогательное представление быть в другом положении в UITableViewCell?

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

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

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

[cell.contentView addSubview:aView];

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

26
rickharrison

Есть способ переместить 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;
}
20
Alexey

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

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

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

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

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

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

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

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

Создайте пользовательский класс, который расширяет 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;
            }
        }
    } 
}
2
Tomasz

Приведенные выше ответы не работают для меня под 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
larshaeuser

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

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 работает.

1
Ana

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

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
ancajic

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

Для Джеймса Куанга, 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
        }
    }
}
0
Cœur