[TIMOB-26211] iOS: Percentage based layout rounds floating widths/heights incorrectly
GitHub Issue | n/a |
---|---|
Type | Bug |
Priority | Medium |
Status | Closed |
Resolution | Fixed |
Resolution Date | 2018-08-24T17:22:22.000+0000 |
Affected Version/s | n/a |
Fix Version/s | Release 7.5.0 |
Components | iOS |
Labels | horizontal, iOS, layout, percent |
Reporter | Joshua Quick |
Assignee | Hans Knöchel |
Created | 2018-07-13T21:04:52.000+0000 |
Updated | 2018-09-11T18:47:25.000+0000 |
Description
*Summary:*
iOS will incorrectly wrap views within a horizontal layout if their percentage based widths total to 100%. This is not an issue on Android.
*Steps to reproduce:*
Build and run [^HorizontalPercent50x50Test.js] on iOS.
Note that the left view width is 50% and the right view width is 50%.
Observe the layout.
*Result:* On iOS, the right view is wrongly wrapped to the next row. !HorizontalPercent-iOS-bad.png|thumbnail! *Expected Result:* Both views are expected to be on the same row since they both have a width of 50%. Android does this correctly as seen here... !HorizontalPercent-Android-good.png|thumbnail! *Work-Around:* UseTi.UI.FILL
to the right-most view's width
property instead of using a percentage.
*Note:*
The attached [^HorizontalFillTest.js] provides a more complex horizontal layout test. iOS has 2 issues with this as well:
* The Left (50%) | Right (50%)
test shows that the views are wrongly shrunk to 25% width instead of 50%.
* The yellow (75%)
label does not have the same width as the (25%)|(50%)
labels above it.
iOS looks like this...
!HorizontaFill-iOS-bad.png|thumbnail!
Android handles it correctly as can be seen here...
!HorizontalFill-Android-good.png|thumbnail!
Attachments
File | Date | Size |
---|---|---|
Bildschirmfoto 2018-07-20 um 22.27.03.png | 2018-07-20T20:27:26.000+0000 | 394664 |
Bildschirmfoto 2018-07-20 um 22.31.05.png | 2018-07-20T20:32:34.000+0000 | 1127329 |
HorizontaFill-iOS-bad.png | 2018-07-13T20:54:20.000+0000 | 59750 |
HorizontalFill-Android-good.png | 2018-07-13T20:54:20.000+0000 | 83435 |
HorizontalFillTest.js | 2018-07-13T20:54:13.000+0000 | 6942 |
HorizontalPercent50x50Test.js | 2018-07-13T20:54:13.000+0000 | 447 |
HorizontalPercent-Android-good.png | 2018-07-13T20:54:20.000+0000 | 30256 |
HorizontalPercent-iOS-bad.png | 2018-07-13T20:54:20.000+0000 | 22167 |
Mhh, it seems to work just fine (tested on [iPhone](https://abload.de/img/simulatorscreenshot-i66i8r.png) and [iPad](https://abload.de/img/simulatorscreenshot-i94ddy.png)):
can you try it with an iphone 7 simulator? I got feedback of an app that wasn't showing all buttons (4 with 25%). The last button is only visible when I change to around 24.85%. All other phones where happy with 25% but one user mentioned that on his iphone 7 it wasn't working right.
Can you try to
Math.ceil
the calculations, see TIMOB-26221ah, if you mean Math.floor then you are right, that works too. Device width is 375 (so it is 93.75 at 25%) for my 4 buttons it will be * setting it to 25% -> the last button is not visible * setting it to Math.ceil() -> one button is 94 width -> sum 376 = button is missing * setting it to Math.floor() -> one button is 93 width -> sum 372 = button is shown
For the other case, Math.ceil worked as well, but that's a quite different case because
more
space was needed. Do you think, this should be done internally? It might be tricky to know if rounding up or down would be requiredLike you say, would be hard to decide which one you need. Perhaps there should be a warning when you set width/height to percentages on iOS and you'll end up with a floating point number? So the user can decide
If you look at !HorizontaFill-iOS-bad.png|thumbnail! you see a 25% and 50% views placed next to each other and a 75% sized view below it. The 2 views above seem to be a couple pixels wider than the bottom 75% view. I got the impression that a view was being set wider than configured and that's why it was wrapping. Note that I reproduced this issue in the iOS simulator. I have not tried on a real devices.
!Bildschirmfoto 2018-07-20 um 22.31.05.png|thumbnail! It seems to be a device specific issue, which is in general a good thing! I'm betting on either the scale factor or the rounding, and I bet on the rounding, because the screen width of the iPhone 7 may have a modulo > 0, resulting in rounding errors, resulting in this glitch. *EDIT*: That's the reason. An iPhone 5 has a base width of 320 px (160 px at 50%). The iPhone 7 has a base width of 375 px (157.5 px at 50 %). And the core rounds up by default, so it's 158+158 = 376, which results in a new line. Any ideas how to solve this practically? *EDIT 2*: It can be solved by removing the
roundf
[here](https://github.com/appcelerator/titanium_mobile/blob/master/iphone/Classes/TiDimension.h#L109), but I need to check on the possible side affects. [~jquick] do we have a full layout test app already? *EDIT 3*: TIMOB-11977 is where the rounding was introduced (SDK 3.1.0), with a valid reason. How does Android handle this?PR: https://github.com/appcelerator/titanium_mobile/pull/10194 Test-Cases: See the ones above + the one from TIMOB-11977.
PR (7_3_X): https://github.com/appcelerator/titanium_mobile/pull/10214
Verified as fixed.Closing ticket.Tested SDK version 7.4.0.v20180820065502 Test Environment: APPC Studio: 5.1.0.201808080937 APPC CLI: 7.0.5 iPhone 7 simulator (11.0) iPhone 5simulator (11.4) iPhone 6s simulator (11.0) iPhone 6s -10.0 Operating System Name: Mac OS High Sierra Operating System Version: 10.13.6 Node.js Version: 8.9.1 Xcode 9.4.1
[~hknoechel] i tested with the sdk mentioned in PR of this ticket and i dont see the bug in the sdk mentioned.it seems not merged in 7.3. GA, bug present in 7.3.GA and latest 7.3.X SDK.
Verified the fix on SDK 7.5.0.v20180911090425. Works fine. Closing.