Keeping a UILabel centered with changing contents and AutoLayout - ios6

I have 2 views. A MapKitView and a UILabel. Auto Layout is on.
I want the MKView to take up the whole screen (this seems to work fine) and the UILabel to remain the auto distance from the bottom of the screen but centered horizontally. The UILabel contents are changed programatically and afterwards I am calling sizeToFit.
After calling sizeToFit on the UILabel then it is no longer centered - the width seems to be adjusted only from the right hand side (trailing edge) keeping the left hand side in a constant position.
My understanding is that I should be able to achieve what I want only by setting the right constraints in IB?
The constraints I have applied to the label are:
Height Equals: 32
Width Equals: 166
Bottom Space to: Superview Equals: Default
Align Center X to: Map View
Only the last one, "Align Center X" is a user constraint - the rest being IB supplied.
I have tried a number of things, though none with much understanding (presumably my problem!).
I have called setTranslatesAutoresizingMaskIntoConstraints: NO on the label.
I have set the label's autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin. I have tried setting preferredMaxLayoutWidth to random values. Calling needsUpdateConstraints on the label. I tried putting the call to sizeToFit in viewDidLayoutSubviews.
I have come to the conclusion I need a little more understanding how I should be approaching this. Is sizeToFit not the thing to be calling when Auto Layout is on? Do I need to prod Auto Layout in some way after calling sizeToFit? I notice that rotating the simulator seems to center the label so prodding sounds a possibility?
I have re-read the Apple Auto Layout guide but I'm afraid I'm still not sure what I am doing wrong and the debugging tips suggested (visualizeConstraints etc) don't seem to work on iOS.
Thanks for any clue you can spare.

My idea about having to prod appears to be correct. After calling sizeToFit I needed to call [label.superview setNeedsLayout]. Whilst this works I'm not really sure why I need to do this manually rather than the label marking the layout as dirty when it's size changes.

Related

WinForms chart zooming X-axis labels temporarily disappear when zooming

I have a chart which looks like this:
When I zoom into a section, the labels disappear:
However, I can get the labels back by scrolling all the way to the right and releasing the mouse:
And then when I scroll back to the left, the labels are all visible:
This behaviour is just super weird am I'm completely dumbfounded as to what would cause this, or even how to debug.
Does anyone have any ideas on what I could try to fix this? I'd like the labels to be shown as in the last image, but when first zooming.
It looks like others have had similar issues, so I'm going to try combining several answers I found online to maybe help fix your issue.
John (DevExpress Support) says:
It appears that the AutoLayout feature leads to this issue. Please set the ChartControl.AutoLayout property to False. This should make axis label elements visible.
https://www.devexpress.com/Support/Center/Question/Details/T328948/x-axis-labels-disappear-in-chartcontrol
Valdemar (DevExpress Support) says:
I suggest that you use the Axis2D.ResolveOverlappingOptions properties. Set AllowHide to False:
[XAML]
<dxc:XYDiagram2D.AxisX>
<dxc:AxisX2D >
<dxc:AxisX2D.Label>
<dxc:AxisLabel>
<dxc:Axis2D.ResolveOverlappingOptions>
<dxc:AxisLabelResolveOverlappingOptions AllowRotate="True" AllowStagger="True" AllowHide="False" />
</dxc:Axis2D.ResolveOverlappingOptions>
</dxc:AxisLabel>
</dxc:AxisX2D.Label>
</dxc:AxisX2D>
</dxc:XYDiagram2D.AxisX>
https://www.devexpress.com/Support/Center/Question/Details/Q489042/chart-axis-labels-disappearing-when-chart-is-resized
SharpStatistics says:
The only way I could replicate the problem you describe is by setting the x axis Label.style interval to a specific value, say,
area1.AxisX.LabelStyle.Interval = 100;
and then when I zoom in on the chart if the zoomed x axis section is less than 100 I don't see any lables.
loi-se (the OP) replies:
Thanks for your suggestion! But as far as i know i don't set the xaxis labelstyle anywhere, i just use: Chartarea1.AxisX.IntervalAutoMode = IntervalAutoMode.VariableCount
This works fine in the case of the yaxis but the xaxis seems to behave on its own will. Maybe i should renew my .net framework installation and get the latest version of the chart component? Any other suggestions?
https://social.msdn.microsoft.com/Forums/vstudio/en-US/d345d4a3-a4be-4b41-9c83-9a9d9dbb69b9/the-labels-of-the-xaxis-are-disappearing-when-i-zoom-in?forum=MSWinWebChart
This one is for SSRS reports, but I'm assuming it uses the same (or similar library) and supports the link right above this one.
When designing an SSRS Report using Chart you may notice that some of the labels whether in X or Y axis are not being displayed, this is because it’s so smart that it detects what you actually want (not!).
To display all labels follow the steps below:
Right click either the X or Y axis, Click Properties:
Set the Interval to 1:
Viola!
https://randypaulo.com/2012/02/20/ssrs-chart-label-missing-xy-axis-missing/
That's about all I can find that are similar, without spending a bunch more time researching this. Hopefully something here helped!

Snapping window has negative value of Left property

I have an issue where I snap the window to the left and after I close the window I will save the location (Left, Top) along with size of the window. Next time the window is loaded I will try to apply the location and size.
I say try because the window might have been viewed on a screen that has larger resolution so it might not be visible at all on our new screen. What I do is - I see if the window(after I apply location and size) fits in the screen. If it doesn't I will show it on the center and if it does, well it's already where I want it.
My issue is when I snap window to the left. The actual Left property is not 0(zero) but -6.something. I suspect this is because the window has shadow around it so the location must be in minus so the actual form(the one with border) is touching left part of the screen. Because of my logic I will get this screen in the center.
Is there a bullet proof way of determining that the form is snapped to one of the sides?
Is there a bullet proof way of determining that the form is snapped to one of the sides?
No, I don't think so. There is at least no "IsSnapped" property or similar that you can use.
You will have to rely on the Left value and adjust it based on the difference in size between the different screens that are involved I am afraid.

Distribute text top-to-bottom instead of left-to-right

I'm working on a view that's implementing a multi-column text layout using CoreText (using CTFramesetter).
CoreText usually fills each frame completely, so when I call CTFramesetterCreateFrame with three rects that make up my columns, I get a layout that's similar to the following image:
So the left column is filled completely, the middle column partially and the right column is empty. But instead, I'd like the text to distribute over the three columns so that they take up the least vertical space possible, like in this image:
How to achieve this with CoreText?
I don't mind going low-level here, even drawing each CTRun by hand is an option if necessary.
One idea I came up with would be to create a large frame with the width of a column and then figure out which CTLine to draw in which column. But this has a few limitations:
It would only work if all columns had the same width.
It does not work with clipping paths.
Unfortunately, I'll need to use clipping paths (as in kCTFrameClippingPathsAttributeName) so this idea is out. I could live the fixed column width limitation, though.
Another idea would be to reduce the height until the last frame overflows but that's a pretty brute-force way that surely wastes resources.
(BTW, due to compability requirements the use of TextKit classes like NSTextStorage isn't possible; the resulting view is intended to be used on Mac and iOS, but it needs to work on iOS < 7)
Since there doesn't seem to be a non-expensive way to solve this, here's how I've done it:
I did go with the "reduce the height until the last frame overflows" approach. To reduce the height, I simply have another clipping path (kCTFrameClippingPathsAttributeName) which is a rectangle that fills the bottom of the view to the required height.
The probably most expensive but simple way would have been to increase the rectangle height until finally the text doesn't fit inside the last frame any more.
Instead I've implemented a binary search for that. For my demo app, I usually find the correct height after 8-10 recursions which still is expensive but at least it's pixel-perfect and doesn't rely on any other information other than "did the last frame overflow".

iOS-6 -- How to achieve conditional autorotation?

I've spend the past three days trying to figure out the iOS-6 autorotation mess, and have not arrived at a solution.
It's relatively straight-forward to have an app where all views rotate, or where rotation is completely disabled. And (conveniently for our needs) if you use a MPMoviePlayerViewController it will autorotate even if the app has autorotation disabled.
But having conditional autorotation, where some views are allowed to rotate and others are not, is elusive. I can achieve conditional autorotation (by having the root view controller "consult" the top view controller to determine what rotation it permits), but when the rotated view is exited it leaves the prior view rotated (when previously it had not been). This is not acceptable.
Has anyone cracked this nut?
(Like I told my boss, if you want a wider view you should just put wider paper in the printer.)
Further problem: Having gotten the basic conditional rotation to work (see comments below), I find that it hoses some screens in the "right wrong" circumstances. On this non-rotatable screen I press "Intro" to go to a rotatable one.
On the rotatable screen I rotate it, then return from it with it rotated. When I get back I have this screen:
The XIB file is pretty vanilla:
The errant piece appears to be the "Image View -- img_hea..." element which for some reason gets "amplified" vertically about 4x. There is no logic moving/resizing elements in the view (other than the standard UITableView stuff), and no reference at all to the problem UIImageView.
With an NSLog placed in viewWillAppear I see that the UIImageView is dimensioned 320x44 initially but 320x160 on return from the rotated screen.
This looks like an out-and-out Apple bug.
More: If I make the problem screen rotatable and rotate it right/left (back to portrait) the image is screwed up. I'm guessing that iOS "returns" to the screen before rotating back, and that's why it gets mucked up. Interestingly, in the rotated view the UIImageView is not showing up at all, with the Y dimension coming out zero in the NSLog.
Also, now that I notice it, the label that had been superimposed over the problem image is gone altogether in both rotated and post-rotation views.
OK: Turned off "Autoresize Subviews" for the overall UIVIew, and that makes things work correctly. This is the second time I've found the "Autoresize Subviews" XIB attribute causes flaky behavior.

iOS 6 AutoLayout Scale and Translate Animation

My aim is to have 3 images shrink, grow, and move along a horizontal axis depending on selection. Using Auto Layout seems to make the images jump about as they try to fulfil the Top space to superview / Bottom space to superview constraints.
So to combat this I have put all the images inside their own UIView. The UIView is set to the maximum size the images can grow to, it is centred on the horizontal axis. So now all the images must do is stay centred inside their corresponding UIView. This has fixed my problem as the UIViews perform the horizontal translation, while the images shrink/grow inside while remaining centred. My question is - is this the correct way to do this? It seems very long and like I am perhaps misusing the ability of Auto Layout. I have to perform similar tasks with more images and so any advice is welcome! Thanks.
I've just written a little essay on this topic here:
How do I adjust the anchor point of a CALayer, when Auto Layout is being used?
Basically autolayout does not play at all well with any kind of view transform. The easiest solution is to take your view out of autolayout's control altogether, but alternatively you can give it only constraints that won't fight back against the particular kind of transform you intend to apply. That second solution sounds like just the sort of thing you're doing.

Resources