I have a UIImageView called draggableImageView that is a subview of a UIView called tiltedView that is tilted backwards via CATransform3DRotate and with perspective transform.m34 = -1 / 400.0. That way, when I drag draggableImageView around, its perspective and absolute size change so that it appears to be moving in 2-space within the tiltedView.
I would like to calculate the frame for draggableImageView within tiltedView but using a different coordinate system (in this case, a UIView called viewForCoordinates that is not tilted and encompasses the whole screen). However, using [self convertRect:self.frame toView:self.viewForCoordinates] from within draggableImageView outputs the same sized frame regardless of where within tiltedView my draggableImageView is located.
I figure using self.frame is more appropriate than self.bounds since bounds is agnostic to the superview while frame is dependent upon it. However, based upon the above, I'm guessing that convertRect is just converting self.frame agnostic of the perspective manipulation applied to self.frame's superview's.
I'm not sure what code would be helpful in this case, so please let me know what code I can provide to help get this question answered.
I solved this!
So I think there were two main issues:
1) When DraggableImageView object is touched, make sure object is indeed being touched via if ([touch view] == self) within - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
2) Convert touch location to superview coordinate system via self.touchLocation = [[touches anyObject] locationInView:self.superview].
3) Convert DraggableImageView's frame from superview coordinate to viewForCoordinates coordinate system. <<< I think my error was that I converted from self rather than superview.
4) If making changes to DraggableImageView's frame or location based on viewForCoordinates, calculate changes within viewForCoordinates's coordinate systemm and then convert back to DraggableImageView's superview. <<< I think I forgot to do this conversion :S
Related
I have UIAlertView and I log it's frame and bounds using:
[self.alertView show];
NSLog(#"frame: %#", NSStringFromCGRect(self.alertView.frame));
NSLog(#"bounds: %#", NSStringFromCGRect(self.alertView.bounds));
I notice that the width and height of the frame and bounds is different. How is this possible?
From UIView's frame, bounds, center, origin, when to use what?
frame - this is the property you most often use for normal iPhone applications. most controls will be laid out relative to the "containing" control so the frame.origin will directly correspond to where the control needs to display, and frame.size will determine how big to make the control.
bounds - this property is not a positioning property, but defines the drawable area of the UIView "relative" to the frame. By default this property is usually (0, 0, width, height).
That being said, it's not surprising nor uncommon for the bounds size to be different from the frame size. Since in this case the bounds rect is smaller than the frame it simply means that only a part of the view is being drawn.
Also consider that UIAlertView view hierarchy it's much more complex than it appears and it also went through a big change with iOS 7.
To further remark this, here's a statement from the documentation
The UIAlertView class is intended to be used as-is and does not support subclassing. The view hierarchy for this class is private and must not be modified.
Which is a nice way to say: here be dragons!
I have an object that is a subview of the main view. This object is moving across other subviews during its existence. I need to get the x, y-coordinates of the object frequently as it moves. I'm using an NSTimer with a 0.01 time interval to update the data however, I can only seem to get it to update the coordinates when it's not on another subview.
I've been trying to use:
[self.window convertPoint:point fromWindow:nil];
and
[self.window convertPoint:point fromView:(the view the object exists on)]
but this still only returns the coordinates when it's not over another subview. Any suggestions?
During the animation you will likely need to access the views layer and get the presentationLayer as the view won't return its true frame while the animation is in progress.
I'm trying to make a rotation on a tableview to tilt the table (to give the effect of a 3d text crawl similar to the star wars opening crawl).
After looking around I found this question objective-с CALayer UIView real rotation
and the accepted answer seems to do what I want, however when I apply the code to my TableView it does nothing and the table appears as usual.
This is the code I am copying:
float distance = 50;
CATransform3D basicTrans = CATransform3DIdentity;
basicTrans.m34 = 1.0 / -distance;
_tableView.layer.transform = CATransform3DRotate(basicTrans, M_PI_4, 1.0f, 0.0f, 0.0f);
I'm placing this in my viewDidLoad method after creating my array of Strings (that populate the tableView)
I currently only have three other methods in the Controller:
didReceiveMemoryWarning (automatically addd when project created)
tableView: numberOfRowsInSelection (used for setting up the table view)
tableView: cellForRowAtIndexPath (used for setting up the table view and setting the cells text form the array)
My understanding is that the tableview has a CALayer, and that the CATransform3D manipulates this to give the representation of the view in a 3d space. If my understanding is correct then I don't get why the list is shown normally on screen? I appreciate the numbers my not give the effect I want yet but they should at lest effect the appearance of the tableView on screen.
Also I have imported QuartzCore etc and added it in linked frameworks
Solution is to use the code marked as OLD answer in the the - (UITableViewCell *)tableView: cellForRowAtIndexPath: method after the cell is checked for being null.
Since the approach suggested below has not worked, another thing I would try out is applying the transform to the UITableView's subviews. Actually, UITableView is a UIScrollView, so it is just a container for subviews that make up the real content of the table view. I would try something like this:
for (UIView* subview in tableView.subviews) {
subview.layer.transform = ...;
}
I have never inspected a table view subviews hierarchy, so I cannot say whether this will work or you should rather apply the transform to just one of the subviews, but I hope this can lead you in the right direction.
OLD ANSWER:
You could try setting your table view's layer sublayerTransform instead of `transform':
You typically use this property to add perspective and other viewing effects to embedded layers. You add perspective by setting the sublayer transform to the desired projection matrix. The default value of this property is the identity transform.
(source).
I am suggesting this based on the hypothesis that a UITableView has quite a complex structure in terms of subviews, so transforming just the view's layer might have no effect. I haven't tried it, though, so I cannot guarantee it will work.
On a NSView there are many other NSViews and some of them are moving with keyboard scroll keys. when moving object come on top of any static one i want to get which object sits under moving one. with mouse this is easy however without mouse i couldn't find a way to achieve this.
You'll need to loop through all of the views you want to test, get each view's frame, convert that rectangle to the relevant view's coordinate system (search for “convertRect:” in the NSView docs), and then use the geometry functions to test whether the moving view's converted frame intersects the static view's frame.
This might help you
-(void)handleTap:(UIGestureRecognizer *)gesture
{
CGPoint tappedPoint = [gesture locationInView:self.view];
NSLog("You tapped in on screen point : %#",tappedPoint);
}
Using this tappedPoint we can check that in which view's rect these points are present.
Important We have to add tap gesture in our view to use this function.
I am trying to check for a collision of an UIView that is in the main view, with a UILabel that is a subview of another view in the main view.
When I use CGRectContainsPoint, it does not return true. When I check the UILabel's frame, it returns values relative to the subview it's in, not it's absolute position. I figured this might be the problem.
If so, how do I specify that I want UILabel's absolute values for the frame?
You can convert coordinates between different coordinate systems using the NSView methods:
- convertRect:(NSRect) fromView:(NSView)
- convertRect:(NSRect) toView:(NSView)
If the second argument is nil, the coordinates are converted from/to window base coordinates. Similar methods exist for NSPoint and NSSize variables. One solution would be to convert all rectangles and points to window base coordinates and check for collision in those coordinates.