How do I set a centered or stretched background image? - ios

I have universal app. In that app I need the background image to be centered or stretched. That way when I rotate the device or switch it the image displays correctly.
Here is my code in viewDidLoad:
self.view.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"tux.png"]]
Can anyone tell me how to accomplish this?

I think you can't easily make it centered with backgroundColor. You may:
Stretch it before setting the image as backgroundColor, see How to fill background image of an UIView.
Create a customized UIView subclass and draw the background image yourself by overriding drawRect: method;
Or add a UIImageView to you view as the background. See "UIView Class Reference: Alternatives to Subclassing":
Image-based backgrounds - For views that display relatively static content, consider using a UIImageView object with gesture recognizers instead of subclassing and drawing the image yourself. Alternatively, you can also use a generic UIView object and assign your image as the content of the view’s CALayer object.

Related

background image for CGContext

Question: How do I display a background image underneath a CGContext?
I have created a view controller using the storyboard and placed a view with a full-screen background image. Then, using the same view controller, I created a outlet to a UIView that has a CGContext where I draw a few lines.
Everything works except that the drawing takes place underneath the background image. (Suddenly I wonder if it's not the CGContext but the UIView that is the problem.)
I found a similar question here, but the solution makes it sound like the background image has to be constantly refreshed using CGContextDrawImage with a CGImageRef. Which may be true, but a static image being constantly refreshed doesn't sound like a very elegant solution. Thank you!
Create custom UIImageView subclass where you will draw your custom background.
Better to subclass UIImageView instead of UIView, because in this case you don't get problems with adding other views above this in Interface Builder.
Add UIImageView to your view controller, and change class to your custom class. Add all other views above.
Question: How do I display a background image underneath a CGContext?
Answer: Set the color of the view with the CGContext to Clear Color.
That way the background image is visible as well as the lines that are subsequently drawn. Guess I kind of overcomplicated that one.
Thank you for the response Vitaliy.

Custom UIView drawRect is called even with UIViewContentModeScaleAspectFill

I'm having the following issue.
Suppose I have my own image view class (to make it easy I've trimmed all the code and just included only the code that is causing the issue). That class inherits from UIView and overrides drawRect. Here is how my drawRect looks (the code is in Xamarin, but it's easy to understand)
public override void Draw(RectangleF rect)
{
base.Draw(rect);
CGContext context = UIGraphics.GetCurrentContext();
if (Image != null)
{
var imageRect = getAspectFillRect(rect, Image.Size);
context.DrawImage(imageRect, Image.CGImage);
}
else
{
this.BackgroundColor.SetFill();
context.FillRect(this.Bounds);
}
}
This code simply draws the image set to Image property in a way which simulates UIImageView's aspect fill option by calculating the rect which will display the image in aspect fill mode using this line of code getAspectFillRect(rect, Image.Size);
I also have UICollectionView with custom layout and custom cells. Each UICollectionViewCell UI is defined in an xib file, there I have all the necessary constraints set and I there I also have my custom view for displaying images. For that view in interface builder I've set content mode to "Aspect Fill". The custom UICollectionViewLayout is made in a way that cell expands (you'll see the example shortly). So the image inside the cell should also scale, and as I've set "Aspect Fill" option, it shouldn't call drawRect of my custom view, rather it should just scale already drawn content. But that is not the case!
LOOK HERE to see the video which demonstrates what happens.
You may see that the image inside is not growing together with the cell. The problem is that before ever the cell expanding animation begins drawRect of my custom UIView is called with the rect which will eventually be established after the animation. So I get a jerky animation. In my custom layout code I just call LayoutIfNeeded after updating the constraints of the cell. I don't call setNeedsDisplay, so I don't get why my drawRect is called.
For experiment I replaced my custom image view with UIImageView, I set it's content mode to "Aspect Fill", and LOOK HERE what happened. YEAH! It worked. So I suppose the issue is not in the custom UICollectionView layout, rather in my custom image drawing class.
What I should take into account?? How I should handle this case? Any Ideas?
Thanks!
DrawRect will be called whenever the system "feels" it should call it. Regardless if you call SetNeedsDisplay or not.
Now, setting ContentMode to ScaleAspectFill does not mean that DrawRect will not be called. In fact, from Apple docs here:
Instead of redrawing the contents of the view every time, you can use
this property to specify that you want to scale the contents (either
with or without distortion) or pin them to a particular spot on the
view.
This means that, if you don't want to go through the hassle of drawing the contents yourself, just set the ContentMode property. In your example, you are using DrawRect to draw.
Now, the fact that DrawRect is called before the animation starts, but with the target value for Bounds (or Frame?) means that the target value of these properties is set before the change finishes. During an animation, these properties do not change. Note during. A Bounds' or Frame's value will not change through all the values of an ongoing transition. It only knows "start" and "end".
What would happen in your app if DrawRect was not called before the animation start, but was called after animation end? Well, the cell would resize along with its subview, but your image would remain small throughout the animation and snap to the large size after the animation finished. So it's one way or the other.
Solutions:
Use the UIImageView.
If you do need to use a custom view, use a UIImageView on that to display your image.
Draw your image on a custom CALayer and add that layer on your custom view's Layer.

How to correctly set background for retina?

May be the question is elementary, but I have a bug with setBackgroundColor.
I have the UIView which contain UITableView. UITableView is clearColored. I'm trying to set background on UIView:
[self.viewForTable setBackgroundColor: [UIColor colorWithPatternImage:[UIImage imageNamed:#"bgIngrList.png"]]];
On normal iPad it's looks like:
But on retina iPad (like the second image began showing):
I have two images "bgIngrList.png" and "bgIngrList#2x.png" with 290x260 and 580x520.
Where can be the bug?
EDIT
I have solved the problem by using UIImageView instead of UIView.
Thanks to everybody!!!
colorWithPatternImage: (as the name suggests) thinks your image as pattern to fill. so if the image you give is smaller than the size of the view, its gonna draw the pattern image again rather than stretching it. that is what happening here. your image's size is smaller than view's size hence its drawing the image again at the bottom. You can avoid this by adding a UIImageView and setting the image property rather than setting the backgroundColor of UIView.

Create custom UIView draw

What is the best way to create a custom UIView? So i got 3 images (top, mid, bot)
and inside the button i want an image (it need to be resizable (in height only)
How can i create this with UIView so i can put a image inside it and that the views resize? (I want this in a UITablecell)
Try these two links for custom UITableView Drawing:
cocoawithlove.com/2009/04/easy-custom-uitableview-drawing.html
http://adeem.me/blog/2009/05/30/iphone-sdk-tutorial-part-6-creating-custom-uitableviewcell-using-interface-builder-uitableview/
Within there you should be able to set each cell' height separately. If not there, then override the UITableViewDelegate method
tableView:heightForRowAtIndexPath:
http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UITableViewDelegate_Protocol/Reference/Reference.html
If you're using iOS 5 have a look at the resizableImageWithCapInsets: method in UIImage.
This allows you to specify which part of your image should resize and which should scale automatically. This is ideal for reusing background images like in your case.
So you would create your resizable image with the blue background and specify the offset from the edges that should resize with the image. You don't have to slice or chop your image, just provide it as one whole image, the scaling will happen automatically and your rounded corners will stay in tact if you specify the cap insets correctly.
// Change the edge insets to match your image...
UIImage *backgroundImage = [[UIImage imageNamed:#"button_background"]
resizableImageWithCapInsets:UIEdgeInsetsMake(10, 10, 10, 10)];
// Create an image view to hold the new image
UIImageView *myBackgroundImageView = [[UIImageView alloc] initWithImage:backgroundImage];
// [...] here make sure to size your image view to match the size of your parent view
// Add the background image view to the view
[self addSubview:myBackgroundImageView];
Then you're free to use a similar technique for custom tableview cells. But the idea here is to use a resizable image with edge insets to scale your background image dynamically.
Here's a good blog post explaining edge insets.
Hope that helps.

Make a UIButton background image larger than frame

I'm trying to make a UIButton with a background image where the image is larger than the button frame.
The problem is, the UIButton automatically scales the image to fit and haven't found a way to change the behavior.
Am I missing something obvious or is it time to make a custom button?
Subclass UIButton and override the
- (CGRect)backgroundRectForBounds:(CGRect)bounds;
method so it returns the size you want.
TIP: Use this method to center your background as well.
Looks like the answer to this one is. Not possible through existing interface on UIButton.
The simplest way to implement seems to be using a custom sub class of UIButton and creating a UIImageView with the same frame as the UIButton, turn off clipping and scaling and then just capture all the setBackground methods and capture state changes to handle "normal" button interaction changing the background images.

Resources