Can I pause a view for a certain amount of time? Basically, while an action is occurring, my view becomes messed up and I cannot figure out why. Everything gets shifted, and I've been looking through the code line by line for hours. So can I prevent the view from changing itself and then somehow resume it after the action is over? I really don't know if this is a stupid question, but thanks for your help!
The action is sending something to a server, for whatever reason the
entire view is shifted. After the view is shifted, I have the
coordinates outputted to the log, and it thinks the view is at 0,0,
even though it's not.
I think you might be getting mixed up in the distinction between frames & bounds?
From this link
The frame of an UIView is the rectangle, expressed as a location (x,y)
and size (width,height) relative to the superview it is contained
within.
The bounds of an UIView is the rectangle, expressed as a location
(x,y) and size (width,height) relative to its own coordinate system
(0,0).
Essentially, if you're looking at the origin coordinates of the bounds of your view, it will always be 0,0. Instead, you should look at its frame coordinates. I hope this helps you in figuring out the problem.
No, there's no general mechanism for preventing changes to a view. If the view in question is your own UIView subclass, you can of course override the methods that modify the view and effectively prevent changes that way. That'd be a lot of work, however, and I don't think the result would be worth the effort; you'll be much better off finding the real problem and fixing it. It's always easier and better to work with the framework and not against it.
Related
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 am banging my head on the wall here due to this problem:
When I create a UIImageView this view has a certain orientation and size. Lets call this state "A".
This view responds to taps. It can be dragged around the screen.
At some point in the code I apply a CGAffineTransform to the view. Does not matter if the affine is a scale, a rotation, a translation or a combination of all. Does not matter also if the transform is absolute or relative. Not to mention the device can change its orientation and the view is autorotated to the correct orientation (that we can cay is a kind of rotation or transformation applied to the view).
The problem is: the moment I touch that object or try to animate its transparency or any other parameter, it "remembers" the state "A" and does all animations from that state, not from current state. If I simply touch the view, it returns instantly to state "A". The code is not doing it by itself. It is pretty annoying. How to I make a view assume its current state of transformations as the reset or initial state? In other words, how do I make a view forget its past transformations or states?
The only way I know is recreating the view, but this is a ridiculous way of doing this.
Is there any way to make this work as I described?
thanks
Afaik, all of the SDK animations automatically create a copy, perform the animation on the copy while hiding the original. In your code you'll have a getState line that starts this and creates the pointer to the animation object. To make it permanent at the end of your animation routine set the original objects view to the animation view.
Iirc it something like this, but I don't have my code samples in front of me:
myOriginalObject.view = myMnimationObject.view
Obviously do this before you release your animations but after you're done with the transforms.
This is probably either real easy, real dumb, or my google fu has taken a serious turn for the worse. Anyway, I'm implementing custom view for my app, which is using pure CGContext drawing, no subviews (for now at least). The thing is, I want it to autorotate, so I have shouldAutorotateToInterfaceOrientation return YES, and voila, the view rotates. But in doing so it's not actually redrawing the content (which I assume is rendered into a texture somewhere in the framework and splashed onto a rect, but that's not really relevant here), the rect is simply stretched, squishing the content. How can I get it to simply issue a draw of a bigger area while rotating? That is, my content is bigger than the screen, and I'd simply like the viewport to change during the rotation.
I've tried setting the view's contentMode to UIViewContentModeRedraw, but that didn't do anything, I've tried playing around with the autoresizeMask stuff, but didn't seem to help either. I've also tried inserting a setNeedsDisplay in willRotateToInterfaceOrientation, however that only caused it to redraw using the new bounds (i.e. squishing it first, and then stretching it out to the right size during the rotation), which is also not what I'd like to see.
Does anyone have any idea how I might go about getting this to work?
As it turns out, it's a mix of dumb and easy. I'm posting it here if anyone should care to read it someday. They way I managed to solve it was actually sandwiching a view between window and my view (I suppose you might be able to go to work on the window directly, but it felt more intuitive this way). That is, I added my view as a child view to that view, which I'll call the frame.
The frame is a resizing as normal, however, I turn OFF resizing of child views, and make my own view LARGER than the viewing area (square actually, 480x480, so it can cover the entire screen either way). Problem solved, basically.
Now I'm playing around with animating the offset of the view in the frame during willRotateToInterfaceOrientation, to have it appear to be rotating around the center, rather than the upper left corner, but that's a different question.
I have a single UIView for drawing any one of a set of items. That is, my one UIView subclass can be told to draw a square, circle, or triangle for example.
I'd like to have a transition to flip that view so that the UIView draws a different shape at the half way point, so it looks like I'm transitioning to a different view, but really I'm just redrawing the single view at the half way point of the transition.
Is there a way to do this, without resorting to using two different UIViews and swapping them out in the animation block? It would be a bit clumsy for me to rejig what I have to use the swap mechanism.
Ideally all I need is some callback or notification that the animation is at the half way point, and then I can redraw the view with the new shape then.
Thanks for any help!
Even if you did know the midpoint of your flip animation, I don't believe redrawing the content of the view mid-animation would do anything. I think that the contents of the view's layer are cached at the beginning of the animation and don't change as the animation proceeds. Also, your view would end up inverted, left to right, at the end of the animation if you didn't have another view behind it.
If you wish to do this as a custom animation, you could break this into two halves using something like Mike Lee's Lemur Flip implementation that I describe in this answer. After the first half of the animation, you could redraw the view's content and complete the animation, ending up back where you started.
However, to me it seems more clumsy to not switch views in response to the transition. It certainly will take a lot more code to do.
you can try to do smth like this. For example, your animationDuration property is set to 2.0f. so, the half way point is 1 second, so you can use
[self performSelector:#selector(yourCallbackMethod) withObject:nil afterDelay:1.0f];
The only way I know of that you could do this is to re-create the animation using Core Animation and then monitor the animation in the presentationLayer using a timer. There is no KVO available in Core Animation Layers so you have to monitor it explicitly.
In other words, it's probably not worth it. I suggest you think of a different way to solve your problem.
Everytime UIView's drawRect is called, the content drawn by previous drawRect (using Core Graphics) is cleared out. How can I make it so that the paths rendered from previous drawRect calls stay until I explicitly clear it?
You basically need to clip the 'dirty' part of your rect where changes have been made, and only this part will be re-drawn.
- (void)setNeedsDisplayInRect:(CGRect)invalidRect
I'm fighting this issue myself right now. The problem is there is a property on the UIView called "clearsContextBeforeDrawing" that according to the documentation is supposed to fix this problem, however it doesn't work that way in my experience.
I think ultimately the solution to this is going to be to allocate an offscreen buffer and do all my drawing there, then blt it over to the UIView in the drawRect method.
I'm pretty certain there's no way around this; it's how UIView is designed to work. If asked to, your custom view should be able to draw any part of itself at any time. This is partly because views can do more than just appear onscreen. e.g. on the desktop they can be printed, and even on the iPhone, you might wish to capture the contents of a view to a bitmap.