Простейший способ равномерного распределения UIButtons по горизонтали по ширине контроллера вида?

Я просмотрел множество ответов, и все они кажутся очень сложными! Совсем недавно я смотрел на этот ответ, хотя я бы предпочел не нажимать свои кнопки внутри просмотров.

У меня есть 6 UIButton, которые имеют одинаковые размеры. Я хочу разместить их равномерно горизонтально по всей ширине и внизу моего контроллера корневого представления.

|                                      |
|                                      |
|  [b1]  [b2]  [b3]  [b4]  [b5]  [b6]  |
________________________________________

Каков самый простой способ достичь этого программно?

Ответы

Ответ 1

Я думаю, что это проще, чем ссылка на принятый ответ. Итак, сначала создайте несколько кнопок:

UIButton *button1 = [UIButton buttonWithType:UIButtonTypeSystem];
button1.translatesAutoresizingMaskIntoConstraints = NO;
[button1 setTitle:@"Btn1" forState:UIControlStateNormal];

... сделайте это 6 раз для 6 кнопок, однако вам понравится, затем добавьте их в представление:

[self.view addSubview:button1];
[self.view addSubview:button2];
[self.view addSubview:button3];
[self.view addSubview:button4];
[self.view addSubview:button5];
[self.view addSubview:button6];

Устраните одну кнопку в нижней части вашего представления:

[self.view addConstraint:[NSLayoutConstraint constraintWithItem:button1 attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1 constant:0]];

Затем скажите всем кнопкам равную ширину и равномерно распределите по ширине:

NSDictionary *views = NSDictionaryOfVariableBindings(button1, button2, button3, button4, button5, button6);
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[button1][button2(==button1)][button3(==button1)][button4(==button1)][button5(==button1)][button6(==button1)]|" options:NSLayoutFormatAlignAllBottom metrics:nil views:views]];

Результат:

enter image description here

Ответ 3

Я знаю, что этот вопрос немного устарел, но я программировал в iOS уже несколько лет и не люблю использовать автозапуск. Поэтому я написал вспомогательный метод для равномерного пространства UIButtons по горизонтали и центрирования по вертикали внутри UIView. Это отлично работает для строк меню.

- (void) evenlySpaceTheseButtonsInThisView : (NSArray *) buttonArray : (UIView *) thisView {
    int widthOfAllButtons = 0;
    for (int i = 0; i < buttonArray.count; i++) {
        UIButton *thisButton = [buttonArray objectAtIndex:i];
        [thisButton setCenter:CGPointMake(0, thisView.frame.size.height / 2.0)];
        widthOfAllButtons = widthOfAllButtons + thisButton.frame.size.width;
    }

    int spaceBetweenButtons = (thisView.frame.size.width - widthOfAllButtons) / (buttonArray.count + 1);

    UIButton *lastButton = nil;
    for (int i = 0; i < buttonArray.count; i++) {
        UIButton *thisButton = [buttonArray objectAtIndex:i];
        if (lastButton == nil) {
            [thisButton setFrame:CGRectMake(spaceBetweenButtons, thisButton.frame.origin.y, thisButton.frame.size.width, thisButton.frame.size.height)];
        } else {
            [thisButton setFrame:CGRectMake(spaceBetweenButtons + lastButton.frame.origin.x + lastButton.frame.size.width, thisButton.frame.origin.y, thisButton.frame.size.width, thisButton.frame.size.height)];
        }

        lastButton = thisButton;
    }
}

Просто скопируйте и вставьте этот метод в любой контроллер представления. Затем, чтобы получить к нему доступ, я сначала создал все нужные мне кнопки, а затем вызвал метод со всеми кнопками в массиве вместе с UIView, в котором я хотел.

[self evenlySpaceTheseButtonsInThisView:@[menuButton, hierarchyMenuButton, downButton, upButton] :menuView];

Преимущество этого метода заключается в том, что вам не нужна автоматическая отладка и она очень проста в реализации. Недостатком является то, что если ваше приложение работает в условиях ландшафта и портрета, вам нужно будет снова вызвать этот метод после поворота представления.

Ответ 4

Обычно я делаю что-то вроде:

int numButtons = 6;
float gap = 10.0f;
float y = 50.0f;
float width = (self.view.frame.size.width - gap * (numButtons + 1)) / numButtons;
float height = 60.0f;
for (int n=0;n<numButtons;n++) {
    float x = gap * (n+1) + width * n;
    UIButton *button = [self.buttons objectAtIndex:n]; //Or get button some other way/make button.
    [button setFrame:CGRectMake(x,y,width,height)];
}

Вы можете установить numButtons на любое количество кнопок, которые вы хотите в строке, и если у вас есть набор кнопок, вы можете установить его в length этого массива.

Y - это то, что вы хотите, и то же самое относится к высоте и разрыву, который представляет собой пробел между кнопками. Ширина - это просто расчет того, насколько широка каждая кнопка будет основываться на ширине экрана и пространстве пробелов, которое вы хотите между каждой кнопкой.

Ответ 5

Вы можете отправить Label/button/view as array этим методам и упорядочить кадры кнопок.

-(void)arrangeViewsXposition:(NSArray*)anyView y:(CGFloat)y width:(CGFloat)width height:(CGFloat)height mainViewWdith:(UIView*)mainview {
int count = (int)anyView.count;
CGFloat widthTemp = mainview.bounds.size.width, temp1 = widthTemp-(width*count),space = temp1/(count+1);
for (int i = 0; i<count; i++) {
    UIView *btnTemp = (UIView*)[anyView objectAtIndex:i];
    if (btnTemp) {
        btnTemp.frame = CGRectMake(space+((space+width)*i), y, width, height);
    }
}
}

Вызвать этот метод следующим образом:

[self arrangeViewsXposition:@[btnSave,btnCancel] y:5 width:80 height:30 mainViewWdith:footerView];

Ответ 6

В этом вопросе обсуждается ряд достойных решений для автоматического макета:

Равномерное пространство нескольких видов в представлении контейнера

В принципе, это может быть много ручного кода определения ограничений, который удобно переносить в расширение категории для инкапсуляции/повторного использования.

Ответ 7

Я только что приготовил это в Swift, используя Cartography.

func disributeEvenlyAcrossWithCartography(views: [UIView], enclosingBox: UIView, spacer: CGFloat = 10.0) {
    var priorView = UIView() // never null
    for (index, view) in views.enumerate() {
        constrain(view, priorView, enclosingBox) { view, prior, enclosingBox in
            view.height == enclosingBox.height
            view.centerY == enclosingBox.centerY
            if index == 0 {
                view.width == enclosingBox.width / CGFloat(views.count) - spacer
                view.left == enclosingBox.left
            } else {
                view.left == prior.right + (spacer + spacer / CGFloat(views.count - 1))
                view.width == prior.width
            }
        }
        priorView = view
    }
}

Результат с 5 видами и небольшим спейсером:

введите описание изображения здесь

Ответ 8

Это мой первый пост в Stackoverflow. Этот сайт очень помог мне ускорить процесс Xcode и быстро. Во всяком случае, ниже мое быстро и грязно исправить этот вопрос.

Нажмите левую самую кнопку и самую правую кнопку, соответственно. Создайте метки "dummy" между каждой из кнопок. Установите все метки "dummy" как равные ширины. Для каждой метки "dummy" добавьте ограничения (от 0 до ближайшего соседа слева и 0 до ближайшего соседа справа). Затем кнопки будут равномерно распределены по всему диапазону, даже если вы перейдете от портретной ориентации к альбомной ориентации.