Hi Team,
I have a RadListView in Xamarin Forms which has a custom cell. This cell contains a number of objects plus an Image. If I deploy this to an Android device is stutters when scrolling the list. If I remove the Image then the list scroll is smooth. How can I get a smooth scrolling list with an image attached? I am using the "UI for Xamarin Q2 2015" dlls.
8 Answers, 1 is accepted
Thank you for contacting us! The described behavior is known limitation in Android image visualization.
Currently, images are loaded in the UI thread and thus blocking the measure cycle. We are working on resolving this by building component that will handle this directly in the native platform in one of our future releases.
Regards,
Tsvyatko
Telerik
Hi Tsvyatko,
Do you know when this future release will be available?
Thanks.
The fix for this issue will be released in a build in a beginning of November.
Please excuse us for the inconvenience caused!
Regards,
Tsvyatko
Telerik
Thank you for getting back to us.
Since, the last November we have some major improvements in the rendering of the listview. In the cases where item template contains images you can boost the list view performance by adding our ImageRenderer the the set of rednderers:
[assembly: Xamarin.Forms.ExportRenderer(
typeof
(Image),
typeof
(Telerik.XamarinForms.Common.Android.AndroidImageRenderer))]
Let us know if this helps. If not would it be possible to share some additional information regarding the setup of the listview - template complexity,variable item size, container that listview is nested in.
Regards,
Tsvyatko
Telerik by Progress
Hi,
I am not the initiator of this thread, I just thought it makes sense to add my problem here. Feel free to move this to a new thread if it suits better for your internals.
I am using a pretty complex ViewCell template (well, at least it is in the Xamarin Forms world). Here is the code I am using:
01.
<telerikDataControls:RadListView x:Name=
"NewsListView"
Grid.Row=
"1"
ItemsSource=
"{Binding NewsTabVm.NewsPosts}"
SelectionMode=
"None"
SelectionGesture=
"Tap"
>
02.
<telerikDataControls:RadListView.LayoutDefinition>
03.
<listView:ListViewLinearLayout VerticalItemSpacing=
"6"
HorizontalItemSpacing=
"6"
></listView:ListViewLinearLayout>
04.
</telerikDataControls:RadListView.LayoutDefinition>
05.
06.
<telerikDataControls:RadListView.Behaviors>
07.
<behaviors:EventToCommandBehavior EventName=
"ItemTapped"
Command=
"{Binding NewsTabVm.PostSelectedCommand}"
Converter=
"{StaticResource ItemTappedConverter}"
></behaviors:EventToCommandBehavior>
08.
</telerikDataControls:RadListView.Behaviors>
09.
10.
<telerikDataControls:RadListView.ItemTemplate>
11.
<DataTemplate>
12.
<listView:ListViewTemplateCell>
13.
<listView:ListViewTemplateCell.View>
14.
<Grid HeightRequest=
"200"
Margin=
"6"
BackgroundColor=
"Black"
>
15.
<Grid>
16.
<Grid.RowDefinitions>
17.
<RowDefinition Height=
"*"
></RowDefinition>
18.
</Grid.RowDefinitions>
19.
<Grid.ColumnDefinitions>
20.
<ColumnDefinition Width=
"*"
></ColumnDefinition>
21.
</Grid.ColumnDefinitions>
22.
<ffImgLoading:CachedImage Grid.Row=
"0"
Grid.Column=
"0"
23.
HorizontalOptions=
"FillAndExpand"
VerticalOptions=
"FillAndExpand"
24.
CacheDuration=
"5"
Source=
"{Binding Image}"
MinimumHeightRequest=
"200"
25.
Aspect=
"AspectFill"
FadeAnimationEnabled=
"True"
>
26.
</ffImgLoading:CachedImage>
27.
</Grid>
28.
29.
<Grid VerticalOptions=
"Start"
HorizontalOptions=
"EndAndExpand"
BackgroundColor=
"Lime"
IsVisible=
"{Binding IsLeitArtikel}"
WidthRequest=
"28"
HeightRequest=
"28"
>
30.
<Image Source=
"ic_star_white_24dp.png"
HorizontalOptions=
"Center"
VerticalOptions=
"Center"
></Image>
31.
</Grid>
32.
33.
<Grid VerticalOptions=
"EndAndExpand"
BackgroundColor=
"#96000000"
Margin=
"0,0,0,-2"
>
34.
<Grid.RowDefinitions>
35.
<RowDefinition Height=
"Auto"
></RowDefinition>
36.
<RowDefinition Height=
"Auto"
></RowDefinition>
37.
</Grid.RowDefinitions>
38.
<Label Grid.Row=
"0"
Text=
"{Binding Title}"
FontAttributes=
"Bold"
FontSize=
"Medium"
Margin=
"6,0"
TextColor=
"White"
></Label>
39.
40.
<Grid Grid.Row=
"1"
Margin=
"6,0"
>
41.
<Grid.ColumnDefinitions>
42.
<ColumnDefinition Width=
"*"
></ColumnDefinition>
43.
<ColumnDefinition Width=
"*"
></ColumnDefinition>
44.
</Grid.ColumnDefinitions>
45.
<StackLayout Orientation=
"Horizontal"
Grid.Row=
"0"
VerticalOptions=
"Center"
Margin=
"0,0,0,6"
>
46.
<Label Text=
"{Binding Date}"
VerticalOptions=
"Center"
></Label>
47.
<Label Text=
"{Binding AuthorName}"
VerticalOptions=
"Center"
></Label>
48.
</StackLayout>
49.
<StackLayout Orientation=
"Horizontal"
Grid.Column=
"1"
HorizontalOptions=
"EndAndExpand"
Margin=
"0,0,0,6"
>
50.
<Label Text=
"{Binding CommentCount}"
VerticalOptions=
"Center"
></Label>
51.
<Image Source=
"ic_mode_comment_white_24dp.png"
WidthRequest=
"18"
HeightRequest=
"18"
></Image>
52.
</StackLayout>
53.
</Grid>
54.
</Grid>
55.
</Grid>
56.
</listView:ListViewTemplateCell.View>
57.
</listView:ListViewTemplateCell>
58.
</DataTemplate>
59.
</telerikDataControls:RadListView.ItemTemplate>
60.
61.
62.
</telerikDataControls:RadListView>
I have used this kind of template already a thousand times on Windows (Phone 7/8.x/10) without any problems.
Adding you ImageRenderer has no recognizable imapct, but that might be due to the fact I am using the FFImageLoading library because of its advanced techniques of caching.
Once I have scrolled down the whole list, it is working a little better during scrolling. The ListView is inside a Grid with two rows, the first one is defined as Star and the second is defined as Auto. The Grid is inside a ContentPage that is part of a two page CarouselPage. Data is bound via MVVM.
I am open for any suggestions.
Thank you for sharing this information. It will help us better identify performance issues in real case scenarios and add improvements in the future releases.
Regarding the image renderer - indeed it will not bring any change as it basically apply performance improvements only to the rendering of the default Xamarin Image control in Android.
What I can suggest that will work good both in the ours and the default listview is creating custom cell that derive from templatecell/viewcell and apply the data in code-behind directly the elements in the View (without using binding or reflection) e.g.:
var product= BindingContext
as
Product;
if
(product!=
null
) {
TextLabel.Text = product.Name;
DescriptionLabel.Text = product.Description;
...
}
We are planing to issue a blogpost how to apply this aproach using our listviewtemplate cell.
Regards,
Tsvyatko
Telerik by Progress
I wanted to follow-up quickly with an example using Tsvyatko's recommended approach, but using FFImageLoading in the template. Find it attached (you didn't specify which platform so I included all but tested extensively on Android).
Ultimately, after applying the custom TemplateCell, I was unable to determine a specific link between the RadListView and FFImage's CachedImage component leading to the performance problem as the images loaded pretty quick despite being high res (demo used Bing Images's 1080 images).
I did some further optimization and got significant improvement in load times by doing these:
- Set the DownsampleWidth to match what the container's width is (significant boost from this)
- Try using a different CacheType (it has both Disk and Memory), I chose Memory for the purposes of the demo. If your app will be showing the same images on multiple app launches, Disk or All is better
Here's a page from the FFImage.CacheImage docs, it has some great examples you could apply (in the custom TemplateCell or in the XAML).
Once the image is downloaded and cached by the control, it loads quickly when scrolling through the item containers. For quick reference, here is the XAML and CustomTemplateCell code.
XAML
<
telerikDataControls:RadListView
ItemsSource
=
"{Binding BingImages}"
>
<
telerikDataControls:RadListView.ItemTemplate
>
<
DataTemplate
>
<
layouts:FastTemplateCell
>
<
layouts:FastTemplateCell.View
>
<
Grid
>
<
Grid.RowDefinitions
>
<
RowDefinition
/>
<
RowDefinition
Height
=
"Auto"
/>
</
Grid.RowDefinitions
>
<
forms:CachedImage
x:Name
=
"image"
Grid.Row
=
"0"
HorizontalOptions
=
"FillAndExpand"
VerticalOptions
=
"FillAndExpand"
CacheDuration
=
"5"
CacheType
=
"All"
DownsampleWidth
=
"300"
HeightRequest
=
"200"
Aspect
=
"AspectFill"
FadeAnimationEnabled
=
"True"
/>
<
Grid
Grid.Row
=
"1"
BackgroundColor
=
"White"
>
<
StackLayout
Padding
=
"16"
>
<
Label
x:Name
=
"title"
TextColor
=
"#362F2D"
FontAttributes
=
"Italic"
FontSize
=
"16"
LineBreakMode
=
"TailTruncation"
/>
<
Label
x:Name
=
"author"
TextColor
=
"#534741"
FontSize
=
"12"
LineBreakMode
=
"TailTruncation"
/>
</
StackLayout
>
</
Grid
>
</
Grid
>
</
layouts:FastTemplateCell.View
>
</
layouts:FastTemplateCell
>
</
DataTemplate
>
</
telerikDataControls:RadListView.ItemTemplate
>
</
telerikDataControls:RadListView
>
C#
public
class
FastTemplateCell : ListViewTemplateCell
{
private
FFImageLoading.Forms.CachedImage image;
private
Label titleLabel;
private
Label authorLabel;
protected
override
void
OnBindingContextChanged()
{
base
.OnBindingContextChanged();
this
.EnsureCachedElements();
var data =
this
.BindingContext
as
BingImage;
if
(data !=
null
)
{
this
.image.Source = $
"http://www.bing.com{data?.url}"
;
this
.authorLabel.Text = data?.copyright;
this
.titleLabel.Text = data?.startdate;
}
}
private
void
EnsureCachedElements()
{
if
(
this
.image ==
null
)
{
this
.image =
this
.View.FindByName<CachedImage>(
"image"
);
}
if
(titleLabel ==
null
)
{
this
.titleLabel =
this
.View.FindByName<Label>(
"title"
);
}
if
(authorLabel ==
null
)
{
this
.authorLabel =
this
.View.FindByName<Label>(
"author"
);
}
}
}
Please let us know if this doesn't resolve the issue and we'll investigate further. If possible, update the demo project to replicate the problem you're seeing.
Thank you for contacting Support and for choosing Telerik!
Regards,
Lance | Tech Support Engineer, Sr.
Telerik by Progress