UITapGestureRecognizer called only once - ios

I have this code:
func initPlaceHolder(width: CGFloat, height: CGFloat){
var firstPlaceHolderPosition: CGFloat = 0;
UIGraphicsBeginImageContextWithOptions(CGSize(width: width, height: height), false, 0)
let context = UIGraphicsGetCurrentContext()
let rectangle = CGRect(x: 0, y: 0, width: width, height: height)
CGContextSetFillColorWithColor(context, UIColor.whiteColor().CGColor)
CGContextSetStrokeColorWithColor(context, UIColor.blackColor().CGColor)
CGContextSetLineWidth(context, 1)
CGContextAddRect(context, rectangle)
CGContextDrawPath(context, .FillStroke)
let img = UIGraphicsGetImageFromCurrentImageContext()
for i in 1...4 {
let imageView = StompUIImageView(frame: CGRect(x: firstPlaceHolderPosition, y: 0, width: width, height: height))
let tap = UITapGestureRecognizer(target: self, action: "doubleTapped:")
tap.numberOfTapsRequired = 2
imageView.image = img
imageView.addGestureRecognizer(tap)
imageView.userInteractionEnabled = true
imageView.stompID = String(i)
imageView.stompSlot = i
addSubview(imageView)
firstPlaceHolderPosition = firstPlaceHolderPosition + width + 10
UIGraphicsEndImageContext()
}
}
func doubleTapped(sender: UITapGestureRecognizer) {
let view = sender.view as! StompUIImageView
print(view.stompID)
}
Basically the doubleTapped handler is called only for the first UIImageView and not for all 4.
Sorry being new to ios development I have difficulties to understand way.
Thanks for any help

Try this ...
Replace your code with this one....
I hope this will help you.
func initPlaceHolder(width: CGFloat, height: CGFloat){
var firstPlaceHolderPosition: CGFloat = 0;
UIGraphicsBeginImageContextWithOptions(CGSize(width: width, height: height), false, 0)
let context = UIGraphicsGetCurrentContext()
let rectangle = CGRect(x: 0, y: 0, width: width, height: height)
CGContextSetFillColorWithColor(context, UIColor.whiteColor().CGColor)
CGContextSetStrokeColorWithColor(context, UIColor.blackColor().CGColor)
CGContextSetLineWidth(context, 1)
CGContextAddRect(context, rectangle)
CGContextDrawPath(context, .FillStroke)
let img = UIGraphicsGetImageFromCurrentImageContext()
let tap = UITapGestureRecognizer(target: self, action: "doubleTapped:")
tap.numberOfTapsRequired = 2
for i in 1...4 {
let imageView = StompUIImageView(frame: CGRect(x: firstPlaceHolderPosition, y: 0, width: width, height: height))
imageView.image = img
imageView.addGestureRecognizer(tap)
imageView.userInteractionEnabled = true
imageView.stompID = String(i)
imageView.stompSlot = i
addSubview(imageView)
firstPlaceHolderPosition = firstPlaceHolderPosition + width + 10
UIGraphicsEndImageContext()
}
}
func doubleTapped(sender: UITapGestureRecognizer) {
let view = sender.view as! StompUIImageView
print(view.stompID)
}

My code was fine answering my own issue.
The problem was the line: addSubview(imageView)
I was adding 4 placeholder (about 300px) to a container smaller than the sum of the widths of all my placeholders.
Although I was seeing all the placeholders correctly displayed, the frame wasn't big enough to contain them and so the double tap not recognised.
Making the container bigger solved the issue.

Related

add rounding for the outline swift

I have a code that adds an outline of the required width and color to an image and it works well
But I still need to adjust the rounding for the contour, please tell me in which direction should I start?
There are two functions here that do the job of laying the outline.
func colorized(with color: UIColor = .white) -> UIImage {
UIGraphicsBeginImageContextWithOptions(size, false, scale)
defer {
UIGraphicsEndImageContext()
}
guard let context = UIGraphicsGetCurrentContext(), let cgImage = cgImage else { return self }
let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
color.setFill()
context.translateBy(x: 0, y: size.height)
context.scaleBy(x: 1.0, y: -1.0)
context.clip(to: rect, mask: cgImage)
context.fill(rect)
guard let colored = UIGraphicsGetImageFromCurrentImageContext() else { return self }
return colored
}
/**
Returns the stroked version of the fransparent image with the given stroke color and the thickness.
- Parameters:
- color: The colors to user. By defaut, uses the ``UIColor.white`
- thickness: the thickness of the border. Default to `2`
- quality: The number of degrees (out of 360): the smaller the best, but the slower. Defaults to `10`.
- Returns: the stroked version of the image, or self if something was wrong
*/
func stroked(with color: UIColor = .red, thickness: CGFloat = 2, quality: CGFloat = 10) -> UIImage {
guard let cgImage = cgImage else { return self }
// Colorize the stroke image to reflect border color
let strokeImage = colorized(with: color)
guard let strokeCGImage = strokeImage.cgImage else { return self }
/// Rendering quality of the stroke
let step = quality == 0 ? 10 : abs(quality)
let oldRect = CGRect(x: thickness, y: thickness, width: size.width, height: size.height).integral
let newSize = CGSize(width: size.width + 2 * thickness, height: size.height + 2 * thickness)
let translationVector = CGPoint(x: thickness, y: 0)
UIGraphicsBeginImageContextWithOptions(newSize, false, scale)
guard let context = UIGraphicsGetCurrentContext() else { return self }
defer {
UIGraphicsEndImageContext()
}
context.translateBy(x: 0, y: newSize.height)
context.scaleBy(x: 1.0, y: -1.0)
context.interpolationQuality = .high
for angle: CGFloat in stride(from: 0, to: 360, by: step) {
let vector = translationVector.rotated(around: .zero, byDegrees: angle)
let transform = CGAffineTransform(translationX: vector.x, y: vector.y)
context.concatenate(transform)
context.draw(strokeCGImage, in: oldRect)
let resetTransform = CGAffineTransform(translationX: -vector.x, y: -vector.y)
context.concatenate(resetTransform)
}
context.draw(cgImage, in: oldRect)
guard let stroked = UIGraphicsGetImageFromCurrentImageContext() else { return self }
return stroked
}
I tried many options but most of the answers are just adding a conerRadius to the UIImageView (this doesn't work)

Adding padding and border to an UIImageView

How can I add padding between an UIImageView and its border?
Img.layer.cornerRadius = Img.bounds.width / 2
Img.layer.borderWidth = 2
Img.layer.borderColor = UIColor.blue.cgColor
Img.clipsToBounds = true
Like this:
As per the this link
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let image = UIImage(named: "imagename")!
let imageView = UIImageView(image: image.imageWithInsets(insets: UIEdgeInsetsMake(30, 30, 30, 30)))
imageView.frame = CGRect(x: 0, y: 0, width: 300, height: 400)
imageView.backgroundColor = UIColor.gray
imageView.layer.borderWidth = 2
imageView.layer.borderColor = UIColor.blue.cgColor
view.addSubview(imageView)
}
}
extension UIImage {
func imageWithInsets(insets: UIEdgeInsets) -> UIImage? {
UIGraphicsBeginImageContextWithOptions(
CGSize(width: self.size.width + insets.left + insets.right,
height: self.size.height + insets.top + insets.bottom), false, self.scale)
let _ = UIGraphicsGetCurrentContext()
let origin = CGPoint(x: insets.left, y: insets.top)
self.draw(at: origin)
let imageWithInsets = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return imageWithInsets
}
}
For adding padding to the UIImage of UIImageView, use the below piece of code in Swift
let padding: CGFloat = 6
myImageView.contentMode = .scaleAspectFill
myImageView.image = UIImage(named: "myImage.png").resizableImage(withCapInsets: UIEdgeInsets(top: padding, left: padding, bottom: padding, right: padding), resizingMode: .stretch)

How to merge two UIImages while keeping the aspect ratio and size?

The code is added to Github to let you understand the real problem.
This is the hierarchy:
-- ViewController.View P [width: 375, height: 667]
---- UIImageView A [width: 375, height: 667] Name: imgBackground
[A is holding an image of size(1287,1662)]
---- UIImageView B [width: 100, height: 100] Name: imgForeground
[B is holding an image of size(2400,982)]
I am trying to merge A with B but the result is stretched.
This is the merge code:
func mixImagesWith(frontImage:UIImage?, backgroundImage: UIImage?, atPoint point:CGPoint, ofSize signatureSize:CGSize) -> UIImage {
let size = self.imgBackground.frame.size
UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.main.scale)
backgroundImage?.draw(in: CGRect.init(x: 0, y: 0, width: size.width, height: size.height))
frontImage?.draw(in: CGRect.init(x: point.x, y: point.y, width: signatureSize.width, height: signatureSize.height))
let newImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return newImage
}
Note:
.contentMode = .scaleAspectFit
Code works but the result is stretched.
See this line in code, let size = self.imgBackground.frame.size – I need to change this to fix the problem. Find the origin of subview with respect to UIImage size
Here's the screenshot to understand the problem:
What should I do to get the proper output of merge function?
You have two bugs in your code:
You should also calculate aspect for document image to fit it into UIImageView. In mergeImages() replace:
img.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
with:
img.draw(in: getAspectFitFrame(sizeImgView: size, sizeImage: img.size))
When calculating aspect you center image horizontally/vertically if its width/height less then UIImageView width/height. But instead of comparing newWidth and newHeight you should compare factors:
if hfactor > vfactor {
y = (sizeImgView.height - newHeight) / 2
} else {
x = (sizeImgView.width - newWidth) / 2
}
Try bellow code it works for me, hope it works for you too,
func addWaterMarkToImage(img:UIImage, sizeWaterMark:CGRect, waterMarkImage:UIImage, completion : ((UIImage)->())?){
handler = completion
let img2:UIImage = waterMarkImage
let rect = CGRect(x: 0, y: 0, width: img.size.width, height: img.size.height)
UIGraphicsBeginImageContext(img.size)
img.draw(in: rect)
let frameAspect:CGRect = getAspectFitFrame(sizeImgView: sizeWaterMark.size, sizeImage: waterMarkImage.size)
let frameOrig:CGRect = CGRect(x: sizeWaterMark.origin.x+frameAspect.origin.x, y: sizeWaterMark.origin.y+frameAspect.origin.y, width: frameAspect.size.width, height: frameAspect.size.height)
img2.draw(in: frameOrig, blendMode: .normal, alpha: 1)
let result = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
if handler != nil {
handler!(result!)
}
}
//MARK - Get Aspect Fit frame of UIImage
func getAspectFitFrame(sizeImgView:CGSize, sizeImage:CGSize) -> CGRect{
let imageSize:CGSize = sizeImage
let viewSize:CGSize = sizeImgView
let hfactor : CGFloat = imageSize.width/viewSize.width
let vfactor : CGFloat = imageSize.height/viewSize.height
let factor : CGFloat = max(hfactor, vfactor)
// Divide the size by the greater of the vertical or horizontal shrinkage factor
let newWidth : CGFloat = imageSize.width / factor
let newHeight : CGFloat = imageSize.height / factor
var x:CGFloat = 0.0
var y:CGFloat = 0.0
if newWidth > newHeight{
y = (sizeImgView.height - newHeight)/2
}
if newHeight > newWidth{
x = (sizeImgView.width - newWidth)/2
}
let newRect:CGRect = CGRect(x: x, y: y, width: newWidth, height: newHeight)
return newRect
}

how to place a scrolling image behind a stationary image in Swift

I am trying to port an artificial horizon app I wrote for a PC in c# to swift. It has a bezel image which does not move and behind it is a horizon image which can move up and down behind the bezel. The "window" part of the bezel is yellow so in c# I just made the yellow opaque.
In swift I stated with the horizon inside of a UIScrollView but I'm not sure how to get that to work with a second image that should not scroll.
Not all that up to speed on this swift stuff, can someone point me in the right direction?
let view: UIView = UIView.init(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
let scrollView = UIScrollView.init(frame: view.bounds)
view.addSubview(scrollView)
let backImage: UIImage = fromColor(UIColor.redColor(), size: CGSize(width: 1000, height: 1000))
let backImageView: UIImageView = UIImageView.init(image: backImage)
scrollView.addSubview(backImageView)
scrollView.contentSize = CGSize.init(width: backImage.size.width, height: backImage.size.height)
let frontImage: UIImage = fromColor(UIColor.blueColor(), size: CGSize(width: 100, height: 100))
let layer: CALayer = CALayer.init()
layer.frame = CGRect.init(x: view.center.x - 50, y: view.center.y - 50, width: 100, height: 100)
layer.contents = frontImage.CGImage
view.layer.addSublayer(layer)
func fromColor(color: UIColor, size: CGSize) -> UIImage {
let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()
CGContextSetFillColorWithColor(context, color.CGColor)
CGContextFillRect(context, rect)
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img
}
fromColor is a helper method.
Result of the code

iOS - Replaced back button too close to edge

I want to globally change the navigation bar back button, so I have this:
UIBarButtonItem.appearance().setBackButtonTitlePositionAdjustment(UIOffsetMake(-100, -5000), forBarMetrics: .Default)
var backImage: UIImage = UIImage(named: "BackButton")!
backImage = backImage.imageWithAlignmentRectInsets(UIEdgeInsetsMake(0, 0, 0, 20))
UINavigationBar.appearance().backIndicatorImage = backImage
UINavigationBar.appearance().backIndicatorTransitionMaskImage = backImage
But the back image is too close to the left of the screen. How do I move it farther to the right?
Just adjust the actual image.
extension UIImage {
func imageWithInsets(insets: UIEdgeInsets) -> UIImage {
UIGraphicsBeginImageContextWithOptions(
CGSizeMake(self.size.width + insets.left + insets.right,
self.size.height + insets.top + insets.bottom), false, self.scale)
let context = UIGraphicsGetCurrentContext()
let origin = CGPoint(x: insets.left, y: insets.top)
self.drawAtPoint(origin)
let imageWithInsets = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return imageWithInsets
}
}
For Swift 4:
extension UIImage {
func withInsets(_ insets: UIEdgeInsets) -> UIImage? {
UIGraphicsBeginImageContextWithOptions(
CGSize(width: size.width + insets.left + insets.right,
height: size.height + insets.top + insets.bottom),
false,
self.scale)
let origin = CGPoint(x: insets.left, y: insets.top)
self.draw(at: origin)
let imageWithInsets = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return imageWithInsets
}
}
You need to adjust the left position on UIEdgeInsetsMake.
You are already calling it here:
backImage = backImage.imageWithAlignmentRectInsets(UIEdgeInsetsMake(0, 0, 0, 20))
Like so:
backImage = backImage.imageWithAlignmentRectInsets(UIEdgeInsetsMake(0, -50, 0, 50))

Resources