Do button's touch size change with a CGAffineTransformScale? - uiview

My goal was to make a View of buttons and have it grow with screen size so it works on all devices, filling 90% of the width of the screen. I am not using constraints as it is an older program, and turning on constraints would be too big a job right now. I was hoping to "cheat" my way around this. So, I tried this:
I have a smaller View created inside a full screen View (created in interface builder) that is basically a standard "view" item. Inside that smaller View are a bunch of UIButtons that make my "keyboard."
I would like to scale the smaller view (which visually scales the buttons too), and still have the buttons respond properly as they change size. So I have done this:
Setup:
View (buttonView) with UIButtons inside that view. The view and the buttons are attached (in Interface Builder) to IBOutlets and IBActions as necessary. The following code scales the view to match the screen:
_keyboardCard.transform = CGAffineTransformIdentity; // reset to normal
CGFloat keyboardWidth = _keyboardCard.bounds.size.width;
// screenWidth is set earlier and has width bounds value for full screen
CGFloat widthScale = (screenWidth/keyboardWidth)*0.9; // 90% of full screen width
_keyboardCard.transform = CGAffineTransformScale(CGAffineTransformIdentity, widthScale, widthScale);
This actually works visually just fine, and the "keyboardCard" grows in size, as do the buttons inside (visually), just like I expected. It looks good as I change from device to device.
But there are times when some of the buttons stop responding. SOME continue to work just fine, especially near the center, while others just stop. The touch failures start on ALL the edges, and work their way inward as the size grows. It is almost as if there is a "mask" stopping the buttons from working on the edges.
So the question is: Is this a legitimate ways to do this? It does not seem to be documented anywhere. And if not, what does one suggest as a way to make a view with buttons scale up and down and still have the buttons work as expected?
Or perhaps I am just better off making a small, medium, and large View of the "keyboard", and just pick the closest one based on screen size?
Suggestions and comments please. Thank you.

Related

Resizing Complex UIView with AutoLayout (Swift)

So I'm pretty new to AutoLayout, but more often than not I'm able to hack my views into shape or model off samples on the web.
However, I've created this rather complex view that just doesn't resize no matter what constraints I try.
Here are a few screenshots of what's going on.
The first shot is my Interface Builder layout. It's got a 4-corners kind of thing going on, with a UIImageView in each corner. In the center is a blurred VisualEffectView; it lays on top of the images. The layout was constructed with the parent view at 200x200
The second shot is a successful rendering at 200x200. As you can see, the 4 images load fine (yeah, I know they're a bit stretched, I just haven't handled their scaling code yet). Programmatically, I set the cornerRadius properties of both the parent view and the blurred view to 1/2 their width, so as to make them circular. Also programmatically, I added a label as a subview to the blurred view.
Then it all goes downhill. The third shot is my attempting to render the view at 250x250. The parent view renders well and maintains a circular shape, but just about everything else is wrong.
The most frustrating part is the UIImageViews, which all go haywire and extend their bounds even though I've set them to be equal widths.
The blurred view at least stays centered, but something isn't called which prevents its bounds.width property to be updated, which is what the cornerRadius is based off of.
The label doesn't stay center in the blurred view, despite setting its autoesizingMask to flexible all around.
Here is a snippet of my initialization code, which might be useful.
Any help that you all could provide would be greatly appreciated (even if it just fixes one of the several issues).
P.S. I apologize for the cats pics.
Edit: I achieved the desired result by writing the code manually and ditching Interface Builder and AutoLayout entirely.

Problems Setting up constraints in IOS8 with Swift and Xcode 6

I have tried for several hours to design and place the different elements accordingly. But it seems like no matter what I do, the elements get messed up with sizes and location when moving to different device (screen sizes).
How would you place constraints in the screen below to ensure proper scaling and position when moving to a different device?
http://postimg.org/image/hl4incjzh/
I only work in portait mode.
The views at the left is a UIImage view and a UIWebview which is hidden, and will show dynamically based on external content.
Label and the textview below is also dynamically populated on ViewDidLoad.
Any ideas, suggestions?
You can click on a view element and use the add-constraints-menu:
There you can set different size-options like the margin, if the view should resize etc.

Finer grained UIView rotation in a UIViewController

I have a UIViewController that overlays controls on a view presenting what the camera sees. I have a couple of scenarios I would like to allow.
For the iPad, I want to keep the controls on the right most edge of the device, by your right thumb, no matter what the device's rotation. The controls should rotate their content so that their top is always upwards (away from the ground). I don't want the camera view to rotate at all, because that would just be silly – its position & size should stay the same and its contents shouldn't rotate either.
For the iPhones, I want to keep the controls at the bottom of the device's screen, by to the home button, wherever the home button actually is. The controls should rotate their content so that up is always pointing upwards. Again, I don't want the camera view's frame or content to take part in any view rotation animation at all.
I'm using auto-layout.
I'm wondering if there is any way to describe some or all of this in a storyboard. In particular, it'd be great to be able to describe that some view positions need to autorotate (ie, the controls, on iPad), but that other views don't (the camera view).
A question from 2011 indicates this wasn't possible at the time, but perhaps things have moved on since then? If it's not directly supported, can you suggest an approach and are there some sensible places to be hooking in to autorotation to achieve this?
Ok, this isn't quite a complete answer, but I tried a few things which look promising.
First, you can create a separate set of constraints for portrait vs. landscape using the size specifiers: landscape is w Regular, h Any; portrait is w Any, h Regular (I think -- double-check these) This is accessible via the pop-up control in the bottom-center of the storyboard view. By installing different constraints for portrait and landscape, it should be possible to scale the width and height of your controls' container view so it appears to be in a constant position w.r.t. device orientation; in other words, the container doesn't actually counter-rotate -- it scales so it effectively looks like it has counter-rotated.
I got this close to working. It looks like it's doing the correct thing in the storyboard view, but when I actually run it, I get debug messages about conflicting constraints. Not sure how to fix this, but maybe play with the constraint priorities? That sometimes helps.
A second thing I (partially) tried was creating a custom container view class which counter-rotates itself to the correct position based on the device orientation (in the UIDevice class). You implement this by overriding layoutSubviews. For each orientation, you define a transform which puts it in the correct position, and set the view's transform property.
Another possible solution is to override updateConstraints in your view controller and add/remove constraints to position/scale your container to the correct place for each orientation.
For all of these, the idea is that you "force" the container to be in the correct place, but leave the subviews (the actual controls) alone. The controls should do the right thing if their constraints are independent of the specific orientation of the container view.
So, those are some ideas anyway... if they lead you to an actual solution, could you post it? I anticipate having a need for this myself.

Autolayout causing UI Elements to "snap" into place at runtime?

I have a UIView with a UIImageView at the very top, a UILabel below it, a UIButton below that, and a UISegmentedControl that determines what determines what embedded UIview to display at the bottom (which also a choice to not show any at all).
I've run into the problem where I've set up all of my constraints in the interface builder, and everything seems to be fine when I switch between screen sizes in the storyboard. However when I actually run the project on a device or emulated, the UIimage at the top is briefly stretched before "snapping" into a size the fits the constraints. Also, it seems as if the label disappears for a brief second and reappears after the image has snapped into a size. After the "snap" has occurred, everything is in place and there are no problems.
This snapping occurs both when testing on a 4 and 3.5 inch display. I find this odd because I've designed the UI for the 4inch screen perfectly.
Does anyone know why this is happening?
Edit
Here's whats the constraints look like in IB.
This is potentially due to adjustments that you might be making to your UI elements (or constraints) from the view controller in code. For example, if you are programmatically setting a different UIImage into your UIImageView, and this code is happening too late in the view lifecycle (for example, in viewDidAppear) after a layout pass has already calculated view positions and sizes, then you will see a visible snap as views take on new positions based on the new intrinsic content size of the image view.
This could be caused by other adjustments such as injecting a localized string into a UILabel in code, which causes the label to have a smaller or larger intrinsic content size, which in turn affects the layout based on your constraints.
If you are making adjustments to your UI in code, make sure they are happening in viewDidLoad or viewWillAppear: so that they occur before the view's initial layout pass (and the view's animation onscreen).
If you're still seeing issues, you can try explicitly forcing an immediate layout pass to occur on the view controller's view at the end of viewWillAppear: by doing the following:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.view setNeedsLayout];
[self.view layoutIfNeeded]; // forces an immediate layout pass
}
Spacing between the UIElements might be the problem . Specially when using Pickers
Got it, You have applied constraint for Picker to adjust along with segmented control. So when app runs on 4 inch screen , picker automatically fits properly, but for 3.5 Inch picker always starts from bottom of the screen and picker will push segmented control upwards and hence segmented control will push rest control automatically.
Remove picker and segmented control constraint.

UIView coordinate transforms on rotation during keyboard appearance

iPad app; I'm trying to resize my view when the keyboard appears. It amounts to calling this code at appropriate times:
CGRect adjustedFrame = self.frame;
adjustedFrame.size.height -= keyboardFrame.size.height;
[self setFrame:adjustedFrame];
Using this technique for a view contained in a uisplitview-based app works in all 4 orientations, but I've since discovered that a vanilla uiview-based app does not work.
What happens is that apparently the uisplitview is smart enough to convert the coordinates of its subviews (their frame) such that the origin is in the "viewer's top left" regardless of the orientation. However, a uiview is not able to correctly report these coordinates. Though the origin is reported as (0,0) in all orientations, the view's effective origin is always as if the ipad were upright.
What is weird about this is that the view correctly rotates and draws, but it always originates in the literal device top left. How can I get the view to correctly make its origin the "top left" to the viewer, not the device's fixed top left? What am I missing? Please, for something so trivial I've spent about 6 hours on this already with every brute force technique and research angle I could think of.
This is the original source which doesn't work in this case:
move up UIToolbar
OK, I don't know what the ACTUAL answer is to the original question, but I can say with certainty that one way to resolve the issue is to always ensure that you don't manipulate a viewController's view directly. Always wrap your view inside a container view inside the main "view", then have that container view adjust its position etc as needed. Works exactly as the splitview does, probably because in both cases now the view in question is a subview of the main "view". What a relief!

Resources