Ответ 1
Нет особого способа сделать это. Лучше всего, если вы действительно должны подклассифицировать UINavigationBar и переопределить layoutSubviews
для вызова [super layoutSubviews]
, а затем найти и изменить положение кнопки.
Как я могу изменить положение UIBarButtonItem в UINavigationBar? Я бы хотел, чтобы моя кнопка была примерно на 5 пикселей выше, чем ее нормальная позиция.
Нет особого способа сделать это. Лучше всего, если вы действительно должны подклассифицировать UINavigationBar и переопределить layoutSubviews
для вызова [super layoutSubviews]
, а затем найти и изменить положение кнопки.
Этот код создает обратную кнопку для UINavigationBar с фоном изображения и пользовательской позицией. Хитрость заключается в создании промежуточного представления и изменении его границ.
UIButton *backBtn = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *backBtnImage = [UIImage imageNamed:@"btn-back"];
UIImage *backBtnImagePressed = [UIImage imageNamed:@"btn-back-pressed"];
[backBtn setBackgroundImage:backBtnImage forState:UIControlStateNormal];
[backBtn setBackgroundImage:backBtnImagePressed forState:UIControlStateHighlighted];
[backBtn addTarget:self action:@selector(goBack) forControlEvents:UIControlEventTouchUpInside];
backBtn.frame = CGRectMake(0, 0, 63, 33);
UIView *backButtonView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 63, 33)];
backButtonView.bounds = CGRectOffset(backButtonView.bounds, -14, -7);
[backButtonView addSubview:backBtn];
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithCustomView:backButtonView];
self.navigationItem.leftBarButtonItem = backButton;
Я решил использовать преобразование и пользовательский вид:
(Swift)
// create the button
let suggestImage = UIImage(named: "tab-item-popcorn-on")!.imageWithRenderingMode(.AlwaysOriginal)
let suggestButton = UIButton(frame: CGRectMake(0, 0, 40, 40))
suggestButton.setBackgroundImage(suggestImage, forState: .Normal)
suggestButton.addTarget(self, action: Selector("suggesMovie:"), forControlEvents:.TouchUpInside)
// here where the magic happens, you can shift it where you like
suggestButton.transform = CGAffineTransformMakeTranslation(10, 0)
// add the button to a container, otherwise the transform will be ignored
let suggestButtonContainer = UIView(frame: suggestButton.frame)
suggestButtonContainer.addSubview(suggestButton)
let suggestButtonItem = UIBarButtonItem(customView: suggestButtonContainer)
// add button shift to the side
navigationItem.rightBarButtonItem = suggestButtonItem
Для тех из вас, кто развивается для iOS 5, который наткнулся на это и был обескуражен... Попробуйте что-то вроде этого:
float my_offset_plus_or_minus = 3.0f;
UIBarButtonItem * item = [[UIBarButtonItem alloc] initWithTitle:@"title"
style:UIBarButtonItemStyleDone
target:someObject action:@selector(someMessage)];
[item setBackgroundVerticalPositionAdjustment:my_offset_plus_or_minus forBarMetrics:UIBarMetricsDefault];
Лучший способ заключается в подклассе вашего UINavigationBar, как описано здесь: fooobar.com/questions/64630/...
Вот мой пример:
#define NAVIGATION_BTN_MARGIN 5
@implementation NewNavigationBar
- (void)layoutSubviews {
[super layoutSubviews];
UINavigationItem *navigationItem = [self topItem];
UIView *subview = [[navigationItem rightBarButtonItem] customView];
if (subview) {
CGRect subviewFrame = subview.frame;
subviewFrame.origin.x = self.frame.size.width - subview.frame.size.width - NAVIGATION_BTN_MARGIN;
subviewFrame.origin.y = (self.frame.size.height - subview.frame.size.height) / 2;
[subview setFrame:subviewFrame];
}
subview = [[navigationItem leftBarButtonItem] customView];
if (subview) {
CGRect subviewFrame = subview.frame;
subviewFrame.origin.x = NAVIGATION_BTN_MARGIN;
subviewFrame.origin.y = (self.frame.size.height - subview.frame.size.height) / 2;
[subview setFrame:subviewFrame];
}
}
@end
Надеюсь, что это поможет.
Попробуйте код ниже,
UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithTitle:@"Logout" style:UIBarButtonItemStyleDone target:self action:nil];
[button setBackgroundVerticalPositionAdjustment:-20.0f forBarMetrics:UIBarMetricsDefault];
[[self navigationItem] setRightBarButtonItem:button];
Используется для изменения позиции "y" в этом коде. Измените значение "y" (здесь оно -20.0f) в соответствии с вашим требованием. Если значение положительное, оно будет вниз по позиции кнопки. Если значение отрицательное, оно будет содержать положение вашей кнопки.
Мне нужно было установить, чтобы моя кнопка была более направлена вправо. Вот как я это сделал, используя UIAppearance в Swift. Там есть свойство вертикальной позиции, так что, я думаю, вы можете настроить в любом направлении.
UIBarButtonItem.appearance().setTitlePositionAdjustment(UIOffset.init(horizontal: 15, vertical: 0), forBarMetrics: UIBarMetrics.Default)
Это кажется мне гораздо менее инвазивным, чем обращение к кадру напрямую или добавление пользовательских subviews.
Если вы просто используете изображение, а НЕ - хром по умолчанию, вы можете использовать скрытые вставки изображения (установленные в инспекторе размера) для перемещения изображения внутри UIBarButtonItem (удобно, потому что по умолчанию горизонтальное заполнение может привести к изображение находится дальше, чем вы хотите). Вы можете использовать вставки изображения, чтобы расположить изображение за пределами UIBarButtonItem, а также все окрестности левой кнопки можно скрыть, так что вам не нужно беспокоиться о том, чтобы он располагался рядом с нажмите цель. (по крайней мере, в пределах разумного.)
Лучшее решение, которое я смог найти, - инициализировать UIBarButtonItem с помощью подсмотра, который включает дополнительное пространство влево/вправо. Таким образом, вам не придется беспокоиться о подклассификации и изменении макета других элементов внутри панели навигации, таких как заголовок.
Например, чтобы переместить кнопку 14 точек влево:
UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, image.size.width + 14, image.size.height)];
UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(-14, 0, image.size.width, image.size.height);
[button setImage:image forState:UIControlStateNormal];
[button addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
[containerView addSubview:button];
UIButton* button2 = [UIButton buttonWithType:UIButtonTypeCustom];
button2.frame = CGRectMake(0, 0, image.size.width + 14, image.size.height);
[button2 addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
[containerView addSubview:button2];
UIBarButtonItem* item = [[[self alloc] initWithCustomView:containerView] autorelease];
Шаг 1: Задайте позицию заголовка, используя API-интерфейс Appearance. Например, в AppDelegate didFinishLaunchingWithOptions
UINavigationBar.appearance().setTitleVerticalPositionAdjustment(-7, for: .default)
Шаг 2: Подкласс UINavigationBar
class YourNavigationBar: UINavigationBar {
let YOUR_NAV_BAR_HEIGHT = 60
override func sizeThatFits(_ size: CGSize) -> CGSize {
return CGSize(width: UIScreen.main.bounds.width,
height: YOUR_NAV_BAR_HEIGHT)
}
override func layoutSubviews() {
super.layoutSubviews()
let navigationItem = self.topItem
for subview in subviews {
if subview == navigationItem?.leftBarButtonItem?.customView ||
subview == navigationItem?.rightBarButtonItem?.customView {
subview.center = CGPoint(x: subview.center.x, y: YOUR_NAV_BAR_HEIGHT / 2)
}
}
}
}
Как сказал @Anomie, нам нужно подкласс UINavigationBar
, и переопределить layoutSubviews()
.
Это приведет к тому, что все элементы правой кнопки панели будут крепко прикреплены к правой стороне навигационной панели (в отличие от регулировки по умолчанию слева):
class AdjustedNavigationBar: UINavigationBar {
override func layoutSubviews() {
super.layoutSubviews()
if let rightItems = topItem?.rightBarButtonItems where rightItems.count > 1 {
for i in 0..<rightItems.count {
let barButtonItem = rightItems[i]
if let customView = barButtonItem.customView {
let frame = customView.frame
customView.frame = CGRect(x: UIApplication.sharedApplication().windows.last!.bounds.size.width-CGFloat(i+1)*44, y: frame.origin.y, width: frame.size.width, height: frame.size.height)
}
}
}
}
}
Единственное место, где можно установить свойство UINavigationBar UINavigationController, находится в его init(), например:
let controllerVC = UINavigationController(navigationBarClass: AdjustedNavigationBar.self, toolbarClass: nil)
controllerVC.viewControllers = [UIViewController()]
Вторая строка устанавливает контроллер корневого представления для UINavigationController.
(Поскольку мы не можем установить его через init(rootViewController:)
Swift 3.1
let cancelBarButtonItem = UIBarButtonItem()
cancelBarButtonItem.setBackgroundVerticalPositionAdjustment(4, for: .default)
vc.navigationItem.setLeftBarButton(cancelBarButtonItem, animated: true)
Здесь решение Adriano с использованием Swift 3. Это было единственное решение, которое сработало для меня, и я попробовал несколько.
let suggestImage = UIImage(named: "menu.png")!
let suggestButton = UIButton(frame: CGRect(x:0, y:0, width:34, height:20))
suggestButton.setBackgroundImage(suggestImage, for: .normal)
suggestButton.addTarget(self, action: #selector(self.showPopover(sender:)), for:.touchUpInside)
suggestButton.transform = CGAffineTransform(translationX: 0, y: -8)
// add the button to a container, otherwise the transform will be ignored
let suggestButtonContainer = UIView(frame: suggestButton.frame)
suggestButtonContainer.addSubview(suggestButton)
let suggestButtonItem = UIBarButtonItem(customView: suggestButtonContainer)
// add button shift to the side
navigationItem.leftBarButtonItem = suggestButtonItem
В моем случае
изменить рамку barbuttonItem для настройки пробелов
Добавить, удалить barButtonItems динамически.
изменить оттенок цвета в табличном представлении contentOffset.y
Если ваша минимальная цель - iOS 11, вы можете изменить кадры barButton в viewDidLayoutSubviews
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// Change the navigationBar item frames
if let customView = wishButton.customView?.superview {
customView.transform = CGAffineTransform(translationX: 7.0, y: 0)
}
if let customView = gourmetCountButton.customView?.superview {
customView.transform = CGAffineTransform(translationX: 9.0, y: 0)
}
}
Но это работает только на iOS 11.
Я также попытался использовать fixedSpace. Но он не работал в нескольких элементах навигационного бара.
let space = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
space.width = -10
Итак, я изменил ширину customView, чтобы настроить горизонтальное пространство.
Это один из моих классов barButtonItem
final class DetailShareBarButtonItem: UIBarButtonItem {
// MARK: - Value
// MARK: Public
***// Change the width to adjust space***
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 32.0, height: 30.0))
override var tintColor: UIColor? {
didSet {
button.tintColor = tintColor
}
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setButton()
}
required override init() {
super.init()
setButton()
}
// MARK: - Function
// MARK: Private
private func setButton() {
// Button
button.setImage( #imageLiteral(resourceName: "navibarIcShare02White").withRenderingMode(.alwaysTemplate), for: .normal)
button.tintColor = .white
button.imageEdgeInsets = UIEdgeInsetsMake(0, 1.0, 1.0, 0)
button.imageView?.contentMode = .scaleAspectFill
let containerView = UIView(frame: button.bounds)
containerView.backgroundColor = .clear
containerView.addSubview(button)
customView = containerView
}
}
Это результат.
Я тестировал на iOS 9 ~ 11, (Swift 4)
Init UIBarButtonItem
с пользовательским представлением и перегрузкой layoutSubviews
в пользовательском представлении, например
-(void) layoutSubviews {
[super layoutSubviews];
CGRect frame = self.frame;
CGFloat offsetY = 5;
frame.origin.y = (44 - frame.size.height) / 2 - offsetY;
self.frame = frame;
}
Вы всегда можете выполнять настройки с помощью вставки на кнопке. Например,
UIButton *toggleBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[toggleBtn setFrame:CGRectMake(0, 0, 20, 20)];
[toggleBtn addTarget:self action:@selector(toggleView) forControlEvents:UIControlEventTouchUpInside];
[toggleBtn setImageEdgeInsets:((IS_IPAD)? UIEdgeInsetsMake(0,-18, 0, 6) : UIEdgeInsetsMake(0, -3, 0, -3))];
UIBarButtonItem *toggleBtnItem = [[UIBarButtonItem alloc] initWithCustomView: toggleBtn];
self.navigationItem.rightBarButtonItems = [NSArray arrayWithObjects:searchBtnItem, toggleBtnItem, nil];
Это работает для меня.
Вот простой способ, который был достаточным для моих нужд. Я добавил информационную кнопку с правой стороны UINavigationBar, но по умолчанию она слишком близко подходит к краю. Расширив ширину рамки, я смог создать дополнительный интервал, необходимый справа.
UIButton *info = [UIButton buttonWithType:UIButtonTypeInfoLight];
CGRect frame = info.frame;
frame.size.width += 20;
info.frame = frame;
myNavigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc]initWithCustomView:info]autorelease];
Я нашел решение этой проблемы, выполнив настройку в вкладках Image Edge в пользовательской кнопке. У меня было требование в приложении увеличить высоту панели навигации, и после увеличения высоты делает проблему RightBarButtonItem и leftBarButtonItem нерегулярной.
Найдите код ниже: -
UIImage *image = [[UIImage imageNamed:@"searchbar.png"];
UIButton* searchbutton = [UIButton buttonWithType:UIButtonTypeCustom];
[searchbutton addTarget:self action:@selector(searchBar:) forControlEvents:UIControlEventTouchUpInside];
searchbutton.frame = CGRectMake(0,0,22, 22);
[searchbutton setImage:image forState:UIControlStateNormal];
[searchbutton setImageEdgeInsets:UIEdgeInsetsMake(-50, 0,50, 0)];
// Make BarButton Item
UIBarButtonItem *navItem = [[UIBarButtonItem alloc] initWithCustomView:searchbutton];
self.navigationItem.rightBarButtonItem = navItem;
Надеюсь, это поможет кому угодно.
Аффинное преобразование может делать то, что вам нужно. В моем случае дизайнер дал мне иконку закрытия 16x16, и я хочу создать область нажатия 44x44.
closeButton.transform = CGAffineTransform(translationX: (44-16)/2, y: 0)
closeButton.snp.makeConstraints { make in
make.size.equalTo(CGSize(width: 44, height: 44))
}
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: closeButton)
Панель навигации с помощью изменения положения левой панели и вставок по краям изображения
Свифт 4
let leftBarButtonItem = UIBarButtonItem.init(image: UIImage(named:"ic_nav-bar_back.png"), landscapeImagePhone: nil, style: .plain, target: viewController, action: #selector(viewController.buttonClick(_:)))
leftBarButtonItem.imageInsets = UIEdgeInsets(top: 0, left: -15, bottom: 0, right: 0)
leftBarButtonItem.tintColor = UIColor(hex: 0xED6E19)
viewController.navigationItem.setLeftBarButton(leftBarButtonItem, animated: true)