UICollectionView - 好奇的流程布局

时间:2013-10-14 09:13:24

标签: xamarin.ios uicollectionview

我第一次遇到UICollectionView(Controller)。实际上它应该像使用TableViews一样简单,但事实并非如此。

不显示流中的所有图像(多行),而是显示顶行。所有其他图像都在某处...滚动已启用但没有任何反应,没有弹跳,没有滚动,... 在方向改变(和返回)之后,可以看到更多的图像,但它们随机出现。每次定向更改后,它们都会显示在其他位置。

我的例子应该有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 个答案:

答案 0 :(得分:1)

如果您只想在统一网格中显示单元格,则首先不必覆盖GetSizeForItem。只需在IB中以编程方式配置流布局的cellsize属性,或者在ViewDidLoad中以编程方式配置它。

您的代码还有另一个问题:

group.Enumerate(AssetsEnumeration)

这将以异步方式运行。这意味着:

CollectionView.ReloadData();

仅覆盖图片的一小部分。当group == null时发出一个ReloadData()会更好,这表明枚举已经完成。

您还可以完全避免使用ReloadData,并在每次添加图像时调用CollectionView.InsertItem()。这样做的好处是,在枚举完所有内容后,您的项目会立即显示而不是全部显示 - 这可能需要一些时间(在设备上)。缺点是你必须小心不要遇到this