2013-10-14 65 views
1

我第一次遇到UICollectionView(控制器)。其實它應該像使用TableViews一樣簡單,但它不是。UICollectionView - 好奇的流程佈局

而不是顯示流中的所有圖像(多行),只顯示頂行。所有其他圖像都在某處...滾動被啓用,但沒有任何反應,沒有彈跳,沒有滾動,... 並且在方向改變(並返回)後,一些更多的圖像可見,但它們隨機出現。在每次方向改變後,它們都出現在其他位置。

我的例子應該有7張圖片。

我在IB性質: IB Settings Screenshot

首播時間: First time

旋轉(反面)後: After rotating

而且我的源代碼來實現照片庫。

using System; 

using MonoTouch.Foundation; 
using MonoTouch.UIKit; 
using System.Collections.Generic; 
using Xamarin.Media; 
using MonoTouch.AssetsLibrary; 
using MonoTouch.CoreGraphics; 
using System.Diagnostics; 
using System.Linq; 
using System.Drawing; 

namespace B2.Device.iOS 
{ 
    public partial class TagesRapportDetailRegieBilderCollectionViewController : UICollectionViewController 
    { 
     private const string Album = "Rapport"; 

     public TagesRapportDetailRegieBilderSource Source { get; private set; } 
     private TagesRapportDetailRegieBilderDelegate _delegate; 

     public TagesRapportDetailRegieBilderCollectionViewController (IntPtr handle) : base (handle) 
     { 
      Source = new TagesRapportDetailRegieBilderSource(this); 
      _delegate = new TagesRapportDetailRegieBilderDelegate(this); 

      // Delegate - Muss im konstruktor sein. ViewDidLoad geht nicht! 
      CollectionView.Delegate = _delegate; 
     } 

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

      // Cell Klasse registrieren 
      CollectionView.RegisterClassForCell (typeof(ImageCell), new NSString("imageCell")); 

      // DataSource 
      CollectionView.Source = Source; 

      // Bilder laden 
      LoadImages(); 
     } 

     private void LoadImages() 
     { 
      Source.Images.Clear(); 

      var assetsLibrary = new ALAssetsLibrary(); 
      assetsLibrary.Enumerate(ALAssetsGroupType.Album, GroupsEnumeration, GroupsEnumerationFailure); 
     } 

     private void GroupsEnumeration(ALAssetsGroup group, ref bool stop) 
     { 
      if (group != null && group.Name == Album) 
      { 
       //notifies the library to keep retrieving groups 
       stop = false; 

       //set here what types of assets we want, 
       //photos, videos or both 
       group.SetAssetsFilter(ALAssetsFilter.AllPhotos); 

       //start the asset enumeration 
       //with ALAssetsGroup's Enumerate method 
       group.Enumerate(AssetsEnumeration); 

       CollectionView.ReloadData(); 
      } 
     } 

     private void AssetsEnumeration(ALAsset asset, int index, ref bool stop) 
     { 
      if (asset != null) 
      { 
       //notifies the group to keep retrieving assets 
       stop = false; 

       //use the asset here 
       var image = new UIImage(asset.AspectRatioThumbnail()); 

       Source.Images.Add(image); 
      } 
     } 

     private void GroupsEnumerationFailure(NSError error) 
     { 
      if (error != null) 
      { 
       new UIAlertView("Zugriff verweigert", error.LocalizedDescription, null, "Schliessen", null).Show(); 
      } 
     } 
    } 

    public class TagesRapportDetailRegieBilderDelegate : UICollectionViewDelegateFlowLayout 
    { 
     private TagesRapportDetailRegieBilderCollectionViewController _controller; 

     public TagesRapportDetailRegieBilderDelegate(TagesRapportDetailRegieBilderCollectionViewController controller) 
     { 
      _controller = controller; 
     } 

     public override System.Drawing.SizeF GetSizeForItem(UICollectionView collectionView, UICollectionViewLayout layout, NSIndexPath indexPath) 
     { 
      var size = _controller.Source.Images[indexPath.Row].Size.Width > 0 
       ? _controller.Source.Images[indexPath.Row].Size : new SizeF(100, 100); 

      size.Width /= 3; 
      size.Height /= 3; 

      return size; 
     } 

     public override UIEdgeInsets GetInsetForSection(UICollectionView collectionView, UICollectionViewLayout layout, int section) 
     { 
      return new UIEdgeInsets(50, 20, 50, 20); 
     } 
    } 

    public class TagesRapportDetailRegieBilderSource : UICollectionViewSource 
    { 
     private TagesRapportDetailRegieBilderCollectionViewController _controller; 

     public List<UIImage> Images { get; set; } 

     public TagesRapportDetailRegieBilderSource(TagesRapportDetailRegieBilderCollectionViewController controller) 
     { 
      _controller = controller; 
      Images = new List<UIImage>(); 
     } 

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

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

     public override UICollectionViewCell GetCell(UICollectionView collectionView, NSIndexPath indexPath) 
     { 
      var cell = collectionView.DequeueReusableCell(new NSString("imageCell"), indexPath) as ImageCell; 

      cell.Image = Images[indexPath.Row]; 

      return cell; 
     } 
    } 

    public class ImageCell : UICollectionViewCell 
    { 
     UIImageView imageView; 

     [Export ("initWithFrame:")] 
     public ImageCell (System.Drawing.RectangleF frame) : base (frame) 
     { 
      imageView = new UIImageView(frame); 
      imageView.AutoresizingMask = ~UIViewAutoresizing.None; 
      ContentView.AddSubview (imageView); 
     } 

     public UIImage Image 
     { 
      set 
      { 
       imageView.Image = value; 
      } 
     } 
    } 
} 

回答

1

如果您只想在統一網格中顯示單元格,首先不需要重寫GetSizeForItem。只需在IB中配置流佈局的cellsize屬性,或者在ViewDidLoad中以編程方式配置這些屬性,並完成它。

有你的代碼的另一個問題:

group.Enumerate(AssetsEnumeration) 

這將異步運行。這意味着:

CollectionView.ReloadData(); 

只會覆蓋一小部分圖像。當group == null時,發出ReloadData()會更好,這表明枚舉已完成。

您也可以避免重新加載數據,並且每次添加圖像時調用CollectionView.InsertItem()。這有利於您的項目在枚舉完成後立即可見而不是一次全部顯示 - 這可能需要一些時間(在設備上)。缺點是你必須小心不要碰到this

+0

我遇到了麻煩,我在Starter帳戶,所以我不能使用Rx組件,因爲它使我的二進制文件大於64 KB。當我滾動瀏覽內容時,我的收藏視圖閃爍,只渲染一些從遠程API獲取的圖像。我還有什麼選擇? –