glidex
glidex copied to clipboard
Xamarin.Forms.Image Does Not Appear
The Image does not appear when HorizontalOptions = LayoutOptions.CenterAndExpand
Reproduction Sample: https://github.com/brminnick/GlideX_HorizontalOptions_Repro
Repro Video: https://1drv.ms/u/s!AnmXwEzpaYLslzhIQmucWNj7U98O
So this brings up a valid concern:
- Xamarin.Forms layouts tend to let the size of image content "push" layouts around. In other words, the size of the image impacts the layout.
- Glide, however, is implemented in reverse. It will scale/transforms/thumbnail images as they are loaded! Hence, an image set to
Center
will not grow when the image is loaded. It will load an image the size of the control...
These two ways of doing things are at odds...
I am uncertain what to do here yet. I tried doing something like what was mentioned here:
//NOTE: SIZE_ORIGINAL is Java.Lang.Integer.MinValue
//https://github.com/bumptech/glide/blob/master/library/src/main/java/com/bumptech/glide/request/target/Target.java#L28
builder.Apply(RequestOptions.OverrideOf (SIZE_ORIGINAL));
But it did not adjust the layout in Xamarin.Forms.
Image in StackLayout Doesn't Appear
Here's another example where the image doesn't appear; this time when it's inside of a StackLayout
public class StackLayoutPage : ContentPage
{
const string _xamarinImageUrl = "https://raw.githubusercontent.com/github/explore/06da849e137507b144448ac2b28bc19d3b909cab/topics/xamarin/xamarin.png";
public StackLayoutPage()
{
var imageLabel = new Label { Text = "This image is broken" };
var brokenImage = new Image { Source = _xamarinImageUrl };
var stackLayout = new StackLayout
{
Children = {
imageLabel,
brokenImage
}
};
Content = stackLayout;
}
}
Workaround
Specifying a value for HeightRequest
will allow the image to appear
public class StackLayoutPage : ContentPage
{
const string _xamarinImageUrl = "https://raw.githubusercontent.com/github/explore/06da849e137507b144448ac2b28bc19d3b909cab/topics/xamarin/xamarin.png";
public StackLayoutPage()
{
var imageLabel = new Label { Text = "This image is not broken" };
var brokenImage = new Image
{
HeightRequest = 100,
Source = _xamarinImageUrl
};
var stackLayout = new StackLayout
{
Children = {
imageLabel,
brokenImage
}
};
Content = stackLayout;
}
}
I'm hitting sort of the same issue: my Image only appears after the source has been changed (for animations between images) or a full layout cycle has been done. I have toggle to show/hide the navigation bar and when I toggle that the images appear, not before.
@rogihee your case sounds different: using an animation + inside navigation bar.
Could you file a new issue with a code example?
hi Jonathan, I meant that that toggling the nav bar on/off was showing it in the page. I'll see if I can reproduce the case, it is quite standard usage of Image, but somewhere in nested layout.
I had the same issue. I realized if the HorizontalOptions don't be set to Fill
or FillAndExpand
, the image don't shows (widht == 0).
But if you update the layout, showing and hide an activity indicator g.ex. the image shows up (width != 0).
I made an example for this.
Same issue here.
I just noticed that every time I toggle the IsVisible
property, I always see this log from the console output:
[glidex] IImageViewHandler of type `Android.Glide.ImageViewHandler`, `LoadImageAsync` called.
Here's a snippet with comments from our code. Hope it would help you figure out what's causing the issue.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- This button gets distorted/disappears when you click it enough times -->
<ImageButton
Grid.ColumnSpan="3"
Margin="0,20,10,10"
VerticalOptions="Start"
HorizontalOptions="End"
WidthRequest="44"
HeightRequest="44"
BackgroundColor="Transparent"
IsVisible="False"
Source="{x:Static res:Images.IcSomeImage}"
Command="{Binding SomeCommand}">
<ImageButton.Behaviors>
<behaviors:FadingVisibilityBehavior
BindingContext="{Binding BindingContext, Source={x:Reference Page}}"
IsVisible="{Binding ShowControls}" />
</ImageButton.Behaviors>
</ImageButton>
<!-- This button have almost the same property as above but it has no issue -->
<ImageButton
Grid.ColumnSpan="3"
VerticalOptions="Start"
HorizontalOptions="Start"
WidthRequest="44"
HeightRequest="44"
Margin="10,20"
BackgroundColor="Transparent"
Source="{x:Static res:Images.IcSomeOtherImage}"
Command="{Binding SomeOtherCommand}">
<ImageButton.Behaviors>
<behaviors:FadingVisibilityBehavior
BindingContext="{Binding BindingContext, Source={x:Reference Page}}"
IsVisible="{Binding ShowControls}" />
</ImageButton.Behaviors>
</ImageButton>
<!-- Other more controls are omitted -->
</Grid>
I suspect it has something to do with the Forms layout engine and size calculation. Either incorrect sizing by Forms or the incorrect size as seen by Glide. I noticed the VerticalOptions and HorizontalOptions did have an effect on whether Glide showed the picture or not, but could not create a simple reproduction.
In some layouts you should try setting HeightRequest
or WidthRequest
.
The problem is a conflict in how Glide and Xamarin.Forms work: https://github.com/jonathanpeppers/glidex/issues/10#issuecomment-433109852
I am trying to create a staggered layout but while using glidex I cannot get the image size. I need to provide height request and width request manually. What should I do to get correct sizes ?
I am trying to create a staggered layout but while using glidex I cannot get the image size. I need to provide height request and width request manually. What should I do to get correct sizes ?
UX wise, you should always specify the sizes in ImageView controls on its @1x equivalent.
But
I am trying to create a staggered layout but while using glidex I cannot get the image size. I need to provide height request and width request manually. What should I do to get correct sizes ?
UX wise, you should always specify the sizes in ImageView controls on its @1x equivalent.
But in a staggered layout, the image size is dynamic
Is there any way to ignore/skip glidex on a per image basis?
Same situation as this - I have one image thats not appearing because of no WidthRequest
(has HeightRequest
, but image sizes are unknown), but this particular page isn't in a list, it's a single image on a page so the performance boost from glidex isn't as important.
@thewoodknight you might implement your own IGlideHandler
to do this, see: https://github.com/jonathanpeppers/glidex/issues/89#issuecomment-790635408
I faced this issue too.
Implementing IGlideHandler solved this problem. However, performance may be degraded.
my workaround:
public class CustomGlideHandler: IGlideHandler
{
public bool Build(ImageView imageView, ImageSource source, RequestBuilder builder, CancellationToken token)
{
// if not using glidex, the file name is attached "_nc".
if (source is FileImageSource imageSource && imageSource.File.EndsWith("_nc"))
{
builder.Dispose();
builder = null;
// call default handler
var defaultHandler = new FileImageSourceHandler();
Task.Run(() =>
{
defaultHandler.LoadImageAsync(imageSource, imageView, token);
});
return true;
}
return false;
}
}