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
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

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
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"
>
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

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
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

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

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
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

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


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;
}
}
};
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

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
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"
After choosing one of the above approaches, rebuild and redeploy your application.
Regards,
Nikolay Iliev
Progress Telerik

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
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