How to convert window coordinates relative to a specific view? - iphone

Example: I have a CGPoint in window coordinates:
CGPoint windowPoint = CGPointMake(220.0f, 400.0f);
There is aView which has a superview in a superview in a superview. Somewhere deep in the view hierarchy, probably even transformed a few times.
When you get a UITouch, you can ask it for -locationInView: and it will return the coordinates relative to that view.
I need pretty much the same thing. Is there an easy way to accomplish that?

I found a really easy solution:
[self.aView convertPoint:windowPoint fromView:self.window];

Perhaps you could iterate through the superview tree, drilling down to subviews by tag, and add or subtract the subview's frame.origin values to get to a translated windowPoint relative to the view-of-interest's frame.origin.

Related

convertRect fromView not returning correct frame after rotation

I have a problem I've run into with the UIView method convertRect: fromView: method. Here is the situation:
I have an overwritten the UIView class to create a view that rotates with the user's movement(very similar to the TaskRabbit spinner). To create the rotation, over I added an additional view to my subclassed view, and I rotated that view. The rotated view contains additional subviews that obviously rotate with the rotated subview. The problem is, after the subview has been rotated, I need to find where those additional subviews are, with respect to the original overritten view - not the rotated view. To do this, in my UIView class, I have the following:
[self convertRect:currentView.frame fromView:rotationView];
However, when I print out the frame of the converted rect, the coordinates are not accurate. Has anyone run into this issue where the convertRect: fromView: isn't accurate after the view is rotated?
Edit
Specifically, about the points being not accurate, I can't even see the relationship between what is should be and what it is-ie off by an specific angle, x/y flipped etc. For example, the point that should be (25, 195) is returned at (325.25, 273.16)
I'm assuming that you are rotating your views by applying a transform to them (either a CGAffineTransform to the view or a CATransform3D to the layer). This is what is causing the problem with your frame. The documentation for UIView frame says:
Warning If the transform property is not the identity transform, the value of this property is undefined and therefore should be ignored.
As you've already seen, the value of the frame is undefined. You can still use the center and bounds properties though.

finding the center point of the screen in a zoom view in iphone

I'm trying to add a box to the centre of the screen in a zoom view. E.g. if I move into an area of the content view and try using the offset coordinates, it becomes erratic if I zoom in or out. I can't seem to figure out the right mathematical formula for this.
If you are working with a UIView or one of it's subclasses. You'll always have a center property available for you. That property is a CGPoint and you can do something like this to test if it is the required result you seek:
CGPoint center = [YourUIViewOrSubclass center];
NSLog(#"Center x is '%f' and y is '%f', center.c, center.y);
I hope this helps you. Otherwise try and rephrase your question and include a little context.

subview location after UIView Rotation

I have UIView which have subviews , I have rotated view with 90.
CGAffineTransform transform = CGAffineTransformMakeRotation(degreesToRadians(degrees));
Now I need to subview location in screen coordinate system and for that I am doing
CGPoint subViewPoint = [[subView superview] convertPoint:subView.frame.origin toView:baseView];
This is working fine , if I am not rotating the View but its not working if i am rotating the view. Please help me on this.
How to get the subview location in screen after its super view 90 rotation.
I'm not sure, but there are two things to know.
1) You should avoid using frame property when you have to deal with transformations. Use center and bounds properties instead. Frames of views that have not identity transformations are invalid.
2) You can always use CGPointApplyAffineTransform function to calculate point coordinates by yourself : )
Hope this'll help.

How to shift item position in UIKit

Sorry guys, I hate asking dumb questions but I have seriously been searching for days online to no avail. Every method I've tried with item.bounds or the like has failed miserably. I'm just trying to move some elements, like a UILabel and a UIButton over a few pixels under a certain circumstance. Just a simple point to a tutorial that I missed would be so helpful.
Generally frame is what you want. It is specified in terms of parent view coordinates. So if my view's frame is CGRectMake(10.f,20.f,50.f,60.f) it appears in the parent's coordinates at x=10 y=20 with width 50 and height 60.
UIView* someView ...
CGRect someViewFrame = someView.frame;
someView.frame.origin.y += 10;
someView.frame = someViewFrame;
moves the view down by 10 pixels.
If you just want to move the view in a superview, leave bounds alone.
This example should be useful.

UIView. How do I constrain scaling to one dimension only

I have an instance of UIScrollview containing an instance of UIView. The UIView is just a container for a horizonal array of UIImageView instances. - Zooming is provided by UIScrollView and UIScrollViewDelegate. I would like to constrain zooming to occur only along the horizontal axis with no vertical scalling at all. How to I do this?
Is there a way, for example, to subclass UIView and override the appropriate method to prevent vertical scaling? I like this approach but I am unclear on which method to override and what that overridden method should actually do.
Cheers,
Doug
Similar to what I describe in this answer, you can create a UIView subclass and override the -setTransform: accessor method to adjust the transform that the UIScrollView will try to apply to your UIView. Set this UIView to host your content subviews and make it the subview of the UIScrollView.
Within your overridden -setTransform:, you'll need to take in the transform that the UIScrollView would like to apply and adjust it so that the scaling only takes effect in one direction. From the documentation on how CGAffineTransform matrices are constructed, I believe the following implementation should constrain your scaling to be just along the horizontal direction:
- (void)setTransform:(CGAffineTransform)newValue;
{
CGAffineTransform constrainedTransform = CGAffineTransformIdentity;
constrainedTransform.a = newValue.a;
[super setTransform:constrainedTransform];
}
Using OS 3.0, you can tell the zoom to zoom to a rect in the scrollview. I have this in my logic that detects taps.
CGRect zoomRect = [self zoomRectForScale:newScale withCenter:CGPointMake(tapPoint.x, tapPoint.y) inScrollView:scrollView];
[scrollView zoomToRect:zoomRect animated:YES];
The for the other part, you will have to stretch your image views by the ratio that the new frame has against the original, and center it in the same center point. You can do this in an animation timed the same as the zoom animation so that it looks right, but I think this will be the only way to do it.
In scrollViewDidZoom:, adjust your content view's variables based on zoomScale, reset zoomScale to 1.0, then do setNeedsDisplay on the content view. Handle the actual zoom (in whatever direction you want) in your content view's drawRect:.
The Ugly Details:
While the zoom is in progress, the UIScollView changes contentOffset and contentScale, so save those prior values in scrollViewWillBeginZooming: and in scrollViewDidZoom: so you can compute a new contentOffset yourself according to the zoom.
Since changing zoomScale will immediately fire another scrollViewDidZoom:, you must set a BOOL before (and clear after) resetting the zoomScale. Test the BOOL at the start of scrollViewDidZoom: and return if true.
You may need to inhibit scrollViewDidScroll: while the zoom is in progress (test a BOOL; set it in scrollViewWillBeginZooming: and clear it in scrollViewDidEndZooming:) so your own contentOffsets are used while the zoom is in progress.