Как настроить uitoolbar левая и правая обивка


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

Из Построителя Интерфейса:

Код:

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. Любая идея, что вызывает это или решить эту проблему.

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

9 55

9 ответов:

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

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

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

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

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

до iOS 11

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

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

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

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

если вы используете swift, код будет выглядеть так

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

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

к сожалению, все решение не может быть использовано в iOS 11

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

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

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

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

Вот Так:

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

  • установить translatesAutoresizingMaskIntoConstraints как false
  • переопределить alignmentRectInsets
    • пункт в правой стороне использовать UIEdgeInsets(сверху: 0, слева: -8, снизу: 0, справа: 8)
    • пункт в левой стороне использовать UIEdgeInsets(сверху: 0, слева: 8, снизу: 0, справа: -8)

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

swift версия

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 version

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. создайте элемент с помощью пользовательской кнопки

swift версия

var item = UIBarButtonItem(customView: customButton)

objective-C version

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

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

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

swift версия

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

objective-C version

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

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

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

swift версия

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

objective-C version

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

Молодец

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

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

Примечание

перед iOS 11 вы должны заботиться о ширине экрана устройства; если экран 5,5 дюйма, отрицательный -12 pt, на других экранах-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);
}

Это отличный вопрос, и даже с предоставленными решениями-это не решило проблему на iOS11.

РАБОЧЕЕ РЕШЕНИЕ

Если вы создадите новое расширение UIButton:

class BarButton: UIButton {

    override var alignmentRectInsets: UIEdgeInsets {
        return UIEdgeInsetsMake(0, 16, 0, 16)
    }

}

затем, когда вы используете его в свой план:

lazy var btnLogin: BarButton = {
    let btn = BarButton(type: .custom)
    // Add your button settings

    btn.widthAnchor.constraint(equalToConstant: self.frame.size.width).isActive = true
    btn.heightAnchor.constraint(equalToConstant: 50).isActive = true
    btn.translatesAutoresizingMaskIntoConstraints = false
    return btn
}()

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

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

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

Я встретил тот же вопрос. Наконец, я решил это путем подкласса UIToolbar и переопределения метода вложенных представлений макета.

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

}

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

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

я наткнулся на это при попытке центрировать панель инструментов в качестве подвида 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];

наконец, для того, чтобы настроить фоновое изображение для 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];

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

[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];