Как правильно отображать объекты UIImage в представлении коллекции с помощью Xamarin для iOS?

Я работаю над некоторыми собственными примерами Xamarin, чтобы лучше понять, как создавать приложения для iOS и кодировать C # (у меня больше опыта программирования для Android).

У меня есть представление, в котором я показываю представление коллекции и две кнопки, нажав любую из них, я отправляю HTTP-запрос к Imgur и получаю другой набор изображений. Эти изображения я хочу отображать в представлении коллекции.

Я делаю запросы с помощью следующего метода в своем контроллере:

    public void makeRequest(string url){
        var request = (HttpWebRequest)WebRequest.Create(url);
        request.Headers.Add ("Authorization", "Client-ID " + clientId);
        request.Method = "GET";

        Task<WebResponse> task = Task.Factory.FromAsync (
                                     request.BeginGetResponse,
                                     asyncResult => request.EndGetResponse (asyncResult),
                                     (object)null);
        task.ContinueWith (t => ReadStreamFromResponse (t.Result));

    }

Для анализа ответа JSON я использую этот метод (меня интересуют только изображения, а не альбомы):

    private void ReadStreamFromResponse(WebResponse response){
        using (Stream responseStream = response.GetResponseStream ()) {
            using (StreamReader sr = new StreamReader (responseStream)) {
                string content = sr.ReadToEnd ();
                var json = JsonObject.Parse (content);
                var array = json ["data"];
                foreach (JsonObject o in array) {
                      string url = o ["link"];
                  bool isAlbum = o ["is_album"];
                  if (!isAlbum) {
                    url = url.Insert (url.Length - 4, "s");
                            AddElement (url);
                  }
                }
            }
        }
    }
}

Я использую следующий метод, чтобы добавить изображение в источник:

    public void AddElement(string url){
        using (var imgUrl = new NSUrl (url)) {
            using (var data = NSData.FromUrl (imgUrl)) {
                photoSource.photos.Add (UIImage.LoadFromData (data));
                InvokeOnMainThread (delegate {
                    PhotoCollection.ReloadData ();
                });
            }
        }

    }

Это мой исходный класс:

class CollectionSource : UICollectionViewSource
{
    public List<UIImage> photos;
    public CollectionSource(){
        photos = new List<UIImage> ();
    }
    public CollectionSource(List<UIImage> photos){
        this.photos = photos;
    }

    public override UICollectionViewCell GetCell(UICollectionView collectionView, NSIndexPath indexPath){
        var photoCell = (ImageCell)collectionView.DequeueReusableCell ((NSString) ImageCell.CELLID, indexPath);
        var photo = photos [indexPath.Row];

        photoCell.ImageView.Image = photo;

        return photoCell;
    }

    public override int GetItemsCount(UICollectionView collectionView, int section){
        return photos.Count;
    }

    public override int NumberOfSections(UICollectionView collectionView){
        return 1;
    }

    public override void ItemHighlighted(UICollectionView collectionView, NSIndexPath indexPath){
        var cell = collectionView.CellForItem (indexPath);
        cell.ContentView.BackgroundColor = UIColor.Yellow;
    }

    public override void ItemUnhighlighted(UICollectionView collectionView, NSIndexPath indexPath){
        var cell = collectionView.CellForItem (indexPath);
        cell.ContentView.BackgroundColor = UIColor.White;
    }

    public override bool ShouldHighlightItem(UICollectionView collectionView, NSIndexPath indexPath){
        return true;
    }

    public override bool ShouldShowMenu(UICollectionView collectionView, NSIndexPath indexPath){
        return true;
    }

    public override bool CanPerformAction(UICollectionView collectionView, MonoTouch.ObjCRuntime.Selector action, NSIndexPath indexPath, NSObject sender){
        return true;
    }

    public override void PerformAction(UICollectionView collectionView, MonoTouch.ObjCRuntime.Selector action, NSIndexPath indexPath, NSObject sender){
        Console.WriteLine ("Perform action");
    }


}

Я избегал использования контроллера CollectionView, потому что мне не нравится оставлять несколько операций только одному классу, я люблю разбивать свой код на классы.

Это мой класс ячеек:

public class ImageCell : UICollectionViewCell
{
    public const string CELLID = "ImageCell";

    [Export ("initWithFrame:")]
    public ImageCell (System.Drawing.RectangleF frame) : base(frame){
        this.Initialize ();
    }

    public UIImageView ImageView { 
        get;
        set;
    }
    private void Initialize(){
        //          this.ImageView = new UIImageView (this.ContentView.Bounds);
        this.ImageView = new UIImageView (UIImage.FromBundle("placeholder.png"));
        this.ContentView.AddSubview (this.ImageView);

    }
}

Наконец, это мой класс контроллера представления:

partial class ViewController3 : UIViewController
{
    public CollectionSource photoSource;

    public ViewController3 (IntPtr handle) : base (handle)
    {
    }

    public override void ViewDidLoad ()
    {
        base.ViewDidLoad ();

        PhotoCollection.RegisterClassForCell (typeof(ImageCell), (NSString)ImageCell.CELLID);
        photoSource = new CollectionSource ();
        PhotoCollection.Source = photoSource;

        makeRequest (); 
    }
    // makeRequest, ReadStreamFromResponse and AddElement are located below this method, I won't place them again
}

Как видите, мой код основан на статье Введение в представления коллекций можно найти в руководствах Xamarin. Мне удалось загрузить удаленные изображения, но они не отображаются должным образом в представлении коллекции.

Изображения загружаются, но по мере загрузки они мигают в представлении коллекции, и результат выглядит следующим образом:

Просмотр коллекции после завершения загрузки изображений

По какой-то причине не вся ячейка отображает изображение правильно, возможно, я неправильно обновляю свой CollectionView?


person Uriel Arvizu    schedule 24.09.2014    source источник


Ответы (1)


Итак, я нашел решение своей проблемы, но понятия не имею, почему оно сработало.

В моем классе ImageCell я добавил следующую строку кода в метод Initialize:

    private void Initialize(){
        this.ImageView = new UIImageView (); 
        this.ImageView.AutoresizingMask = ~UIViewAutoresizing.None;
        // if no image is assigned to the ImageView, then the cell won't be rendered correctly if later you add the image
        // not familiar with iOS guidelines so I don't know if that is the real reason
        this.ImageView = new UIImageView (UIImage.FromBundle("temp.png"));

        this.ContentView.AddSubview (this.ImageView);

    }

При этом изображения отображаются правильно в ячейках, все же необходимо улучшить способ загрузки этих удаленных изображений, но на этом все, если вы заметили, что ваши ячейки не отображаются правильно на месте, тогда, возможно, вам следует проверить, требует ли какой-либо компонент в вашей ячейке заполнитель, чтобы не оставлять его пустым.

person Uriel Arvizu    schedule 01.10.2014