web-dev-qa-db-ja.com

UITextViewに基づいて動的に高さを調整するUITextViewを内部に持つUITableViewCellを作成する方法は?

AppleのiPhone連絡先アプリに似た動作のTablewビューが欲しい:内部にuitextviewを含むuitableviewcell。高さ。私はウェブ全体を検索しましたが、部分的な解決策とサンプルコードの不足しか見つかりませんでした!

私を助けてください私は必死です

トニー

42
Tony

これを見て、ややトリッキーにする必要があります。 textViewの高さを動的に計算し、TextViewのHeightに基づいて、セルのHeightを返す必要があります。

とても簡単で、ややトリッキーです。

これは、文字列のサイズを計算できるコードです...

最初に文字列のサイズを取得します

NSString *label =  @"Sample String to get the Size for the textView Will definitely work ";
CGSize stringSize = [label sizeWithFont:[UIFont boldSystemFontOfSize:15]
                      constrainedToSize:CGSizeMake(320, 9999)
                          lineBreakMode:UILineBreakModeWordWrap];

over here ....
NSLog(@"%f",stringSize.height);

次に、セル内にtextViewを動的に作成します。stringSize.heightを指定します。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    //if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    //}

    NSDictionary *d=(NSDictionary *)[self.menuArray objectAtIndex:indexPath.section];

    NSString *string = [d valueForKey:@"Description"];
    CGSize stringSize = [string sizeWithFont:[UIFont boldSystemFontOfSize:15] constrainedToSize:CGSizeMake(320, 9999) lineBreakMode:UILineBreakModeWordWrap];

    UITextView *textV=[[UITextView alloc] initWithFrame:CGRectMake(5, 5, 290, stringSize.height+10)];
    textV.font = [UIFont systemFontOfSize:15.0];
    textV.text=string;
    textV.textColor=[UIColor blackColor];
    textV.editable=NO;
    [cell.contentView addSubview:textV];
    [textV release];

    return cell;
}


- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath  {  

    NSDictionary *d=(NSDictionary *)[self.menuArray objectAtIndex:indexPath.section];
    NSString *label =  [d valueForKey:@"Description"];
    CGSize stringSize = [label sizeWithFont:[UIFont boldSystemFontOfSize:15]
                          constrainedToSize:CGSizeMake(320, 9999) 
                              lineBreakMode:UILineBreakModeWordWrap];

    return stringSize.height+25;

} 

私の指にそんなに苦痛を与えた後、......これは十分なコードだと思います...&は確かにあなたの問題を解決するのに役立ちます..

幸運を

37
Ajay Sharma

カスタムUITableViewCellを作成し、UITextViewをセルのcontentViewに追加します。

LayoutSubviewsで、textView.frameをセルのcontentView.boundsに設定します(または他のカスタムレイアウトを実行します)。

TextViewの内容が変更された場合(UITextViewDelegateを介して検出)、次の2つのことを行います。

1)[tableView beginUpdates]; [tableView endUpdates];を呼び出します。これにより、Table Viewはすべてのセルの高さを再計算します(tableView:heightForRowAtIndexPath:を呼び出します)。セルがtextViewのデリゲートである場合、tableViewへのポインターを取得する方法を理解する必要がありますが、それを実現する方法はいくつかあります。または、デリゲートをView Controllerにすることもできます...

2)このセルに対してtableView:heightForRowAtIndexPath:が呼び出されると、textView.contentSize.heightを返します。 [tableView cellForRowAtIndexPath];を呼び出すことで、ここからセルを取得できます。または、これらのセルのいずれか1つだけを使用している場合は、viewControllerにそのセルへのポインターをキャッシュします。

12
TomSwift

受け入れられた答えで見つけた唯一の問題は、UITextViewを毎回割り当てていることです。これにより、ビューに入力してテキストをすぐに更新し、ビューを最初のレスポンダーとして保持することで問題が発生することがわかりました。新しい高さでセルをリロードしようとすると、新しいtextViewを追加しようとしました。

このため、同じ目標を達成するために少し異なる方法を見つけました。この異なる方法が、上記のコードの実装に苦労している人々の助けになることを願っています。

1)ヘッダーファイルで、テキストとtextViewの高さの変数を定義します。

UITextView * _textView;
NSInteger _textHeight;

変数を設定すると、textViewにテキストをロードする場合にビューを特定の高さにロードできるようになり、複雑さも軽減されます。

2)テキストビューを読み込み、セルに追加します

_textView = [[UITextView alloc] init];
_textView.delegate = self;
_textView.returnKeyType = UIReturnKeyDone;
_textView.font = [UIFont fontWithName:@"Helvetica" size:16];

if (![_user metaStringForKey:bBioKey].length) {
    _textView.text = @"Placeholder text";
    _textView.textColor = [UIColor lightGrayColor];
}


- (UITableViewCell *)tableView:(UITableView *)tableView_ cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    if (indexPath == 0) { // Add logic to choose the correct cell

        if (_textView.superview != cell) {

            [cell addSubview:_textView];     

            _textView.keepTopInset.equal = KeepRequired(7);
            _textView.keepBottomInset.equal = KeepRequired(7);
            _textView.keepRightInset.equal = KeepRequired(10);
            _textView.keepLeftInset.equal = KeepRequired(70);
            }
        }
    }
}

Keeplayoutを使用すると、テキストフィールドを常にセルと同じ高さに保つことができます。また、UITextViewを一度追加するだけです。

3)テキストの高さを計算するコードを追加します

- (NSInteger)getHeightOfBio: (NSString *)text {

    UILabel * gettingSizeLabel = [[UILabel alloc] init];
    gettingSizeLabel.font = [UIFont fontWithName:@"Helvetica" size:16];
    gettingSizeLabel.text = text;
    gettingSizeLabel.numberOfLines = 0;
    CGSize maximumLabelSize = CGSizeMake(240, 9999); // this width will be as per your requirement

    CGSize expectedSize = [gettingSizeLabel sizeThatFits:maximumLabelSize];

    return expectedSize.height;
}

私は多くのことを試してみましたが、これが最適に機能することがわかりました

4)これを利用するために、セルの高さにいくつかのロジックを追加します。

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    if (indexPath.row == 0) { // Set the height for our changing textView

        return 30 + [self getHeightOfBio:_textView.text];
    }

    return 44;
}

明らかに、テキストの高さよりも少し高い高さが必要なので、試してみられるクッションの量を追加しました。

5)文字を入力するたびにビューを更新して、サイズを増やす必要があるかどうかを確認します。

- (void)textViewDidChange:(UITextView *)textView {

    if ([self getHeightOfText:textView.text] != _textHeight) {

       _textHeight = [self getHeightOfText:textView.text];

       [self.tableView beginUpdates];
       [self.tableView endUpdates];
    }
}

このセクションでは、ユーザーが入力するたびにテキストの高さを取得します。

次に、保存された値を使用して、現在の値と保存された値を比較します。明らかに同じであれば、ビューを更新しても意味がありません。それらが異なる場合、値を更新してからテーブルを更新します。

このビットは、セル自体の代わりにテーブルの高さのみを更新する方法を示すstackOverflowに関する良い答えを見つけました。必要のないときにセルを更新するのはなぜですか?これは、これが呼び出されるとセルの高さが更新され、うまく増加することを意味します。

とにかく、これは本当にうまく機能し、簡単に組み合わせて、他の人のコードに別の部分を取り込んで配置できることがわかりました。

途中でさまざまなピースを略奪された受け入れられた答えの小道具ですが、この答えが私と同じ困難を抱えている一部の人々に役立つことを願っています。

3
simon_smiley

私はブログで 内部UITextViewに基づくUITableViewCellの高さ を計算するための学習とソリューションを作成しました。この投稿には、テーブルビュースタイルと自動回転の両方のユニバーサルアプリで機能するコードが含まれています。

2
dennisreimann

私はそれを行うための最良の方法であるTomSwiftレスポンスを編集します:

ここに私のセルコードがあります(Swift)

class CommentaireTextViewCell: UITableViewCell,UITextViewDelegate {

@IBOutlet weak var textViewCom: UITextView!
weak var parentTableView:UITableView?

@IBOutlet weak var constraintTextViewTopMargin: NSLayoutConstraint!
@IBOutlet weak var constraintTextViewHeight: NSLayoutConstraint!
@IBOutlet weak var constraintTextViewBottomMargin: NSLayoutConstraint!
override func awakeFromNib() {
    self.textViewCom.delegate = self;
}

func textViewDidChange(textView: UITextView) {
    self.parentTableView?.beginUpdates();
    self.parentTableView?.endUpdates();
}

func getHeight() -> CGFloat
{
    constraintTextViewHeight.constant = self.textViewCom.contentSize.height;
    // cell height = textview marge top+ textview height+ textView Marge bottom
    return constraintTextViewTopMargin.constant+constraintTextViewHeight.constant+constraintTextViewBottomMargin.constant+8
    // add 8 because it seems to have an inset inside the textView
}

override func setSelected(selected: Bool, animated: Bool) {
    self.textViewCom.becomeFirstResponder();
}
}

説明のために、セルテーブルビューはセルの弱い特性なので、ユーザーがテキストを入力したときにレイアウトを更新するように指示できます。セルの高さは、contentViewの上部の制約、contentViewの下部の制約、およびtextViewの一定の高さに等しいtextView.contantSize.heightの合計です。

enter image description here

1
Vassily

最後に、私はそれを機能させました。主な問題は、セルのcontentView正しい幅を取得する方法です。ハードコードされた幅は、プレーン/グループ化されたテーブルスタイル、追加されたアクセサリ、またはランドスケープ/ポートレートレイアウトに応じて変化する可能性があるため、すべてのケースで機能するわけではありません。 100%正しい幅を取得する唯一の方法は、セルオブジェクトから要求することです。そこで、heightForRowAtIndexPathにセルを作成してキャッシュに保存すると、このキャッシュされたセルがcellForRowAtIndexPathメソッドによって返されます。別の問題は、使用前にセルにサブビューをレイアウトさせる方法です。セルをtableViewに一時的に追加し、tabelViewの幅でセルのフレームを更新する場合に実行できます。その後、すべてのサブビューが正しい方法でレイアウトされます。 ここ は、 TableKit ライブラリでどのように動作するかです。

1
onegray

HeightForRowAtIndexPathデリゲートメソッドで正しい高さを返す必要があります。

0
Rengers

次のコードを試してください:

CGSize constraintSize;
constraintSize.height = MAXFLOAT;
constraintSize.width = yourTextView.frame.size.width;
NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                                      [UIFont fontWithName:@"yourFontName" size:yourFontSize], NSFontAttributeName,
                                      nil];

CGRect frame = [yourTextView.text boundingRectWithSize:constraintSize
                                  options:NSStringDrawingUsesLineFragmentOrigin
                               attributes:attributesDictionary
                                  context:nil];

CGSize stringSize = frame.size;//The string size can be set to the UITableViewCell
0