Display image using Xamarin forms

Solved:. The answer was to upgrade all nuget packages and configure a newer version of Android. Images are now loading as expected. I am not happy with this, since I used exactly the code that Xamarin provided and intended for newer versions, did not approve of some of the elements that the code refers to. The original version was Xamarin.Forms v23 and I upgraded to V25

I have a new Xamarin forms project with a simple view in which I am trying to display an image. I tried several ways to get the image to display, and I was not lucky at all.

I am using <image> and I also tried the FFImageLoader control.

 <StackLayout Orientation="Vertical"> <ff:CachedImage Source="https://static.pexels.com/photos/104827/cat-pet-animal-domestic-104827.jpeg" WidthRequest="100" HeightRequest="100" /> <Button x:Name="btn" Text="Image" Clicked="Button_Clicked" /> <Frame OutlineColor="Red"> <Image x:Name="StupidImage" Source="{Binding Thumbnail}" Aspect="Fill" HeightRequest="100" WidthRequest="100" /> </Frame> </StackLayout> 

This is the current view. I also set the source directly to a value with no result.

I can get the stream for the image. I can read all bytes from the stream. I built a debug visualizer to display bytes as an image. Getting the image from the source is not a problem. Obtaining image controls to display an image is a problem.

I tried binding to the view model. When this failed, I tried to directly set the source

 StupidImage.Source = ImageSource.FromStream(() => result.Stream); 

I also made a copy of the bytes and tried

 StupidImage.Source = ImageSource.FromStream(() => new MemoryStream(imageBytes)); 

I tried ImageSource.FromFile() and .FromUri . I tried to add an image to the project as a resource. Each attempt was the same, the resource was read, and bytes were available, but the image control simply does not display it.

I thought this was a size issue, so I set the size of the control. Nothing. I thought this was a resolution problem, so I used a smaller image. I tried several different images of various quality.

Then I gave up image control, and I got the FFImageLoading nuget package and gave it the direct image URL. Same example as the FFImageLoading examples. No image yet.

I tried the emulator and I tried 2 different physical devices. The same result.

I also tried to set the image on the button using btn.Image = "whatever.jpg" with the same result.

This is the result every time. I'm lost. How do I display images?

EDIT: I got this to work, but only on an emulator

 <Image x:Name="StupidImage" Source="https://static.pexels.com/photos/104827/cat-pet-animal-domestic-104827.jpeg" /> 

and the same for

 StupidImage.Source = ImageSource.FromUri(new Uri("https://static.pexels.com/photos/104827/cat-pet-animal-domestic-104827.jpeg")); 

EDIT 2 - Clarification

My goal is to allow the user to select a photo from the device and then display its preview.

enter image description here

+5
source share
5 answers

If you want to use images in your application, you can upload them to your common project, for example

Embedded Resource

Make sure you change the Build action to Embedded Resource

Then in your code

 image.Source = ImageSource.FromResource("App5.Images.useravatar.png"); 

Pay attention to the name of the resource.

And xaml

 <ContentPage.Content> <StackLayout> <Image x:Name="image" WidthRequest="50"/> </StackLayout> </ContentPage.Content> 
+2
source

A few things you can remove from the list:

[x] Adding an image from Visual studio:

  • Right-click the desired folder.
  • select Add β†’ New file ... NB: you have to add it with visual studio, and not just drop it into a folder. Visual Studio needs to know about this.

[x] When adding the image is in the right place:

  • For android: it should be in

ProjectName.Driod.Resources.drawable folder

  • For ios: it should be in

ProjectName.iOS.Resources folder

[x] Naming Convention

  • It is always better to use .png , all lowercase , no spaces or special char on Android and ios

  • with ios you usually get 3 images of the same image with the following legend

    • theman.png
    • theman@2x.png
    • theman@3x.png
  • They all have the same image in only different sizes.

[x] Display in xaml:

  <StackLayout> <Image Source="thedog.png" HeightRequest="100" WidthRequest="100" /> </StackLayout> 
  • In your example, you used a frame, what about stacklayout? frame has more requirements.
  • for MVVM you can change Source with the following, do not forget that twoway :)
    • Source="{Binding Thumbnail, Mode=TwoWay}"

NB These are VERY basic explanations

+1
source

You can try running CrossMedia Plugin .

Then, in the section with the mouse button, enter the following:

  Button_Clicked.Clicked += async (sender, args) => { if ( !CrossMedia.Current.IsPickPhotoSupported ) { DisplayAlert("Error message here", "More message", "OK"); return; } var file = await Plugin.Media.CrossMedia.Current.PickPhotoAsync(new Plugin.Media.Abstractions.PickMediaOptions { PhotoSize = Plugin.Media.Abstractions.PhotoSize.Medium }); if (file == null) return; image.Source = ImageSource.FromStream(() => { var stream = file.GetStream(); file.Dispose(); return stream; }); }; 

After clicking the button, the gallery / directory will be displayed. You can select the desired photo. As soon as you click OK, the image will be displayed in the control / image tag. I am not sure if this is the solution you are looking for. Hope you get you back in the right direction.

+1
source

This may or may not help. I will add some code, one of the amazing things about Xamarin and Android formats and the use of memory stream .. is that the device density multiplier is still applied even if you are not using the resource (if I remember correctly), so I I would suggest that if you look at the ADB interface, you will see memory problems, so you can’t display the image ... I solved this earlier with a selection

As I decided, this is creating a new subclass of Image -ResourceImage,

 public class ResourceImage :Image { public enum SourceTypes{ Database, File, Function, } private bool _LoadAct = false; public bool LoadAct { get{ return _LoadAct; } set{ _LoadAct = value; OnPropertyChanged ("LoadAct"); } } public Func<Stream> Func{ get; set; } public SourceTypes SourceType{ get; set;} public string ResName{ get; set;} public ResourceImage () { } public ResourceImage (string name) { ResName = name; } public ResourceImage(Func<Stream> func){ SourceType = SourceTypes.Function; Func = func; } } 

then in Android Renderer: I did the following

  public class ResourceImageRenderer : ImageRenderer { protected override void OnElementChanged (ElementChangedEventArgs<Image> e) { base.OnElementChanged (e); if (e.OldElement == null) { var el = (ResourceImage)Element; if (el.SourceType == ResourceImage.SourceTypes.Database) { //Ignore for now } else if (el.SourceType == ResourceImage.SourceTypes.File) { using (global::Android.Graphics.BitmapFactory.Options options = new global::Android.Graphics.BitmapFactory.Options ()) { options.InJustDecodeBounds = false; options.InSampleSize = 1;//calculateInSampleSize (options, outS.X / 4, outS.Y / 4); var gd = Context.Resources.GetIdentifier (el.ResName.Split (new char[]{ '.' }) [0], "drawable", Context.PackageName); using (global::Android.Graphics.Rect rt = new global::Android.Graphics.Rect (0, 0, 0, 0)) { var bitmap = global::Android.Graphics.BitmapFactory.DecodeResource (Context.Resources, gd, options);//DecodeStream (ms, rt, options); bitmap.Density = global::Android.Graphics.Bitmap.DensityNone; Control.SetImageDrawable (new global::Android.Graphics.Drawables.BitmapDrawable (bitmap)); } } } else if (el.SourceType == ResourceImage.SourceTypes.Function) { new Task (() => { var ms = el.Func(); if(ms == null)return; global::Android.Graphics.BitmapFactory.Options options = new global::Android.Graphics.BitmapFactory.Options (); options.InJustDecodeBounds = false; options.InSampleSize = 2;//calculateInSampleSize (options, outS.X / 4, outS.Y / 4); ms.Position = 0; Device.BeginInvokeOnMainThread(()=>{ using (global::Android.Graphics.Rect rt = new global::Android.Graphics.Rect (0, 0, 0, 0)) { try{ var bitmap = global::Android.Graphics.BitmapFactory.DecodeStream (ms, rt, options); bitmap.Density = global::Android.Graphics.Bitmap.DensityNone; Control.SetImageDrawable (new global::Android.Graphics.Drawables.BitmapDrawable (bitmap)); }catch(Exception eee){ } } }); }).Start(); } } } 

Looking back at the code (did not touch it for many years). There are many places for improvement, I had to add a selection to solve the same problem, users chose images to display in the messaging application, and it worked fine on iOS, which never displayed on Android

0
source

So I allow the user to select an image and then display it on the page.

I call my image service. Select the Image method passed in by the callback method.

  await _imageService.SelectImage(ImageSelected); 

This is my SelectImage method. First, there is an access control check. It uses the Media Plugin to display the gallery and allows the user to select an image.

 public async Task SelectImage(Action<MediaFile> imageAction) { var allowed = await _permissionService.CheckOrRequestStoragePermission(); if (!allowed) return; if (!_media.IsPickPhotoSupported) { throw new GalleryUnavailableException("Gallery unavailable"); } var file = await _media.PickPhotoAsync(new PickMediaOptions { PhotoSize = PhotoSize.Small, CompressionQuality = 92 }); imageAction(file); } 

It returns MediaFile

Below is the Image Selected callback method

 private void ImageSelected(MediaFile image) { if (image == null) { return; } ChosenImage = new IncidentImage { ImageBytes = image.ToByteArray() }; } 

ChosenImage is a property in my view model

 public IncidentImage ChosenImage {get; set;} 

I use PropertyChanged.Fody to trigger property changes, but you can also use INotifyPropertyChanged.

And IncidentImage is the class that I use to store and display images

 public class IncidentImage { [PrimaryKey, AutoIncrement] public int Id { get; set; } public int IncidentDetailsId { get; set; } public byte[] ImageBytes { get; set; } [Ignore] public ImageSource ImageSource { get { ImageSource retval = null; try { if (ImageBytes != null) { retval = ImageSource.FromStream(() => new MemoryStream(ImageBytes)); } } catch (Exception e) { Debug.WriteLine(e); } return retval; } } } 

And here is XAML

 <Image Source="{Binding ChosenImage.ImageSource}" Aspect="AspectFit"/> 
0
source

Source: https://habr.com/ru/post/1273443/


All Articles