Подтвердить что ты не робот

Как настроить UIToolBar влево и вправо

Я создаю один UIToolbar с кодом, а другой - с построителем интерфейса. Но выяснилось, что две панели инструментов имеют различную левую и правую прокладку, которые показаны ниже:

Из интерфейса Builder:

enter image description here

Из кода:

enter image description here

UIImage *buttonImage = [[UIImage imageNamed:@"button.png"] stretchableImageWithLeftCapWidth:10 topCapHeight:0];
UIButton *btnTest = [UIButton buttonWithType:UIButtonTypeCustom];
[btnTest setBackgroundImage:buttonImage forState:UIControlStateNormal];
[btnTest setTitle:@"Back" forState:UIControlStateNormal];   
[btnTest.titleLabel setFont:[UIFont boldSystemFontOfSize:13]];  
[btnTest setBackgroundImage:[imgToolbarButton stretchableImageWithLeftCapWidth:5 topCapHeight:0]  forState:UIControlStateNormal];
[btnTest addTarget:self action:@selector(clearDateEdit:) forControlEvents:UIControlEventTouchUpInside];
btnTest.frame = CGRectMake(0.0, 0.0, 50, 30);
UIBarButtonItem *btnTestItem = [[UIBarButtonItem alloc] initWithCustomView:btnTest];
[self.toolbar setItems:[NSArray arrayWithObjects:btnTestItem,nil]];
[btnTestItem release];

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

Обновление

Я обнаружил, что эта проблема выравнивания происходит только с UIBarButtonItem с customView UIButton, выравнивание в порядке с UIBarButtonItem. Любая идея, что вызывает это или разрешает это.

Единственное решение, о котором я могу сейчас подумать, - это вручную установить фрейм.

4b9b3361

Ответ 1

У меня была такая же проблема, и там был аккуратный трюк, который вы можете сделать с UIBarButtonSystemItemFixedSpace, добавьте одну из них с отрицательной шириной перед первой кнопкой и после последней кнопки, и она переместит кнопку на край.

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

UIBarButtonItem *negativeSeparator = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
negativeSeparator.width = -12;

Поля слева и справа 12px.

Обновление для iOS7 - поля 16px на iPhone и 20px на iPad!

Ответ 2

До iOS 11

У вас было три возможных решения:

  • Первым был использование элемента пространства UIBarButtonItem (barButtonSystemItem:.fixedSpace...) с отрицательной шириной
  • Другим было переопределить alignmentRectInsets в пользовательском представлении
  • Последний, если вы используете UIButton в качестве пользовательского представления вашего элемента, вы можете переопределить contentEdgeInsets и hitTest (_: with:)

Абсолютно, первое решение кажется лучше других

UIBarButtonItem *negativeSeparator = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
negativeSeparator.width = -12;

если вы используете быстрый, код будет выглядеть следующим образом:

var negativeSeparator = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
negativeSeparator.width = -12

После iOS 11 (содержит iOS 11)

К сожалению, все решения не могут использоваться в iOS 11

  • первое решение: установка отрицательной ширины больше не работает
  • второе решение: переопределить alignmentRectInsets приведет к тому, что часть элемента перестанет получать штрихи
  • последнее решение: я думаю, что override hitTest (_: with:) не очень хорошая идея, не делайте этого, пожалуйста!

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

О, боже, все, что я хочу сделать, это изменить прокладку, а не панель навигации!

К счастью, мы можем сделать это с помощью трюка в iOS 11!

Здесь мы идем:

1. создать пользовательскую кнопку

  • set translatesAutoresizingMaskIntoConstraints как false
  • переопределение выравниванияRectInsets
    • в правой части используйте UIEdgeInsets (сверху: 0, слева: -8, внизу: 0, справа: 8) Элемент
    • в левой стороне использует UIEdgeInsets (вверху: 0, слева: 8, внизу: 0, справа: -8)

      если вы не знаете alignmentRectInsets, вы можете прочитать этот блог первый

быстрая версия

var customButton = UIButton(type: .custom)
customButton.overrideAlignmentRectInsets = UIEdgeInsets(top: 0, left: x, bottom: 0, right: -x) // you should do this in your own custom class
customButton.translatesAutoresizingMaskIntoConstraints = false;

objective-c версия

UIButton *customButton = [UIButton buttonWithType:UIButtonTypeCustom];
customButton.overrideAlignmentRectInsets = UIEdgeInsetsMake(0, x, 0, -x); // you should do this in your own custom class
customButton.translatesAutoresizingMaskIntoConstraints = NO;

2. создайте элемент с помощью настраиваемой кнопки

быстрая версия

var item = UIBarButtonItem(customView: customButton)

objective-c версия

UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithCustomView:customButton]

3. создайте тип UIBarButtonItem с фиксированным пространством с положительной шириной

установите положительное значение, а не отрицательное значение

быстрая версия

var positiveSeparator = UIBarButtonItem(barButtonSystemItem:.fixedSpace, target: nil, action: nil)
positiveSeparator.width = 8

objective-c версия

UIBarButtonItem *positiveSeparator = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil];
positiveSeparator.width = 8;

4. установить массив в leftitems или rightitems

fixedSpace type Элемент UIBarButton должен быть первым элементом в массиве.

быстрая версия

self.navigationItem.leftBarButtonItems = [positiveSeparator, item, ...]

objective-c версия

self.navigationItem.leftBarButtonItems = @{positiveSeparator, item, ...}

Готово

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

Если вы найдете что-то не так, пожалуйста, дайте мне знать! Я постараюсь ответить на ваш вопрос!

Примечание

Перед iOS 11 вам следует позаботиться о ширине экрана устройства; если экран составляет 5,5 дюйма, отрицательный - 12 пт, на других экранах - -8pt.

Если вы используете мое решение на iOS 11, вам не нужно заботиться о экране устройства, просто установите 8pt, Вы должны заботиться о позиции позиции в навигационной панели, левой или правой стороне, это повлияет на ваш пользовательский просмотр alignmentRectInsets

Требуется больше области отвода

Если вы хотите пообещать, что область вашего крана больше 44 * 44, вы можете переопределить метод ниже

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{
    CGSize acturalSize = self.frame.size;
    CGSize minimumSize = kBarButtonMinimumTapAreaSize;
    CGFloat verticalMargin = acturalSize.height - minimumSize.height >= 0 ? 0 : ((minimumSize.height - acturalSize.height ) / 2);
    CGFloat horizontalMargin = acturalSize.width - minimumSize.width >= 0 ? 0 : ((minimumSize.width - acturalSize.width ) / 2);
    CGRect newArea = CGRectMake(self.bounds.origin.x - horizontalMargin, self.bounds.origin.y - verticalMargin, self.bounds.size.width + 2 * horizontalMargin, self.bounds.size.height + 2 * verticalMargin);
    return CGRectContainsPoint(newArea, point);
}

Ответ 3

используйте эту кнопку

UIBarButtonItem *spaceItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
                                                                           target:nil
                                                                           action:nil];

Ответ 4

Я встретил ту же проблему. Наконец, я решил это путем подклассификации UIToolbar и переопределить метод subviews макета.

- (void)layoutSubviews {

  [super layoutSubviews];

  if (leftItem_ && leftItem_.customView
      && [leftItem_.customView isKindOfClass:[UIButton class]]) {
    CGRect newFrame = leftItem_.customView.frame;
    newFrame.origin.x = 0;   // reset the original point x to 0; default is 12, wired number
    leftItem_.customView.frame = newFrame;    
  }

  if (rightItem_ && rightItem_.customView
      && [rightItem_.customView isKindOfClass:[UIButton class]]) {
    CGRect newFrame = rightItem_.customView.frame;
    newFrame.origin.x = self.frame.size.width - CGRectGetWidth(newFrame);
    rightItem_.customView.frame = newFrame;
  }

}

Ответ 5

Вы можете изменить смещение и ширину панели инструментов, если вы хотите использовать customview (initWithCustomView)

[myToolBar setFrame:CGRectMake(-10, 0, [UIScreen mainScreen].bounds.size.width+10, 44)];

Ответ 6

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

UIBarButtonItem flexibleButtonItemLeft = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];

UIBarButtonItem centeredButtonItem = ...

UIBarButtonItem flexibleButtonItemRight = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];

UIToolbar toolbar = ...

toolbar.items = @[flexibleButtonItemLeft, centeredButtonItem, flexibleButtonItemRight];

Ответ 7

Наконец, для настройки настроенного фонового изображения для UIBarButtonItem и для размещения выравнивания я отказался от UIBarButtonItem и добавил UIButton вручную.

UIImage *buttonImage = [[UIImage imageNamed:@"button.png"] stretchableImageWithLeftCapWidth:10 topCapHeight:0];
UIButton *btnTest = [UIButton buttonWithType:UIButtonTypeCustom];
[btnTest setBackgroundImage:buttonImage forState:UIControlStateNormal];
[btnTest setTitle:@"Back" forState:UIControlStateNormal];   
[btnTest.titleLabel setFont:[UIFont boldSystemFontOfSize:13]];  
[btnTest setBackgroundImage:[imgToolbarButton stretchableImageWithLeftCapWidth:5 topCapHeight:0]  forState:UIControlStateNormal];
[btnTest addTarget:self action:@selector(clearDateEdit:) forControlEvents:UIControlEventTouchUpInside];
btnTest.frame = CGRectMake(0.0, 0.0, 50, 30);
[self.toolbar addSubview:btnTest];
[btnTestItem release];

Ответ 8

Я думаю, что сложный способ - использовать Аспекты (или метод swizzling), как blew:

[UINavigationBar aspect_hookSelector:@selector(layoutSubviews) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> info){
        UINavigationBar *bar = info.instance;

        //[bar layoutSubviews];

        if ([bar isKindOfClass:[UINavigationBar class]]) {
            if (@available(iOS 11, *)) {
                bar.layoutMargins = UIEdgeInsetsZero;

                for (UIView *subview in bar.subviews) {
                    if ([NSStringFromClass([subview class]) containsString:@"ContentView"]) {
                        UIEdgeInsets oEdges = subview.layoutMargins;
                        subview.layoutMargins = UIEdgeInsetsMake(0, 0, 0, oEdges.right);
                    }
                }
            }
        }
    } error:nil];