I want to use custom background image for UISegmentedControl like "Find My Friends". Here's how their resizable images look like:
source http://feedzr.com/source.png
source http://feedzr.com/inwork.png
How do I create that complex shadow effect in Core Graphics?
EDIT
The bottom image is just how the above looks like when working with a leather background in a real UISegmentedControl.There're lot's of effects in the resizable image like:
bottom gloss, top inner shadow and partial gradient from top to bottom.
I just can't see how & what effects are being used in this image. I'm not asking how to use UIEdgeInsets.
These are just 2 images. One with the shadow one without…
You have to create these Images with CapInsets to make them resizable
For example
UIImage *buttonImage = [[UIImage imageNamed:#"yourImage"]
resizableImageWithCapInsets:UIEdgeInsetsMake(1, 11, 0, 20)];
To know how UIEdgeInsets work read:
How does UIEdgeInsetsMake work?
Or in the Apple Doc:
UIEdgeInsetsMake
Creates an edge inset for a button or view.
UIEdgeInsets UIEdgeInsetsMake (
CGFloat top,
CGFloat left,
CGFloat bottom,
CGFloat right
);
Parameters
top
The inset at the top of an object.
left
The inset on the left of an object
bottom
The inset on the bottom of an object.
right
The inset on the right of an object.
Return Value
An inset for a button or view
Discussion
An inset is a margin around the drawing rectangle where each side (left, right, top, and bottom) can have a different value.
Availability
Available in iOS 2.0 and later.
See Also
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIKitFunctionReference/Reference/reference.html
Related
I have an UIImageView with image as AspectFit. I need to place two buttons, one at top-right and other at bottom-left position of image as shown in image below.
How can I get image coordinates of these position to place the buttons correctly.
Thanks in advance.
You can get the image rect fitting the UIImageView using the AVFoundation framework:
import AVFoundation ´
let fittedRect = AVMakeRect(aspectRatio: (image?.size)!, imageView.frame)
let height = fittedRect.height
let width = fittedRect.width
Then use it to calculate button position (depending on which view you're adding the button to).
I don't know whether it could solve your problem but i have put that two button just like this.
Step 1:
Did Autolayout in imageView.Fixed Width and height and center aligned(It's your wish to be aligned)
Step 2:
And aligned those two buttons with respect to this imageView.
1.Trailing
2.Vertical Spacing
3.Fixed width and height
This way those buttons are now aligned with image.
Portrait
Landscape
I have a UIImage inside a UITableViewCell.
What is the best way to have upper and lower borders around the UIImage?
[cell.backgroundImageView.layer setBorderColor: [[UIColor blackColor] CGColor]];
[cell.backgroundImageView.layer setBorderWidth: 2.0];
cell.backgroundImageView.layer.frame = CGRectMake(0, 0, cell.backgroundImageView.layer.frame.size.width + 10, cell.backgroundImageView.layer.frame.size.height);
Doesn't seem to work.
The border properties manage a border around the whole layer, not a partial one.
I'd go with a couple of UIViews (with their background color set as needed), pinned to the UIImageView using autolayout and pinned within the cell frame. In that way you don't risk drawing the borders outside the bounds of the cell, or having your other cell content mis-aligned to the image, since the image appears to be a certain size but it actually larger because you have been playing with the layers.
If performance is not a consideration you can add a UIView with 1px height above and below the image and set its background color.
I have a static image with an area on it that is meant to display some multi-line text. Like a speech bubble from a character in a video game. I grabbed a stock image that looks like this:
I have a UIImageView set up to be aspect-fit (see this question) inside of a subview of the main view. I have a UILabel also set up inside of the subview, which will hold the multi-line text. I want to be able to move the subview around the screen and have it be any size and still have the UIImageView stay the same aspect and have the UILabel fit inside the bubble of the image.
I made a sample project which has this set up already.
The way I intend to keep the UILabel's bounds inside the speech bubble area is by setting up constraints that are proportional to the center x and y of the UIImageView. For my image, the left edge multiplier is 0.65, the right is 1.8, the top is 0.19 and the bottom is 0.63.
I wrote a couple functions that extend from UIView to confirm this:
/**
Draws a vertical line proportional to the center x of the view.
A `proportional` value of 0 is the left edge, while 2 is the right edge.
:param: proportion The value from the left edge (0.0) to the right edge (2.0)
:param: inColor The color to draw the line in (red by default)
*/
func drawVertLineAtProportion(proportion: CGFloat, inColor: UIColor = UIColor.redColor()) {
let size = self.frame.size
UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
let context = UIGraphicsGetCurrentContext()
let x = self.bounds.origin.x + proportion*self.frame.size.width/2
var vertPath = UIBezierPath()
vertPath.lineWidth = size.height/150.0
vertPath.moveToPoint(CGPointMake(x, 0))
vertPath.addLineToPoint(CGPointMake(x, self.frame.size.height))
inColor.setStroke()
vertPath.stroke()
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
self.addSubview(UIImageView(image: image))
}
And drawHorizLineAtProportion is similar, but for horizontal lines.
I can confirm that my multiplier values are correct by running these 4 lines in viewDidAppear:
imageView.drawVertLineAtProportion(0.65)
imageView.drawVertLineAtProportion(1.8)
imageView.drawHorizLineAtProportion(0.19)
imageView.drawHorizLineAtProportion(0.63)
And then the imageView looks like this:
I can change the size of the subView that contains the imageView to any size I want, and the imageView stays aspect-fit and the red box in the intersection of those red lines is always exactly what I want.
So how come when I set up the constraints of the edges of the UILabel to follow the same formula the edges don't line up?
It seems that when the width of the imageView is maxed the left and right edges are correct but the top and bottom are wrong:
And if the height is maxed, then the top and bottom are correct, but the left and right are wrong:
So how come the UILabel bounds aren't lining up with the red lines?
EDIT to specify that I know there is a runtime fix, but I want to know why storyboard doesn't work.
If I add these lines in viewDidAppear to fix the frame of the UILabel, it works:
let upperLeft: CGPoint = CGPointMake(imageView.frame.origin.x + 0.65*imageView.frame.size.width/2, imageView.frame.origin.y + 0.19*imageView.frame.size.height/2)
let lowerRight: CGPoint = CGPointMake(imageView.frame.origin.x + 1.8*imageView.frame.size.width/2, imageView.frame.origin.y + 0.63*imageView.frame.size.height/2)
let size: CGSize = CGSizeMake(lowerRight.x - upperLeft.x, lowerRight.y - upperLeft.y)
speechLabel.frame = CGRectMake(upperLeft.x, upperLeft.y, size.width, size.height)
But I still want to know why what I have set in storyboard doesn't work.
I figured out a solution, fully in storyboard, that gets me what I want, although I do believe my original question shows that there is a bug in Xcode.
I was noticing that since Xcode didn't seem to respect that I wanted to align speechLabel to the sister-UI element imageView, I just made the UIView I was aligning to no longer the imageView.
The solution I implemented was to put the imageView and speechLabel into a new parent view, which I call aspectFitView. All of the constraints that I put on the imageView to make it aspect-fit, I put on aspectFitView instead.
Then I set the constraints of imageView to make it the size of aspectFitView: align center x and y and equal width and height.
Now that the parent of speechLabel is the exact size, position, and aspect ratio of the imageView, I set up my proportional constraints for the speechLabel against the aspectFitView instead, and voila. It all works beautifully. It looks correct on my storyboard, I don't have to add any post-viewDidAppear frame-correcting code, and it works perfectly on any device I run it on.
I updated the sample project (Xcode 6.4) with the solution for anyone interested.
I create all my constraints programmatically for my UI controls. So my button has a text: title
So if I don't set any restriction for width of the button, the app will create for me button based on text width, and this works fro me.
But I want to add few extra padding at left and right sides. How can I do it?
Use the contentEdgeInsets property of UIButton, e.g.:
`yourButton.contentEdgeInsets = UIEdgeInsetsMake(0.f, 10.f, 0.f, 10.f);`
will add 10 points to the left and right edges.
in my app the UITableViewCell size are dynamic which means each has it's own height. inside of each cell there is a background image in a UIImageView. Through storyboard, i used autolayouts to customize the UIImageView to automatically stretch as the cell is stretched. The problem is that when they stretch the whole image stretches with the corners. So i was looking up online and i came over using resizableImageWithCapInsets: in order to stretch the stretchable sides and exclude the unwanted ones. So i tried the following code in tableView: cellForRowAtIndexPath: as i wanted the image to be stretched vertically only (height):
[cell.backgroundImage.image resizableImageWithCapInsets:UIEdgeInsetsMake(16, 0, 16, 0)];
however, the problem persisted as in the picture below
As you can see, the image corners are still stretched. What am i doing wrong? is the edgeInset values wrong? or should i place the code somewhere else ?
You create UIEdgeInsets values using the UIEdgeInsetsMake() function. UIEdgeInsets encapsulates four different CGFloat values for the inset values of the top, bottom, left, and right individually. Positive inset values shrink the content area, while negative inset values will effectively increase it. Make sure you create the image first and apply the insets there and then, Once that is done then apply the image to the backgroundView as opposed to trying to edit the edge insets from the backgroundView.image property.
UIImageView *cellBGIV =
[[UIImageView alloc] initWithImage:[[UIImage imageNamed:#"imageName"]
resizableImageWithCapInsets:UIEdgeInsetsMake(5.0, 5.0, 5.0, 5.0)]];
cell.backgroundView = cellBGIV;