This is a migrated thread and some comments may be shown as answers.

Color of selected items not visible when RadListView has backgroundColor

16 Answers 416 Views
ListView
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Marc
Top achievements
Rank 1
Marc asked on 30 May 2017, 10:32 AM

Hello,

we are applying some color templates to our app and the RadListView on iOS is causing some trouble during this process.

When no backgroundColor is set for the RadListView and its items, its background is going to be just white, but we want it to have the same backgroundColor like the rest of the page. When setting the backgroundColor of the page to the RadListView and its items in CSS, the selection color is not visible anymore on Press/LongPress.

Here is our CSS snippet (using the nativescript platform-css plugin)

.ios ListView,
.ios RadListView,
.ios .list-item,
.ios .rlv-item {
    background-color: #F1F1EB;
}

 

Then we tried to set the backgroundColor to transparent (works very well on Android). This brings the selection color back, but as describes in this post, the list will have a while background and we would have to set the background of every cell to transparent.

Is there a way to keep the native selection behaviour when applying a backgroundColor to the RadListView?

Our testing envirnonment:

  • NativeScript 2.5 (tns-core-modules 2.5.2)
  • Telerik AppBuilder 3.7.4

 

Best regards,

Marc

16 Answers, 1 is accepted

Sort by
0
Nick Iliev
Telerik team
answered on 30 May 2017, 11:54 AM
Hello Marc,

As far as I understood the issue on your side is when you are setting backgroundColor="transparent" for your RadListView along with the code for setting the item background color it will loose the default styling for all selecting items. However, as I do not have the actual code that stands behind your implementation and with the way nativescript-platform-css is affecting your project I  have created this test application to recreate the code as much as possible but the end the result is that I am not able to reproduce the issue as the selected styles are preserved on my side.

Here are the steps I have taken:

In the test application, I am setting the backgroundColor to transparent (for RadListView) while using Press as selection behavior. Then in the component class in itemLoading, I am changing the color of each item.
The final result is that the RadListView is transparent with custom color applied for each item and at the same time the selection styling is preserved just as it is by design (the selected cells are getting darker).

My guess here is that you are loosing the default styles due to overwriting them with the CSS rules and more specifically the one that is setting class .riv-item. I am only speculating here (as I do not have eyes on the actual source code) but if this class is used to overwrite the backgroundColor of your items it is expected that it will overwrite the selected styles as well. Simply removing this rule and applying the item color via itemLoading should resolve your issue.

If you still have troubles overcoming this one please send us a GitHub link or archive containing sample project which best illustrates and reproduces the issue.

Regards,
Nikolay Iliev
Progress Telerik
Did you know that you can open private support tickets which are reviewed and answered within 24h by the same team who built the components? This is available in our UI for NativeScript Pro + Support offering.
0
Marc
Top achievements
Rank 1
answered on 30 May 2017, 03:52 PM

Hello Nikolay,

thank you for your reply.

Indeed, the cause for loosing the selection color is due to overwriting it using my rlv-item class. I needed to set the backgroundColor for the ListView and for the list item as well, otherwise only the background of the RadListView would be colored, the list items themselves would stay white.

It is the same problem for the regular ListView component by the way.

So I am trying to find a way to handle this in the itemLoading event for both RadListViews and regular ListViews.

//itemLoading event for ListView/RadListView
exports.onItemLoading = function(args) {
    if(args.ios) {
        sharedModule.setIosListItemTransparentBackground(args);
    }
};
 
//shared function to set backgroundColor to transparent for any ListView/RadListView
exports.setIosListItemTransparentBackground = function(args) {
    if(args.object instanceof listViewModule.ListView) { //regular ListView?
        args.ios.backgroundColor = utilsModule.ios.getter(UIColor, UIColor.clearColor);
    } else if(args.object instanceof radListViewModule.RadListView) { //RadListView?
        //not executed - in RadListViews itemLoading event: args.object is undefined
        args.ios.backgroundColor = utilsModule.ios.getter(UIColor, UIColor.clearColor);
    }
}

 

Now I have some trouble in detecting, if the itemLoading event is executed by a regular ListView or a RadListView (like you can see in the comments of my code snippet).

Do you have any advice for me?

 

Best regards,

Marc

0
Nick Iliev
Telerik team
answered on 31 May 2017, 06:36 AM
Hey Marc,

The args.object in itemLoading event for RadListView won't' return a reference to your RadListView (but the same would do the job for the core ListView). However, an easy solution would be to check instance type of your list using the loaded event for your component. I have modified my test application to demonstrate this approach.

Here are the exact steps I have used:
Use the loaded event in your RadListView (or ListView)
<lv:RadListView loaded="onRadListLoaded">
And in the code behind file
export function onRadListLoaded(args) {
    let radList = <RadListView>args.object;
 
    if (args.object instanceof RadListView) {
        console.log("RadListView");
        isRad = true;
    }
}

Note that I am using a boolean property isRad to mark if the args.object is instance of RadListView

And then in setIosListItemTransparentBackground method using the boolean marker
function setIosListItemTransparentBackground(args) {
    if (isRad) { 
        console.log("isRad RadListView");
        var iosColor = new Color(20, 255, 0, 0).ios;
        args.ios.backgroundView.backgroundColor = iosColor;
    }
}


Regards,
Nikolay Iliev
Progress Telerik
Did you know that you can open private support tickets which are reviewed and answered within 24h by the same team who built the components? This is available in our UI for NativeScript Pro + Support offering.
0
Marc
Top achievements
Rank 1
answered on 31 May 2017, 08:41 AM

Hello Nikolay,

what I forgot to mention is, that the setIosListItemTransparentBackground method is defined and exported in a shared module. We have many pages with ListViews/RadListViews, so that's why I try to figure out the type of the ListView (regular or RadListView) centrally in this shared method. Then we want to require the module in every page where we need to set the background of the ListView/RadListView to transparent in its itemLoading event.

I noticed, that args.object in the itemLoading event returns a reference to the regular ListView, while args.view.parent SEEMS TO WORK for RadListView.

 

//shared.js
exports.setIosListItemTransparentBackground = function(args) {
    if(args.ios) {
        if(args.object instanceof listViewModule.ListView) {
            args.ios.backgroundColor = utilsModule.ios.getter(UIColor, UIColor.clearColor);
        } else if(args.view.parent instanceof radListViewModule.RadListView) {
            args.ios.backgroundView.backgroundColor = new colorModule.Color(0,0,0,0).ios;
        }
    }
};

 

I am not sure if this is a save way to fdo this or if the access to the parent element for args.view affects the performance in any way. Maybe you can suggest an even better/saver approach?

 

Best regards,

Marc

0
Nick Iliev
Telerik team
answered on 31 May 2017, 10:32 AM
Hello Marc,

You approach with args.view.parent is perfectly fine especially considering that you are already going to pass the args to your imported method setIosListItemTransparentBackground. If you want to workaround this, you can still pass the boolean isRad as an additional argument, however, your approach is even better as you won't need to write additionally loaded fallbacks for each page where RadListView or ListView is present.

Important note:
As of the upcoming versions of we are planning to introduce this change and the itemLoading (and all other RadListView events) would return a reference to the RadListView via args.object (and args.view.parent won't work). So if you decide to migrate to NativeScript 3.x.x and the latest version of nativescript-telerik-ui-pro you might need to update your code as well. We plan to introduce this breaking change so we would have identical event arguments for both the core ListView and RadListView.

Regards,
Nikolay Iliev
Progress Telerik
Did you know that you can open private support tickets which are reviewed and answered within 24h by the same team who built the components? This is available in our UI for NativeScript Pro + Support offering.
0
Marc
Top achievements
Rank 1
answered on 31 May 2017, 11:03 AM

Hello Nikolay,

Alright, so I'm going to use this approach until we migrate to NS 3. We still want to wait a wail before migrating our project, but I'm going to take a note concerning the event arguments, so thank you for informing me about the introduction of this breaking change.

Once again, thank you for your help and your advices.

 

Best regards,

Marc

0
Marc
Top achievements
Rank 1
answered on 01 Jun 2017, 04:54 PM

Hi Nikolay,

I have some trouble with this solution when the ListView/RadListView is embedded in a modal page (while everything works as expected when embedding it in a usual page).

The setIosListItemTransparentBackground method does not affect the backgroundColor of the list items, they are still white.

What I do:

<Page xmlns:lv="nativescript-telerik-ui-pro/listview"
      loaded="pageStoriesPagesLoaded"
      shownModally="pageStoriesPagesShownModally">
    <GridLayout rows="auto,*" className="modal-page">
        <lv:RadListView
                row="1"
                items="{{ pages }}"
                itemTap="selectPage"
                selectionBehavior="None">
            <lv:RadListView.listViewLayout>
                <lv:ListViewLinearLayout scrollDirection="Vertical" />
            </lv:RadListView.listViewLayout>
            <lv:RadListView.itemTemplate>
                <StackLayout>
                    <Label text="{{ 'Seite ' + page }}" className="list-item" />
                </StackLayout>
            </lv:RadListView.itemTemplate>
        </lv:RadListView>
        <AbsoluteLayout row="1" className="fab-center">
            <Image src="res://fab_cancel" tap="cancelModalPage"/>
        </AbsoluteLayout>
    </GridLayout>
</Page>

 

The result:

 

Do you know if there is something special that I need to care for in modal pages?

 

Best regards,

Marc

0
Nick Iliev
Telerik team
answered on 05 Jun 2017, 06:43 AM
Hello Marc,

For some reason, I am not seeing the image you have attached in your previous thread. However, I've tried the described scenario by putting the list view in a modal page and when using the solution with caching the instance of the RadListView using boolean variable isRad everything works as expected. I have updated the test application to demonstrate the solution while using a modal page. I hope this scenario is applicable your case but do let me know if you need further assistance.

Regards,
Nikolay Iliev
Progress Telerik
Did you know that you can open private support tickets which are reviewed and answered within 24h by the same team who built the components? This is available in our UI for NativeScript Pro + Support offering.
0
Marc
Top achievements
Rank 1
answered on 06 Jun 2017, 09:42 AM

Hi Nikolay,

I don't know what happened with the screenshot.

Here it is again:

 

I am doing the same as for other ListViews/RadListViews. The setIosListItemTransparentBackground is called as expected, but as you can see, the RadListView is just white, but ist should be transparent, so that the background should have the same color as the rest of the modal page (#F1F1EB).

 

Best regards,

Marc

0
Marc
Top achievements
Rank 1
answered on 06 Jun 2017, 09:43 AM
Okay, now I know why the screenshot was not visible. Have a look at the attachment now.
0
Marc
Top achievements
Rank 1
answered on 06 Jun 2017, 09:51 AM

Just to clarify once again, what I am doing to set the List-items transparent:

exports.setIosListItemTransparentBackground = function(args) {
    if(args.ios) {
        if(args.object instanceof listViewModule.ListView) {
            args.ios.backgroundColor = utilsModule.ios.getter(UIColor, UIColor.clearColor);
        } else if(args.view.parent instanceof radListViewModule.RadListView) {

             //transparent, so that list item has same color as page-background

            args.ios.backgroundView.backgroundColor = new colorModule.Color(0,0,0,0).ios; 
        }
    }
};
0
Nick Iliev
Telerik team
answered on 06 Jun 2017, 11:27 AM
Hi Marc,

I was able to fully reproduce the described behavior, and it appears that the default style for Modal pages that are going to be presented in fullscreen is disabling the transparency mode. To overcome this problem we need to overwrite the way the modal page is created by assigning a transparency styling.
To achieve that you will need to change the source code for node_modules/tns-core-modules/ui/page/page.ios.js (this should be done after npm install). Keep in mind that everytime you delete node_modules folder you will need to reapply the code for this feature

Here are the steps to apply the transparent mode for your modal page.
- run npm install
- go to node_modules/tns-core-modules/ui/page/page.ios.js
- find the method called _showNativeModalView
- change this code:
if (fullscreen) {
    this._ios.modalPresentationStyle = 0;
}

to this one
if (fullscreen) {
    this._ios.providesPresentationContextTransitionStyle = true;
    this._ios.definesPresentationContext = true;
    this._ios.modalPresentationStyle = UIModalPresentationOverFullScreen;
    this._ios.view.backgroundColor = UIColor.clearColor;
}

After this is done - remove only the platforms folder to make sure that previously applied logic from the modules is removed. You can now also set backgroundColor to transparent on each container view including the modalpage itslef as done here. After all this is set the modal page and the list-view along with its items will be all transparent and the main-page will be visible.

You can use this project as a reference but notice taht after tns build or npm install you will need to modify the code in node_modules/tns-core-modules/ui/page/page.ios.js as described above.

Regards,
Nikolay Iliev
Progress Telerik
Did you know that you can open private support tickets which are reviewed and answered within 24h by the same team who built the components? This is available in our UI for NativeScript Pro + Support offering.
0
Marc
Top achievements
Rank 1
answered on 06 Jun 2017, 01:24 PM

Hello Nikolay,

thanks for your reply.

we are working with PhpStorm and the Telerik AppBuilder CLI. Ho I can I it achieve it there?

I used npm install as well, but when I run appbuilder deploy ios, it seems that my local changes would not be used for the build.

And will this be only a temporary workaround, so that these lines might be added to the tns-core-modules?

 

Best regards,

Marc

0
Nick Iliev
Telerik team
answered on 06 Jun 2017, 02:04 PM
Hi Marc,

Before replying to your questions I want to underline that it is possible to change the transparency of a page runtime using almost the same approach but after or during the page loading.The approach is decided here for an Angular application, but the principle is the same in NativeScript core application as well. So if you prefer you can directly "allow" the transparency without having to change the source code of tns-core-modules.

That said the decision for the modal pages to be created with the default styling conventions in iOS is made considering that we want NativeScript to be as native as possible and comply with the iOS recommendations. Creating transparent modal pages is not recommended approach, so this is the reason why they are not enabled by default and why the default setting from iOS API is preventing this behavior.

However, you can overcome the issue with AppBuilder by passing the modified code in the form of your own generated package or via repository link to a forked repository where the code is applied.

Solution using your own generated package.

- clone the main NativeScript repository 
- navigate to tns-core-modules folder and change the code where needed
- then from the same folder make new npm pack (will generate *.tgx file)
- import the newly generated file as described here

Solution using forked repository
- fork the main NativeScript repository
- change the code where needed
- refer the forked repo in your project's package.json file
"tnws-core-modules" : "git://github.com/user/app.git#commit-ish"
Where "git://github.com/user/app.git#commit-ish"  should be the git ink to the forked repository with the modified code.
After choosing one of the above approaches, rebuild and redeploy your application.

Regards,
Nikolay Iliev
Progress Telerik
Did you know that you can open private support tickets which are reviewed and answered within 24h by the same team who built the components? This is available in our UI for NativeScript Pro + Support offering.
0
Marc
Top achievements
Rank 1
answered on 06 Jun 2017, 04:33 PM

Hi Nikolay,

I believe, this is going in the wrong direction and I do not want to work against the native styling conventions in Android and iOS as well.

Actually I do not want to create a transparent modal page and even the ListView/RadListView does not need to be transparent really. The only reason why i use my setIosListItemTransparentBackground method is, that I thought this would be the easiest way to make the ListView/RadListview having the same backgroundColor as the page behind and keeping the selection color.

Now I tried to go back to my first approach by setting the background-color of a list-item from CSS and bringing back the selection color by setting args.ios.selectionStyle = UITableViewCellSelectionStyle.UITableViewCellSelectStyleGray in the itemLoading event but that does not work.

I could set the backgroundColor like this: args.ios.backgroundView.backgroundColor = new colorModule.Color("#F1F1EB").ios instead to transparent, but the backgroundColor of the list depends on the color-template that the user of our app can select at runtime. Everything is organized by css themes, so I try to avoid of adding a switch-case statement that is passed in every itemLoading event to detect, which template is selected and which backgroundColor the list item needs.

 

Best regards,

Marc

 

0
Nick Iliev
Telerik team
answered on 07 Jun 2017, 06:05 AM
Hello,

As far as I understand your problem the users might change the CSS style runtime and depend on the chosen colors you want to update the background color of your list view items as well (without losing the selection styling).
What comes to mind is that perhaps you can use an observable property which value should be changed depending on the user choice. For example, once the user selects theme A, the observable property might store the color needed as a background color and then you can pass it to your itemLoading event with something like
var selectedColor = viewModel.get("mySelectedColor");
 
args.ios.backgroundView.backgroundColor = new colorModule.Color(selectedColor).ios;

Regards,
Nikolay Iliev
Progress Telerik
Did you know that you can open private support tickets which are reviewed and answered within 24h by the same team who built the components? This is available in our UI for NativeScript Pro + Support offering.
Tags
ListView
Asked by
Marc
Top achievements
Rank 1
Answers by
Nick Iliev
Telerik team
Marc
Top achievements
Rank 1
Share this question
or