1

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

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

我的示例应该有 7 张图片。

我在IB的属性: IB设置截图

第一次: 第一次

旋转(和返回)后: 旋转后

还有我实现照片库的源代码。

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

1 回答 1

1

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

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

group.Enumerate(AssetsEnumeration)

这将异步运行。这意味着:

CollectionView.ReloadData();

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

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

于 2013-10-14T09:38:20.507 回答