How do I connect my scrollView with my PageController? (Swift) - swift

Okay So I'm having real trouble trying to get my pageControl to cooperate with my scroll. I tried different functions but I can seem to get it right. I'm able to call the right amount of views such as the white dots match the number of pictures I have but the dots don't move when I scroll from one picture to the other. How would you connect my pageControl to my scroll so when I scroll left and right it will respond the the pageControl?
// Number of views
var numberOfViews = picSource.count
var picNum:CGFloat = CGFloat(picSource.count)
// Image Scroller
let scroll = UIScrollView(frame:CGRectMake(-5, 650, screenWidth, 260))
scroll.pagingEnabled = true
scroll.showsHorizontalScrollIndicator = false
scroll.showsVerticalScrollIndicator = false
scroll.contentSize = CGSizeMake(picNum*screenWidth, 220)
scroll.delegate = self
let pageControl = UIPageControl(frame: CGRectMake(0, 600, 100, 25))
pageControl.numberOfPages = numberOfViews
pageControl.currentPage = 0
pageControl.addTarget(self, action: "pageControlSwipe:", forControlEvents: UIControlEvents.ValueChanged)
pageControl.backgroundColor = UIColor.redColor()
pageControl.userInteractionEnabled = true
self.view.bringSubviewToFront(pageControl)
border.addSubview(pageControl)
// pageControl swipe
func pageControlSwipe(sender: AnyObject) -> () {
let x = CGFloat(pageControl.currentPage) * scroll.frame.size.width
scroll.setContentOffset(CGPointMake(x, 0), animated: true)
}
func scrollViewDidEndDecelerating(scroll: UIScrollView) -> () {
let pageNumber = round(scroll.contentOffset.x / (scroll.frame.size.width))
pageControl.currentPage = Int(pageNumber)
}

To Connnect ScrolView With PageController See the link... link here
in this have Main ScrollView -> PageController -> SubScrollView -> UIImageView -> UIImage

Related

Make page control work only for 1 collection view(multiple collectionViews in View Controller)

I have 3-4 collectionViews in a page and one of them has page control which is working as expected. The problem is its also working when I scroll through cells of other collection views. So the dots will move regardless of whichever collectionView I'm scrolling through while it should only move for 1st collectionView. Here is how I'm enabling paging for 1 collectionView which is probably applying for every collection view:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
//Collection View Delegates & Datasource
let flowLayout = UICollectionViewFlowLayout()
flowLayout.itemSize = CGSize(width: UIScreen.main.bounds.size.width, height: cvGarages.frame.size.height)
flowLayout.scrollDirection = .horizontal
flowLayout.minimumLineSpacing = 0
collectionView1.collectionViewLayout = flowLayout
collectionView1.isPagingEnabled = true
collectionView1.showsHorizontalScrollIndicator = false
collectionView1.delegate = self
collectionView1.dataSource = self
let flowLayout2 = UICollectionViewFlowLayout()
flowLayout2.itemSize = CGSize(width: 171, height: 232)
flowLayout2.scrollDirection = .horizontal
flowLayout2.minimumLineSpacing = 0
flowLayout2.minimumInteritemSpacing = 0
collectionView2.collectionViewLayout = flowLayout2
collectionView2.contentInset = UIEdgeInsets(top: 0, left: 7, bottom: 0, right: 0)
collectionView2.delegate = self
collectionView2.dataSource = self
//Page Control
pageControl.numberOfPages = 4
}
//ScrollView delegate method
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let pageWidth = scrollView.frame.width
self.currentPage = Int((scrollView.contentOffset.x + pageWidth / 2) / pageWidth)
self.pageControl.currentPage = self.currentPage
}
In scrollViewDidScroll() method check if scrollView is equal to (===) the specific collectionView. === operator will check the reference point of same instance.
public func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView === self.collectionView1 {
let pageWidth = scrollView.frame.width
self.currentPage = Int((scrollView.contentOffset.x + pageWidth / 2) / pageWidth)
self.pageControl.currentPage = self.currentPage
}
}

How to make Height and Width of ScrollView Still The same Before ZoomIn on UIImage?

Hello All iOS developer I'm new at iOS development. at the moment I work In the case I want to Zoom Picture, I use UIImageView in UIScrollView. Everything is Ok on ScrollView Height and Width but when I try to ZoomIn and ZoomOut to make to current Size of Image the UIScrollView has Increase the Height and Width. and I try to find out the solution but it's work.I need some help.thank you in advance.
This's The Problem
Here is my code
override func viewDidLoad() {
super.viewDidLoad()
initializeLanguages()
checkForm()
scrollView.showsVerticalScrollIndicator = false
scrollView.showsHorizontalScrollIndicator = false
scrollView.bounces = false
scrollView.delegate = self
lblRetake.textColor = TrueColor.trueColorbrand()
updateZoom()
scrollView.layer.cornerRadius = 10
scrollView.layer.masksToBounds = true
setShadowView(view: viewContainer)
imageView.isUserInteractionEnabled = true
addViewGesture()
displayImage()
}
//MARK: ZoomOut/ZoomIn Image
func updateZoom() {
let fwidth = self.imageView.image?.size.width ?? 0
let fheight = self.imageView.image?.size.height ?? 0
var minZoom = min(fwidth, fheight);
if (minZoom > 1) {
minZoom = 1;
}
self.scrollView.minimumZoomScale = minZoom;
self.scrollView.zoomScale = minZoom;
scrollView.maximumZoomScale = 10.0
}

How to commence the dragging of a UIImage using UIDraginInteraction?

I am trying to drag an UIImage using UIDragInteraction. I am trying to implement the procedure as documented in Apple's documentation. My code is below. I am trying to perform the drag feature but currently my image is not moving even when i hold the left mouse button on the image and try to drag it (I have yet to implement the Drop implementation as i am trying to do this one step at a time). I am executing the code on a simulator.
my code:
class StartGameViewController: UIViewController{
var dragInteraction: UIDragInteraction!
var dragInteractionDelegate: UIDragInteractionDelegate!
var dragSourceImgView: UIImageView = {
let imgView = UIImageView()
imgView.backgroundColor = UIColor.red.withAlphaComponent(0.5)
imgView.contentMode = UIImageView.ContentMode.scaleToFill
return imgView
}()
var dropImgSourceView: UIImageView = {
let imgView = UIImageView()
imgView.contentMode = UIImageView.ContentMode.scaleAspectFit
imgView.backgroundColor = UIColor.blue.withAlphaComponent(0.5)
return imgView
}()
override func viewDidLoad() {
super.viewDidLoad()
dragSourceImgView.image = UIImage.init(named: "rider")
let frame = CGRect.init(x: 50, y: 50, width: 100, height: 100)
dragSourceImgView.frame = frame
container1.addSubview(dragSourceImgView)
let frameDrop = CGRect.init(x: 200, y: 50, width: 100, height: 100)
dropImgSourceView.frame = frameDrop
container1.addSubview(dropImgSourceView)
// Enable imageView as a drag source
dragInteraction = UIDragInteraction.init(delegate: self)
dragSourceImgView.addInteraction(dragInteraction)
}
}
// DRAG
extension StartGameViewController: UIDragInteractionDelegate{
// Create a Drag Item
func dragInteraction(_ interaction: UIDragInteraction, itemsForBeginning session: UIDragSession) -> [UIDragItem] {
guard let image = dragSourceImgView.image else{return []}
let itemProvider = NSItemProvider.init(object: image)
let dragItem = UIDragItem.init(itemProvider: itemProvider)
return [dragItem]
}
}
You should set your UIImageView to allow user interaction:
dragSourceImageView.userInteractionEnabled = true
If you are running on an iPhone you must also set the UIDragInteraction to be enabled:
dragInteraction.isEnabled = true

Add annotation to resizable image within scrollview

I have a Scroll View in which I load an Image that can be zoomed and where I can "navigate".
I'm trying to add buttons programmatically to the view such as MKAnnotation that are used in MapKit.
Is that possible?
The methods I use are scrollViewDidZoom
func scrollViewDidZoom(scrollView: UIScrollView) {
centerScrollViewContents()
}
where the function centerScrollViewContents is
func centerScrollViewContents() {
let boundsSize = scrollView.bounds.size
var contentFrame = imageView.frame
if contentFrame.size.width < boundsSize.width {
contentFrame.origin.x = (boundsSize.width - contentFrame.size.width) / 2
} else { contentFrame.origin.x = 0 }
if contentFrame.size.height < boundsSize.height {
contentFrame.origin.y = (boundsSize.height - contentFrame.size.height) / 2
} else { contentFrame.origin.y = 0 }
imageView.frame = contentFrame
}
I add the button/annotation with a UITapGestureRecognizer implemented as
let posTocco = sender.locationInView(scrollView)
println("\(posTocco), \(scrollView.zoomScale)")
var button = UIButton()
let image = UIImage(named: "arrow.png") as UIImage?
button.frame = CGRectMake(posTocco.x, posTocco.y, 30, 30)
button.setImage(image, forState: .Normal)
scrollView.addSubview(button)
For sure I need to define the button/annotation outside the tapGesture function but I cannot figure out how to move the button within the image zoom.
Any help?
EDIT:
I partially figured out how to solve this, but the button slightly move at the first zoom in/out.
I create a new variable which stores the latest zoomValue fattoreScalaCorrente and in the scrollViewDidZoom(scrollView:) I do the magic
var newLoc = CGPoint(x: posAssolute.x * scrollView.zoomScale, y: posAssolute.y * scrollView.zoomScale)
button.frame = CGRectMake(newLoc.x, newLoc.y, button.frame.width, button.frame.height)
Do you have any idea why my button is moving slightly at the first zoom?
EDIT2:
After the suggestion given using
button.frame = CGRectMake(newLoc.x - button.frame.width/2, newLoc.y - button.frame.height/2, button.frame.width, button.frame.height)
The button seems to move a little and I cannot understand why.
Try to replace
button.frame = CGRectMake(newLoc.x, newLoc.y, button.frame.width, button.frame.height)
with
button.frame = CGRectMake(newLoc.x - button.frame.width/2, newLoc.y - button.frame.height/2, button.frame.width, button.frame.height)

How to adjust space between two UIBarButtonItem in rightBarButtonItems

I am using the following codes to add two button to self.navigationItem.rightBarButtonItems, and I think in iOS7, the space between two buttons are too wide, is there a way to decrease the space between these two buttons?
UIBarButtonItem *saveStyleButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"save.png"] style:UIBarButtonItemStyleBordered target:self action:#selector(saveStyle)];
UIBarButtonItem *shareStyleButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:#selector(shareStyle)];
NSArray *arr= [[NSArray alloc] initWithObjects:shareStyleButton,saveStyleButton,nil];
self.navigationItem.rightBarButtonItems=arr;
Appreciate any hint or idea.
Updated at Jul 2015
A better way to do this is to use storyboard (tested in Xcode 6.4). First, add a UINavigationItem; secondly, add a Bar Button Item; thirdly, add a view to the Bar Button Item you just created in step 2; fourthly, add as many buttons as you wish into that view you just dragged in; lastly, adjust the space with your mouse and constraints.
Related Questions
Can't assign multiple Buttons to UINavigationItem when using Storyboard with iOS 5
How to add buttons to navigation controller visible after segueing?
Old Answer (Only acceptable for small insets)
Use imageInsets property:
leftButton.imageInsets = UIEdgeInsetsMake(0.0, 0.0, 0, -15);
rightButton.imageInsets = UIEdgeInsetsMake(0.0, -15, 0, 0);
for three or more buttons, the middle one(s) get both insets:
leftButton.imageInsets = UIEdgeInsetsMake(0.0, 0.0, 0, -15);
middleButton.imageInsets = UIEdgeInsetsMake(0.0, -15, 0, -15);
rightButton.imageInsets = UIEdgeInsetsMake(0.0, -15, 0, 0);
For the right side buttons, be careful: the FIRST button in the item array is the RIGHT one:
rightButton.imageInsets = UIEdgeInsetsMake(0.0, -15, 0, 0);
middleButton.imageInsets = UIEdgeInsetsMake(0.0, -15, 0, -15);
leftButton.imageInsets = UIEdgeInsetsMake(0.0, 0.0, 0, -15);
IMPORTANT: Split the inset between the two neighbors; if apply the entire inset to one edge, it will become obvious that the buttons are overlapping in the "blank" space - one button gets all of the "gap" touches. Even when "split" the adjustment like this, at -40 on both edges, the tap will definitely go to wrong button sometimes. -15 or -20 is the most to consider using with this technique.
By applying this method, the button could even be moved around in four directions.
My solution is using a custom view for right bar buttons.
Create a horizontal stackview with equal spacing and add any number of buttons as subview.
Sample code:
func addRightBarButtonItems()
{
let btnSearch = UIButton.init(type: .custom)
btnSearch.setImage(UIImage(systemName: "magnifyingglass"), for: .normal)
btnSearch.addTarget(self, action: #selector(MyPageContainerViewController.searchButtonPressed), for: .touchUpInside)
let btnEdit = UIButton.init(type: .custom)
btnEdit.setImage(UIImage(systemName: "pencil"), for: .normal)
btnEdit.addTarget(self, action: #selector(MyPageContainerViewController.editButtonPressed), for: .touchUpInside)
let stackview = UIStackView.init(arrangedSubviews: [btnEdit, btnSearch])
stackview.distribution = .equalSpacing
stackview.axis = .horizontal
stackview.alignment = .center
stackview.spacing = 8
let rightBarButton = UIBarButtonItem(customView: stackview)
self.navigationItem.rightBarButtonItem = rightBarButton
}
Swift 5
In your AppDelegate add this code:
let stackViewAppearance = UIStackView.appearance(whenContainedInInstancesOf: [UINavigationBar.self])
stackViewAppearance.spacing = -10
This will work with no additional code in more recent SDK versions as UIBarButtonItems are already contained in a horizontal UIStackView
First:
For UIBarButtonItem you must use constructor init(customView: UIView)
Second:
Use fixedSpace for set space between buttons
example:
let firstButton = UIButton()
let firstButtonItem = UIBarButtonItem(customView: firstButton)
let secondButton = UIButton()
let secondButtonItem = UIBarButtonItem(customView: secondButton)
let space = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)
space.width = WIDTH
self.navigationItem.rightBarButtonItems = [firstButtonItem, space, secondButtonItem]
One line of code is all you need to decrease the space between buttons in the navigation bar:
UIStackView.appearance(whenContainedInInstancesOf: [UINavigationBar.self]).spacing = -10
You must place this line in your code before you add the buttons to the navigation bar.
If you are looking to have 2 buttons on the top right with no space in between them or on the right, this has worked for me.
let imgLeft = UIImage(named: "buttonLeft")?.imageWithRenderingMode(.AlwaysOriginal)
let bLeft = UIBarButtonItem(image: imgLeft, style: UIBarButtonItemStyle.Done, target: self, action: "action1:")
let space = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FixedSpace, target: nil, action: nil)
space.width = -16.0
bLeft.imageInsets = UIEdgeInsetsMake(0, 0, 0, -25.0)
let imgRight = UIImage(named: "buttonRight")?.imageWithRenderingMode(.AlwaysOriginal)
let bRight = UIBarButtonItem(image: imgRight, style: UIBarButtonItemStyle.Done, target: self, action: "action2:")
bRight.imageInsets = UIEdgeInsetsMake(0, -25, 0, 0)
self.navigationItem.rightBarButtonItems = [space,bLeft,bRight ]
My situation was about giving horizontal space to logOut Button to the right edge.
func addLogOutButtonToNavigationBar(triggerToMethodName: String)
{
let button: UIButton = UIButton()
button.setImage(UIImage(named: "logOff.png"), forState: .Normal)
button.frame = CGRectMake(20, 0, 30, 25)
button.contentEdgeInsets = UIEdgeInsets.init(top: 0, left: 10, bottom: 0, right: -10)
button .addTarget(self, action:Selector(triggerToMethodName), forControlEvents: UIControlEvents.TouchUpInside)
let rightItem:UIBarButtonItem = UIBarButtonItem()
rightItem.customView = button
self.navigationItem.rightBarButtonItem = rightItem
}
Might be a bit late for this answer however this can help the newest IOS+Swift combination (IOS 10 and Swift 3 in my case). Here I describe a general approach for how to move items right/left for rightBarButtonItems/leftBarButtonItems:
The property you we have use here to move a barButtonItem is "imageEdgeInsets" . So, Here how to use this property -
yourBarButtonItem.imageEdgeInsets = UIEdgeInsetsMake(top, left, bottom, right)
These top, left, bottom, right are of type CGFloat and these are basically margin value that pushes your item from/to each other.
For decreasing a space, we can just use minus (-) values like this " -10 ".
So, for example if we want to use this for a group of leftBatButtonItems and say, if we want to move a item to the a bit right, then we can do this -
ourBarButtonItem.imageEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, 0.0, -15)
I hope we get the general idea here and hope it helps :)
Without any code. I just put another UIBarButtonItem in-between the buttons that need spacing in storyboard. The button is just a placeholder for spacing and the UIBarButton should have UIView as subview of the UIBarButtonItem. adjust the view's width for your spacing. See Screen shots.
Create a UIBarButtonItem with type flexible or fixed space. Set the width and add it to the array of barbuttonitems. Try using a negative width, see if that works.
Or, you could maybe adjust your image. The system buttons i think have a fixed size, and might include some transparent part, so even when packed together the still seem spaced.
Swift 5
If you want to add space between two Bar Button items then add a flexible space in between, the two buttons will be pushed to the left and right edge as the flexible space expands to take up most of the toolbar.
For Example:
let toolBar = UIToolbar()
var items = [UIBarButtonItem]()
let backBarButton = UIBarButtonItem(image: UIImage(named: "icon-back.png"), style: .done, target: self, action: #selector(backButtonTapped))
let nextBarButton = UIBarButtonItem(image: UIImage(named: "icon-next.png"), style: .done, target: self, action: #selector(nextButtonTapped))
let spacer = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
items.append(backBarButton)
items.append(spacer)
items.append(nextBarButton)
toolBar.setItems(items, animated: true)
To accomplish this in code without adding an extra container view, use a UIBarButtonItem with the system item type set to FixedSpace. Then set the width of the fixed space to -10 and place it between the two buttons.
another answer :
It works in ios 9 - 12.
You should call fixNavigationItemsMargin(margin:) in function viewDidAppear(_ animated: Bool) and viewDidLayoutSubviews().
fixNavigationItemsMargin(margin:) would modify the UINavigationController stack.
you could call fixNavigationItemsMargin(margin:) in BaseNavigationController ,do the common work. And call fixNavigationItemsMargin(margin:) in UIViewController do precise layout.
// do common initilizer
class BaseNavigationController: UINavigationController {
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
fixNavigationItemsMargin()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
fixNavigationItemsMargin()
}
}
extension UINavigationController {
func fixNavigationItemsMargin(_ margin: CGFloat = 8) {
let systemMajorVersion = ProcessInfo.processInfo.operatingSystemVersion.majorVersion
if systemMajorVersion >= 11 {
// iOS >= 11
guard let contentView = navigationBar.subviews
.first(
where: { sub in
String(describing: sub).contains("ContentView")
}) else { return }
// refer to: https://www.matrixprojects.net/p/uibarbuttonitem-ios11/
// if rightBarButtonItems has not any custom views, then margin would be 8(320|375)/12(414)
// should use customView
let needAdjustRightItems: Bool
if let currentVC = viewControllers.last,
let rightItems = currentVC.navigationItem.rightBarButtonItems,
rightItems.count > 0,
rightItems.filter({ $0.customView != nil }).count > 0 {
needAdjustRightItems = true
} else {
print("Use 8(320|375)/12(414), if need precious margin ,use UIBarButtonItem(customView:)!!!")
needAdjustRightItems = false
}
let needAdjustLeftItems: Bool
if let currentVC = viewControllers.last,
let leftItems = currentVC.navigationItem.leftBarButtonItems,
leftItems.count > 0,
leftItems.filter({ $0.customView != nil }).count > 0 {
needAdjustLeftItems = true
} else {
print("Use 8(320|375)/12(414), if need precious margin ,use UIBarButtonItem(customView:)!!!")
needAdjustLeftItems = false
}
let layoutMargins: UIEdgeInsets
if #available(iOS 11.0, *) {
let directionInsets = contentView.directionalLayoutMargins
layoutMargins = UIEdgeInsets(
top: directionInsets.top,
left: directionInsets.leading,
bottom: directionInsets.bottom,
right: directionInsets.trailing)
} else {
layoutMargins = contentView.layoutMargins
}
contentView.constraints.forEach(
{ cst in
// iOS 11 the distance between rightest item and NavigationBar should be margin
// rightStackView trailing space is -margin / 2
// rightestItem trailing to rightStackView trailing is -margin / 2
let rightConstant = -margin / 2
switch (cst.firstAttribute, cst.secondAttribute) {
case (.leading, .leading), (.trailing, .trailing):
if let stackView = cst.firstItem as? UIStackView,
stackView.frame.minX < navigationBar.frame.midX {
// is leftItems
if needAdjustLeftItems {
cst.constant = margin - layoutMargins.left
}
} else if let layoutGuide = cst.firstItem as? UILayoutGuide,
layoutGuide.layoutFrame.minX < navigationBar.frame.midX {
// is leftItems
if needAdjustLeftItems {
cst.constant = margin - layoutMargins.left
}
}
if let stackView = cst.firstItem as? UIStackView,
stackView.frame.maxX > navigationBar.frame.midX {
// is rightItems
if needAdjustRightItems {
cst.constant = rightConstant
}
} else if let layoutGuide = cst.firstItem as? UILayoutGuide,
layoutGuide.layoutFrame.maxX > navigationBar.frame.midX {
// is rightItems
if needAdjustRightItems {
cst.constant = rightConstant
}
}
default: break
}
})
// ensure items space == 8, minispcae
contentView.subviews.forEach(
{ subsub in
guard subsub is UIStackView else { return }
subsub.constraints.forEach(
{ cst in
guard cst.firstAttribute == .width
|| cst.secondAttribute == .width
else { return }
cst.constant = 0
})
})
} else {
// iOS < 11
let versionItemsCount: Int
if systemMajorVersion == 10 {
// iOS 10 navigationItem.rightBarButtonItems == 0
// space = 16(320|375) / 20(414)
// should adjust margin
versionItemsCount = 0
} else {
// iOS 9 navigationItem.rightBarButtonItems == 0
// space = 8(320|375) / 12(414)
// should not adjust margin
versionItemsCount = 1
}
let spaceProducer = { () -> UIBarButtonItem in
let spaceItem = UIBarButtonItem(
barButtonSystemItem: .fixedSpace,
target: nil,
action: nil)
spaceItem.width = margin - 16
return spaceItem
}
if let currentVC = viewControllers.last,
var rightItems = currentVC.navigationItem.rightBarButtonItems,
rightItems.count > versionItemsCount,
let first = rightItems.first {
// ensure the first BarButtonItem is NOT fixedSpace
if first.title == nil && first.image == nil && first.customView == nil {
print("rightBarButtonItems SPACE SETTED!!! SPACE: ", abs(first.width))
} else {
rightItems.insert(spaceProducer(), at: 0)
// arranged right -> left
currentVC.navigationItem.rightBarButtonItems = rightItems
}
}
if let currentVC = viewControllers.last,
var leftItems = currentVC.navigationItem.leftBarButtonItems,
leftItems.count > versionItemsCount,
let first = leftItems.first {
if first.title == nil && first.image == nil && first.customView == nil {
print("leftBarButtonItems SPACE SETTED!!! SPACE: ", abs(first.width))
} else {
leftItems.insert(spaceProducer(), at: 0)
// arranged left -> right
currentVC.navigationItem.leftBarButtonItems = leftItems
}
}
}
}
}
// do precise layout
class ViewController: UIViewController {
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
navigationController?.fixNavigationItemsMargin(40)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
navigationController?.fixNavigationItemsMargin(40)
}
Found a crazy idea that works.
func createCustomToolbar(items: [UIBarButtonItem]) -> UIToolbar
{
// no spacing between bar buttons
let customToolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: items.count*45, height: 44))
customToolbar.items = items
customToolbar.barStyle = UIBarStyle(rawValue: -1)!
customToolbar.clearsContextBeforeDrawing = false
customToolbar.backgroundColor = UIColor.clearColor()
customToolbar.tintColor = UIColor.clearColor()
customToolbar.translucent = true
return customToolbar
}
let customToolbar = createCustomToolbar([item0,item1,item2,item3])
navigationItem.rightBarButtonItems = [UIBarButtonItem(customView: customToolbar)]
Tested on iOS7 and upper. Even this is written in swift the concept is clear.
I gave up with fighting this bug, and came up with the following extension:
import UIKit
extension UIBarButtonItem {
convenience init(buttonImage: UIImage?, target: Any?, action: Selector?) {
let button = UIButton(type: .system)
button.frame = CGRect(origin: CGPoint.zero, size: buttonImage != nil ? buttonImage!.size : CGSize.zero)
button.setImage(buttonImage, for: .normal)
if let action = action {
button.addTarget(target, action: action, for: .touchUpInside)
}
self.init(customView: button)
}
public func updateButton(image: UIImage?) {
if let button = self.customView as? UIButton {
button.setImage(image, for: .normal)
let size = image != nil ? image!.size : CGSize.zero
let frame = button.frame
button.frame = frame.insetBy(dx: ceil((frame.size.width - size.width) / 2), dy: ceil((frame.size.height - size.height) / 2))
}
}
}