Ios UICollectionView装饰视图

Ios UICollectionView装饰视图,ios,ios6,uicollectionview,Ios,Ios6,Uicollectionview,是否有人为iOS 6 UICollectionView实现了装饰视图?这是不可能的 查找有关在web上实现装饰视图的任何教程。基本上,在我的应用程序中,我有多个部分,我只想在每个部分后面显示一个装饰视图。这应该是简单的实现,但我没有运气。这让我快发疯了。。。谢谢。我通过自定义布局获得了以下内容: 创建UICollectionReusableView的子类,例如向其添加UIImageView: @implementation AULYFloorPlanDecorationViewCell - (

是否有人为iOS 6 UICollectionView实现了装饰视图?这是不可能的
查找有关在web上实现装饰视图的任何教程。基本上,在我的应用程序中,我有多个部分,我只想在每个部分后面显示一个装饰视图。这应该是简单的实现,但我没有运气。这让我快发疯了。。。谢谢。

我通过自定义布局获得了以下内容:

创建UICollectionReusableView的子类,例如向其添加UIImageView:

@implementation AULYFloorPlanDecorationViewCell

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        UIImage *backgroundImage = [UIImage imageNamed:@"Layout.png"];
        UIImageView *imageView = [[UIImageView alloc] initWithFrame:frame];
        imageView.image = backgroundImage;
        [self addSubview:imageView];
    }
    return self;
}

@end
然后在viewDidLoad中的控制器中,用以下代码注册此子类(用自定义布局替换代码)

然后在自定义布局中实现以下方法(或类似方法):

-(UICollectionViewLayoutAttributes*)layoutAttributesForDecorationViewOfKind:(NSString*)decorationViewKind atIndexPath:(NSIndexPath*)indexPath
{
UICollectionViewLayoutAttributes*layoutAttributes=[UICollectionViewLayoutAttributes layoutAttributes layoutAttributes ForDecorrationViewOfKind:decorationViewKind withIndexPath:indexPath];
layoutAttributes.frame=CGRectMake(0.0,0.0,self.collectionViewContentSize.width,self.collectionViewContentSize.height);
layouttributes.zIndex=-1;
返回布局属性;
}
-(NSArray*)布局属性ForElementsInRect:(CGRect)rect
{
NSMutableArray*allAttributes=[[NSMutableArray alloc]initWithCapacity:4];
[allAttributes addObject:[self-layoutAttributesForDecorationViewOfKind:@“FloorPlan”atIndexPath:[NSIndexPath indexPathForItem:0第0节]];
对于(NSInteger i=0;i<[self.collectionView numberofitemsin部分:0];i++)
{
NSIndexPath*indexPath=[NSIndexPath indexPathForItem:i第1节:0];
UICollectionViewLayoutAttributes*layoutAttributes=[self-layoutAttributesForItemAtIndexPath:indexPath];
[allAttributes addObject:layoutAttributes];
}
返回所有属性;
}
似乎没有相关文档,但以下文档让我走上了正确的道路:


更新:可能最好将UICollectionReusableView子类化为装饰视图,而不是UICollectionViewCell

public class DecorationView : UICollectionReusableView
{
    private static NSString classId = new NSString ("DecorationView");
    public static NSString ClassId { get { return classId; } }

    UIImageView blueMarble;

    [Export("initWithFrame:")]
    public DecorationView (RectangleF frame) : base(frame)
    {
        blueMarble = new UIImageView (UIImage.FromBundle ("bluemarble.png"));

        AddSubview (blueMarble);    
    }
}


public class SimpleCollectionViewController : UICollectionViewController
{
    public override void ViewDidLoad ()
    {
        base.ViewDidLoad ();
        //Register the cell class (code for AnimalCell snipped)
        CollectionView.RegisterClassForCell (typeof(AnimalCell), AnimalCell.ClassId);
        //Register the supplementary view class (code for SideSupplement snipped)
        CollectionView.RegisterClassForSupplementaryView (typeof(SideSupplement), UICollectionElementKindSection.Header, SideSupplement.ClassId);

        //Register the decoration view
        CollectionView.CollectionViewLayout.RegisterClassForDecorationView (typeof(DecorationView), DecorationView.ClassId);
    }

 //...snip...
}

public class LineLayout : UICollectionViewFlowLayout
{
    public override UICollectionViewLayoutAttributes[] LayoutAttributesForElementsInRect (RectangleF rect)
    {
        var array = base.LayoutAttributesForElementsInRect (rect);
        /* 
        ...snip content relating to cell layout...
        */
        //Add decoration view
        var attributesWithDecoration = new List<UICollectionViewLayoutAttributes> (array.Length + 1);
        attributesWithDecoration.AddRange (array);
        var decorationIndexPath = NSIndexPath.FromIndex (0);
        var decorationAttributes = LayoutAttributesForDecorationView (DecorationView.ClassId, decorationIndexPath);
        attributesWithDecoration.Add (decorationAttributes);

        var extended = attributesWithDecoration.ToArray<UICollectionViewLayoutAttributes> ();

        return extended;
    }

    public override UICollectionViewLayoutAttributes LayoutAttributesForDecorationView (NSString kind, NSIndexPath indexPath)
    {
        var layoutAttributes = UICollectionViewLayoutAttributes.CreateForDecorationView (kind, indexPath);
        layoutAttributes.Frame = new RectangleF (0, 0, CollectionView.ContentSize.Width, CollectionView.ContentSize.Height);
        layoutAttributes.ZIndex = -1;
        return layoutAttributes;
    }
//...snip...
}
公共类装饰视图:UICollectionReusableView { 私有静态NSString classId=新NSString(“装饰视图”); 公共静态NSString ClassId{get{return ClassId;}} UIImageView蓝色大理石; [导出(“initWithFrame:”)] 公共装饰视图(矩形框架):基础(框架) { Blue大理石=新的UIImageView(UIImage.FromBundle(“blueMarble.png”); 添加子视图(蓝色大理石); } } 公共类SimpleCollectionViewController:UICollectionViewController { 公共覆盖无效ViewDidLoad() { base.ViewDidLoad(); //注册单元类(AnimalCell snipped的代码) CollectionView.RegisterClassForCell(typeof(AnimalCell),AnimalCell.ClassId); //注册补充视图类(侧边补充剪下的代码) CollectionView.RegisterClassForSupplementaryView(typeof(SideReplacement),UICollectionElementKindSection.Header,SideReplacement.ClassId); //注册装饰视图 CollectionView.CollectionViewLayout.RegisterClassForDecorationView(typeof(DecorationView),DecorationView.ClassId); } //…剪断。。。 } 公共类LineLayout:UICollectionViewFlowLayout { 公共覆盖UICollectionViewLayoutAttributes[]LayoutAttributesForElementsInRect(RectangleF rect) { var数组=base.layouttributesforementsinrect(rect); /* …剪切与单元格布局相关的内容。。。 */ //添加装饰视图 var attributesWithDecoration=新列表(array.Length+1); attributesWithDecoration.AddRange(数组); var decorationIndexPath=nsindepath.FromIndex(0); var decorationAttributes=layouttributesfordecorationview(DecorationView.ClassId,decorationIndexPath); 添加(装饰属性); var extended=attributesWithDecoration.ToArray(); 回报延长; } 公共重写UICollectionViewLayoutAttributes LayoutAttributesForDecorationView(NSString类,NSIndexPath indexPath) { var layoutAttributes=UICollectionViewLayoutAttributes.CreateForDecorationView(种类,indexPath); LayoutAttribute.Frame=新矩形F(0,0,CollectionView.ContentSize.Width,CollectionView.ContentSize.Height); layouttributes.ZIndex=-1; 返回布局属性; } //…剪断。。。 } 最终结果类似于:

这是Swift中的集合视图布局装饰视图教程(这是Swift 3,Xcode 8 seed 6)


装饰视图不是UICollectionView功能;它们本质上属于UICollectionViewLayout。没有UICollectionView方法(或委托或数据源方法)提到装饰视图。UICollectionView对它们一无所知;它只是做它被告知的事情

要提供任何装饰视图,需要UICollectionViewLayout子类;这个子类可以自由定义自己的属性和委托协议方法,这些方法可以自定义装饰视图的配置方式,但这完全取决于您

为了说明这一点,我将为UICollectionViewFlowLayout创建子类,以便在集合视图的内容矩形顶部添加一个标题标签。这可能是对装饰视图的愚蠢使用,但它完美地说明了基本原则。为了简单起见,我将从硬编码开始,让客户机无法自定义此视图的任何方面

在布局子类中实现装饰视图有四个步骤:

class MyTitleView : UICollectionReusableView {
    weak var lab : UILabel!
    override init(frame: CGRect) {
        super.init(frame:frame)
        let lab = UILabel(frame:self.bounds)
        self.addSubview(lab)
        lab.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        lab.font = UIFont(name: "GillSans-Bold", size: 40)
        lab.text = "Testing"
        self.lab = lab
    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
  • 定义UICollectionReusableView子类

  • 通过调用
    Register(\ufo:fo),将UICollectionReusableView子类注册到布局中(而不是集合视图)
    
    public class DecorationView : UICollectionReusableView
    {
        private static NSString classId = new NSString ("DecorationView");
        public static NSString ClassId { get { return classId; } }
    
        UIImageView blueMarble;
    
        [Export("initWithFrame:")]
        public DecorationView (RectangleF frame) : base(frame)
        {
            blueMarble = new UIImageView (UIImage.FromBundle ("bluemarble.png"));
    
            AddSubview (blueMarble);    
        }
    }
    
    
    public class SimpleCollectionViewController : UICollectionViewController
    {
        public override void ViewDidLoad ()
        {
            base.ViewDidLoad ();
            //Register the cell class (code for AnimalCell snipped)
            CollectionView.RegisterClassForCell (typeof(AnimalCell), AnimalCell.ClassId);
            //Register the supplementary view class (code for SideSupplement snipped)
            CollectionView.RegisterClassForSupplementaryView (typeof(SideSupplement), UICollectionElementKindSection.Header, SideSupplement.ClassId);
    
            //Register the decoration view
            CollectionView.CollectionViewLayout.RegisterClassForDecorationView (typeof(DecorationView), DecorationView.ClassId);
        }
    
     //...snip...
    }
    
    public class LineLayout : UICollectionViewFlowLayout
    {
        public override UICollectionViewLayoutAttributes[] LayoutAttributesForElementsInRect (RectangleF rect)
        {
            var array = base.LayoutAttributesForElementsInRect (rect);
            /* 
            ...snip content relating to cell layout...
            */
            //Add decoration view
            var attributesWithDecoration = new List<UICollectionViewLayoutAttributes> (array.Length + 1);
            attributesWithDecoration.AddRange (array);
            var decorationIndexPath = NSIndexPath.FromIndex (0);
            var decorationAttributes = LayoutAttributesForDecorationView (DecorationView.ClassId, decorationIndexPath);
            attributesWithDecoration.Add (decorationAttributes);
    
            var extended = attributesWithDecoration.ToArray<UICollectionViewLayoutAttributes> ();
    
            return extended;
        }
    
        public override UICollectionViewLayoutAttributes LayoutAttributesForDecorationView (NSString kind, NSIndexPath indexPath)
        {
            var layoutAttributes = UICollectionViewLayoutAttributes.CreateForDecorationView (kind, indexPath);
            layoutAttributes.Frame = new RectangleF (0, 0, CollectionView.ContentSize.Width, CollectionView.ContentSize.Height);
            layoutAttributes.ZIndex = -1;
            return layoutAttributes;
        }
    //...snip...
    }
    
    class MyTitleView : UICollectionReusableView {
        weak var lab : UILabel!
        override init(frame: CGRect) {
            super.init(frame:frame)
            let lab = UILabel(frame:self.bounds)
            self.addSubview(lab)
            lab.autoresizingMask = [.flexibleWidth, .flexibleHeight]
            lab.font = UIFont(name: "GillSans-Bold", size: 40)
            lab.text = "Testing"
            self.lab = lab
        }
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    }
    
    private let titleKind = "title"
    private let titleHeight : CGFloat = 50
    private var titleRect : CGRect {
        return CGRect(10,0,200,self.titleHeight)
    }
    override init() {
        super.init()
        self.register(MyTitleView.self, forDecorationViewOfKind:self.titleKind)
    }
    
    override func layoutAttributesForDecorationView(
        ofKind elementKind: String, at indexPath: IndexPath) 
        -> UICollectionViewLayoutAttributes? {
            if elementKind == self.titleKind {
                let atts = UICollectionViewLayoutAttributes(
                    forDecorationViewOfKind:self.titleKind, with:indexPath)
                atts.frame = self.titleRect
                return atts
            }
            return nil
    }
    
    override func layoutAttributesForElements(in rect: CGRect) 
        -> [UICollectionViewLayoutAttributes]? {
            var arr = super.layoutAttributesForElements(in: rect)!
            if let decatts = self.layoutAttributesForDecorationView(
                ofKind:self.titleKind, at: IndexPath(item: 0, section: 0)) {
                    if rect.intersects(decatts.frame) {
                        arr.append(decatts)
                    }
            }
            return arr
    }
    
    class MyFlowLayout : UICollectionViewFlowLayout {
        var title = ""
        // ...
    }
    
    func setUpFlowLayout(_ flow:UICollectionViewFlowLayout) {
        flow.headerReferenceSize = CGSize(50,50)
        flow.sectionInset = UIEdgeInsetsMake(0, 10, 10, 10)
        (flow as? MyFlowLayout)?.title = "States" // *
    }
    
    class MyTitleViewLayoutAttributes : UICollectionViewLayoutAttributes {
        var title = ""
    }
    
    override func layoutAttributesForDecorationView(
        ofKind elementKind: String, at indexPath: IndexPath) -> 
        UICollectionViewLayoutAttributes? {
            if elementKind == self.titleKind {
                let atts = MyTitleViewLayoutAttributes( // *
                    forDecorationViewOfKind:self.titleKind, with:indexPath)
                atts.title = self.title // *
                atts.frame = self.titleRect
                return atts
            }
            return nil
    }
    
    class MyTitleView : UICollectionReusableView {
        weak var lab : UILabel!
        // ... the rest as before ...
        override func apply(_ atts: UICollectionViewLayoutAttributes) {
            if let atts = atts as? MyTitleViewLayoutAttributes {
                self.lab.text = atts.title
            }
        }
    }