How to change the shape of a UIButton in Swift? - swift

I am trying to make an arrow shape. I understand that it will be done with CGRect method but can you give a complete example of how it will be done in SWIFT?

This can be done programmatically by first subclassing UIButton and overriding drawRect within it to form the shape of an arrow via bezier paths. Then simply set the title of the button to be whatever you want your text to be and position it accordingly within the shape you have drawn.
The benefit of doing it this way is that you can easily change the color of, scale and dimensions of the arrow since you control how the object is actually being drawn.
A good tool for drawing complex bezier paths is paintCode. I'm using the trial version and can pretty easily make shapes like this now.

Related

How to draw custom line on MKMapview?

I've been searching for a way to draw a custom line, but the only help I can find is how to draw lines with an UIColor.
I want to draw a straight line but not just with a color. I want the appearance of the line to be customizable.
(So right now I can draw lines between 2 points, but not the line I want)
The line I want got straight 45 degree lines on it, and it's grey and black.
Anybody can help?
The line looks like this, I'm also thinking that I could stretch this image, but if I stretch it, it will look kinda weird.
Why don't you add image then? I'm new developer so I don't know other way to do it. Only OpenGL with texturing, but there is no need to use openGL. So my suggestion is to add image.
Sound like what your looking for is the MKPolylineView Class. You assign it a polyline which contains the points in your line. Since the polyline view is an MKOverlayPathView you can set the stroke and fill colors.
Since it's also a UIView subclass you can manipulate the appearance even further by grabing the views layer property and adding gradients, shadows, masks, etc.
Is there a specific effect that you're trying to achieve?

Creating a bounding box for a UIImageView

How can a bounding box be created for a UIImageView that is not a CGRect?
I would like to have objects in my view which should display images as well as detection collisions.
The issue is I would like these object to be whatever shape they are rather than fitting them into a CGRect and detecting collisions on areas which are inside the box but are nit the actual image.
How does one achieve this?
This is a non-trivial problem. But the basics are a CGRect is a rectangle and a hit test inside of a rectangle is fairly easy to understand. However, you sound like you want a more complex shape. UIImageView displays an image. It does not have any idea about what shape you want to use for your collision test. So you are going to have to tell it.
One easy thing to do is to look at the alpha/transparent values of the display image to create a shape. So to answer the question is a point hitting an image we figure out the location of point in the image and return true if the alpha is greater than 0. If you do this you can create any image with a transparent background and the code will just work.
If that will not work for you then can can also run a hit test on a point and a polygon this post covers that in detail.
How can I determine whether a 2D Point is within a Polygon?

Add shading to clipped UIView

I'm creating an iphone application. I have this UIView whose content is clipped with a path. I want to add shading and/or shadow to it. What's the best way to do this? For shadow, I tried CGContextSetShadow() but it doesn't seem to have an effect (perhaps it's drawing outside the shown region?) . How about shading? I want it to appear along the path. What's the best way to go about it? Is it to create another narrow clip strip along the original clipping path (if it's possible to have two clip path... ) Or does this need to be done in another CALayer? I am not even sure what that is yet.
You can't add shadows to layers which are clipped or masked. The way I would do this is use two CALayers, one for the clipped content and place this inside another for the shadow which isn't clipped.

implementing stretchable dialog borders in iphone sdk

I want to implement dialog borders that scale to the size I require the dialog to be. Perhaps there is a better more conventional name for this sort of thing. If there is, if someone would edit the title, that'd be great.
Anyhow, I'd like to do this so I can have dialogs of any size without the visual artifacts that come with scaling border art to small, large, or wacky unproportional dimentions. I have a few ideas on how this is done, but am not sure which is better for iphone. I have a few questions.
1) Should I make a containing view object that basically overloads its drawRect method and draws the images where they should be at their appropriate scale when the method is called, or should I main a containing view object that simply contains 8 UIImageViews? I suspect the latter approach won't work if I need to actively scale the resulting dialog class like in an animation.
1b) If overloading drawRect is the way to go, does someone have some sample code or a link to an example that demonstrates drawing an image directly from drawRect()?
2) Is it generally better to create
a) a 3 x 3 image where the segments are in their appropriate 1x1 grid of the image? If so, is it simple to draw from a portion of this image onto my target view in drawRect (if the former assumption is correct that I should use drawRect)?
b) The pieces separately in 8 different files?
UPDATE:
To clarify, the idea is to take any customized border art and be able to stretch the 2nd, 4th, 6th, and 8th cell (in a 3x3-cell grid) to form a border of any size with just those assets. Stretching just a plain image would result in distortion of the corners, so I'd like to stretch those even numbered cells as needed and tack on the corners so there is no distortion. I'd seen this done before so thought it might be a standard thing and have a standard naming to it other than what I called it.
Anyhow, I was advised that adding 8 UIImageViews to a container would not be as efficient as drawing the UIImages on the fly in drawRect so took that approach using CGContextDrawImage() after applying the necessary transformations to the context to translate and scale the Y. Because this function draws from the bottom left corner of an image but onto a top-left origined UIView, the image is upside down without the Y axis invert. I noticed the suggestion to use UIImage functions like drawAtPoint works as well and similarly but for the invert since UIImage draws in the same orientation as UIViews. I will continue my implementation with the former and see how it goes, but one other question.
Would someone happen to know which of these approaches is more efficeint, faster, etc?
I'm not sure I follow, but here's my best shot at an answer...
Using drawRect: or adding individual UIImageViews to a parent view is entirely up to you. UIImageView gives you a bit of encapsulated functionality for free, but otherwise they are the same as far as appearances go.
If you do want to go the drawRect route, you just need to use UIImage's drawAtPoint: method. Do the math for where you want it to be, and draw it. You can calculate your points based on the parent view's dimensions.
As far as scaling, it's impossible to resize these images without scaling them, so I'd plan ahead and make your originals as large or larger than you ever expect to display them.
Hope that helps a little?
Cheers
If you want a border on a dialog box, assuming the box is a UIView (or subclass), then set the layer's border properties and let the system draw the border for you.
#import <QuartzCore/QuartzCore.h>
// ...
view.layer.borderWidth = 2;
view.layer.borderColor = [UIColor whiteColor].CGColor;
view.layer.cornerRadius = 0; // 0=square corners, >0 for rounded

How to animate a polygon mask with performance?

I'm having a performance issue.
I've created an UIView and overwrited it's drawRect function. At this function, I was drawing an image (big one), and over that, an white square at the entire screen with a polygon inside it, with CGContextEOFillPath. The result is an white screen with portion of the image (defined by the polygon) displayed.
After that, I created a function to animate the transition of that polygon to another one. Besides the polygon animation, the image should also be scaled and moved to fix the diplayed at the screen. I did that with an NSTimer. The animation of the polygon consists in calculating the distance between each vertex and moving then to a position according to elapsedTime. It worked just fine at the simulator, but got really stucked at device.
Reading about performance, here at stackoverflow, I found the alternative to use beginAnimations and commitAnimations. I'm changing everything to use that approach with the image. But what can I do with the polygon. The polygon is drawn with CGContextMoveToPoint and CGContextAddLineToPoint, so I believe it can't be animated with beginAnimations. An I correct? Is there a better approach to do that?
The desired result is something like this comic reader app: http://www.comixology.com/iphoneapp (click on guided tour. at the middle of the video they show the "automatic masking" feature)
My suggestion would be to use a CAShapeLayer overlaid on your main image view, with the CAShapeLayer being the size of the view you want to mask and having a polygon path for a hole in the center of it. CAShapeLayers let you animate from one CGPathRef to another smoothly, as long as the two paths have the same number of control points. You will need to use a CABasicAnimation here to do that animating, rather than a UIView begin / commitAnimations block, but it's not too difficult.
Joe Ricioppo has a nice example of animating CAShapeLayer paths in his post here.
With Core Animation you can animate "animatable" (sic) properties. Apple's documentation enumerates animatable properties in Mac OS X:
http://url.akosma.com/55
In the case of the iPhone, the UIView documentation explicitly says "animatable" when a given property is, hum, animatable. The most powerful of these are (IMHO) UIView's "transform" property, which takes CGAffineTransform structs as inputs, or CALayer's "transform" property (which takes CATransform3D structs). Both are animatable and give you tremendous power to create any kind of transition you want.
Now, in your case, indeed, you can't animate the polygon in an "easy" way. My bet would be in your case to try to map CGAffineTransforms that fit your needs (scale, translation) and apply that to a fixed view, non-animated, created using your Quartz code.
I hope I'm clear enough :)