0

UICollectionViews で非常に奇妙な動作が見られます。

これがシナリオです。

UINavigationController スタックにプッシュされた UIViewController があります。

UIViewController ビューには、グリッド レイアウトのナビゲーション バーと UICollectionView があります。幅 3 セル、高さ無制限。

画面の範囲のすぐ下に、UIToolbar も非表示にしています。UIToolbar は、レイヤー階層の UICollectionView の上にあります。

次に、ユーザーがビューを「編集モード」にできるようにし、UIToolbar を画面上でアニメーション化し、UICollectionView の下部をカバーします。ユーザーが「編集モード」を離れると、UIToolbar を画面外に戻します。

「編集モード」では、チェックボックスが表示され、uitoolbar に削除ボタンがある複数のセルをユーザーが選択できるようにします。

削除は次のことを行います。

- (void)deletePhotos:(id)sender {
if ([[self.selectedCells allKeys] count] > 0) {
    [[DataManager instance] deletePhotosAtIndexes:[self.selectedCells allKeys]];
    [self.selectedCells removeAllObjects];
    [self.collectionview reloadData];
    [self.collectionview performBatchUpdates:nil completion:nil];
}
}

// Data Manager method in singleton class:

- (void)deletePhotosAtIndexes:(NSArray *)indexes {
NSMutableIndexSet *indexesToDelete = [NSMutableIndexSet indexSet];
for (int i = 0; i < [indexes count]; i++) {
    [indexesToDelete addIndex:[[indexes objectAtIndex:i] integerValue]];
    NSString *filePath = [self.photosPath stringByAppendingPathComponent:[self.currentPhotos objectAtIndex:[[indexes objectAtIndex:i] integerValue]]];
    NSString *thumbnailPath = [self.thumbPath stringByAppendingPathComponent:[self.currentPhotos objectAtIndex:[[indexes objectAtIndex:i] integerValue]]];
    if ([[NSFileManager defaultManager] fileExistsAtPath: filePath]) {
        [[NSFileManager defaultManager] removeItemAtPath: filePath error:NULL];
        [[NSFileManager defaultManager] removeItemAtPath: thumbnailPath error:NULL];
    }
}
[self.currentPhotos removeObjectsAtIndexes:indexesToDelete];
}

データマネージャには写真オブジェクトが含まれており、セル作成などで使用されます。

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{    
ImageCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"imageCell" forIndexPath:indexPath];

NSString  *pngfile = [[[DataManager instance] thumbPath] stringByAppendingPathComponent:[[[DataManager instance] currentPhotos] objectAtIndex:indexPath.row]];

if ([[NSFileManager defaultManager] fileExistsAtPath:pngfile]) {
    NSData *imageData = [NSData dataWithContentsOfFile:pngfile];
    UIImage *img = [UIImage imageWithData:imageData];
    [cell.imageView setImage:img];
}

if ([self.selectedCells objectForKey:[NSString stringWithFormat:@"%d", indexPath.row]] != nil) {
    cell.checkbox.hidden = NO;
} else {
    cell.checkbox.hidden = YES;
}

return cell;
}

だからここに私が問題を見つけているところがあります:

表示される行の数が変わるように十分な数のセルを削除すると、UIToolbar が消えます。3行いっぱいの場合、1つまたは2つのアイテムだけを削除すると、UIToolbarは消えません。UIToolbar の delete メソッドでアニメーションを実行しておらず、編集モードを終了する Done ボタンを押したときだけです。このメソッドが呼び出されていないことを確認しました。

また、UIToolbar が実際に動いていないことも確認しました。UIToolbar が通常は消える場合に削除を押すときに「self.collectionview removeFromSuperView」を追加すると、UIToolbar は画面上の期待どおりの場所になります。これは、親ビューの描画で UICollectionView が何らかの形でレイヤー階層を変更しているという印象を与えます。

UIToolbar の BringSubviewToFront と collectionview の sendSubviewToBack を試みましたが、影響はありません。

開いているツールバーを再度開始すると、uitoolbar が再びアニメーション化されます。ただし、奇妙なことに、画面の下からアニメーション化されるようです! これは、removeFromSuperview 呼び出しを呼び出した後で UICollectionView が何らかの理由で UIToolbar を画面から押し出して再作成できない場合を除き、意味がありません。

私が持っている1つの「解決策」は、UIToolbarを強制的に元の位置に戻すことですが、0.01秒の遅延後にアニメーションはありません

    [self performSelector:@selector(showToolbarNoAnimation) withObject:nil afterDelay:0.01];

これは機能します。

ここに質問があります: UICollectionView がこの動作を引き起こし、行全体が削除された後に UIToolbar を画面外に押し出す理由は何ですか? ハックは機能しますが、問題を説明していません。

ありがとう、ジェームズ

4

1 に答える 1

1

自動レイアウトを使用し、ビューがストーリーボード (または xib) から読み込まれる場合、ビューのフレームを設定できません。そうすることは最初はうまくいくように見えるかもしれませんが、ある時点で自動レイアウトが制約に基づいてビューのフレームをリセットし、何が起こったのか理解できなくなり、スタック オーバーフローに質問を投稿します。

ビューのレイアウトを変更する必要がある場合は、代わりにビューの制約を更新する必要があります。

ツールバーの下端とそのスーパービューの下端の間の距離を指定する制約があります。おそらく、その距離は -44 (44 はツールバーの高さ) です。

その制約をView Controllerのアウトレットに接続する必要があります。アウトレットのタイプはNSLayoutConstraint *. それを呼び出しますtoolbarBottomEdgeConstraint

ツールバーを画面上でアニメーション化する場合は、制約constantをゼロに設定layoutIfNeededし、アニメーション ブロックを呼び出します。

- (void)showToolbarAnimated {
    [UIView animateWithDuration:0.25 animations:^{
        self.toolbarBottomEdgeConstraint.constant = 0;
        [self.toolbar layoutIfNeeded];
    }];
}

ツールバーを非表示にするには、制約constantを元の値に戻します。

- (void)hideToolbarAnimated {
    [UIView animateWithDuration:0.25 animations:^{
        self.toolbarBottomEdgeConstraint.constant = -toolbar.bounds.size.height;
        [self.toolbar layoutIfNeeded];
    }];
}
于 2013-08-19T16:32:32.173 に答える