可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have a custom UITableViewCell
and I'm trying to resize the UITextView
inside it based on the content size. I'm on iOS7 and using Autolayout.
I've tried using the following:
[cell.question setScrollEnabled:YES]; [cell.question sizeToFit]; [cell.question setScrollEnabled:NO];
and
- (CGRect)textViewHeightForAttributedText: (NSAttributedString*)text andWidth: (CGFloat)width { UITextView *calculationView = [[UITextView alloc] init]; [calculationView setAttributedText:text]; CGSize size = [calculationView sizeThatFits:CGSizeMake(width, FLT_MAX)]; CGRect finalFrame = CGRectMake(0, 0, width, size.height); return finalFrame; }
from different SO posts. I'm able to resize the frame. But the issue is I'm not able to see the change visibly. In the sense, when I log it, I can see the change. But the UITextView
doesnt resize. I cant find any autolayout dependencies either.
When I disabled AutoLayout, it seems to work. How do I do this, by enabling AutoLayout?
Thanks.
EDIT
Here's my UITextView
constraints
回答1:
You have to do this calculation in
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
method and also resize the cell height accordingly.
If you got it, it's okay. Or If you need the code sample, just ask again. I think you got it !
Updated
- (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); }
回答2:
You may forget implement the heightForRowAtIndexPath method of TableView's delegete;
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { CGFloat yourTextViewsHeight = ... calculate it here return yourTextViewsHeight; }
回答3:
I think you might have too many constraints for the text view. I can't be sure of this because it's difficult to communicate information about constraints that are built in IB.
Your text view only needs two constraints, one for each axis, in order to be fully constrained. One constraint should position the text view horizontally, the other vertically. The text view's intrinsic content size will be used by the Auto Layout system to automatically generate size constraints for the text view.
I think some of the constraints you have in place now are preventing resizing of the text view. This happens because, by default, constraints you create yourself are required (priority 1000). The automatically-generated sizing constraints, on the other hand, have a lower priority and will be overruled by any conflicting constraints that are required.
Note: just because the text view only needs two constraints to be fully constrained doesn't mean that you can't have more constraints. A table cell with 4 labels, 3 image views, and 1 text view is a complex layout, so you will most likely constrain other UI objects relative to the text view, rather than the superview.
回答4:
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.

回答5:
Your layout is a bit more complex, but it should not matter if everything is set up properly.
You do not have to calculate anything (by using sizeThatFits
).
All you have to do is disable UITextView's scrolling enabled property then on textViewDidChange call tableView.beginUpdates() and tableView.endUpdates(). That doesn't break the first responder and resizes the table view smoothly.
For a detailed explanation, check out a post I wrote which also includes a working sample project.
回答6:
try this
set your UITextView outlet like this in your custom UITableViewCell class
[yourTextView setAutoresizesSubviews:YES]; yourTextView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
hope this will work for you