outside border for UIImageView - objective-c

I know I can create border using below code.
[[myImageView layer] setBorderWidth:2.0f];
[[myImageView layer] setBorderColor:[UIColor greenColor].CGColor];
However this draw border inside image.
What I was looking is draw border outside ImageView.
Note:
I search online for this and found below.
Can be done by using another image which will have border.
Can be done by drawing another view which is little bigger then current image.
Is there quick way (especially in-built in iOS), where I can draw border outside UIImageView? Any views?

Why don't you try border with using imageview's frame ?
CGFloat borderWidth = 5.0f;
self.imgview.frame = CGRectInset(self.imgview. frame, -borderWidth, -borderWidth);
self.imgview. layer.borderColor = [UIColor blueColor].CGColor;
self.imgview. layer.borderWidth = borderWidth;

There is no quickway in-built in iOS, there is no margin that you could set on the image layer.
If I were you, I'd develop a new class that inherit from UIView (ex UIImageWithBorderView) and which include a UIImageView and making the "UIImageWithBorderView" bigger than the UIImageView (and think about NOT to autoresize the UIImageView with the UIView parent, otherwise your UIImageView will be stretched, and prevent the UIImageWithBorderView from being smaller than the UIImageView frame), and then add borders to the "UIImageWithBorderView".
This way, your UIImageView will be intact and you'll have a specific, reusable composant for your needs.
Hope it helps !

Related

Blank pixels left when NSWindow with opaque set to NO

I have a NSWindow where I set opaque attribute to NO. The problem is that when I put any view inside that window it's corners has blank pixels.
Everything works well when opaque attribue is left with YES value, however, window's corners are not rounded anymore. See picture:
I've created repository with simple example project at bitbucket: https://bitbucket.org/lukaszb/animationartifacts
Is there a way I can fix this (remain window's corners rounded and blank pixels not appearing)? Or should I try another solution (without setOapque:NO at NSWindow subclass)?
Try enabling the Core Animation layer for your RoundedView, i.e., open MainMenu.xib, select RoundedView and in the “View Effects” tab (rightmost one) check the view under “Core Animation Layer”.
Alternatively you can do it programmatically, e.g., in RoundedView add:
- (void)awakeFromNib {
self.wantsLayer = YES;
self.layer = [CALayer layer];
self.layer.backgroundColor = [[NSColor blackColor] CGColor];
self.layer.cornerRadius = RADIUS;
}
Also #import <QuartzCore/QuartzCore.h> and add QuartzCore.framework to the project. You can then delete the drawRect method since CALayer already does rounded corners for you. (Actually you can delete your whole RoundedView class if you just set up this layer for a regular NSView that you use in its place.)
You can create a Subclass of NSView, make a custom drawing using NSBezierPath in it's drawRect: method, and then set it as the content view of the window.

UITableViewCell's backgroundView overlapping contentView

I am trying to set the backgroundView parameter of a UITableViewCell, but the backgroundView is overlapping the bounds of the cell. I have tried setting masksToBounds to YES, but that doesn't seem to make a difference. Please can you tell me where I am going wrong?
Here is an image showing my problem:
Here is my code:
UIImageView *iv = [[[UIImageView alloc] initWithFrame:cell.frame] autorelease];
[iv setImage:[UIImage imageNamed:#"paper"]];
[iv.layer setMasksToBounds:YES];
[cell.layer setMasksToBounds:YES];
[cell.contentView.layer setMasksToBounds:YES];
[cell setBackgroundView:iv];
Using masksToBounds doesn't work because the bounds of the cell are a rectangle.
Even if the corners of the cell are rounded, they're still part of the cell (but they contain transparent pixels). When a cell is displayed in a grouped table view, its background view (and its selected background view) is drawn in regard of its position in its section (middle, top, bottom, single).
So, if you want to provide a custom background view, you need to compute the position of the cell in its section and provide the adequate background :
either by using 4 different images
or by using the mask property of the background image's layer
or by subclassing UIView and implementing drawRect: so the graphic context is clipped before the image is drawn.
Are you setting every cell that background view, if so why don't you just set it to the table view background.

Drawing on top of UIImageView to make the image transparent

I am working on one iPhone App wherein I need to make a portion of the image transparent by setting its alpha level to 0 as the user moves around his finger on the image. Basically if you happen to know the app store application iSteam, user should be able to move his finger around on a top image which will make the background image transparent.
Currently I am using two UIImageView. One that holds the background image and the other on top of it which holds a darker image. Now user should be able to draw random curves on this darker image which will make the part of the background image appear on top. I am not able to figure out how should go about making the top image transparent which the top most of two UIImageView holds.
Any idea on this? Also what should I use for this? Quartz or Open GL. I am a newbie to the iPhone App Dev and have absolutely no idea about these APIs so some guidance from the experts will surely help me getting ahead with iPhone SDK Development.
The UIImageView has a layer which you can refer to as its layer and talk to when you've linked your project to QuartzCore. As the user moves a finger, clip a clear shape in an opaque-color-filled graphics context the same size as the UIImageView, turn that into a CGImageRef, set that as a CALayer's contents (again this CALayer needs to be the same size as the UIImageView), and set that layer as the UIImageView's layer.mask. Wherever the mask is clear, that punches a transparent hole in the layer, which means the view, which means the image the UIImageView is showing. (If that doesn't work, because the UIImageView doesn't like your interfering with its layer, you can use a superview of the UIImageView instead.)
EDIT (next day) - Here's sample code for a layer's delegate that punches a circular hole in the center:
-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)c {
CGRect r = CGContextGetClipBoundingBox(c);
CGRect r2 = CGRectInset(r, r.size.width/2.0 - 10, r.size.height/2.0 - 10);
UIImage* maskim;
{
UIGraphicsBeginImageContextWithOptions(r.size, NO, 0);
CGContextRef c = UIGraphicsGetCurrentContext();
CGContextAddEllipseInRect(c, r2);
CGContextAddRect(c, r);
CGContextEOClip(c);
CGContextSetFillColorWithColor(c, [UIColor blackColor].CGColor);
CGContextFillRect(c, r);
maskim = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
CALayer* mask = [CALayer layer];
mask.frame = r;
mask.contents = (id)maskim.CGImage;
layer.mask = mask;
}
So, if that layer is a view's layer, and if the UIImageView is that view's subview, a hole is punched in the UIImageView.
Here's a screen shot of the result:

How do you position a larger NSImage inside of a smaller NSImageView programmatically?

Let's say I have an NSImage that's 100x100. I also have an NSImageView that's 50x50. Is there a way I can place the NSImage at coordinates inside the NSImageView, so I can control which part of it shows? It didn't seem like NSImage had an initWithFrame method...
I did this in my NSImageView subclass, as Andrew suggested.
- (void)drawRect:(NSRect)rect
{
[super drawRect:rect];
NSRect cropRect = NSMakeRect(x, y, w, h);
[image drawAtPoint:NSZeroPoint
fromRect:cropRect
operation:NSCompositeCopy
fraction:1];
}
I don't believe so, but it's trivial to roll your own NSImageView equivalent that supports center/stretch options by drawing the image yourself.
Make your imageview as big as the image, and put it inside a scrollview. Hide the scrollers if you want. No need for subclassing in this case.
NSImageView has a method -setImageAlignment: which lets you control how the image is aligned within the image view. Unfortunately, if you want to display part of the image that doesn't correspond to any of the NSImageAlignment values, you're going to have to draw the image programmatically.
Depends on what your eventual goal is but the easiest thing to me seems to put your NSImageView inside an NSView (or a subclass – doesn't have to be NSScrollView as "#NSResponder" user suggests but this should work well too), set its imageScaling to NSImageScaleProportionallyUpOrDown and its frameSize to image's size. Then you can move your NSImageView freely around the upper view using setFrame:myDesiredFrame. No subclassing, no manual redrawing, etc.

How do I pan the image inside a UIImageView?

I have a UIImageView that is displaying an image that is wider and taller than the UIImageView is. I would like to pan the image within the view using an animation (so that the pan is nice and smooth).
It seems to me that I should be able to just adjust the bounds.origin of the UIImageView, and the image should move (because the image should paint inside the view with that as its origin, right?) but that doesn't seem to work. The bounds.origin changes, but the image draws in the same location.
What almost works is to change the contentsRect of the view's layer. But this begins as a unit square, even though the viewable area of the image is not the whole image. So I'm not sure how I would detect that the far edge of the image is being pulled into the viewable area (which I need to avoid, since it displays by stretching the edge out to infinity, which looks, well, sub-par).
My view currently has its contentsGravity set to kCAGravityTopLeft via Interface Builder, if that makes a difference (Is it causing the image to move?). No other options seemed to be any better, though.
UPDATE: to be clear, I want to move the image inside the view, while keeping the view in the same spot.
I'd highly recommend enclosing your UIImageView in a UIScrollView. Have the UIImageView display the full image, and set the contentSize on the UIScrollView to be the same as your UIImageView's size. Your window into the image will be the size of the UIScrollView, and by using scrollRectToVisible:animated: you can pan to particular areas on the image in an animated fashion.
If you don't want scroll bars to appear, you can set the showsHorizontalScrollIndicator and showsVerticalScrollIndicatorproperties to NO.
UIScrollView also provides pinch-zooming functionality, which may or may not be useful to you.
Brad Larson pointed me down the right road with his suggestion to put the UIImageView inside a UIScrollView.
In the end I put the UIImageView inside of a UIScrollView, and set the scrollView's contentSize and the imageView's bounds to be the same size as the image in the UIImage:
UIImage* image = imageView.image;
imageView.bounds = CGRectMake(0, 0, image.size.width, image.size.height);
scrollView.contentSize = image.size;
Then, I can animate the scrollView's contentOffset to achieve a nice panning effect:
[UIView beginAnimations:#"pan" context:nil];
[UIView setAnimationDuration:animationDuration];
scrollView.contentOffset = newRect.origin;
[UIView commitAnimations];
In my particular case, I'm panning to a random space in the image. In order to find a proper rect to pan to and a proper duration to get a nice constant speed, I use the following:
UIImage* image = imageView.image;
float xNewOrigin = [TCBRandom randomIntLessThan:image.size.width - scrollView.bounds.size.width];
float yNewOrigin = [TCBRandom randomIntLessThan:image.size.height - scrollView.bounds.size.height];
CGRect oldRect = scrollView.bounds;
CGRect newRect = CGRectMake(
xNewOrigin,
yNewOrigin,
scrollView.bounds.size.width,
scrollView.bounds.size.height);
float xDistance = fabs(xNewOrigin - oldRect.origin.x);
float yDistance = fabs(yNewOrigin - oldRect.origin.y);
float hDistance = sqrtf(powf(xDistance, 2) + powf(yDistance, 2));
float hDistanceInPixels = hDistance;
float animationDuration = hDistanceInPixels / speedInPixelsPerSecond;
I'm using a speedInPixelsPerSecond of 10.0f, but other applications might want to use a different value.