1

プロトタイプセルを持つ UICollectionView があります。セルが読み込まれ、画像が表示され、ラベルが表示されます。セルのサイズが異なるため、CollectionViewFlowLayout を介して変更されます。それはうまくいきます。

シミュレーターでビューをスクロールすると、ラベルが再利用され、画像に間違って追加されたように見えます。これが発生せず、コレクションビューで画像のラベルが 1 つだけであることを確認するにはどうすればよいですか?

問題のスクリーンショット

UICollectionView

#pragma mark - Collection view 
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
    self.Data = [NSArray arrayWithObjects:@1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @11, @12, @13, @14, @15, @16, nil];
    return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return self.magazineLayout.count;
}

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    MagazineCell *mCell = (MagazineCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellID forIndexPath:indexPath];
    int item = [indexPath row];

    mCell.backgroundColor = [UIColor lightGrayColor];

    // Set Image
    UIImage *image;
    image = [UIImage imageNamed:@"testimage.png"];
    mCell.imageView.image = image; 


    // Set Label
    NSString *title = [[NSString alloc] initWithFormat:@"Image %@", self.Data[item]];
    [mCell addSubview:[self cellTitle:title indexPath:indexPath]];

    return mCell; 
}

// Title will be reused and placed wrongly on pictures !
-(UILabel *)cellTitle:(NSString *)name indexPath:(NSIndexPath *)indexPath {

    CGSize itemSize = [self collectionView:self.collectionView layout:self.collectionView.collectionViewLayout sizeForItemAtIndexPath:indexPath];
    int top = itemSize.height - 40;
    int width = itemSize.width;

    UILabel *title = [[UILabel alloc] initWithFrame:CGRectMake(0, top, width, 40)];
    title.textColor = [UIColor blackColor];
    title.text = name;
    title.backgroundColor = [UIColor whiteColor];
    title.alpha = 0.5f;

    return title; 
}

編集:回避策の解決策

viewWithTagうまくいきましたが、ラベルの位置を変更できませんでした。悲しいことに、これが最善の方法だと思います。ここで私の回避策viewWithTag

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    MagazineCell *mCell = (MagazineCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellID forIndexPath:indexPath];
    mCell.backgroundColor = [UIColor lightGrayColor];

    // Set Image
    UIImage *image;
    image = [UIImage imageNamed:@"testimage.png"];
    mCell.imageView.image = image; 

    [self cellTitleAndBackground:mCell indexPath:indexPath];

    return mCell; 
}


-(void)cellTitleAndBackground:(MagazineCell *)mCell indexPath:(NSIndexPath *)indexPath {

    // Get title
    NSString *name = [[NSString alloc] initWithFormat:@"Image %@", self.Data[indexPath.row]];

    // Get current cell size
    CGSize itemSize = [self collectionView:self.collectionView layout:self.collectionView.collectionViewLayout sizeForItemAtIndexPath:indexPath];
    int top = itemSize.height - 40;
    int width = itemSize.width;

    // Create title background
    UILabel *titleBackground = [[UILabel alloc] initWithFrame:CGRectMake(0, top, width, 40)];
    titleBackground.backgroundColor = [UIColor blackColor];
    titleBackground.alpha = 0.2f;
    titleBackground.tag = 70;
    [self removeReusedLabel:mCell tag:70]; 
    [mCell addSubview:titleBackground];

    // Create titleLabel
    UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(8, top-8, width, 40)];
    titleLabel.textColor = [UIColor whiteColor];
    titleLabel.font = [UIFont boldSystemFontOfSize:14];
    titleLabel.text = name;
    titleLabel.backgroundColor = [UIColor clearColor];
    titleLabel.tag = 72;
    [self removeReusedLabel:mCell tag:72];
    [mCell addSubview:titleLabel];
}

-(void)removeReusedLabel:(MagazineCell *)mCell tag:(int)tag {
    UILabel *foundLabelBackground = (UILabel *)[mCell viewWithTag:tag];
    if (foundLabelBackground) [foundLabelBackground removeFromSuperview];
}

乾杯 -- ジェリック

4

2 に答える 2

6

これは細胞の再利用が原因です。このようにラベルを追加する場合は、dequeue メソッドから取得したセルにラベルがあるかどうかを確認し、存在する場合は削除する必要があります。ラベルにタグを付けてから、viewWithTag: を使用してラベルが存在するかどうかを確認し、removeFromSuperview を呼び出すことができます。私はこれをテストしていませんが、次のようなものがうまくいくと思います:

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    MagazineCell *mCell = (MagazineCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellID forIndexPath:indexPath];
    UILabel *foundLabel = [mCell viewWithTag:47];
    if (foundLabel) [foundLabel removeFromSuperview];
    .......

cellTitle:indexPath メソッドでラベルを作成するときは、ラベルのタグを同じ番号に設定することを忘れないでください。ところで、セル自体ではなく、セルの contentView にこのラベルを追加する必要があります。

編集後:

あなたのコードのこの変更は、viewWithTagを使用してうまくいきました:

-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    CGSize cellSize = [self.magazineLayout[indexPath.item] size];
    return cellSize;
}

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    MagazineCell *mCell = (MagazineCell *)[collectionView dequeueReusableCellWithReuseIdentifier:@"RDCell" forIndexPath:indexPath];
    mCell.backgroundColor = [UIColor lightGrayColor];
    if ([mCell viewWithTag:47]) [[mCell viewWithTag:47] removeFromSuperview];
    UIImage *image = self.magazineLayout[indexPath.item];
    mCell.imageView.image = image;

    NSString *title = [[NSString alloc] initWithFormat:@"Image %@", self.data[indexPath.item]];
    [mCell addSubview:[self cellTitle:title indexPath:indexPath]];

    return mCell;
}


-(UILabel *)cellTitle:(NSString *)name indexPath:(NSIndexPath *)indexPath {
    CGSize itemSize = [self.magazineLayout[indexPath.item] size];
    int top = itemSize.height - 40;
    int width = itemSize.width;
    UILabel *title = [[UILabel alloc] initWithFrame:CGRectMake(0, top, width, 40)];
    title.textColor = [UIColor blackColor];
    title.text = name;
    title.backgroundColor = [UIColor whiteColor];
    title.alpha = 0.5f;
    title.tag = 47;
    return title;
}

この例では、配列 magazineLayout に、サイズの異なる 16 枚の画像が格納されています。

ただし、より簡単な方法は、ストーリーボード (または xib) のカスタム セルにラベルを追加することです。側面と底面にピン留めし、高さを 40 に設定すると、ラベルを作成したり、その存在を確認したりするコードなしで、必要なものが得られます。

于 2013-02-19T22:38:45.860 に答える
1

私は答えが受け入れられ、閉じられたことを知っています。しかし、誰かがこのスレッドに出くわした場合に備えて、この問題を回避するための正しいアプローチは、UICollectionViewCell をサブクラス化してから使用することです

[self.collectionView registerClass:[LPCollectionViewCell class] forCellWithReuseIdentifier:cellIdentifier];

サブクラスの initWithFrame メソッドですべての要素を初期化します

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {

        self.lblName = [[UILabel alloc] initWithFrame:CGRectMake(0.0, 95.0, 106.0, 20)];
        self.lblName.text = @"";
        self.lblName.textAlignment = NSTextAlignmentCenter;
        [self.lblName setFont:[UIFont fontWithName:@"GothamRounded-Bold" size:10]];
        [self.lblName setTextColor:[UIColor colorWithRed:137.0f/255.0 green:137.0f/255.0 blue:137.0f/255.0 alpha:1.0]];
        [self.lblName setBackgroundColor:[UIColor clearColor]];
        [self addSubview:self.lblName];
}

後でコレクション ビューのデータ ソース呼び出しでアクセスできるように、要素をパブリックにします。

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {

    LPCollectionViewCell *cell = (LPCollectionViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
    cell.backgroundColor = [UIColor whiteColor];
    [cell.lblName setText:@"This is awesome"];
}

以上です!

于 2014-06-11T12:28:12.410 に答える