0

セル内の UILabel には NSLocalizedString が含まれています。言語によって、数文字から 1 段落までさまざまです。UILabel のフレームは、文字列の長さに合わせて描画される場合と描画されない場合があります。これは再利用の問題だと思いますが、修正方法がわかりません。

Nibs から読み込まれた一連の 5 つの異なる UITableViewCell サブクラスがあります (プロジェクト要件) viewDidLoad

UINib *Cell1Nib = [UINib nibWithNibName:@"customCell1" bundle:nil];
[[self tableView] registerNib:Cell1Nib forCellReuseIdentifier:@"custCell1"];

UINib *Cell2Nib = [UINib nibWithNibName:@"customCell2" bundle:nil];
[[self tableView] registerNib:Cell2Nib forCellReuseIdentifier:@"custCell2"];
//etc.

使用するテキストに応じて UILabel の高さを取得するためのヘルパーがあります。

- (CGFloat)getTextHeight:(NSString *)locStr forLabelWidth:(CGFloat)w {
    UILabel  *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, w, 110)];
    label.numberOfLines=0;
    label.lineBreakMode=NSLineBreakByCharWrapping;
    label.text = locStr; // highly variable & already localized
    label.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; 
    CGSize maxSize = CGSizeMake(w, CGFLOAT_MAX);
    CGSize requiredSize = [label sizeThatFits:maxSize];
    label = nil; // ARC paranoia
    return requiredSize.height;
}

heightForRowAtIndexPathI callでは、それgetTextHeight:forLabelWidth:を使用してセルの高さを決定し、その結果を NSMutableArray という名前で格納しlabelHeightforRow.ます。これまでのところ、すべてうまく機能しています。

次のようにテーブルを作成します。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = nil;
    DLX_CellDescriptor *desc = [[DLX_CellDescriptor alloc] initWithRow:indexPath.row];
    //DLX_CellDescriptor describes attributes for cell at index , essentially a list of strings
    CGFloat helpTextHeight = [[labelHeightforRow objectAtIndex:indexPath.row] floatValue];

    if ([desc.nibToUse caseInsensitiveCompare:@"custCell1"] == NSOrderedSame ) {
        DLX_CustCell1 *currCell = (DLX_CustCell1 *)[self.tableView dequeueReusableCellWithIdentifier:@"custCell1"];
        CGPoint origin = currCell.theLabel.frame.origin;
        CGFloat w = currCell.theLabel.frame.size.width;
        currCell.theLabel.frame = CGRectMake(origin.x, origin.y, w, helpTextHeight);
        currCell.theLabel.text = desc.localizedText;
        currCell.theLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
        currCell.tag = indexPath.row;
        cell = currCell;
    } else if ([desc.nibToUse caseInsensitiveCompare:@"custCell2"] == NSOrderedSame ) {
        DLX_CustCell2 *currCell = (DLX_CustCell2 *)[self.tableView dequeueReusableCellWithIdentifier:@"custCell2"];
        CGPoint origin = currCell.theLabel.frame.origin;
        CGFloat w = currCell.theLabel.frame.size.width;
        currCell.theLabel.frame = CGRectMake(origin.x, origin.y, w, helpTextHeight);
        currCell.theLabel.text = desc.localizedText;
        currCell.theLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
        currCell.tag = indexPath.row;
        cell = currCell;
    } // for about 26 rows of 5 different non-identical sytles
      // simplified in this example
    return cell;
}

この問題は、最初の TableView が作成されるときに、UILabel が Nib で指定された高さになることです。余分な長いテキストを切り捨て、下に大きな空白を与えます (正しいセルの高さ調整から)。テーブルが再描画されると、UILabel はコードで指定された正しい高さに変わります。文字列全体を表示します。次に、セルが再作成された場合。たとえば、画面からスクロールして別のセル タイプが描画された後、長いテキスト ラベルは Nib から切り捨てられた高さを再び使用しています。

layoutSubviewsカスタムUITableViewCell(たとえば、customCell1.m)に次のように入れてみました:

- (void)layoutSubviews {
    NSInteger currCell = self.tag;
    DLX_CellDescriptor *desc = [[DLX_CellDescriptor alloc] initWithRow:currCell];
    CGPoint origin = theLabel.frame.origin;
    CGSize size = theLabel.frame.size;
    CGFloat textHeight = [self getTextHeight:desc.localizedText forLabelWidth:size.width];
    theLabel.frame = CGRectMake(origin.x, origin.y, size.width, textHeight);
    [super layoutSubviews];
}

しかし、これには、ニブからの高さが使用されることを不変に保証する効果がありました。調べtextheightてみると、正しかったのですが (一部の言語では、ペン先の高さよりもはるかに大きくなっています)。

4

1 に答える 1

1

セルは比較的単純であるため、問題を解決する簡単な方法の 1 つは、再利用を使用しないことです。バンドルからnibファイルをロードするだけです。registerNib関連するコードを削除します。そして、次のようにします。

NSString *reuseIdentifier = @"DistrictCellReuseIdentifier";
DistrictCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
if (cell == nil) {
    cell = [[NSBundle mainBundle] loadNibNamed:@"DistrictCell" owner:self options:nil][0];
}
于 2013-09-23T01:57:41.690 に答える