I have a Xamarin.Forms app that has a header in a rather complex grid layout. When the page is loaded the first time, it does not show the header. If I go back and the reload the page, the header now shows and every time after that it shows. I'm using FFImageLoading 2.2.9. I'm using Xamarin.Forms 2.3.4.231. Any ideas why this might be occurring?
<ffimageloading:CachedImage Grid.Row="1"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
DownsampleToViewSize="true"
Source="header.png" />
I'm trying to get a sample project together.
I'm unable to recreate it in a sample project. I think part of the issue is that the layout system has finished laying out before the image is loaded. Are all images loaded asynchronously? Are we able to specify that the images are loaded before the page is shown? Regular Images are pulled before the page loads; I'd love the same to happen for CachedImages, unless I'm misunderstanding their use.
I'm simply trying to optimize image resource usage due to Android OutOfMemory issues. I am trying to load images that are in the /Resources/ on iOS and /drawable/ on Android folders.
Thanks!
Here's the sample I was running, trimmed down for the test project, but not actually showing the issue... It won't help replicate the issue, but it may point out something I'm doing wrong:
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:ffimageloading="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms"
xmlns:local="clr-namespace:tester;assembly=tester"
x:Class="tester.testerPage"
Title="Main"
BackgroundColor="White">
<ContentPage.Resources>
<ResourceDictionary>
<Color x:Key="DebugBackgroundColor">Red</Color>
<Color x:Key="LightBackgroundColor">#E5E5EA</Color>
<Color x:Key="AppBackgroundColor">#000000</Color>
<Color x:Key="PrimaryColor">#99242F</Color>
<Color x:Key="SecondaryColor">#414042</Color>
<Color x:Key="HeaderTextColor">#FFFFFF</Color>
<Color x:Key="ErrorColor">#E00000</Color>
<Color x:Key="WarningColor">#F09000</Color>
<Color x:Key="MenuBackgroundColor">#000000</Color>
<Color x:Key="MenuButtonBackground">#7F7F7F</Color>
<Color x:Key="MenuButtonTextColor">#FFFFFF</Color>
<Style x:Key="BackgroundPrimaryStyle"
TargetType="VisualElement">
<Setter Property="BackgroundColor"
Value="{DynamicResource PrimaryColor}" />
</Style>
<Style x:Key="BackgroundSecondaryStyle"
TargetType="VisualElement">
<Setter Property="BackgroundColor"
Value="{DynamicResource SecondaryColor}" />
</Style>
<Style x:Key="PasscodeButtonStyle"
TargetType="Button">
<Setter Property="BackgroundColor"
Value="{DynamicResource PrimaryColor}" />
<Setter Property="TextColor"
Value="White" />
<Setter Property="BorderRadius"
Value="20" />
<Setter Property="FontSize"
Value="20" />
</Style>
<Style x:Key="HeaderLabelStyle"
TargetType="Label">
<Setter Property="TextColor"
Value="{DynamicResource HeaderTextColor}" />
<Setter Property="FontAttributes"
Value="Bold" />
<Setter Property="HorizontalOptions"
Value="Center" />
<Setter Property="VerticalOptions"
Value="Center" />
</Style>
<Style x:Key="BottomLabelButtonStyle"
TargetType="Label"
BasedOn="{StaticResource HeaderLabelStyle}">
<Setter Property="HorizontalOptions"
Value="FillAndExpand" />
<Setter Property="VerticalOptions"
Value="FillAndExpand" />
<Setter Property="HorizontalTextAlignment"
Value="Center" />
</Style>
<Style x:Key="MainStackLayoutStyle"
TargetType="StackLayout">
<Setter Property="HorizontalOptions"
Value="FillAndExpand" />
<Setter Property="VerticalOptions"
Value="FillAndExpand" />
<Setter Property="Spacing"
Value="0" />
<Setter Property="Padding"
Value="1" />
</Style>
<Style x:Key="MainButtonStyle"
TargetType="Button">
<Setter Property="TextColor"
Value="{DynamicResource PrimaryColor}" />
<Setter Property="FontSize"
Value="Large" />
</Style>
<Style x:Key="MainLabelStyle"
TargetType="Label">
<Setter Property="TextColor"
Value="{DynamicResource PrimaryColor}" />
<Setter Property="HorizontalTextAlignment"
Value="Center" />
<Setter Property="VerticalTextAlignment"
Value="Center" />
<Setter Property="FontSize"
Value="Large" />
<Setter Property="HorizontalOptions"
Value="Fill" />
<Setter Property="VerticalOptions"
Value="Fill" />
</Style>
<Style x:Key="MainLabelSubStyle"
TargetType="Label">
<Setter Property="TextColor"
Value="{DynamicResource SecondaryColor}" />
<Setter Property="HorizontalTextAlignment"
Value="Center" />
<Setter Property="VerticalTextAlignment"
Value="Center" />
<Setter Property="FontSize"
Value="Medium" />
<Setter Property="HorizontalOptions"
Value="Fill" />
<Setter Property="VerticalOptions"
Value="Fill" />
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout Spacing="0">
<Grid Grid.Row="0"
x:Name="headerSection"
Grid.RowSpacing="0"
Style="{DynamicResource BackgroundPrimaryStyle}">
<Grid.RowDefinitions>
<RowDefinition>
<RowDefinition.Height>
<OnPlatform x:TypeArguments="GridLength">
<On Platform="iOS">20</On>
<On Platform="Android">0</On>
</OnPlatform>
</RowDefinition.Height>
</RowDefinition>
<RowDefinition Height="35" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ContentView Padding="10,0,0,0"
Grid.Row="1"
Grid.Column="0"
HorizontalOptions="Start">
<!--<Button x:Name="btnMenu" Text="Back" TextColor="White" Command="{Binding MenuCommand}" />-->
</ContentView>
<Label Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="3"
Text="App Name"
Style="{StaticResource HeaderLabelStyle}" />
<ContentView Padding="0,0,10,0"
Grid.Row="1"
Grid.Column="2"
HorizontalOptions="End">
<ContentView Padding="0,0,10,0"
Grid.Row="1"
Grid.Column="2"
HorizontalOptions="End">
<Button Text="Logout"
TextColor="White" />
</ContentView>
</ContentView>
</Grid>
<ffimageloading:CachedImage Grid.Row="1"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
FadeAnimationEnabled="false"
Source="header.png" />
<!--<Image Source="header.png"
Grid.Row="1"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand" />-->
<Grid Grid.RowSpacing="0"
Grid.Row="2"
BackgroundColor="White"
Margin="5">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid Grid.Row="0"
Grid.Column="0"
Padding="25"
BackgroundColor="{DynamicResource LightBackgroundColor}">
<Grid.RowDefinitions>
<RowDefinition Height="8*" />
<RowDefinition Height="2*" />
<RowDefinition Height="1.5*" />
</Grid.RowDefinitions>
<Label Grid.Row="1"
Text="StartAChat"
Style="{DynamicResource MainLabelStyle}">
</Label>
<Label Grid.Row="2"
Text="StartAChatSub"
Style="{DynamicResource MainLabelSubStyle}">
</Label>
<ffimageloading:CachedImage Grid.Row="0"
Source="chat.png" />
</Grid>
<Grid Grid.Row="0"
Grid.Column="1"
Padding="25"
BackgroundColor="{DynamicResource LightBackgroundColor}">
<Grid.RowDefinitions>
<RowDefinition Height="8*" />
<RowDefinition Height="2*" />
<RowDefinition Height="1.5*" />
</Grid.RowDefinitions>
<Label Grid.Row="1"
Text="SubmitATip"
Style="{DynamicResource MainLabelStyle}">
</Label>
<Label Grid.Row="2"
Text="SubmitATipSub"
Style="{DynamicResource MainLabelSubStyle}">
</Label>
<ffimageloading:CachedImage Grid.Row="0"
Source="tip.png" />
</Grid>
<Grid Grid.Row="1"
Grid.Column="0"
Padding="25"
BackgroundColor="{DynamicResource LightBackgroundColor}">
<Grid.RowDefinitions>
<RowDefinition Height="8*" />
<RowDefinition Height="2*" />
<RowDefinition Height="1.5*" />
</Grid.RowDefinitions>
<Label Grid.Row="1"
Text="StartACall"
Style="{DynamicResource MainLabelStyle}">
</Label>
<Label Grid.Row="2"
Text="StartACallSub"
Style="{DynamicResource MainLabelSubStyle}">
</Label>
<ffimageloading:CachedImage Grid.Row="0"
Source="call.png" />
<!--<Image Grid.Row="0"
Source="call.png" />-->
</Grid>
<Grid Grid.Row="1"
Grid.Column="1"
Padding="25"
BackgroundColor="{DynamicResource LightBackgroundColor}">
<Grid.RowDefinitions>
<RowDefinition Height="8*" />
<RowDefinition Height="2*" />
<RowDefinition Height="1.5*" />
</Grid.RowDefinitions>
<ffimageloading:CachedImage Grid.Row="0"
Source="resources.png" />
<!--<Image Grid.Row="0"
Source="resources.png" />-->
<Label Grid.Row="1"
Text="ExistingTips"
Style="{DynamicResource MainLabelStyle}" />
<Label Grid.Row="2"
Text="ExistingTipsSub"
Style="{DynamicResource MainLabelSubStyle}" />
</Grid>
</Grid>
</StackLayout>
</ContentPage>
A point to note is that the images are being dynamically sized based on the available space on the screen and the assigned row heights for the grids. My goal is to have them autoresize between phone and tablet screen sizes filling the available space.
From my experience, the problems you're experiencing are because of the too deep layout hierarchy. Remove those two grids and stack layout, create only one Grid with 4 rows for all elements. I'm quite sure it will solve your issue. It's probably a Xamarin.Forms issue, not FFImageLoading one.
I am having the same issue here. FFImageLoading with Xamarin.Forms on iOS. Sometimes, the first time image is not loaded (local image with FileImageSource, not uri). Is too difficult to reproduce, because is random.
Having same issue. On first load, it does not show any images(remote url) on Xamarin.Forms on iOS. but subsequent load of app, it show the images.
Tried with different version of FFimageloading
2.2.9,
2.2.13,
2.2.19
and 2.2.20
with Xam.Forms 2.4.0.280 and 2.4.0.282
@softsan First question. Does it work when you replace CachedImage with Image?
@daniel-luberda - yes. It is working fine with normal Image control.
@softsan Is it possible to have a reproduction?
I'm also facing the same problem.. At first I thought it is a problem with my data binding, but images show up if load the page again.
I was running into the same issue in Xamarin.iOS. My UIImageViews are created dynamically in ViewDidLoad() and get their images set via LoadUrl().Into(). The first time the view controller loaded, the images would not be displayed, even though the Success and Finished events were triggered. However, if I triggered the image load through a user action (e.g. a button press), or if I closed the view controller and reopened it, the images would immediately be visible.
My fix for this was to call SetNeedsLayout on the image view in the Success event like this:
var imageView = new UIImageView(new CGRect(0, 0, 30, 30));
ImageService.Instance
.LoadUrl(imageUrl)
.Success(() => {
InvokeOnMainThread(() => {
imageView.SetNeedsDisplay();
});
})
.Into(imageView);
Daniel, I'm not very familiar with the FFImageLoading source code, but maybe the call to SetNeedsDisplay can be added before the Success callback is invoked, so that the image is always loaded the first time?
@walkerj77 It's implemented in upcoming 2.3.5
@daniel-luberda I get the same issue when loading images in a UITableView.
Scrolling the UITableView so the cell is redrawn then displays the image again.
I've installed 2.3.6 - Xamarin.IOS
Thanks to @walkerj77 for the work-around :)
Still this issue in Version 2.4.11.982
Most helpful comment
@walkerj77 It's implemented in upcoming 2.3.5