I have a UIview with some subviews in it! When I transform that view (scale, rotate.. use CATransform3D). These subviews grow bigger or smaller but the subviews do not change the frame. How can I detect the real frame of them? Thanks!
viewTransfromContainer?.layer.transform = CATransform3DScale((viewTransfromContainer?.layer.transform)!, pinchGes.scale, pinchGes.scale, pinchGes.scale)
I used convert(<#T##rect: CGRect##CGRect#>, to: <#T##UIView?#>) It's work fine with scale But Not return true value when rotate.
image bellow
Related
In my app, I need to add subview in another view but my issue is that height and width of parentView is 50*50 and height of subview is 150*150 so how can I add this? because when I add this view, rest portion of subview is getting cropped.
The edges are bounded in the smaller UIView. Because the UIView is smaller it is going to crop out the larger subview. if you still want the super view to be 50x50 and don't want the larger subview cropped out then turn off setClipsToBound property of the UIView:
Swift: view.setClipsToBound = false
Objective-C: [view setClipsToBound:NO];
Another solution is just to make the subview smaller or make the superview containing the large subview larger.
So after compiling an app on XCode 6, I noticed a strange bug that happens only when running on iOS 8:
The UITableView takes the wrong inner dimensions after updating its frame.
Now I'll try to explain the exact situation:
We have a UITableView rotated on its side, which basically makes a horizontal UITableView. It happens through tableView.transform = CGAffineTransformMakeRotation(-M_PI / 2);.
Now after setting the transform, and then settings its frame - everything is fine.
But of course the system in most cases sends the parent another frame change because it needs to set the parent to the real sizes and not the XIB sizes or any initialization size. In that moment - when I relayout the subviews, including the table view - everything goes wrong.
Actually the frame of the table view is simply set to the bounds of the containing view, but then the inner scrollview (In iOS 8 the UITableView has another UIScrollView inside it, called UITableViewWrapperView. As UITableView is a UIScrollView by itself, I can't figure out why they needed another one...) takes a "height" which equals the parent width. And "height" is actually the width property, only rotated.
Now we can easily estimate the they have a bug with relating the width of the inner UIScrollView to the actual width of the parent UITableView, which could possibly be by reading the .frame.size.width instead of the .bounds.size.width.
But the strange thing is that when investigating the frame of the subviews of the UITableView- it seems that they are all good! So it must be a rendering problem somewhere.
So we are left with a horizontal table which has a blank gap on top, because the "height" of the cells is 320 instead of 568, while the "width" of the cells is fine, set to 320.
I'll be very happy to hear from other people experiencing this problem (Or from Apple), but I have finally found a solution and posting it here with the question, for future reference for me and for others.
So the change that made it behave, was instead of doing this:
- (void)layoutSubviews
{
tableView.frame = self.bounds;
}
I have reset the transform, set the frame to the bounds which the UITableView would expect locally after the transform, and then set the transform and set the correct frame. This is a bit confusing, but here it goes:
- (void)layoutSubviews
{
if (UIDevice.currentDevice.systemVersion.floatValue >= 8.f)
{
// iOS 8 layout bug! Table's "height" taken from "width" after changing frame. But then if we cancel transform, set width/height to the final width/height, and rotate it and set to the virtual width/height - it works!
CGRect rotatedFrame = self.bounds,
unrotatedFrame = rotatedFrame;
unrotatedFrame.size.width = rotatedFrame.size.height;
unrotatedFrame.size.height = rotatedFrame.size.width;
tableView.transform = CGAffineTransformIdentity;
tableView.frame = unrotatedFrame;
tableView.transform = CGAffineTransformMakeRotation(-M_PI / 2);
tableView.frame = rotatedFrame;
}
else
{
tableView.frame = self.bounds;
}
}
This appears to be a new problem with iOS8. When you want to rotate an object it no longer appears to rotate around the upper left corner of the object's frame.
Apple docs for iOS8 state that "an object is rotated about it's center point". So when a vertical UITableView is rotated 90 degrees, it may disappear from view because the center point may be off the visible area. In order to make the table appear as if it was rotated about the upper left corner of the table, you must now also translate the frame by an amount equal to the difference between the frame width and frame height.
It's important to note you need to concatenate the transforms in order to get the desired result, like the following:
First create a 90 degree rotation transform:
CGAffineTransform xform_rotate = CGAffineTransformMakeRotation(-M_PI * 0.5);
Then create a translation amount variable equal to the difference between table width and height:
float translateAmount = (camThumbsTableView.frame.size.height/2)-(camThumbsTableView.frame.size.width/2);
Then concatenate the original rotation transform with the translation:
CGAffineTransform xform_total = CGAffineTransformTranslate(xform_rotate, translateAmount, translateAmount);
When done, you can now transform your tableView as follows:
self.camThumbsTableView.transform = xform_total;
This will have the effect of both rotating and translating your tableView such that it now appears to have been rotated around the upper left corner of the tableView instead of about the center point.
I have a UIScrollView displayed in fullscreen holding a UIImageView that fills the contentView of the scrollView. I added a method to register the contentOffset and the contentSize of the scrollview at a specific pan and zoom.
I'm trying to convert those coordinates to a CALayer that I can animate using the position and bounds in order to animate a pan and zoom to the desired point.
How to convert the contentOffset and contentSize of a UIScrollView to a CALayer bounds and position properties. The CALayer is a screen sized CALayer and is add to another screen sized CALayer.
Looks like I just had to ask the question to finally answer my own problem!
set the anchorPoint of the CALayer to CGPointZero
then set the bounds size to the contentSize
set the position to the negative contentOffset {-contentOffset.x,-contentOffset.y}
Finally.
I have an image as a subview of a UIScrollView. I want the image to initially fit the screen's bounds using autoResizingMask and contentMode (UIViewContentModeAspectFit) property of UIView. When the scrollview's frame is changed to make room for the keyboard, I don't want the child image view to scale down to fit the smaller frame. I can't disable autoResizeSubviews on the scroll view when it is created because the child view must be re-sized once at the beginning. Right now I can turn off subview re-sizing when the keyboard appears and re-enable it when it dissapears. This seems to work fine but seems hackish. Is that an acceptable way to do it or is there a better solution? Thanks.
Don't worry about the autoResizingMask since it's a subview of the UIScrollView.
The autoResizingMask on a UIView allows for the view to be automatically resized when its parent view's frame has been resized. In this scenario, it sounds like your scrollView's frame is being adjusted vertically to accommodate the keyboard's on screen frame. When the parent view's frame shrinks, so does your UIImageView, which means it works as designed if you're using UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleHeight as the autoResizingMask of your UIImageView.
Instead of using autoResizingMask on your UIImageView, you should manually set its frame to be the same size as the UIScrollView's frame via the bounds property:
imageView.frame = scrollView.bounds;
Then let's set the scrollView's contentSize to be the same size as the imageView.
scrollView.contentSize = imageView.frame.size;
This way, your imageView should be the full size of your scrollView, and won't move if you adjust the size of the scrollView frame.
I am implementing an app with a trackbar which itself is a view and it needs to display the minimum and maximum values (of the variable which is associated with the bar) so I have added two labels to the top left and top right of it. Think of something like this without an enabled slider:
I would like to be able to shrink or magnify this view with pinch gesture and the below code does work fine :
-(void) handlePinch:(UIPinchGestureRecognizer *)gr
{
//Shrinking
if(gr.scale < 1)
{
//Get screen width
CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
//If the view's would be size is smaller than half the screen's size then don't do anything
//Otherwise shrink the view
if(self.frame.size.width * gr.scale >= screenWidth / 2)
{
//Only scale on x axis, y axes stays the same
self.transform = CGAffineTransformScale(self.transform, gr.scale, 1);
}
}
//Magnifying
else if (gr.scale > 1)
{
//Only scale on x axis, y axes stays the same
self.transform = CGAffineTransformScale(self.transform, gr.scale, 1);
}
//Set scale amount back to 1
gr.scale = 1;
}
The problem is when the view is shrank the labels on top left and right are also shrank and their font size gets smaller. Since I scale the view only horizontally this looks bizarre. I want to set the labels' size constant and shrink everything else inside the view.
I have tried to assign a new frame rectangle with the original labels' sizes after shrinking but it didn't work.Do you have any tips?
edit : Setting minimumFontSize property did not work either (I don't try minimumScaleFactor because I'm still using ios 5 sdk)
I think this behavior is actually controlled by the view you have your label on - it's not controlled by the label itself. There is a autoresizesSubviews property of UIView that defaults to YES, and that makes anything inside a view shrink when the UIView shrinks. Since your pinch gesture is actually attached to the view behind the label and not the label itself, your pinch is shrinking the view, then the view shrinks the label. Try setting autoresizesSubviews = NO, and let me know if that works for you.
I found the solution in separating my trackbar from the view that shall support pinch gesture. It was bad design to include trackbar in it beforehand, check your ui design before putting effort on more complicated stuff.