How to make an custom button with an self-stretching image? - iphone

I slightly remember that there is an class which is capable of stretching an image in such a way, that the first x pixels and the last y pixels won't get stretched.
For example if you have an button image with round corners, you would want those round corners to stay intact while the middle part of that image gets stretched.

This is a feature of class UIImage itself.
- (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCapHeight
You can assign the resulting image to the appropriate property of UIButton as required.

Related

How to crop a UIImageView to a custom shape

Is it possible for a user to draw a dotted line (in a circle) around the bit of the UIImageView they wish to crop to, and then for the UIImageView to resize to those points? It's a bit like the lasso/marquee effect in Photoshop:
Update: Since iOS 8.x, UIImageView provides a maskView property. Just prepare an image with some opaque pixels, create another image view with that mask image, and set this mask image view as the maskView. The opaque pixels in the mask image will be the ones shown in the underlying image.
UIImageView *maskView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"somemask"]];
maskView.frame = imageView.bounds;
imageView.maskView = maskView;
// imageView will be masked by maskView
.
Original Answer
There's quite a bit to do, but here's a high-level outline:
create an empty image which will become a mask
build a path in that image from user input
fill the path to turn it into a mask
apply the mask to the imageview's image
Create image: A simple idea here is to just ship a black image with your project. It should be sized to match the maximum region a user can select. Read the image into memory (UIImage imageNamed:) and set it up as the drawing context by calling UIGraphicsBeginImageContext.
Create path: (see apple docs). When the user starts stroking the region, call CGContextBeginPath, then follow user gestures, sampling the touches and adding small segments by calling CGContextMoveToPoint repeatedly as touchesMoved.
Create mask: To turn the path into a mask you want a black background and the path filled with white. If you started with a black image, you just need to do the fill. See the same apple guide about doing that.
Finally, you'll apply this mask to your imageView's image. Here's a decent reference for that.
This answers just one part of your question i suppose, but here's an example on how to draw and animate the dotted line (i.e. marching ants effect).

How can i make multiple customized uiimageview frame in one view?

I have to make view where there will be multiple curved or irregular shaped imageview. Now when i will touch a UIImageview then it will import image from photo gallery.For example: Suppose
I have an UIView with background image.
On that view i have 3 irregular shaped UIImageview.every UIImageview is attached with each other.
Now suppose i have touch in the first UIImageview then it will take an image from photo gallery.
When i have imported the image then that image will be as the background image of the UIImageview.
I have to make sure that if my UIImageviewis smaller then its background image then i will able to move the image or rotate the image or scale or zoom the image to adjust the image according to the size of UIImageview.
How can i do that whole process??? any help by link,source code,tutorial or anything else will be cordially appreciable.
Basically my first priority is that how can i make those irregular shaped UIImageView pro-grammatically.
IF ANY FURTHER QUERY TO ASK THEN PLEASE DON'T HESITATE.
Thanks In Advance
The one way of doing this is as follows:
Subclass from UIImageView set touchesBegan methods for each UIImageView for import image, setting on background and whatever you want to do on touch.
What does 'attached' mean? If all of them should move together, then, again, you have to deal with it in touchesBegan methods, sending messages like 'Hey views, i've moved on this vector:[vector], please do it too'.
In pt. 3.2 i didn't get your point. :( You can set in UIImageView subclass self.contentMode = UIViewContentModeScaleAspectFit or UIViewContentModeScaleToFill, so its image will always fit the view.
About irregular shape, did you read links below? I suppose there's not an super easy way to do it :(
http://www.iphonedevsdk.com/forum/iphone-sdk-development/76923-hittest-collision-for-irregular-shaped-uiviews.html
Draggable UIImageView Partially Transparent & Irregular Shaped
Simple way of using irregular shaped buttons

How to subdivide uiimage on tap event?

I have a image in UIImageView. When user taps one particular area on image, that part of image should be highlighted by a square and the subpart of image in that square should be used for scaling.
How can I do it?
Well, it's actually going to involve:
user tap gesture handling
overlay a UIView for the square to highlight
crop and scale the certain area of the original image, you may need some helpers like: https://github.com/Nyx0uf/NYXImagesKit

UIButton backgroundImage stretchableImageWithLeftCapWidth:topCapHeight issue

I have a UIButton with a specified width of 200. Its autoresizingMask property is set to UIViewAutoresizingFlexibleWidth. A UIImage is applied to this button's backgroundImage property. This UIimage is defined as follows:
[[UIImage imageNamed:#"buttonimage.png"] stretchableImageWithLeftCapWidth:10 topCapHeight:0]
buttonimage.png has a width of 400px (2x width of button, because of retina resolution) and represents a rounded rectangle. In portrait mode, everything is fine. As soon as the user rotates the device and the iPhone enters landscape mode, the UIButton is stretched. Due to this behaviour, the left rounded border of the image stays the same (stretchableImageWithLeftCapWidth:) but the right corners are also stretched. Is there any property I forgot to set that ensures only one specified pixel (e.g. the tenth one) is stretched and anything else retains it dimensions?
Thanks in advance!
Edit: If I use a smaller image, that is already stretched in portrait mode, both borders seem to be expanded.
Solved!
If your image is called "myImage.png" and it is the retina version, just call it "myImage#2x.png"
Is there any property I forgot to set
that ensures only one specified pixel
(e.g. the tenth one) is stretched and
anything else retains it dimensions?
Not really, but given the size of your images, you should re-read the leftCapWidth property.
The way stretchable images work is: you provide the left cap, the next pixel is stretched, and the right side of the image with width = (total width - left cap + 1) stays the same. Given that you are setting left cap to 10, and the original image is 400, you are telling iOS that the right non stretchable right side of your image is 400-10-1=389px. The same thing applies vertically. Check if you are using #2x images on a normal device without a #2x on its name, or if the 2x versions don't have exactly twice the pixels, or there is an uppercase/lowercase difference. You can find this out nslogging the size of the image loaded.
I don't know why the right side of your image is stretched. Given that you have height=0, the whole image can be stretched vertically if the button height changes, but it's unlikely that this causes a distortion of only the right side.
There is nothing wrong with your code as far as I can tell, that should be causing the right side of the image to be cropped. Below is the exact code I use, which I know works, to produce the same effect you're looking for.
UIButton *button=[[UIButton alloc] initWithFrame:CGRectMake(0, 0, 245, 51)];
button.autoresizingMask=UIViewAutoresizingFlexibleWidth;
[button setBackgroundImage:[[UIImage imageNamed:#"userbubble.png"] stretchableImageWithLeftCapWidth:40 topCapHeight:0] forState:UIControlStateNormal];
[self.view addSubview:button];
My guess is that the problem is coming from the png you're using, or possibly from the Compress PNG Files setting in your project. Also, since the image you are using is so big, try putting the left cap out further, say 40 or 50 pixels in.

iPhone - Center UIImage in UIImageView

I have a UIImageView. I get a UIImage from a URL. The image displays in the UIImageView, but I can't get it to center correctly. The UIImage is 80 x 68 pixels. The UIImaveView's size is 90 x 90. When I display the UIImage in the UIImageView the UIImage is shrunken so that it fits, although it is already smaller than the UIImageView. I have tried all the Content Modes in IB. Some of them shift the image up so that it is no longer in the UIImageView. None of this really makes sense to me. It seems that the UIImage should display inside the UIImageView fine if it is already within the required size. Any help would be great.
With Mode of Center on the UIImageView
alt text http://img406.imageshack.us/img406/3696/screenshot20090915at447.png
With Mode of Aspect Fit on the UIImageView
alt text http://img406.imageshack.us/img406/9373/screenshot20090915at447e.png
With Center, the size of the image seems correct but you can see that it goes out of the UIImageView which has a red UIView underneath it and is actually 2px on each side larger than the image view. But with the Aspect Fit, it makes the image smaller so that it fits inside. But I don't understand why it would make it smaller if it is already small enough to fit.
Sorry for wasting anyone's time. Turns out I didn't try all of the content modes. Seems that Content Mode of Bottom top works. This is backwards from how I understood it. Thanks for all your help.
Try this. Change your UIImageView to be the same size as the UIImage that you are going to load, then position the UIImageView so that it's centered. This is the approach I've taken since I find UIImageView to be a bit funny to work with. Or, if you prefer, skip the UIImageView and just draw the UIImage using it's - (void)drawInRect:(CGRect)rect method.
Sounds like your image contains transparent areas, at least at the bottom, which shift the image off center.
Edit: Also, you should check that the resolution of the image is set to 72dpi.