简体   繁体   English

使用两个相似的集合视图单元格,从而避免代码重复

[英]Using two similar collection view cells and thereby avoiding code duplication

I want to have two nearly similar cells. 我想拥有两个几乎相似的单元。 The difference is only in displaying one more view on it. 区别仅在于在其上显示更多视图。

Therefore I thought to use a custom constructor. 因此,我想使用自定义构造函数。 Normally you have a constructor similar to this one: 通常,您有一个与此类似的构造函数:

public class AnimalCell : UICollectionViewCell
{
    [Export ("initWithFrame:")]
    public AnimalCell (CGRect frame) : base (frame)
    {
        // do something
    }
}

I want to pass a type and depending on this type I want to display different items on the cell. 我想传递一种类型,并且根据这种类型,我想在单元格上显示不同的项目。 The best way would be to use a constructor like this: 最好的方法是使用这样的构造函数:

public AnimalCell(MyCustomType type)
{
    if(type == XXX){
        // add as subview, add constraints, ...
    }else{
        // normal setup
    }
}

I want to keep cell reuse of course. 我当然想保持单元重用。 Can this be achived? 可以实现吗? How? 怎么样?

Another thing which comes to my mind is to use subclassing. 我想到的另一件事是使用子类化。 Has anybody an idea how I can define cell so that I don't have to duplicate the same code? 有谁知道如何定义单元格,这样我就不必重复相同的代码? Eg 例如

var cell = null;
if (MyCustomType == XXX) {
    cell = collectionView.DequeueReusableCell (DefaultCell.Key, indexPath) as DefaultCell;
} else {
    cell = collectionView.DequeueReusableCell (CustomizedCell.Key, indexPath) as CustomizedCell;
}
cell.DoSomething("someValue"); // this doesn't work because you have to define cell with a certain class
// do some more initialization

My current solution: 我当前的解决方案:

public abstract class DefaultCell : UICollectionViewCell
{
    protected bool someVariable;

    [Export ("initWithFrame:")]
    public DefaultCell (CGRect frame) : base (frame)
    {
    }

    public void DoSomething(string text)
    {
        label.Text = text;
    }
}

public class Custom1Cell : DefaultCell
{
    public static readonly NSString Key = new NSString ("Custom1Cell");

    [Export ("initWithFrame:")]
    public Custom1Cell (CGRect frame) : base (frame)
    {
        initialize ();
    }

    private void initialize()
    {
        // some initialization
    }
}

public class Custom2Cell : DefaultCell
{
    public static readonly NSString Key = new NSString ("Custom2Cell");

    [Export ("initWithFrame:")]
    public Custom2Cell (CGRect frame) : base (frame)
    {
        initialize ();
    }

    private void initialize()
    {
        // some initialization
    }

    public void SomeMethod(string text)
    {
        if(someVariable)
            someOtherLabel.Text = text;
    }
}

The dequeuing works as described by Mahmoud: 如Mahmoud所述,出队工作:

DefaultCell cell;
if (type = XXX) {
    cell = collectionView.DequeueReusableCell (Custom1Cell.Key, indexPath) as Custom1Cell;
} else {
    cell = collectionView.DequeueReusableCell (Custom2Cell.Key, indexPath) as Custom2Cell;
}
cell.DoSomething("works on both cell types");
((Custom2Cell)cell).SomeMethod("works only on one cell type");

maybe you consider an abstract class with shared variables and methods (name it BaseClass) and two other classes which inherits from abstract one and in the code you can define cell as an Object and initialize it in the if statement just like as below: 也许您考虑一个具有共享变量和方法的抽象类(将其命名为BaseClass)以及另外两个从抽象类继承的类,并且可以在代码中将单元格定义为Object并在if语句中对其进行初始化,如下所示:

Object cell;
if (MyCustomType == XXX) {
    cell = new class1()
   ((Class1) cell).MethodInClass1();
} else{
   cell = new class2();
   ((Class2) cell).MethodInClass2();
}

You can Add a UICollectionViewCell's Subclass let's say YourCell. 您可以添加UICollectionViewCell的子类,比如说YourCell。 Now give YourCell to the cell in the storyboard. 现在,将YourCell交给情节提要中的单元格。 And in YourCell you can add any number of views and you can Outlet them FROM your Storyboard cell TO the YourCell Class and then you can customise your view as you need. 在YourCell中,您可以添加任意数量的视图,还可以将它们从Storyboard单元中输出到YourCell类中,然后可以根据需要自定义视图。

Updat: ok let say you don't add that view in the storyboard but you have it as a property(Which i just a pointer so wont take memory :) a lot ) Just do lazy instantiation on the getter and set it's constraints in this getter methor. Updat:好的,可以说您没有在情节提要中添加该视图,但是您将其作为属性使用(我只是一个指针,因此不会占用内存:)很多)只需在getter上进行惰性实例化并在其中设置其约束即可。吸气剂甲醚。 Here's an example of lazy instantiation we have a label which is not in storyboard view. 这是一个延迟实例化的示例,我们有一个不在情节提要视图中的标签。

-(UILabel *)yourLabel
{
    if(!_yourLabel){
        _yourLabel=[[UILabel alloc]init];
        NSLayoutConstraint *leadingConstraint= [NSLayoutConstraint constraintWithItem:self.contentView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:_yourLabel attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0];
         NSLayoutConstraint *topConstraint= [NSLayoutConstraint constraintWithItem:self.contentView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:_yourLabel attribute:NSLayoutAttributeTop multiplier:1.0 constant:0];
        [self.contentView addConstraints:@[leadingConstraint,topConstraint]];
    }
    return _yourLabel;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM