I'm drawing three rectangles, one of which falls off the end of the view, (i.e. the drawing is bigger than the current view bounds) so you don't see the right edge. This is good, but when the view is rotated, the right edge is still clipped, even though there's plenty of room to draw it. How can I get the view to redraw the full rectangle?
I've tried:
1) changing the frame and bounds rectangles to bigger
2) calling setNeedsLayout
3) calling setContentMode:UIViewContentModeRedraw;
4) calling [self.view setClipsToBounds:NO]
Trying a CGLayer is next, unless somebody suggests something else.
-Owen
Make sure your autoresizing mask on this layer is set properly in IB. If its not stretching the right way on rotation then the view will not take the new shape of the screen.
Related
Is there a way to a bounding box for a view so that its subviews cannot leave the view?
I currently have UIImageViews which I move around, scale, rotate etc and they are able to leave the view area.
How does one set the superview to bound/hold the subviews within it?
How else can this be done. I currently detect the origin of the image this works to the point that the image moves until it reaches this origin, when it does, the image is stuck.
I use gestureRecognizers and this origin technique only works for panning/moving an image.
Any suggestions?
If you want to stop a view's subviews from being drawn outside its borders, you need to set its clipsToBounds property to YES. (See the UIView class reference for details.)
If you want to stop your views from being in certain positions, don't move them there! It's your code that's putting them where you don't want them to be. If you're using a gesture recogniser, presumably you have a method that responds to gestures by adjusting the frame of a view - put some conditions on this movement that prevent it from happening when you don't want it.
When you write these conditions, bear in mind that a view's origin is relative to its superview. For example, say you have a view controller with a view that takes up the whole screen of the device, and inside that a box that starts at 0, 100, and inside that some squares and circles and squiggly shapes that the user can move around. If you examine containerBox.bounds.origin, you'll find that it's 0, 100, but if you want to put a square in the top left corner of the box, you need to get its frame and set the origin to 0, 0. Something to look out for.
I didn't follow your explanation of the 'origin technique'. If you paste your code, I might be able to help.
My question is very similar to this one Not drawing outside bounds when clipToBounds=NO which received no clear answer.
Basically I have a UIView, and I want to draw a line from the center of it, to the edge of the screen. Calculating where these points are is easy, using [self convertPoint:(CGPoint){0,0} fromView:[self superview]]; (which finds the origin with respect to my view's superview. But when I draw a line from my view's drawRect: it gets clipped at my view's bounds.
Is there a way to draw outside of my view's bounds? I've tried changing the clipsToBounds property, but it doesn't seem to have any effect.
I can't draw my lines from the superview because I need to do this with multiple views and some will be in front of others... figuring out the layer from the superview's drawRect seems like a bad idea.
Similarly, I don't think I can just resize my view's bounds to include the entire screen, because my views need to be dynamically re-sizable... the bounds would have to be HUGE (>20,000 points square) for this to work.
I wouldn't recommend ever drawing outside of a view's bounds. Either your view needs to resize automatically to include your drawing or you need to have transparent overlapping views. Or both. I can't think of a situation that either of these cases wouldn't cover, but I may lack imagination. =)
Likely what is happening currently is that when the super view gets redrawn it tells the super view that it needs redrawn, resulting in erasing the drawing you are doing outside. It's been a while, anyone more knowledgeable can (should!) correct me here if I'm wrong.
I don't know if "Quartz Debug" (from the standard apple developer tools install, /Developer/Applications/Performance Tools/Quartz Debug) works in the simulator, but it's worth a try. It has a mode that will show you when and how often redrawing takes place, with a border and optional delay on the refreshes.
You can do what you are asking, but you need to force redraw your sub-views every time you go outside the sub-view's bounds, meaning that your super-view needs to manually draw it's children inside of it's draw function. Essentially you would be throwing out apple's drawing paradigm and simply causing your sub-views to act like a drawing extension of your main view anyway.
Additionally, if your ranges are so dynamic you may want to consider drawing in percentages of the screen or super-view rather than in points, it may make more sense to code.
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.
In my iPhone app, I have a view (let's call it RectangleView) within the content view that I'd like to scale, along with all its subviews, when the iPhone is rotated. So, when the phone is rotated from landscape to portrait mode, I'd like RectangleView (and all its subviews) to keep their original shape and position relative to each other, but just get smaller. I am using autoresizing on it and all its subviews in Interface Builder to try and do this.
Now here's the problem. When the phone is rotated, all of RectangleView's subviews scale and move relative to the entire content view, not relative their parent view (which is RectangleView). This is a problem because the content view is now a different shape (portrait) than it was before (landscape), and so all the elements on the screen are in the wrong places, when they should just be scaled down within RectangleView. And I am confused because some of these elements even move out of RectangleView, which I didn't even know was possible since they are supposed to be contained within RectangleView.
Can anyone explain what might be happening here, and how I can just scale RectangleView and all its subviews to retain their original shape and positions, but just on a smaller scale? Thanks in advance!
Are you sure that they are moving out of the RectangleView, and it isn't that the RectangleView is resizing and filling the content area? Also, I'm not sure if it makes a difference, but I found that I needed to call [view setNeedsDisplay] after rotation to make my custom view work properly.
I've got a UIScrollview which fills a landscape screen, which contains a small tree of UIViews around inside it which I can scroll horizontally. I'd like to apply a barrel distortion to the scrollview, so that as the subviews move from the outside to the centre of the scrollview, they change shape.
What is a good what to go about applying distortions like this?
Is there a way to override drawRect for the scroll view, draw onto a bitmap, distort it, then draw that to the ScrollView's context instead? Or are there built in APIs to do this sort of distortion?
(source: arielnet.com)
You could get close to this effect by properly transforming the layers for each of your UIViews. Using a CATransform3D, you can rotate and translate each of the layers in 3-D, as well as apply a perspective effect. For your case, you can translate each of your UIView layers so that they are like a carousel, with the middle view forward and straight-on to the screen, and the side layers tilted and recessed slightly from the screen. This would not cause a curvature of the layers themselves (they will still be drawn as rectangles), but if you apply a transform on the main view's layer to create a perspective effect you should be able to get very close.
For an example of this kind of 3-D positioning of layers, I recommend this example where a full 3-D maze is constructed out of CALayers.
As far as the scroll view goes, you probably will have to do custom touch handling for this. You might be able to get by with respinding to the UIScrollViewDelegate methods like scrollViewDidScroll:, but I've not tried this myself.