MKMarkerAnnotationView has a truncated image - ios

I want to get a UIImage from a MKMarkerAnnotationView but with the following code the image is truncated (at the top and bottom, see the screenshot)
let newAnnotation = SimpleAnnotation(sourceCoordinate: annotation.coordinate, sourceTitle: "Hello", sourceSubtitle: "world")
let pinAnnotation = MKMarkerAnnotationView(annotation: newAnnotation, reuseIdentifier: "Test")
pinAnnotation.markerTintColor = UIColor.red
pinAnnotation.glyphText = "1"
pinAnnotation.animatesWhenAdded = false
pinAnnotation.glyphTintColor = UIColor.white
pinAnnotation.titleVisibility = .hidden
pinAnnotation.subtitleVisibility = .hidden
UIGraphicsBeginImageContextWithOptions(pinAnnotation.bounds.size, false, 0.0)
pinAnnotation.drawHierarchy(in: CGRect(x:0,
y:0,
width:pinAnnotation.bounds.width,
height:pinAnnotation.bounds.height),
afterScreenUpdates: true)
let snapshotImageFromMyView = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
Any idea why it's truncated? In the Xcode debugger I can see the image is already truncated in the pinAnnotation (before I use UIGraphics... to get the UIImage)

I have found the solution! I have just to set the contentMode to scaleAspectFit and to change the bounds to the size of the image I need (40x40px).
Here's the code displaying the full MKMarkerAnnotationView.
let pinAnnotation = MKMarkerAnnotationView()
pinAnnotation.markerTintColor = UIColor.red
pinAnnotation.glyphText = "1"
pinAnnotation.animatesWhenAdded = false
pinAnnotation.glyphTintColor = UIColor.white
pinAnnotation.titleVisibility = .hidden
pinAnnotation.subtitleVisibility = .hidden
pinAnnotation.contentMode = .scaleAspectFit
pinAnnotation.bounds = CGRect(x: 0, y: 0, width: 40, height: 40)
UIGraphicsBeginImageContextWithOptions(pinAnnotation.bounds.size, false, 0.0)
pinAnnotation.drawHierarchy(in: CGRect(x:0,
y:0,
width:pinAnnotation.bounds.width,
height:pinAnnotation.bounds.height),
afterScreenUpdates: true)
let snapshotImageFromMyView = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
This page Demystifying iOS Layout has helped me a lot to find this solution.

I can't get the drawHierarchy to work I just get back an empty image.

Related

Set UIBarButtonItem with circular Image profile

How to set UIBarButton with circular image profile
func loadProfile(){
let url = URL(string: "https://res.cloudinary.com/demo/image/upload/v1312461204/sample.jpg")!
let data = try! Data(contentsOf: url)
let img = UIImage(data: data)
let imageView = UIImageView(frame: CGRect(x: 0.0, y: 0.0, width: 40.0, height: 40.0))
imageView.image = img?.withRenderingMode(.alwaysOriginal)
imageView.layer.cornerRadius = 20.0
imageView.layer.masksToBounds = true
let barButton = UIBarButtonItem(customView: imageView)
self.tabBarController?.navigationItem.setRightBarButton(barButton, animated: false)
Failed to set Constrains thats why its behaviors!
imageView.widthAnchor.constraint(equalToConstant: buttonWidth).isActive = true
imageView.heightAnchor.constraint(equalToConstant: buttonHeight).isActive = true
Fixed Issue.
Have you tried set content mode in your imageView ?
imageView.contentMode = .scaleAspectFill
For anyone that finds this, as suggested by kiran, setting the imageView frame size is not enough. You should also set the height and width constraints. Otherwise, any animation to the navigation bar will result in the imageView.image occupying the whole navigationBar width, as seen in the image posted by the OP.
func loadProfile(){
let url = URL(string: "https://res.cloudinary.com/demo/image/upload/v1312461204/sample.jpg")!
let data = try! Data(contentsOf: url)
let img = UIImage(data: data)
let imageView = UIImageView(frame: CGRect(x: 0.0, y: 0.0, width: 40.0, height: 40.0))
// NEW CODE HERE: Setting the constraints
imageView.widthAnchor.constraint(equalToConstant: 40).isActive = true
imageView.heightAnchor.constraint(equalToConstant: 40).isActive = true
imageView.image = img?.withRenderingMode(.alwaysOriginal)
imageView.layer.cornerRadius = 20.0
imageView.layer.masksToBounds = true
let barButton = UIBarButtonItem(customView: imageView)
self.tabBarController?.navigationItem.setRightBarButton(barButton, animated: false)
}

Setting content mode in UIImageView no longer works in iOS 11

I have this code in order to put an UIImageView in the center of a navigation controller bar and properly scale the image:
override func viewDidAppear(_ animated: Bool) {
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 150, height: 28));
imageView.contentMode = .scaleAspectFit;
let image = UIImage(named: "image_title.png");
imageView.image = image;
self.navigationItem.titleView = imageView;
}
The code works fine in iOS 10, however in iOS 11 the ".scaleAspectFit" property is not considered and the images is not scaled in the UIImageView size.
I tried with some solutions i found:
Setting the frame of the UIImageView after setting the "contentMode" property
Setting imageView.setNeedsLayout()
Setting imageView.setNeedsDisplay()
unfortunately, no one of these solutions works. The "contentMode" property is simply ignored,
Any idea on what the problem could be?
Thank you in advance
Works for me such way (using additional UIView)
let titleView = UIView(frame: CGRect(x: 0, y: 0, width: 120, height: 40))
let image = UIImageView(image: UIImage(named: "img-logo"))
image.contentMode = .scaleAspectFit
image.frame = titleView.bounds
titleView.addSubview(image)
viewController.navigationItem.titleView = titleView
let imageView = UIImageView(image: UIImage(named: "img-logo"))
imageView.contentMode = .scaleAspectFit
navigationItem.titleView = imageView

how to add a background image to a UITextView

I am trying to add a background image to my UITextView, but there doesn't seem to be an option to do so. I have tried adding an imageView with the image as a sub view
self.bioTextView.delegate = self
let imgView = UIImageView(frame: self.bioTextView.frame)
imgView.image = #imageLiteral(resourceName: "text_field_bio")
self.bioTextView.addSubview(imgView)
But this didn't work either. The color of the textView Background is clear. I have also tried including sending that imgView to the back, but that didn't work either.
add the foll0wing two lines and check once
bioTextView.addSubview(imgView)
bioTextView.sendSubview(toBack: imgView)
or use
bioTextView.backgroundColor = UIColor(patternImage: UIImage(named: "Image.png"))
updated
let textView = UITextView(frame: CGRect(x: CGFloat(20), y: CGFloat(20), width: CGFloat(400), height: CGFloat(400 )))
textView.text = "this is a test \n this is test \n this is a test"
let img = UIImageView(frame: textView.bounds)
img.image = UIImage(named: "1.jpg")
textView.backgroundColor = UIColor.clear
textView.addSubview( img)
self.view.addSubview(textView)
textView.sendSubview(toBack: img)
you get the output

Center element on paginated scroll view

I am creating UIImageViews programatically and scroll between them as pagination
How can I center each image with auto-layout programatically?
// manual attempt
viewDidLoad() {
self.scroll.frame = CGRect(x:0, y:0, width:self.view.frame.width, height:self.view.frame.height)
let scrollWidth: CGFloat = self.scroll.frame.width
let imgOne = UIImageView(frame: CGRect(x:65, y:120, width:180, height:300))
let imgTwo = UIImageView(frame: CGRect(x:scrollWidth + 65, y:120, width:180, height:300))
let imgThree = UIImageView(frame: CGRect(x:scrollWidth*2 + 65, y:120,width:180, height:300))
imgOne.image = UIImage(named: "one.png")
imgTwo.image = UIImage(named: "two.png")
imgThree.image = UIImage(named: "three.png")
imgOne.center = self.view.center // works
imgTwo.center = ??
imgThree.center = ??
self.scroll.addSubview(imgOne)
self.scroll.addSubview(imgTwo)
self.scroll.addSubview(imgThree)
}
Use UICollectionView. You can set pagingEnabled for paging between images and UICollectionViewScrollDirectionHorizontal in layout for horizontal direction. See good example of using it here.

UIImageView not positioning correctly in Navbar and Status Bar

I am trying to use an Image in my Navigation Bar. Keep getting close but no cigar. With the code below, it loads the image fine and positions it nearly correct. It appears to have a pad around the view, but I have no constraints around it. When I remove the Status bar it shrinks the image but positions it fine within the NavBar.
let nav = self.navigationController?.navigationBar
for parent in self.navigationController!.navigationBar.subviews {
for childView in parent.subviews {
if(childView is UIImageView) {
childView.removeFromSuperview()
}
}
}
nav?.barStyle = UIBarStyle.Default
nav?.tintColor = UIColor.blueColor()
let app = UIApplication.sharedApplication()
let SBheight = app.statusBarFrame.size.height
let totalheight = SBheight + nav!.frame.height
let totalwidth = nav!.frame.width
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: totalwidth , height: totalheight))
imageView.clipsToBounds = true
imageView.contentMode = .ScaleAspectFill
var image = UIImage(named: "HRC")
imageView.image = image
navigationItem.titleView = imageView
Here is the shot of the NavBar Area:
I can set the background picture of a navigation bar with no issue with the code below.
Swift 3.0
let backgroundImage = UIImage(named: "name_of_background_image")?.resizableImage(withCapInsets: UIEdgeInsetsMake(0, 0, 0, 0), resizingMode: .stretch)
self.navigationController?.navigationBar.setBackgroundImage(backgroundImage, for: .default)
Swift 2.3
let backgroundImage = UIImage(named: "name_of_background_image")?.resizableImageWithCapInsets(UIEdgeInsetsMake(0, 0, 0, 0), resizingMode: .Stretch)
self.navigationController?.navigationBar.setBackgroundImage(backgroundImage, forBarMetrics: .Default)
You can add the code above to viewDidLoad, and customize the background image for each viewController.
Make sure you render the image as Original from the asset catalog.
And double check if your image has the right size.
#2x -> 750 x 128
#3x -> 1125 x 192

Resources