Nativescript: [iOS 13] SegmentedBar has changed look & feel

Created on 22 Sep 2019  路  6Comments  路  Source: NativeScript/NativeScript

Environment

  • CLI: 6.1.2
  • Cross-platform modules: 6.1.1
  • iOS Runtime: 6.1.1
  • Plugin(s): nativescript-theme-core

Describe the bug
It appears that Apple has updated the UISegmentedControl component. Take a look at the screenshots below to see the difference between ios 12 & 13 in the same app.

They have removed tintColor and added selectedSegmentTintColor property. Tested the new property localy and it works, but breaks on ios12 and earlier. https://developer.apple.com/documentation/uikit/uisegmentedcontrol/3335209-selectedsegmenttintcolor

Earlier versions handled the selected items text color automatically (I believe it was transparent, so that it gets the color of the background). But now it is the same as the rest of the items as it just applies the color property value.

Would be great if we could get it to behave as it did before, with the selected-item text color beeing transparent.

XML code:

<StackLayout class="fkz-blue-bg">
        <SegmentedBar selectedBackgroundColor="white" color="white" selectedIndex="0">
                <SegmentedBarItem title="Raspored" />
                <SegmentedBarItem title="Rezultati" />
                <SegmentedBarItem title="Tabela" />
        </SegmentedBar>
</StackLayout>

iOS 12.2
segmentbar_ios_12

iOS 13.0
segmentbar_ios_13

backlog bug ios

Most helpful comment

Yeah I still have the original issue I posted in the latest version (6.4.0). The font color on the selected item is the same as the background color...

All 6 comments

Here is a temporary qick-fix if you need this fast. Open the segmented-bar.ios.js and modifiy the following properties.

Need to include this at the top:
var platform_1 = require("../../platform");

Fix selected item background color:

SegmentedBar.prototype[segmented_bar_common_1.selectedBackgroundColorProperty.getDefault] = function () {
        if(platform_1.device.osVersion < "13"){
            return this.ios.tintColor;
        }
        else {
            return this.ios.selectedSegmentTintColor;
        }
};
    SegmentedBar.prototype[segmented_bar_common_1.selectedBackgroundColorProperty.setNative] = function (value) {
        var color = value instanceof segmented_bar_common_1.Color ? value.ios : value;
        if(platform_1.device.osVersion < "13"){
            this.ios.tintColor = color;
        }
        else {
            this.ios.selectedSegmentTintColor = color;
        }
};

Fix selected item text color:

SegmentedBar.prototype[segmented_bar_common_1.colorProperty.setNative] = function (value) {
        // Normal State
        var color = value instanceof segmented_bar_common_1.Color ? value.ios : value;
        var bar = this.ios;
        var currentAttrs = bar.titleTextAttributesForState(0);
        var attrs = currentAttrs ? currentAttrs.mutableCopy() : NSMutableDictionary.new();
        attrs.setValueForKey(color, NSForegroundColorAttributeName);
        bar.setTitleTextAttributesForState(attrs, 0);

        // Selected State - Add this to make the selected item text color be same as backgroundColor
        var colorBg = this.backgroundColor instanceof segmented_bar_common_1.Color ? this.backgroundColor.ios : this.backgroundColor;
        var selectedAttrs = bar.titleTextAttributesForState(4);
        var attrsSelected = selectedAttrs ? selectedAttrs.mutableCopy() : NSMutableDictionary.new();
        attrsSelected.setValueForKey(colorBg, NSForegroundColorAttributeName);
        bar.setTitleTextAttributesForState(attrsSelected, 4);
};

Result:
segmentbar_ios_13_fixed

The only issue after applying the fixes is that when pressing down & holding on the items (highlight state), the text color is same as the color value. So if you have selectedBackgroundColor and color set to white, pressing down on _selected item_, will make everything white. Identical to the image in the first post (ios 13).

If you want to control the higlight state text color just add this as well. This will apply same color for both non-selected and selected items. Rememer to include this at the top:
var color_1 = require("../../color");

// Highlight State - Add this if you want to control the color of the text when the item is highlighted. In this case a lighter gray color...
var highlightAttrs = bar.titleTextAttributesForState(1);
var attrsHighlight = highlightAttrs ? highlightAttrs.mutableCopy() : NSMutableDictionary.new();
attrsHighlight.setValueForKey(new color_1.Color("#DBDBDB").ios, NSForegroundColorAttributeName);
bar.setTitleTextAttributesForState(attrsHighlight, 1);

Hi @manijak,
Thank you for the provided info. I was able to recreate the issue and marked it as a bug. I also tested the provided solution and noticed that only replacing the tintColor with selectedSegmentTintColor seems to fix the problem for both(iOS 12 and iOS13).

How is the new selectedSegmentTintColor property used?
An update from tns-ios 6.1.1 to tns-ios 6.2.0 changed all SegmentedBar elements that could be coloured with css:
.segmentedBar { border-color: rgb(226, 0, 26); color: rgb(226, 0, 26); selected-background-color: rgb(226, 0, 26); background-color: white; }
to blue again.

Yeah I still have the original issue I posted in the latest version (6.4.0). The font color on the selected item is the same as the background color...

I can confirm that the issue is still present on 6.7.4 and iOS 13.5 while running in the simulator. You get a white background with white foreground on the SegmentedBar selected "button".

Here is a temporary qick-fix if you need this fast. Open the segmented-bar.ios.js and modifiy the following properties.

Need to include this at the top:
var platform_1 = require("../../platform");

Fix selected item background color:

SegmentedBar.prototype[segmented_bar_common_1.selectedBackgroundColorProperty.getDefault] = function () {
        if(platform_1.device.osVersion < "13"){
            return this.ios.tintColor;
        }
        else {
            return this.ios.selectedSegmentTintColor;
        }
};
    SegmentedBar.prototype[segmented_bar_common_1.selectedBackgroundColorProperty.setNative] = function (value) {
        var color = value instanceof segmented_bar_common_1.Color ? value.ios : value;
        if(platform_1.device.osVersion < "13"){
            this.ios.tintColor = color;
        }
        else {
            this.ios.selectedSegmentTintColor = color;
        }
};

Fix selected item text color:

SegmentedBar.prototype[segmented_bar_common_1.colorProperty.setNative] = function (value) {
        // Normal State
        var color = value instanceof segmented_bar_common_1.Color ? value.ios : value;
        var bar = this.ios;
        var currentAttrs = bar.titleTextAttributesForState(0);
        var attrs = currentAttrs ? currentAttrs.mutableCopy() : NSMutableDictionary.new();
        attrs.setValueForKey(color, NSForegroundColorAttributeName);
        bar.setTitleTextAttributesForState(attrs, 0);

        // Selected State - Add this to make the selected item text color be same as backgroundColor
        var colorBg = this.backgroundColor instanceof segmented_bar_common_1.Color ? this.backgroundColor.ios : this.backgroundColor;
        var selectedAttrs = bar.titleTextAttributesForState(4);
        var attrsSelected = selectedAttrs ? selectedAttrs.mutableCopy() : NSMutableDictionary.new();
        attrsSelected.setValueForKey(colorBg, NSForegroundColorAttributeName);
        bar.setTitleTextAttributesForState(attrsSelected, 4);
};

Result:
segmentbar_ios_13_fixed

The only issue after applying the fixes is that when pressing down & holding on the items (highlight state), the text color is same as the color value. So if you have selectedBackgroundColor and color set to white, pressing down on _selected item_, will make everything white. Identical to the image in the first post (ios 13).

If you want to control the higlight state text color just add this as well. This will apply same color for both non-selected and selected items. Rememer to include this at the top:
var color_1 = require("../../color");

// Highlight State - Add this if you want to control the color of the text when the item is highlighted. In this case a lighter gray color...
var highlightAttrs = bar.titleTextAttributesForState(1);
var attrsHighlight = highlightAttrs ? highlightAttrs.mutableCopy() : NSMutableDictionary.new();
attrsHighlight.setValueForKey(new color_1.Color("#DBDBDB").ios, NSForegroundColorAttributeName);
bar.setTitleTextAttributesForState(attrsHighlight, 1);

It works great! Thanks!

Do you think it's possible to set the selected element also BOLD?

Thanks

Marco

Was this page helpful?
0 / 5 - 0 ratings