2017-11-16 29 views
5

Giải quyết:Câu trả lời là cập nhật tất cả các gói gói và nhắm mục tiêu phiên bản Android mới hơn. Bây giờ hình ảnh tải như mong đợi. Tôi không hài lòng với điều này vì tôi đã sử dụng chính xác mã mà Xamarin cung cấp và nhắm mục tiêu các phiên bản mới hơn đã không còn sử dụng một số mục mà mã dựa vào. Phiên bản đầu tiên là Xamarin.Forms v23 và tôi đã cập nhật thành V25Hiển thị hình ảnh có Biểu mẫu Xamarin

Tôi có một dự án biểu mẫu Xamarin hoàn toàn mới với một cái nhìn đơn giản mà tôi đang cố gắng hiển thị hình ảnh. Tôi đã thử một số cách để có được một hình ảnh để hiển thị và tôi không có bất kỳ may mắn nào cả.

Tôi đang sử dụng <image> và tôi cũng đã thử kiểm soát FFImageLoader.

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

Đây là chế độ xem hiện tại. Tôi cũng đã đặt Nguồn trực tiếp thành giá trị không có kết quả.

Tôi có thể tải luồng cho hình ảnh. Tôi có thể đọc tất cả các byte từ luồng. Tôi đã xây dựng trình hiển thị lỗi để hiển thị các byte dưới dạng hình ảnh. Lấy hình ảnh từ một nguồn không phải là một vấn đề. Bắt (các) điều khiển hình ảnh để hiển thị hình ảnh là một vấn đề.

Tôi đã thử ràng buộc với mô hình chế độ xem. Khi điều đó thất bại, tôi đã cố gắng trực tiếp thiết lập các nguồn

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

Tôi cũng làm một bản sao của các byte và cố gắng

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

Tôi đã thử ImageSource.FromFile().FromUri. Tôi đã thử thêm hình ảnh vào dự án làm tài nguyên. Mỗi lần thử là như nhau, tài nguyên đã được đọc và các byte đã có sẵn, nhưng điều khiển hình ảnh không hiển thị nó.

Tôi nghĩ có lẽ đó là vấn đề về kích thước, vì vậy tôi đặt kích thước của điều khiển. Không có gì. Tôi nghĩ có lẽ đó là một vấn đề về độ phân giải, vì vậy tôi đã sử dụng một hình ảnh nhỏ hơn. Tôi đã thử một số hình ảnh khác nhau về chất lượng khác nhau.

Sau đó, tôi đã từ bỏ điều khiển hình ảnh và tôi đã nhận gói gói FFImageLoading và cung cấp cho nó một url trực tiếp tới một hình ảnh. Ví dụ tương tự mà các ví dụ FFImageLoading được sử dụng. Vẫn không có hình ảnh.

Tôi đã thử trình mô phỏng và tôi đã thử 2 thiết bị vật lý khác nhau. Cùng một kết quả.

Tôi cũng đã thử đặt hình ảnh trên nút bằng cách sử dụng btn.Image = "whatever.jpg" với cùng một kết quả.

Đây là kết quả mỗi lần. Tôi bị lạc. Làm cách nào để hiển thị hình ảnh?

EDIT: tôi đã làm được điều này để làm việc, nhưng chỉ trên các giả lập

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

và tương tự cho

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

EDIT 2 - Làm rõ

Mục tiêu của tôi là cho phép người dùng chọn ảnh từ thiết bị và sau đó hiển thị trước ew của nó.

enter image description here

+0

Đặt hình ảnh của bạn ở chế độ xem nội dung và thử hình ảnh đến hoặc không –

+0

Bạn đã thử trên một nền tảng khác ngoại trừ Android? Đây là tài liệu chính thức: https://developer.xamarin.com/guides/xamarin-forms/user-interface/images/#Downloading_Images Hãy thử vô hiệu hóa bộ nhớ đệm ... – EvZ

+0

@EvZ Tôi đang cố tải một tệp từ thiết bị , không phải là url. Tôi đã thử các ví dụ uri trong liên kết của bạn cung cấp và tôi đã làm cho nó hoạt động (trên trình giả lập ít nhất), nhưng vẫn không thể làm cho nó làm việc với một dòng hoặc tập tin –

Trả lời

2

Nếu bạn muốn sử dụng hình ảnh trong bạn ứng dụng bạn có thể tải chúng vào dự án chia sẻ của bạn, giống như

Embedded resource

Hãy chắc chắn rằng bạn thay đổi hành động Build để nguồn nhúng

Sau đó, trong mã của bạn

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

Lưu ý tên tài nguyên.

Và XAML

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

Mục đích là cho phép người dùng chọn một hình ảnh từ thiết bị của họ và sau đó hiển thị bản xem trước của nó. –

+0

Bạn đã thấy plugin này https://github.com/jamesmontemagno/MediaPlugin –

+1

Tôi chưa thấy điều đó, nhưng nhìn vào nó, tôi có thể biết vấn đề của tôi là gì. Tôi đã đọc rằng khi bạn chụp ảnh trong quá trình lựa chọn hình ảnh, bạn phải lưu một bản sao của nó và sau đó tham khảo bản sao, có lẽ tôi cần phải làm điều đó. –

1

Chỉ cần một vài điều bạn có thể lấy ra khỏi danh sách:

[x] Thêm một hình ảnh từ Visual studio:

  1. Nhấp chuột phải vào thư mục đúng
  2. chọn Thêm >> Tệp mới ... NB: bạn phải thêm nó bằng studio trực quan chứ không phải chỉ ném nó vào thư mục. Visual studio cần phải biết về nó

[x] Khi Thêm hình ảnh là nó ở địa điểm chính xác:

  • Đối với android: nó có được trong

ProjectName.Driod.Resources.drawable thư mục

  • Đối với ios: nó phải ở trong

ProjectName.iOS.Resources thư mục

[x] Naming Convention

  • của nó luôn luôn tốt nhất để sử dụng .png, tất cả chữ thường, không có khoảng trống hoặc char đặc biệt trên cả Android và iOS

  • với ios bạn thường nhận được 3 hình ảnh của cùng một hình ảnh với ước namting sau

  • Họ đều là những hình ảnh tương tự chỉ kích cỡ khác nhau

[x] Hiển thị nó trong XAML:

<StackLayout> 
    <Image Source="thedog.png" HeightRequest="100" WidthRequest="100" /> 
    </StackLayout> 
  • Trong ví dụ của bạn, bạn sử dụng một khung, làm thế nào về một stacklayout? một khung có nhiều yêu cầu hơn.
  • cho MVVM bạn có thể thay đổi Nguồn với những điều sau đây, đừng quên rằng TwoWay :)
    • Source="{Binding Thumbnail, Mode=TwoWay}"

NB Đây là lời giải thích rất cơ bản

0

này có thể hoặc có thể không giúp tôi thêm một số mã, một trong những điều đáng ngạc nhiên về các biểu mẫu Xamarin và Android và sử dụng luồng bộ nhớ .. là hệ số mật độ thiết bị là sti sẽ áp dụng ngay cả khi bạn không sử dụng tài nguyên (Nếu tôi nhớ chính xác) vì vậy tôi sẽ tưởng tượng nếu bạn đang xem giao diện ADB, bạn sẽ thấy các vấn đề về bộ nhớ, đó là lý do tại sao bạn không thể hiển thị hình ảnh ... qua lấy mẫu

Con đường tôi giải quyết nó đã tạo ra một hình ảnh -ResourceImage phân lớp mới,

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; 

    } 

} 

sau đó trong Renderer Android: tôi đã làm như sau

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

      } 

     }  

    } 

Nhìn lại đoạn code (đã không chạm vào nó trong nhiều năm.) Có rất nhiều plac Để cải thiện, tôi phải thêm mẫu để giải quyết cùng một vấn đề, người dùng đã chọn hình ảnh để hiển thị trong ứng dụng nhắn tin và nó hoạt động hoàn hảo trên iOS không bao giờ được hiển thị trên Android

+0

Plugin FFImageLoading xử lý vấn đề này https://github.com/luberda-molinet/FFImageLoading –

0

Đây là cách tôi cho phép người dùng chọn một hình ảnh và sau đó hiển thị nó trên một trang.

tôi gọi dịch vụ hình ảnh Chọn hình ảnh phương pháp đi qua tôi trong một phương thức callback

await _imageService.SelectImage(ImageSelected); 

Đây là phương pháp SelectImage tôi. Có một số kiểm tra quyền khi bắt đầu. Nó sử dụng Media Plugin để hiển thị thư viện và cho phép người dùng chọn một hình ảnh.

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

Nó trả về một MediaFile

Dưới đây là hình ảnh được lựa chọn phương thức callback

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

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

ChosenImage là một tài sản trong mô hình quan điểm của tôi

public IncidentImage ChosenImage {get; set;} 

tôi sử dụng PropertyChanged.Fody để kích hoạt tài sản thay đổi thông báo nhưng bạn cũng có thể sử dụng INotifyPropertyChanged.

Và IncidentImage là một lớp tôi sử dụng cho cả hai cửa hàng và hiển thị hình ảnh

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

} 

Và đây là XAML

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

Bạn có thể thử thực hiện CrossMedia Plugin.

Sau đó, trong nút của bạn nhấp phần mã, đặt sau:

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

Khi nút được nhấn vào, các bộ sưu tập/thư mục sẽ được hiển thị. Bạn có thể chọn ảnh bạn muốn. Khi bạn nhấn OK, hình ảnh sẽ được hiển thị trong thẻ/điều khiển hình ảnh. Tôi không chắc chắn nếu đây là giải pháp bạn đang tìm kiếm. Hy vọng nó sẽ giúp bạn đi đúng hướng.

+0

Tôi đã cố gắng để có được điều này để làm việc, nhưng đã không thành công. Các vấn đề với phiên bản đã giữ tôi trở lại. –

Các vấn đề liên quan