Как настроить 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. Любая идея, что вызывает это или разрешает это.
Единственное решение, о котором я могу сейчас подумать, - это вручную установить фрейм.
Ответы
Ответ 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];