Distance between screen border and bar button item - ios

Is there a way to get the the distance between the outer screen border and the bar button item. I was thinking of something similar like how to get the status bar height?
(I am asking this, because it is different depending on the device.)
This is some trial code:
let navigationBar = UINavigationBar(frame: CGRectMake(0, 0, view.frame.size.width, 64))
let navigationBar.backgroundColor = UIColor.redColor()
let barButtonItem = UIBarButtonItem(barButtonSystemItem: .Camera, target: self, action: nil)
navigationItem.leftBarButtonItem = barButtonItem
navigationBar.items = [navigationItem]
let buttonItemView = barButtonItem.valueForKey("view") as! UIView
let frame = buttonItemView.superview!.convertRect(buttonItemView.frame, toView: UIApplication.sharedApplication().keyWindow?.rootViewController?.view)
let xCoordinateMin = CGRectGetMinX(frame)
let yCoordinateMax = CGRectGetMaxY(frame)
let yCoordinateMin = CGRectGetMinY(frame)
let label = UILabel(frame: CGRectMake(CGFloat(xCoordinateMin), CGFloat(yCoordinateMin), 100, yCoordinateMax - yCoordinateMin))
label.backgroundColor = UIColor.greenColor()
But it still gives me 0 as xMin, although it seems to work with the y-coordinate..

By outer screen, I assume you are talking about the main window.
You can try converting the bar button's frame into window's coordinate in order to find the distance to each direction:
let buttonItemView = barButtonItem.valueForKey("view") as! UIView
let frame = buttonItemView.superview!.convertRect(buttonItemView.frame, toView: nil)
print("Distance to left: ", CGRectGetMinX(frame))
print("Distance to top: ", CGRectGetMinY(frame))
However, main window receives rotation events and passes them onto controllers which means it doesn't change its frame size so the above solution will not work properly for landscape mode.
You can try converting button's rect to the root view controller's coordinate system, but now you have to take the status bar height into consideration:
let frame = buttonItemView.superview!.convertRect(buttonItemView.frame, toView: UIApplication.sharedApplication().keyWindow?.rootViewController?.view)

Solved with this code:
let navigationBar = UINavigationBar(frame: CGRectMake(0, 0, view.frame.size.width, 124))
navigationBar.backgroundColor = UIColor.redColor()
let barButtonItem = UIBarButtonItem(barButtonSystemItem: .Camera, target: self, action: nil)
navigationItem.leftBarButtonItem = barButtonItem
navigationBar.items = [navigationItem]
let buttonItemView = barButtonItem.valueForKey("view") as! UIView
let frame = buttonItemView.superview!.convertRect(buttonItemView.frame, toView: nil)
let xCoordinateMin: CGFloat = CGRectGetMinX(frame)
let xCoordinateMax: CGFloat = CGRectGetMaxX(frame)
let yCoordinateMax: CGFloat = CGRectGetMaxY(frame)
let yCoordinateMin = CGRectGetMinY(frame)
let label = UILabel(frame: CGRectMake(abs(xCoordinateMin), yCoordinateMin, xCoordinateMax - xCoordinateMin, yCoordinateMax - yCoordinateMin))
label.backgroundColor = UIColor.greenColor()
The trick was to declare the let xCoordinateMin as CGFloat because then it was considered as negative value. Then when creating the label just use abs() to get the absolute value. You now have a label that is absolutely the same size as your bar button item!

UIApplication.sharedApplication().statusBarFrame.height

Related

Give inset to UIImageView before setting Its frame

I have an UITextField component which has an icon on the right side of it. Icon is just an UIImageView. I'm trying to give inset to UIImageView with below code
imageView.image = UIImage(named: "example")?.withAlignmentRectInsets(UIEdgeInsets(top: -4, left: 0, bottom: -4, right: 0))
However, It doesn't work cuz It's frame hasn't been set when setting Its' Image. I'm giving Its frame with below code;
iconImageView.frame = CGRect(
x: bounds.size.width - iconWidth - iconMarginLeft,
y: bounds.size.height - textHeight() - iconMarginBottom,
width: iconWidth,
height: textHeight()
)
and how I setup UIImageView
fileprivate func createIconImageView() {
let iconImageView = UIImageView()
iconImageView.backgroundColor = .clear
iconImageView.contentMode = .scaleAspectFill
iconImageView.autoresizingMask = [.flexibleTopMargin, .flexibleRightMargin]
if (hasToolTip) {
let tapGesture = UITapGestureRecognizer(target: self, action:#selector(toolTipTapped(_:)))
iconImageView.addGestureRecognizer(tapGesture)
iconImageView.isUserInteractionEnabled = true
let image = UIImage(named: "infotooltip")
image?.accessibilityIdentifier = "tooltipImage"
iconImageView.image = image!
changeIconAlphaToOne()
self.iconImageView = iconImageView
} else {
self.iconImageView = iconImageView
changeIconAlphaToZero()
}
addSubview(iconImageView)
}
My problem is that, I need to give UIEdgeInset to the image. However, because I'm trying to give it before setting the frame, It doesn't work. How can I achieve this?
I also try to resize the image by referencing below post but doesn't work for me. I also DO NOT want to put it inside a content view which will make my component class more complicated.
The simplest way to resize an UIImage?

How to resize UIImage ratio into view in ios swift?

I am trying to resize uiimage ratio. Right now i am getting image into square not in correct aspect ratio. If i change the width and height uiimage into pickImage.frame.size.width, pickImage.frame.size.hight then UIImage look so large.
If i set pickImage?.contentMode = .scaleAspectFit then image set its position but drop shadow is shown full image view not image picked one.
Here is the screenshots of result i got
And close button should be top left corner, here when i pick image from image picker any other position of close button image set to properly based on landscape or portrait.
Here is the code i used:
func addImage(url : URL) {
let tag = Int(arc4random_uniform(6))
pickImage = UIImageView()
pickImage?.sd_setImage(with:url)
pickImage?.sd_setShowActivityIndicatorView(true)
pickImage?.backgroundColor = UIColor.lightGray
pickImage?.sd_setIndicatorStyle(.gray)
pickImage?.frame = CGRect(x: randomNumber(inRange:
200...Int(touchDrawview.frame.width - 200)), y: Int(getYValue(maxYValue:
Int(touchDrawview.frame.height - 200))), width: 200, height: 200)
pickImage?.autoresizingMask = [.flexibleTopMargin, .flexibleHeight,
.flexibleRightMargin, .flexibleLeftMargin, .flexibleTopMargin,
.flexibleWidth]
pickImage?.contentMode = .scaleAspectFit
pickImage?.tag = tag
pickImage?.isUserInteractionEnabled = true
let imageclose = UIImage(named: "imageclose")
closeImage = UIImageView(image : imageclose)
closeImage?.frame = CGRect(x: 10, y: 10, width: 30, height: 30)
closeImage?.tag = tag
closeImage?.isHidden = true
closeImage?.isUserInteractionEnabled = true
pickImage?.layer.shadowColor = UIColor.white.cgColor
pickImage?.layer.shadowOffset = CGSize(width: 0, height: 3)
pickImage?.layer.shadowOpacity = 1
pickImage?.layer.shadowRadius = 1.0
pickImage?.clipsToBounds = false
let longGuetureImage = UILongPressGestureRecognizer(target: self, action:
#selector(longPressImage(sender:)))
longGuetureImage.minimumPressDuration = 0.1
pickImage?.isUserInteractionEnabled = true
longGuetureImage.delegate = self
pickImage?.addGestureRecognizer(longGuetureImage)
let panGesture = UIPanGestureRecognizer(target: self, action:
#selector(handlePanImage(recognizer:)))
panGesture.delegate = self
pickImage?.isUserInteractionEnabled = true
pickImage?.addGestureRecognizer(panGesture)
let tapGuetureImage = UITapGestureRecognizer(target: self, action:
#selector(removeImage(sender:)))
tapGuetureImage.delegate = self
closeImage?.addGestureRecognizer(tapGuetureImage)
let tapGueturemainImage = UITapGestureRecognizer(target: self, action:
#selector(selectdragImageTap(_:)))
tapGueturemainImage.delegate = self
pickImage?.addGestureRecognizer(tapGueturemainImage)
let rotate = UIRotationGestureRecognizer(target: self, action:
#selector(handlerotateImage(recognizer:)))
rotate.delegate = self
pickImage?.addGestureRecognizer(rotate)
let pinch = UIPinchGestureRecognizer(target: self, action:
#selector(handlePinchImage(sender:)))
pinch.delegate = self
pickImage?.addGestureRecognizer(pinch)
pickImage?.dropShadowOff()
addPickedImage(image: pickImage!, closeimage: closeImage!,imageType :
PickedType.image.rawValue,imageData: url.absoluteString)
pickImage = nil
closeImage = nil
}
Try This:
pickImage?.contentMode = .scaleAspectFill
pickImage?.clipsToBounds = true
Create a UIView with clipsToBounds = true first, apply shadow on this view and then add your pickimage and button as a subView in this view. because clipsToBounds = true stop dropping shadow on current view.
When the image is resized, the aspect ratio of image may not be the same as the view. There are two approaches for what you are trying to achieve.
Approach 1:
Resize the image to fit the view. Here the aspect ratio may be different than view hence image may get distorted. To resize image, refer below,
Refer:
https://aurvan.github.io/atkit-ios-release/index.html
Class Reference:
https://aurvan.github.io/atkit-ios-release/helpbook/Extensions/UIImage.html
Code:
import ATKit
let anImage :UIImage = UIImage(named: "DefaultAvatar")!
let aResizedImage :UIImage? = anImage.resize(size: CGSize(width: 100.0, height: 200.0), scaleMode: UIImageScaleMode.aspectFit)
Approach 2: Calculate the image size manually and adjust the close button from the horizontal center of the view. I have not tried the code, but something like below should work,
anImageX = (anImageViewWidth - anImageWidth) / 2.0
anImageY = (anImageViewHeight - anImageHeight) / 2.0

Add overlay to cover entire screen(including status bar)

I have an overlay (UIImageView) which should have a transparent background and alpha. How can I set the imageview such that it covers the entire screen? Currently, it covers the screen but not the UIStatusBar. I am adding the view in AppDelegate's main window as a subview.
The code:
let overlay1 = UIImageView(image: UIImage(named: "overlay-image"))
overlay1.contentMode = .scaleAspectFit
overlay1.backgroundColor = UIColor.black
overlay1.alpha = 0.87
overlay1.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
overlay1.isUserInteractionEnabled = true
overlay1.layer.zPosition = 1
(UIApplication.shared.delegate as? AppDelegate).window.addSubview(overlay1)
After discussion in comments found that changing the backgroundColor of statusBar is the reason why your code is not working properly.
By printing the superView of statusBar I found that statusBar is not added on UIWindow instead it is on UIStatusBarWindow which is probably above the mainWindow.
Also please don't use force unwrapping it can be cause of crash. At last I put a guard to fetch the statusBar, to check if it responds to backgroundColor property, to fetch its superView and adding the overlay on this superView got it working.
Your check for respondToSelector is also wrong. See below code it works as per your requirement.
guard let statusBar = UIApplication.shared.value(forKey: "statusBar") as? UIView, statusBar.responds(to: NSSelectorFromString("backgroundColor")), let superView = statusBar.superview else {return}
statusBar.backgroundColor = UIColor.red
let overlay1 = UIImageView(image: UIImage(named: "overlay-image"))
overlay1.contentMode = .scaleAspectFit
overlay1.backgroundColor = UIColor.black
overlay1.alpha = 0.87
overlay1.frame = superView.bounds
overlay1.isUserInteractionEnabled = true
overlay1.layer.zPosition = 1
superView.addSubview(overlay1)
Note: Changing the statusBar color is not recommended. You can set its style to default or light.
Okay I just tried with something and it worked. Just use it in your ViewController like:
// You should be using viewDidAppear(_:)
override func viewDidAppear(_ animated: Bool) {
if let appDelegate = UIApplication.shared.delegate as? AppDelegate, let window = appDelegate.window {
let windowFrame = window.frame
let imageView = UIImageView(frame: windowFrame)
imageView.image = #imageLiteral(resourceName: "TakeOff") // use your image
imageView.contentMode = .scaleAspectFit
imageView.backgroundColor = UIColor.green.withAlphaComponent(0.2) // replace green with the color you want
window.addSubview(imageView)
}
}
But, remember one thing. It's not a good idea to add an image view as
an overlay. You should always use a UIView as an overlay and add the
image view as a sub view to that overlay.
Screenshot:

Is it possible to pass a gesture from the current view controller to popover viewcontroller

In my presented ViewController i have a button where on the long press I present a ViewController with modalPresentationStyle popover. The thing is I would like to pass the same touch gesture to the popover so that I don't have to make another touch event to make things work. Is it possible in my current situation or do u suggest work around?
interactionViewController?.delegate = self
interactionViewController?.indexpathRow = indexPathRow
interactionViewController?.modalPresentationStyle = .popover
interactionViewController?.popoverPresentationController?.backgroundColor = .clear
interactionViewController?.preferredContentSize = CGSize(width: 320, height: 220)
interactionViewController?.view.layer.cornerRadius = 25
let popoverMenuViewController = interactionViewController?.popoverPresentationController
popoverMenuViewController?.permittedArrowDirections = UIPopoverArrowDirection.init(rawValue: 0)
popoverMenuViewController?.sourceView = sender as? UIView
popoverMenuViewController?.popoverBackgroundViewClass = PopupControllerBackgroundView.self
popoverMenuViewController?.sourceRect = CGRect(x: 0,y:0,width: 1,height: 1)
popoverMenuViewController?.delegate = self
self.present(self.interactionViewController!, animated: false, completion: { [weak self] in
self?.interactionViewController?.view.superview?.layer.cornerRadius = 40
self?.interactionViewController?.view.superview?.backgroundColor = .clear
})

iOS swift how to place an imageview in a uiview exactly

I have an issue, I'm creating an imageView programmatically and then add it to a center view, which is kind of working. But the problem is that is not taking the whole space in the center view, it appears yes in the uiview but not covering all always a bit down. Any help?
The code:
//let backgroundImage = UIImageView(frame: centerView.frame)
let backgroundImage: UIImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: self.centerView.bounds.size.width, height: self.centerView.bounds.size.height))
print("backgorundImage coordinates: \(backgroundImage.frame)")
backgroundImage.image = drawOverImage
backgroundImage.sizeThatFits(CGSizeMake(centerView.bounds.width, self.centerView.bounds.height))
//check this the image is being drawn bottom because is the fame for the previous 0.0
//backgroundImage.autoPinEdgeToSuperviewMargin(ALEdge.Top, relation: NSLayoutRelation.Equal)
//backgroundImage.contentMode = UIViewContentMode.ScaleAspectFill //too big
//backgroundImage.contentMode = UIViewContentMode.ScaleAspectFit //sama
backgroundImage.contentMode = UIViewContentMode.ScaleAspectFill
backgroundImage.clipsToBounds = true
//imageView.image = background
backgroundImage.center = view.center
let coordinatesForImage: CGRect = self.view.convertRect(backgroundImage.frame, toView: centerView)
let pointOfImage: CGPoint = backgroundImage.convertPoint(self.centerView.frame.origin, toView: backgroundImage)
print("coordinates test: \(coordinatesForImage)")
print("point x: \(pointOfImage.x)")
print("point y: \(pointOfImage.y)")
//backgroundImage.contentMode = UIViewContentMode.ScaleToFill
self.centerView.insertSubview(backgroundImage, atIndex: 0)
let pointOfImageToSuperView: CGPoint = (backgroundImage.superview?.convertPoint(backgroundImage.center, toView: self.centerView))!
print("superview imagepoint: \(pointOfImageToSuperView)")
The comments are all the thing I'm trying to do.
EDIT:
This is what is happening.
I missing a little bit from the bottom, now I don't know if is the size of the image or what, could i change the size of the uiview to match the image?
Simply try:
let backgroundImage: UIImageView = UIImageView(frame: self.centerView.bounds)
backgroundImage.clipsToBounds = true
backgroundImage.contentMode = .ScaleAspectFill
self.centerView.addSubview(backgroundImage)

Resources