Как настроить 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 ответов:
У меня была та же проблема, и есть аккуратный трюк, который вы можете сделать с 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];