2017-11-16 28 views
5

Gelöst angezeigt:Die Antwort war all die nuget Pakete zu aktualisieren und eine neuere Version von Android Ziel. Jetzt werden Bilder wie erwartet geladen. Ich bin nicht zufrieden damit, da ich genau den Code verwendet habe, den Xamarin zur Verfügung gestellt hat, und das Targeting auf neuere Versionen hat einige der Elemente, auf die sich der Code stützt, für veraltet erklärt. Erste Version war Xamarin.Forms v23 und ich auf V25ein Bild mit Xamarin Forms

Ich habe eine brandneue Xamarin Formen Projekt mit einer einfachen Ansicht, in der ich versuche, ein Bild anzuzeigen. Ich habe verschiedene Möglichkeiten ausprobiert, um ein Bild zur Anzeige zu bringen, und ich habe überhaupt kein Glück.

Ich benutze <image> und ich habe auch FFImageLoader Kontrolle ausprobiert.

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

Dies ist die aktuelle Ansicht. Ich habe auch die Quelle direkt auf einen Wert ohne Ergebnis gesetzt.

Ich bin in der Lage, einen Stream für das Bild zu bekommen. Ich kann alle Bytes aus dem Stream lesen. Ich baute einen Debug-Visualizer, um die Bytes als Bild anzuzeigen. Das Bild von einer Quelle zu bekommen ist kein Problem. Es ist ein Problem, die Bildsteuerung (en) zur Anzeige des Bildes zu bekommen.

Ich versuchte, mit einem Ansichtsmodell zu binden. Als das scheiterte, versuchte ich, dass direkt die Quelle Einstellung

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

Ich habe auch eine Kopie des Bytes und versuchte

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

Ich habe versucht, ImageSource.FromFile() und .FromUri. Ich habe versucht, dem Projekt ein Bild als Ressource hinzuzufügen. Jeder Versuch war der gleiche, die Ressource wurde gelesen und die Bytes waren verfügbar, aber das Bildsteuerelement zeigt es nicht an.

Ich dachte, vielleicht war es ein Größenproblem, also habe ich die Größe des Steuerelements festgelegt. Nichts. Ich dachte, es wäre vielleicht ein Auflösungsproblem, also habe ich ein kleineres Bild verwendet. Ich habe verschiedene Bilder unterschiedlicher Qualität ausprobiert.

Dann gab ich die Bildkontrolle auf und ich bekam das FFImageLoading nuget-Paket und gab ihm eine direkte URL zu einem Bild. Das gleiche Beispiel, das FFImageLoading-Beispiele verwendet haben. Immer noch kein Bild.

Ich habe den Emulator versucht und ich habe 2 verschiedene physikalische Geräte ausprobiert. Gleiches Ergebnis.

Ich habe auch versucht, ein Bild auf einer Schaltfläche mit btn.Image = "whatever.jpg" mit dem gleichen Ergebnis zu setzen.

Dies ist das Ergebnis jedes Mal. Ich bin verloren. Wie kann ich Bilder anzeigen lassen?

EDIT: Ich tat dies, aber

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

und gleich für

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

EDIT 2 nur auf dem Emulator zu arbeiten - Klärung

Mein Ziel ist es, dem Benutzer zu erlauben, ein Foto von dem Gerät auszuwählen und dann ein Previ anzuzeigen ew davon.

enter image description here

+0

Setzen Sie Ihr Bild in die Inhaltsansicht und versuchen Sie es kommt oder nicht –

+0

Haben Sie es auf anderen Plattformen außer Android versucht? Hier ist die offizielle Dokumentation: https://developer.xamarin.com/guides/xamarin-forms/user-interface/images/#Downloading_Images Versuchen Sie das Caching zu deaktivieren ... – EvZ

+0

@EvZ Ich versuche eine Datei vom Gerät zu laden , keine URL. Ich habe versucht, das Beispiel uri in der Link Ihre zur Verfügung gestellt und ich habe es funktioniert (zumindest auf dem Emulator), aber immer noch nicht mit einem Stream oder Datei –

Antwort

2

Wenn Sie Bilder in den Sie verwenden app Sie sie in der Shared-Projekt laden können, wie

Embedded resource

Stellen Sie sicher, die Build Action ändern zu Embedded Ressource

Dann in Ihrem Code

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

Beachten Sie den Ressourcennamen.

Und XAML

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

Das Ziel besteht darin, dem Benutzer zu ermöglichen, ein Bild von seinem Gerät auszuwählen und dann eine Vorschau davon anzuzeigen. –

+0

Haben Sie dieses Plugin https://github.com/jamesmontemagno/MediaPlugin gesehen –

+1

Ich hatte das nicht gesehen, aber wenn ich es ansehe, weiß ich vielleicht, was mein Problem ist. Ich habe gelesen, dass wenn Sie während der Bildauswahl ein Foto machen, Sie eine Kopie davon speichern und dann auf die Kopie verweisen müssen, vielleicht muss ich das tun. –

1

einfach ein paar Dinge, die Sie die Liste starten können:

[x] ein Bild aus Visual Studio Hinzufügen:

  1. rechts auf den richtigen Ordner klicken
  2. Wählen Sie Hinzufügen >> Neue Datei ... NB: Sie müssen es mit Visual Studio hinzufügen und nicht einfach in den Ordner werfen. Visual Studio muss es wissen

[x] Wenn das Bild hinzuzufügen ist es an der richtigen Stelle:

  • für Android: Es hat in

ProjectName.Driod.Resources.drawable Ordner sein

  • Für ios: es hat in
sein

ProjectName.iOS.Resources Ordner

[x] Naming Convention

  • Es ist immer am besten zu verwenden.png, alle Klein, keine Leerzeichen oder spezielles Zeichen auf Android und ios

  • mit ios Sie normalerweise erhalten 3 Bilder des gleichen Bildes mit der folgenden namting Konvention

  • Sie sind alle das gleiche Bild nur verschiedene Größen

[x] es in XAML Angezeigt:

<StackLayout> 
    <Image Source="thedog.png" HeightRequest="100" WidthRequest="100" /> 
    </StackLayout> 
  • In Ihrem Beispiel verwendet man einen Rahmen, wie etwa einem stacklayout? Ein Rahmen hat mehr Anforderungen.
  • für MVVM Sie Quelle mit der folgenden ändern können, nicht diese twoway vergessen :)
    • Source="{Binding Thumbnail, Mode=TwoWay}"

NB Dies ist sehr grundlegende Erklärungen

0

Dies kann, nicht helfen, ich werde etwas Code hinzufügen, eine der überraschenden Dinge über Xamarin Formen und Android und mit einem Speicher-Stream .. ist, dass der Gerätedichte Multiplikator ist Auch wenn Sie keine Ressource verwenden (wenn ich mich richtig erinnere), würde ich mir vorstellen, wenn Sie sich die ADB-Schnittstelle ansehen, werden Speicherprobleme auftreten, weshalb Sie kein Bild anzeigen können ... Ich habe das vorher gelöst über Sampling

So wie ich es gelöst wurde eine neue Bildunterklasse -ResourceImage Erstellen

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; 

    } 

} 

dann im Android Renderer: ich habe die folgende

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(); 

      } 

     }  

    } 

zurück auf den Code der Suche (habe es seit Jahren nicht mehr angefasst.) Es gibt jede Menge Platz es für die Verbesserung, ich musste die Probenahme, um das gleiche Problem zu lösen, die Benutzer ausgewählt Bilder zur Anzeige in einer Messaging-App und es funktioniert perfekt auf iOS nur nie auf Android angezeigt

+0

FFImageLoading-Plugin behandelt dieses Problem https://github.com/luberda-molinet/FFImageLoading –

0

Dies ist, wie ich einem Benutzer zu wählen ein Bild und dann auf einer Seite anzeigen.

Ich nenne meine Bild Service Bild auswählen Methode Gang in einer Callback-Methode

await _imageService.SelectImage(ImageSelected); 

Das ist meine SelectImage Methode. Es gibt einige Berechtigungsprüfung am Anfang. Es verwendet das Medien-Plugin, um die Galerie anzuzeigen und dem Benutzer zu ermöglichen, ein Bild auszuwählen.

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

Es gibt einen Mediafile

Hier ist das Bild ausgewählt Callback-Methode

private void ImageSelected(MediaFile image) 
{ 
    if (image == null) 
    { 
     return; 
    } 

    ChosenImage = new IncidentImage 
    { 
     ImageBytes = image.ToByteArray() 
    }; 
} 

ChosenImage ist eine Eigenschaft meiner Ansicht nach Modell

public IncidentImage ChosenImage {get; set;} 

I PropertyChanged.Fody verwenden, um trigger property changed notifications, aber Sie können auch INotifyPropertyChanged verwenden.

Und IncidentImage ist eine Klasse I auf beide Speicher und Anzeigen von Bildern verwenden

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

} 

Und hier ist die XAML

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

Sie können versuchen, die CrossMedia Plugin implementieren.

dann in Ihre Schaltfläche Codeabschnitt geklickt haben, setzen die folgenden:

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

Sobald die Schaltfläche geklickt wird, wird die Galerie/Verzeichnis angezeigt werden. Sie können das gewünschte Foto auswählen. Sobald Sie auf OK klicken, wird das Bild im Bildsteuerelement/Tag angezeigt. Ich bin mir nicht sicher, ob dies die Lösung ist, nach der Sie suchen. Hoffnungen es bringt dich in die richtige Richtung.

+0

Ich habe versucht, dies zur Arbeit zu bringen, waren aber nicht erfolgreich. Probleme mit der Versionierung haben mich zurückgehalten. –