Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-26211] iOS: Percentage based layout rounds floating widths/heights incorrectly

GitHub Issuen/a
TypeBug
PriorityMedium
StatusClosed
ResolutionFixed
Resolution Date2018-08-24T17:22:22.000+0000
Affected Version/sn/a
Fix Version/sRelease 7.5.0
ComponentsiOS
Labelshorizontal, iOS, layout, percent
ReporterJoshua Quick
AssigneeHans Knöchel
Created2018-07-13T21:04:52.000+0000
Updated2018-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:* Use Ti.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

FileDateSize
Bildschirmfoto 2018-07-20 um 22.27.03.png2018-07-20T20:27:26.000+0000394664
Bildschirmfoto 2018-07-20 um 22.31.05.png2018-07-20T20:32:34.000+00001127329
HorizontaFill-iOS-bad.png2018-07-13T20:54:20.000+000059750
HorizontalFill-Android-good.png2018-07-13T20:54:20.000+000083435
HorizontalFillTest.js2018-07-13T20:54:13.000+00006942
HorizontalPercent50x50Test.js2018-07-13T20:54:13.000+0000447
HorizontalPercent-Android-good.png2018-07-13T20:54:20.000+000030256
HorizontalPercent-iOS-bad.png2018-07-13T20:54:20.000+000022167

Comments

  1. Hans Knöchel 2018-07-20

    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)):
  2. Michael Gangolf 2018-07-20

    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.
  3. Hans Knöchel 2018-07-20

    Can you try to Math.ceil the calculations, see TIMOB-26221
  4. Michael Gangolf 2018-07-20

    ah, 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
  5. Hans Knöchel 2018-07-20

    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 required
  6. Michael Gangolf 2018-07-20

    Like 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
  7. Joshua Quick 2018-07-20

    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.
  8. Hans Knöchel 2018-07-20

    !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?
  9. Hans Knöchel 2018-07-20

    PR: https://github.com/appcelerator/titanium_mobile/pull/10194 Test-Cases: See the ones above + the one from TIMOB-11977.
  10. Hans Knöchel 2018-07-26

    PR (7_3_X): https://github.com/appcelerator/titanium_mobile/pull/10214
  11. Keerthi Mahalingam 2018-08-21

    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
  12. Keerthi Mahalingam 2018-08-21

    [~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.
  13. Keerthi Mahalingam 2018-09-11

    Verified the fix on SDK 7.5.0.v20180911090425. Works fine. Closing.
        Operating System
          Name                        = Mac OS X
          Version                     = 10.13.6
        Node.js
          Node.js Version             = 8.9.1
          npm Version                 = 5.5.1
        Titanium CLI
          CLI Version                 = 5.1.1
        Titanium SDK
          SDK Version               = 7.5.0.v20180911090425
        iPhone6s                      =Ios 11
        iPhone 5s .                   = Ios 12 emulator
        

JSON Source