Ios 在自定义UITableViewCell中调整UITextView的大小

Ios 在自定义UITableViewCell中调整UITextView的大小,ios,objective-c,uitableview,Ios,Objective C,Uitableview,我有一个自定义的UITableViewCell,我正试图根据内容大小调整其中的UITextView。我在iOS7上使用自动布局 我尝试使用以下方法: [cell.question setScrollEnabled:YES]; [cell.question sizeToFit]; [cell.question setScrollEnabled:NO]; 及 来自不同的SO帖子。我可以调整框架的大小。但问题是我看不到明显的变化。从某种意义上说,当我记录它时,我可以看到变化。但是,UITextVie

我有一个自定义的
UITableViewCell
,我正试图根据内容大小调整其中的
UITextView
。我在iOS7上使用自动布局

我尝试使用以下方法:

[cell.question setScrollEnabled:YES];
[cell.question sizeToFit];
[cell.question setScrollEnabled:NO];

来自不同的SO帖子。我可以调整框架的大小。但问题是我看不到明显的变化。从某种意义上说,当我记录它时,我可以看到变化。但是,
UITextView
不会调整大小。我也找不到任何自动布局依赖项

当我禁用自动布局时,它似乎可以工作。如何通过启用自动布局来实现这一点

谢谢

编辑

这是我的
UITextView
约束


您必须在

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
方法,并相应调整单元格高度

如果你知道了,没关系。或者,如果您需要代码示例,请再次询问。 我想你明白了

已更新

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
            UITextView *tempTV = [[UITextView alloc] init];
            [tempTV setText:@"your text"];
            CGFloat width = self.tableView.frame.size.width - TEXT_ORIGIN_X - TEXT_END_X;
            CGSize size = [tempTV sizeThatFits:CGSizeMake(width, MAX_HEIGHT)];
            return (TEXT_ORIGIN_Y + size.height + TEXT_BOTTOM_SPACE);
    }

您可能忘记了实现TableView的deleget的heightForRowAtIndexPath方法

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    CGFloat  yourTextViewsHeight = ... calculate it here
    return yourTextViewsHeight;
}
试试这个

在自定义UITableViewCell类中设置UITextView插座,如下所示

[yourTextView setAutoresizesSubviews:YES];
yourTextView.autoresizingMask = UIViewAutoresizingFlexibleWidth;

希望这对您有用

我想您可能对文本视图有太多限制。我不能确定这一点,因为很难传达有关IB中内置的约束的信息

文本视图只需要两个约束,每个轴一个,就可以完全约束。一个约束应将文本视图水平放置,另一个约束应垂直放置。自动布局系统将使用文本视图的固有内容大小自动生成文本视图的大小约束

我认为您现在存在的一些限制正在阻止调整文本视图的大小。这是因为默认情况下,您自己创建的约束是必需的(优先级1000)。另一方面,自动生成的调整大小约束具有较低的优先级,并且将被所需的任何冲突约束所否决

注意:仅仅因为文本视图只需要两个约束就可以完全约束,并不意味着不能有更多的约束。具有4个标签、3个图像视图和1个文本视图的表格单元格是一个复杂的布局,因此您很可能会相对于文本视图而不是超级视图约束其他UI对象

I had the same issue but in a different situation. I have UItableview with two custom cells.

First Custom cell - self expanding textview. (like email type message box)
Second Custom Cell -  Static image. 

Have a  look at my code. You will get an insight to automatic resizing of cells.

//  ViewController.swift
//  ListWrap

import UIKit

class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate, UITextViewDelegate {

    @IBOutlet var listWrapTableView: UITableView!

    //CustomCells
    var CellIdentifier: String = "ListWrapTableViewCellID"
    var tapGesture: UITapGestureRecognizer!

    override func viewDidLoad() {
        super.viewDidLoad()
    }
    override func viewWillAppear(animated: Bool) {
        //Adding Tap Gesture To Table
        tapGesture = UITapGestureRecognizer(target: self, action: "tapRecognized:")
        self.listWrapTableView.addGestureRecognizer(tapGesture)
        tapGesture.cancelsTouchesInView = false
        tapGesture.enabled =  true
    }
    func tapRecognized(recognizer: UITapGestureRecognizer){
        self.listWrapTableView.endEditing(true)
    }
    func textViewDidBeginEditing(textView: UITextView) {
        if (CellIdentifier == "ListWrapTableViewCellID")
        {
            tapGesture.enabled =  true
        }
        else
        {
            tapGesture.enabled =  false
        }
    }
    // MARK: - Table view data source
    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }
    func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
    {
        self.listWrapTableView.rowHeight = UITableViewAutomaticDimension
        return self.listWrapTableView.rowHeight
    }
    func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        return UITableViewAutomaticDimension
    }
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 2
    }
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        if (indexPath.row == 0)
        {
            let surveyCell = tableView.dequeueReusableCellWithIdentifier(CellIdentifier)! as! ListWrapTableViewCell
            return surveyCell
        }
        else if (indexPath.row == 1)
        {
            let reportsCell = tableView.dequeueReusableCellWithIdentifier("ListWrapSecondTableViewCellID")! as! ListWrapSecondTableViewCell
            return reportsCell
        }
        else
        {
            let cell:UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "")
            return cell
        }
    }
    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
    {
    }
}



The first Custom cell:

//  ListWrapTableViewCell.swift
//  ListWrap

import UIKit

class ListWrapTableViewCell: UITableViewCell{

    @IBOutlet var listWrapTextView: UITextView!

//
//  override init?(style: UITableViewCellStyle, reuseIdentifier: String!) {
//      super.init(style: style, reuseIdentifier: reuseIdentifier)
//  }

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!
    }

    /// Custom setter so we can initialise the height of the text view
    var textString: String {
        get {
            return listWrapTextView.text
        }
        set {
            listWrapTextView.text = newValue
            textViewDidChange(listWrapTextView)
        }
    }

    override func awakeFromNib() {
        super.awakeFromNib()
        listWrapTextView.scrollEnabled = false
        listWrapTextView.delegate = self
    }
    override func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
        if selected {
            listWrapTextView.becomeFirstResponder()
        } else {
            listWrapTextView.resignFirstResponder()
        }
    }
}
extension ListWrapTableViewCell: UITextViewDelegate {
    func textViewDidChange(textView: UITextView) {

        let size = textView.bounds.size
        let newSize = textView.sizeThatFits(CGSize(width: size.width, height: CGFloat.max))

        // Resize the cell only when cell's size is changed
        if size.height != newSize.height {
            UIView.setAnimationsEnabled(false)
            tableView?.beginUpdates()
            tableView?.endUpdates()
            UIView.setAnimationsEnabled(true)

            if let thisIndexPath = tableView?.indexPathForCell(self) {
                tableView?.scrollToRowAtIndexPath(thisIndexPath, atScrollPosition: .Bottom, animated: false)
            }
        }
    }
}
extension UITableViewCell {
    /// Search up the view hierarchy of the table view cell to find the containing table view
    var tableView: UITableView? {
        get {
            var table: UIView? = superview
            while !(table is UITableView) && table != nil {
                table = table?.superview
            }

            return table as? UITableView
        }
    }
}

The second custom cell: 

//  ListWrapSecondTableViewCell.swift
//  ListWrap


import UIKit

class ListWrapSecondTableViewCell: UITableViewCell {

    override func awakeFromNib() {
        super.awakeFromNib()
    }
    override func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    }

}


attaching storyBoard for further reference.

您的布局有点复杂,但如果一切都设置正确,这应该无关紧要

您不必计算任何东西(通过使用
sizeThatFits

您只需禁用UITextView的滚动启用属性,然后在textViewDidChange上调用tableView.BeginUpdate()和tableView.EndUpdate()。这不会中断第一个响应程序并平滑地调整表视图的大小


要获得详细的解释,请查看一个包含工作示例项目的项目。

我认为下面的答案已经解决了单元格高度问题,但是您对文本视图的限制在哪里?我发布的图像。这些不是限制条件吗?@wormlxd我做到了。但变化并不明显。但是,在记录日志时,我能够看到不同之处。让我们看看文本视图的约束。他们在IB吗?是的。我过去有一天也遇到过同样的问题。解决方案是,你必须用上面提到的方法调整textview的大小,并返回行的计算高度。你是如何处理这种情况的?你的约束是可以的。我想您正在调整'-(UITableViewCell*)tableView:(UITableView*)tableView cellforrowatinexpath:(nsindepath*)indepath'方法中的textview的大小!!我明白。但这样做是为了调整单元格的高度。如果我这样做,我的手机的高度会改变。知道了。但是UITextView的高度仍然保持不变。我想更改它。只有在设置了适当的约束条件下,当单元格调整大小时,文本视图才会调整大小。这不是魔法造成的。如果文本视图有高度限制,那么它不会调整大小。这似乎没有帮助。如果使用自动布局,请忘记调整遮罩的大小。
I had the same issue but in a different situation. I have UItableview with two custom cells.

First Custom cell - self expanding textview. (like email type message box)
Second Custom Cell -  Static image. 

Have a  look at my code. You will get an insight to automatic resizing of cells.

//  ViewController.swift
//  ListWrap

import UIKit

class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate, UITextViewDelegate {

    @IBOutlet var listWrapTableView: UITableView!

    //CustomCells
    var CellIdentifier: String = "ListWrapTableViewCellID"
    var tapGesture: UITapGestureRecognizer!

    override func viewDidLoad() {
        super.viewDidLoad()
    }
    override func viewWillAppear(animated: Bool) {
        //Adding Tap Gesture To Table
        tapGesture = UITapGestureRecognizer(target: self, action: "tapRecognized:")
        self.listWrapTableView.addGestureRecognizer(tapGesture)
        tapGesture.cancelsTouchesInView = false
        tapGesture.enabled =  true
    }
    func tapRecognized(recognizer: UITapGestureRecognizer){
        self.listWrapTableView.endEditing(true)
    }
    func textViewDidBeginEditing(textView: UITextView) {
        if (CellIdentifier == "ListWrapTableViewCellID")
        {
            tapGesture.enabled =  true
        }
        else
        {
            tapGesture.enabled =  false
        }
    }
    // MARK: - Table view data source
    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }
    func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
    {
        self.listWrapTableView.rowHeight = UITableViewAutomaticDimension
        return self.listWrapTableView.rowHeight
    }
    func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        return UITableViewAutomaticDimension
    }
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 2
    }
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        if (indexPath.row == 0)
        {
            let surveyCell = tableView.dequeueReusableCellWithIdentifier(CellIdentifier)! as! ListWrapTableViewCell
            return surveyCell
        }
        else if (indexPath.row == 1)
        {
            let reportsCell = tableView.dequeueReusableCellWithIdentifier("ListWrapSecondTableViewCellID")! as! ListWrapSecondTableViewCell
            return reportsCell
        }
        else
        {
            let cell:UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "")
            return cell
        }
    }
    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
    {
    }
}



The first Custom cell:

//  ListWrapTableViewCell.swift
//  ListWrap

import UIKit

class ListWrapTableViewCell: UITableViewCell{

    @IBOutlet var listWrapTextView: UITextView!

//
//  override init?(style: UITableViewCellStyle, reuseIdentifier: String!) {
//      super.init(style: style, reuseIdentifier: reuseIdentifier)
//  }

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!
    }

    /// Custom setter so we can initialise the height of the text view
    var textString: String {
        get {
            return listWrapTextView.text
        }
        set {
            listWrapTextView.text = newValue
            textViewDidChange(listWrapTextView)
        }
    }

    override func awakeFromNib() {
        super.awakeFromNib()
        listWrapTextView.scrollEnabled = false
        listWrapTextView.delegate = self
    }
    override func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
        if selected {
            listWrapTextView.becomeFirstResponder()
        } else {
            listWrapTextView.resignFirstResponder()
        }
    }
}
extension ListWrapTableViewCell: UITextViewDelegate {
    func textViewDidChange(textView: UITextView) {

        let size = textView.bounds.size
        let newSize = textView.sizeThatFits(CGSize(width: size.width, height: CGFloat.max))

        // Resize the cell only when cell's size is changed
        if size.height != newSize.height {
            UIView.setAnimationsEnabled(false)
            tableView?.beginUpdates()
            tableView?.endUpdates()
            UIView.setAnimationsEnabled(true)

            if let thisIndexPath = tableView?.indexPathForCell(self) {
                tableView?.scrollToRowAtIndexPath(thisIndexPath, atScrollPosition: .Bottom, animated: false)
            }
        }
    }
}
extension UITableViewCell {
    /// Search up the view hierarchy of the table view cell to find the containing table view
    var tableView: UITableView? {
        get {
            var table: UIView? = superview
            while !(table is UITableView) && table != nil {
                table = table?.superview
            }

            return table as? UITableView
        }
    }
}

The second custom cell: 

//  ListWrapSecondTableViewCell.swift
//  ListWrap


import UIKit

class ListWrapSecondTableViewCell: UITableViewCell {

    override func awakeFromNib() {
        super.awakeFromNib()
    }
    override func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    }

}


attaching storyBoard for further reference.