Zebble: Percentage value for ScrollView Height doesn't work - xamarin-zebble

I'm trying to use a ScrollView in my UWP project. The problem is that when I assign a fixed value to my ScrollView Height, it works perfectly fine. However, if I assign a percentage value to its Height, it simply doesn't work and nothing is shown on that page, only a white blank screen.
Here's an example of a fixed value that works:
<ScrollView Id="MainScroll" Style.Height="700">
<Modules.TimeLineList></Modules.TimeLineList>
</ScrollView>
But, the following doesn't work and shows a white blank screen:
<ScrollView Id="MainScroll" Style.Height="100%">
<Modules.TimeLineList></Modules.TimeLineList>
</ScrollView>
In addition, the Modules.TimeLineList in the above examples is a ListView defined in another file and it contains some normal ImageView and TextView elements.
Any help is much appreciated.

I suppose you have placed the ScrollView inside a Stack (Pages are Stacks too). When you place a ScrollView inside a Stack you can't set the percentage based height for it.
Vertical stacks' height is calculated based on the overall height of their content (In this case ScrollView). At the same time, ScrollView tries to find the height of its parent (Stack) to calculate it's height based on its height. And it will prevent both from having proper height.
If you read your output messages, you will probably find some errors or warnings about it.
You can fix it by using a fixed height either for ScrollView or Stack.

Related

How to constrain height for ScrollView with dynamic content inside?

We are trying to resolve the warning for ScrollView "needs constraint for y position or height"
The scrollView has
a card View which has dynamic content inside, e.g. various text that expands with accessibility
a tableview with undetermined number of cells whose content can also expand with accessibility
So far we can only put >= height constraint for the tableView/cardView, but the scrollView doesn't know the exact height of its subcomponents so it can't calculate itself.
However, even with the warning, it does run fine and as expected.
An alternative strategy we've tried is to put an explicit height on the the tableView, let's say 500, then when the view has loaded, get the calculated content size and set height = actual content size.
Is there a better way to handle height constraints for ScrollView with dynamic content inside?
DonMag is right. I was not aware of the Intrinsic Size: PlaceHolder but that is the exact solution to my problem.
For those looking, it will be at the bottom of the Size Inspector, the second last IB Inspectors pane.
This topic should help anyone else:
What is the difference of intrinsic size vs system width/height constraints?

Hide arrangedSubviews in UIStackView instead of clipping contents

I have a UIStackView with three labels whose height is determined using Dynamic Type and text that have can wildly varying lengths. The container for the stack view has a fixed width and height depending on device screen size (small on iPhone SE, for example.) I want to center the stack view within the container (with some outer margins.)
The problem is that depending on the font size and container height, some of the labels in the stack view will be clipped. Here is an example with the third label:
I have experimented with layout constraint priorities for both the stack view and the labels, but this doesn't appear to be the right approach. Instead setting the visibility of the labels works better: correct spacing between elements is maintained.
My question is then what is the right time to detect that the label's height isn't fully displayed and to hide it.
The label height is close to, but not exactly equal to the UIFont's lineHeight so there's some rounding involved that makes this a little difficult.
The biggest problem is that after a layout pass in the UIStackView's layoutSubviews the heights of the arranged subviews can be detected, but you can't hide the arranged views at that point because it causes another layout pass and recursion.
So what am I missing? :-)
Here's a test project - build for iPhone Xs in the Simulator and you'll see the same results in the screenshot above.
Solution
Tom Irving's gist below pointed me in the right direction. The trick is to enumerate the subviews after a layout pass and remove them if height requirements aren't met.
The updated project shows how to do this in DebugStackView's layoutSubviews. And yes, UIStackView is a worthy adversary.
Could you act on viewDidLoad?
My intuition would be to add up the height of all visible subviews in the stack view and then hide the last if there's a problem.
In the sample you've provided I would recommend getting a CGSize with [self.firstLabel textRectForBounds:self.view.bounds limitedToNumberOfLines:0] for each visible label, making sure to take the margin between items into acount, and determining if the total height is greater than the constant height you've assigned to the stack view. If so, hide the elements that go beyond the stack view's height.
Of course, there might be more to the problem than I understand, but that would allow you to calculate before the layoutSubview pass happens.

UIScrollView auto layout not working the width of contentView

i'm back developing IOS after a year and a half. I'm really having difficulty in make use of UIScrollView and auto layout.
I'm developing an application running just in Iphone and portrait orientation.
I have a simple form inside my content view...
label
textField
textField
textField
textField
button
textField
view
imageView
label
The problem is with the width of the contentView's content. The size is been defined for the labels. I would like (And really have to do) o size it according with the screen size.
Here is my constraints of my first text field:
Here is my simulator screen running the app:
how I mentioned before, it seems to get the size according the label and not according the screen size. If I create a constraint of size for the first label, this size change but I would like to get the size dinamically based on screen.
I didn't write any code, I want to do it preferentially using auto layout to understand the concepts of auto layout better.
If someone could help me to solve it... I would be very grateful.
Pin your contentView.width equal to scrollview.width.
Add a constraint to your scroll view's content view child to be the same width as the root-level view.

Where is this vertical spacing coming from in UILabelView?

I'm creating an iOS view that displays various static text elements. The xib looks like this:
It uses four labels for the title, timestamp, body, and footer. Every view is anchored to the sibling view above it vertically and anchored to the left/right of the parent view. All labels have a fixed height except the body which has a >= height and the number of lines set to 0 with "word wrap" as the line wrapping style. The parent view is a UIScrollView.
On the iPhone it looks like fine:
However on the iPad it looks like this:
Huh? Where is all that extra vertical space in the body label coming from? The xib and its view controller are identical between iPhone and iPad (there is no custom iPad code at the moment). I've found that the vertical space is directly related to how many line-wraps the label renders. If no lines wrap, no extra vertical space. If only a few lines wrap, there's a little extra vertical space. If nearly every line wraps, well, that's what it looks like.
First of all any ideas on why UILabel is behaving this way?
Second of all, if I can't make it stop doing this how can I work around it?
I've already tried a few things. If I call [bodyLabel sizeToFit] within -viewDidLayoutSubViews then it fixes the label but doesn't fix the layout of any of the sibling views (e.g. the Footer label is stuck way at the bottom of the screen instead of pulled up to just under the body). Any attempts to get the entire view to re-layout its children after calling sizeToFit is ignored. I've also tried sizing the UILabel by calculating height based on font, which results in the same behavior as -sizeToFit (albeit with more code).
Replacing the Body UILabel with a UITextView instead doesn't give me the weird vertical spacing issues but I need to calculate the height of the UITextView manually (using font calculations) and something about resizing the UITextView within the parent UIScrollView makes it so the UIScrollView simply refuses to scroll (as if it doesn't know its contents are too big for its bounds).
So at the moment I'm stuck. Even just an explanation of why UILabel behaves this way on the iPad layout would be helpful.
In case anyone else runs into this same issue using autolayout... I may have been able to solve the same issue by creating a constraint as Coche suggests, but I realized I had a preferredMaxLayoutWidth that was too small set on the uilabel. Once I set an accurate preferredMaxLayoutWidth (the actual width of the label) the spacing on top and bottom disappeared.
The main problem is that the method for auto resizing the text inside your Label is failing because in iPad your Label doesn't have a set width from the beginning, it is calculated on run time and that's the source of that mess. On iPhone, as your Label has a set width (on IB) there is no troubles.
There are two ways for solving the problem:
Having two storyboards : one for iPhone and one for iPad
Doing this will make that your Label knows its width since the beginning and it will just works as on iPhone.
Having just one Storyboard for both iPhone and iPad
You can go around the problem by calculating the size that best fits its text and with that result add a height constraint by code to the Label. For calculating the desiredSize you can calculate the width with this formula: Current View's width - (Leading space + Trailing Space). Here is my code
CGSize desiredSize = [_bodyLabel sizeThatFits:CGSizeMake(self.view.frame.size.width-40, 10)];
NSString *visualContraint = [NSString stringWithFormat:#"V:[_bodyLabel(%.0f)]",desiredSize.height];
[_bodyLabel addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:visualContraint
options:NSLayoutFormatDirectionLeadingToTrailing
metrics:nil
views:NSDictionaryOfVariableBindings(_bodyLabel)]];
objective-c

Fluid UI layout on iPhone

I have an Android app with a UI like this for viewing emails:
I'm trying to port this to iOS and need it to work with iOS 5.0 and above (so can't use auto-layout in iOS 6.0). Hopefully you can tell how the layout should adjust/flow based on the example.
What would be the best way to handle this type of layout? The From and Re lines need to be variable height as shown (actually the To: line as well). The message body needs to be variable height of course.
My only attempt so far has been trying to use UITableViewController with static cells. I am able to get the variable height that way, by using sizeWithFont inside heightForRowAtIndexPath, to return the required height for each row. Using that method I'm having a heck of a time trying to get the style I want (rounded corners and background only for the top part).
So is there a better way? Maybe something that uses Collection View or Container View? On some other screens I need to port I have similar issues, but they have more levels of nesting (rounded blue section inside a white section inside a rounded blue section). Or would I be better off not using IB and building the entire UI in code from just basic label elements and generic views?
The easiest way I can think of is to manually compute for the label frames inside viewDidLayoutSubviews. Here's some pseudo-code:
On creation:
In IB, put all labels as subviews of the blue area. Check that the autoresizing mask of the container sticks to the top, left, and right, as well as have stretchable width. We'll fix the height and the subview frames in code. The message body can be a label or a textview as a separate view.
In viewDidLoad, set the containing view's layer cornerRadius, borderColor, etc. as appropriate.
In viewDidLayoutSubviews:
Time label: Easy. Just set the width to the superview width minus some padding, set the height with sizeWithFont:
For To:, From:, and Re:; call sizeToFit. Get the max width and hold on to that.
To: label: Set the x to 0 and y to the time label's bottom.
Receiver's name label: Set x to the width you got from (2.) and y to same as (3.). Set width to (container width - (2.)) and height with sizeWithFont:.
Do the same steps from (3.) to (4.) for the From: and Re: rows.
Set the blue view height to the frame bottom of the subject label.
Fill the rest of the frame with the body textview/label.
You have to add paddings on your own because sizeToFit and sizeWithFont: won't do that for you. Also, the body UITextView can scroll on it's own, but if you are expecting long subject titles then you should wrap the whole thing in another UIScrollView (or in IB just set the main view's class to UIScrollView)

Resources