Stretching a portion of a UIView using contentStretch - iphone

I need some help understanding the use of the contentStretch property on a UIView. I'd appreciate 1) some guidance on how to achieve the effect I'm going for and 2) a reference to any comprehensive documentation that exists on how to use this property. While I thought I understood the Apple documentation, I now see that I don't. Here is what I'm trying to do.
I have a custom UIView that renders a view that looks like figure a. below. The drawRect method of this UIView paints the inner box on the left (with the rounded corners and white background) with a different color and affect than is used for the rest of the view. Also, the 4 corners of the UIView are not stretchable (this would result in distortion) so I need to stretch only the center of the UIView background.
I want to grow this view to a shape similar to that pictured in figure b. below. In doing so I want only the portion of the view outside the white box (or to the right of the white box) to be stretched/repeated as I increase the UIView's height.
In all of my attempts I have only been able to produce a strecth that affects the entire width of the view and results in a view similar to figure c.
Is it possible for me to achieve the effect that I want (figure b.) using contentStretch? Is there some other technique I should be using short of re-drawing the entire view, or is re-drawing the only (or best) way to go about this?
Thanks,

To make this happen with contentStretch, you would have to set the contentStretch rectangle so that its top edge is below the bottom edge of the white box, and so that its left edge is to the right of the right edge of the white box. You will probably find that your background pattern gets stretched too much and looks ugly.
Instead, give your view a subview that draws just the white box. Set the subview's springs and struts so that the box stays at the upper left and doesn't stretch.

I would make the white box stretchable on top, and a background view filled with a pattern using colorWithPatternImage:
patternView.backgroundColor = [UIColor colorWithPatternImage:#"myBackgroundPattern.png"];
and the black stroke could be done with:
#include <QuartzCore/QuartzCore.h>
...
patternView.layer.borderWidth = 2.f;
patternView.layer.borderColor = [[UIColor blackColor] CGColor];

What you are trying to achieve can be done using the resizableImageWithCapInsets method of a UIImage. This way, you can set cap widths on each side of the image and specify which part of the image needs to be repeated (not stretched).
An UIEdgeInset is a struct consisting of four components as follows (CGFloat topCapWith, CGFloat leftCapWith, CGFloat bottomCapWith, CGFloat rightCapWith)
The code below would do the trick
UIImage * backgroundImage = [[UIImage imageNamed:#"Stretch.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(80, 4, 4, 10)];
backgroundImageView.image = backgroundImage;

Since content stretch is deprecated, best approach is to use auto layout. In the inner rectangle give a defining height and width constant and bind its top and leading constraints to the parent view.
In order to get a bottom growth in outer rectangle, bind its bottom constraint or alternatively you can also chnage it height.

Related

Make bottom part of UITextField(UIScrollView) transparent

Here's a good example that sums it up:
This is a UITextField that contains long text, so the user is able to scroll down to view the rest of the text.
How can I make the bottom rows appear "transparent"?
UITextField only allows setting global text properties (like color, font size, etc).
The trick is to create a CALayer containing a gradient and use it as mask layer of your UIView's layer (alpha values of the mask layer will be used.) see this answer: UIView border with fade or blur effect
This will help you.Not sure but some functionality like you want.
Hope this helps you.
All the best !!!

Stretchable image in drawRect causes slow scrolling

I am subclassing a UITableViewCell and in the drawRect: method I want to draw a stretchable image but I have experienced that this has a big impact on the scroll performance.
Does anyone know how I can use a stretchable image and still have a good scroll performance? Alternatively, I could make five images and draw those instead. One for each corner and a center image which would be stretched. This just seems such a hassle, and I actually thought that's what a stretchable image would do.
EDIT: If I should split up the image and stretch it myself, it should of course be nine images, not four. One for each corner, one for top middle, bottom middle, left middle, right middle and one for the center.
Try using [UIImage resizableImageWithCapInsets:] to create a resizable image instead of your own code. Create an UIImageView with image and just add it as subview to cell.contentView at index 0

How to anchor UIView a few pixel off the middle point using Autoresizing Mask?

Observe the following screenshot:
How do I anchor UIView a few pixel off the middle point using Autoresizing Mask so that it is always 20px to the left of the middle point?
I have tried setting the autoresizingMask property to UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin and it's not really doing it.
I did manage to do it if I wrap the view in another bigger view that fills the entire screen and doesn't resize at all. But is there a way to do it without an additional view?
Autoresizing masks don't handle this case very well, as you've already discovered. They work great if you want to keep something a fixed distance from its superview or proportionally resizing/repositioning somewhere in the middle. You can do a surprising amount with just those options, but off-center anchoring is not something you can do easily
If you want do this with autoresizing masks, you'll need to put your box inside another empty UIView, one that is in a more convenient position for autoresizing masks. It will look like this.
Here's what you've got right now:
center
|
|---------------------------------------------------| <-- The main parent view
|-----| <-- your view
What you want is this:
center
|
|---------------------------------------------------| <-- The main parent view
|--------------------| <-- The new view, centered in the parent
|-----| <-- your view
The new view should be completely transparent, have a fixed width, and a flexible distance from both sides of the parent view. It should be wide enough to fully contain the off-center box, and no wider. If it is positioned exactly in the center of the main parent view, it will stay centered no matter what happens to the size of the parent view.
Then add your box as a subview of the new view, with a fixed width and fixed distance from the left edge of the parent. Now, using only autoresizing masks, your view will stay where you want it.
A simpler option might be to override -layoutSubviews on your view, or -viewDidLayoutSubviews on your controller (available iOS 5.0 and later) and just manually position the view. But you asked how to do it with autoresizing masks, so that's what you got. Without adding an extra view, there's no way to use autoresizing masks to get the positioning behavior you want.
I guess the best solution is to set center property to:
myview.center = CGPointMake(self.view.frame.size.width/2-20, myview.center.y);
And set up it in willRotate method.
Not exactly an answer, more of an avenue for exploration. You can try playing with the layer-level property anchorPoint. Setting it to (1.0, 0.5) means the layer's position will be defined by its right edge. In that case centered would mean the right edge is centered. Set flexible left margin and flexible right margin and it might stay left of the center.
To get it exactly 20p left of the center, just set the anchorPoint to 20p right of the center of the view. (But anchorPoint units are a fraction of the size of the layer, so do some math to find the right value.)
I'm not sure if it will work. I'm not sure what the effects are of mixing layer-level positioning with autoresizing.

how to create a pointy UIView

I just saw local mind's app and they have a horizontal UIScrollView that has a selection with a pointy tip. How can I create such thing? I saw this often times in many apps where you don't just have a square frame, but you have a pointy edge to it, is this just a UIImage overlayed on top?
Other example would be this
If you disable clipsToBounds in the horizontal UIView (which is default), its subviews are allowed to stick out and draw past the edge of the frame.
Thus, yes, a UIImageView was probably how it was accomplished.
This is most likely achieved using an image. As simple as that.

How to auto rotate your own custom views?

I've learned that the best way to get graceful rotation is to set the auto rotation mask on the view that you want resize or move. This works fine if you're using SDK views like UILabel, but if you have your own custom view that uses the drawRect method it doesn't rotate as gracefully. In fact the only thing that happens is that it stretches whatever you drew in drawRect.
I've tried redrawing both before and after the rotation, but it doesn't give me that smooth rotation.
I looked at a UITextField auto rotating (flexible width) in slow motion and it follows the edge perfectly during the rotation. That is what I want my view to do, so how do I do that? My views jump to the right position either before or after the rotation.
The following line will make your UIView stretch the middle pixel only. If this is not your desired behavior I suggest you read the documentation for contentStretch to learn how to manipulate the values of the CGRect.
[self setContentStretch:CGRectMake(0.5, 0.5, 0.0, 0.0)];
I would guess that the UITextField you're looking at has at least three subviews, one displaying the left cap of the field's border, one displaying the right cap, and one displaying the middle, with autoresizing masks of "flexible right margin", "flexible left margin", and "flexible width", respectively. If you set up your custom view something like that, and make sure its autoresizesSubviews property is set to YES, then you should get the same smooth resize that the text field does.