如何使用Xamarin for iOS正确显示集合视图上的UIImage对象?

时间:2014-09-24 14:40:47

标签: ios xamarin.ios xamarin xamarin-studio

我正在研究自己的一些Xamarin示例,以便更好地了解制作iOS应用程序和C#编码(我对Android编程有更多经验)。

我有一个View,我正在显示一个Collection View和两个Buttons,按下我向Imgur发出HTTP请求并检索不同的图像集。我想在集合视图中显示这些图像。

我在Controller中使用以下方法发出请求:

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

我用来尝试将Image添加到Source的方法如下:

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

    }

这是我的Source类:

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

    }
}

最后这是我的View Controller类:

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指南中的Introduction to Collection Views文章。我现在成功地下载了远程图像,但它们没有在集合视图中正确显示。

图像已下载,但在下载图像时,它们会在集合视图中闪烁,结果如下所示:

Collection View after images finished downloading

由于某些原因,并非所有单元格都能正确渲染图像,或许我错误地刷新了CollectionView?

1 个答案:

答案 0 :(得分:0)

所以我找到了解决问题的方法,但我不知道它为什么能让它发挥作用。

在我的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);

    }

有了这个图像在单元格中正确呈现,仍然必须改进我加载这个远程图像的方式,但就是这样,如果你注意到你的单元格没有正确渲染,那么也许你应该检查是否有任何组件您的单元格需要占位符以避免将其留空。