Ios 当单元格';s元素';s帧更改

Ios 当单元格';s元素';s帧更改,ios,uitableview,swift2,uitextview,Ios,Uitableview,Swift2,Uitextview,我正在尝试添加查看更多功能,例如。在我的UITextView上,它位于tableView的单元格中,为此我使用这个类,它基本上是tableView的一个子类,带有一个按钮,可以将TextView扩展到所需的高度: @IBDesignable class ReadMoreTextView: UITextView { override init(frame: CGRect, textContainer: NSTextContainer?) { super.init(

我正在尝试添加
查看更多功能,例如。在我的
UITextView
上,它位于
tableView的
单元格
中,为此我使用这个类,它基本上是tableView的一个子类,带有一个按钮,可以将TextView扩展到所需的高度:

    @IBDesignable
class ReadMoreTextView: UITextView {

    override init(frame: CGRect, textContainer: NSTextContainer?) {
        super.init(frame: frame, textContainer: textContainer)
        scrollEnabled = false
        editable = false
    }



    convenience init(frame: CGRect) {
        self.init(frame: frame, textContainer: nil)
    }

    convenience init() {
        self.init(frame: CGRectZero, textContainer: nil)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        scrollEnabled = false
        editable = false
    }

    convenience init(maximumNumberOfLines: Int, trimText: NSString?, shouldTrim: Bool) {
        self.init()
        self.maximumNumberOfLines = maximumNumberOfLines
        self.trimText = trimText
        self.shouldTrim = shouldTrim
    }

    convenience init(maximumNumberOfLines: Int, attributedTrimText: NSAttributedString?, shouldTrim: Bool) {
        self.init()
        self.maximumNumberOfLines = maximumNumberOfLines
        self.attributedTrimText = attributedTrimText
        self.shouldTrim = shouldTrim
    }

    @IBInspectable
    var maximumNumberOfLines: Int = 0 {
        didSet { setNeedsLayout() }
    }



    @IBInspectable
    var trimText: NSString? {
        didSet { setNeedsLayout() }
    }

    var attributedTrimText: NSAttributedString? {
        didSet { setNeedsLayout() }
    }

    @IBInspectable
    var shouldTrim: Bool = false {
        didSet { setNeedsLayout() }
    }

    var trimTextRangePadding: UIEdgeInsets = UIEdgeInsetsZero
    var appendTrimTextPrefix: Bool = true
    var trimTextPrefix: String = "..."

    private var originalText: String!

    override var text: String! {
        didSet {
            originalText = text
            originalAttributedText = nil
            if needsTrim() { updateText() }
        }
    }

    private var originalAttributedText: NSAttributedString!

    override var attributedText: NSAttributedString! {
        didSet {
            originalAttributedText = attributedText
            originalText = nil
            if needsTrim() { updateText() }
        }
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        needsTrim() ? updateText() : resetText()

    }

    func needsTrim() -> Bool {
        return shouldTrim && _trimText != nil
    }

    func updateText() {
        textContainer.maximumNumberOfLines = maximumNumberOfLines
        textContainer.size = CGSizeMake(bounds.size.width, CGFloat.max)

        let range = rangeToReplaceWithTrimText()
        if range.location != NSNotFound {
            let prefix = appendTrimTextPrefix ? trimTextPrefix : ""

            if let text = trimText?.mutableCopy() as? NSMutableString {
                text.insertString("\(prefix) ", atIndex: 0)
                textStorage.replaceCharactersInRange(range, withString: text as String)
            }
            else if let text = attributedTrimText?.mutableCopy() as? NSMutableAttributedString {
                text.insertAttributedString(NSAttributedString(string: "\(prefix) "), atIndex: 0)
                textStorage.replaceCharactersInRange(range, withAttributedString: text)
            }
        }
        invalidateIntrinsicContentSize()


    }

    func resetText() {
        textContainer.maximumNumberOfLines = 0
        if originalText != nil {
            textStorage.replaceCharactersInRange(NSMakeRange(0, countElements(text!)), withString: originalText)

            print("Trim Pressed resetText")

        }
        else if originalAttributedText != nil {
            textStorage.replaceCharactersInRange(NSMakeRange(0, countElements(text!)), withAttributedString: originalAttributedText)
        }
        invalidateIntrinsicContentSize()

         // maybe this is what we're looking for



    }

    override func intrinsicContentSize() -> CGSize {
        textContainer.size = CGSizeMake(bounds.size.width, CGFloat.max)
        var intrinsicContentSize = layoutManager.boundingRectForGlyphRange(layoutManager.glyphRangeForTextContainer(textContainer), inTextContainer: textContainer).size
        intrinsicContentSize.width = UIViewNoIntrinsicMetric
        intrinsicContentSize.height += (textContainerInset.top + textContainerInset.bottom)
        return intrinsicContentSize


    }

    override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {

        if needsTrim() && pointInTrimTextRange(point) {
            shouldTrim = false
            maximumNumberOfLines = 0
        }

        return super.hitTest(point, withEvent: event)

    }

    //MARK: Private methods

    private var _trimText: NSString? {
        get {
            return trimText ?? attributedTrimText?.string
        }
    }

    private var _trimTextPrefixLength: Int {
        get {
            return appendTrimTextPrefix ? countElements(trimTextPrefix) + 1 : 1
        }
    }

    private var _originalTextLength: Int {
        get {
            if originalText != nil {
                return countElements(originalText!)
            }
            else  if originalAttributedText != nil {
                return originalAttributedText!.length
            }
            return 0
        }
    }

    private func rangeToReplaceWithTrimText() -> NSRange {
        let emptyRange = NSMakeRange(NSNotFound, 0)

        var rangeToReplace = layoutManager.characterRangeThatFits(textContainer)
        if NSMaxRange(rangeToReplace) == _originalTextLength {
            rangeToReplace = emptyRange
        }
        else {
            rangeToReplace.location = NSMaxRange(rangeToReplace) - _trimText!.length - _trimTextPrefixLength
            if rangeToReplace.location < 0 {
                rangeToReplace = emptyRange
            }
            else {
                rangeToReplace.length = textStorage.length - rangeToReplace.location
            }
        }
        return rangeToReplace
    }

    private func trimTextRange() -> NSRange {
        var trimTextRange = rangeToReplaceWithTrimText()
        if trimTextRange.location != NSNotFound {
            trimTextRange.length = _trimTextPrefixLength + _trimText!.length
        }
        return trimTextRange
    }

    private func pointInTrimTextRange(point: CGPoint) -> Bool {
        let offset = CGPointMake(textContainerInset.left, textContainerInset.top)
        var boundingRect = layoutManager.boundingRectForCharacterRange(trimTextRange(), inTextContainer: textContainer, textContainerOffset: offset)
        boundingRect = CGRectOffset(boundingRect, textContainerInset.left, textContainerInset.top)
        boundingRect = CGRectInset(boundingRect, -(trimTextRangePadding.left + trimTextRangePadding.right), -(trimTextRangePadding.top + trimTextRangePadding.bottom))
        return CGRectContainsPoint(boundingRect, point)
    }

    func countElements(text: String) -> Int {
        return text.characters.count
    }
}

//MARK: NSLayoutManager extension

extension NSLayoutManager {

    func characterRangeThatFits(textContainer: NSTextContainer) -> NSRange {
        var rangeThatFits = self.glyphRangeForTextContainer(textContainer)
        rangeThatFits = self.characterRangeForGlyphRange(rangeThatFits, actualGlyphRange: nil)
        return rangeThatFits
    }

    func boundingRectForCharacterRange(range: NSRange, inTextContainer textContainer: NSTextContainer, textContainerOffset: CGPoint) -> CGRect {
        let glyphRange = self.glyphRangeForCharacterRange(range, actualCharacterRange: nil)
        let boundingRect = self.boundingRectForGlyphRange(glyphRange, inTextContainer: textContainer)
        return boundingRect
    }

}
@IBDesignable
类ReadMoreTextView:UITextView{
重写init(frame:CGRect,textContainer:NSTextContainer?){
super.init(frame:frame,textContainer:textContainer)
scrollEnabled=false
可编辑=假
}
便利初始化(帧:CGRect){
self.init(frame:frame,textContainer:nil)
}
便利初始化(){
init(frame:CGRectZero,textContainer:nil)
}
必需的初始化?(编码器aDecoder:NSCoder){
super.init(编码者:aDecoder)
scrollEnabled=false
可编辑=假
}
便利初始化(maximumNumberOfLines:Int,trimText:NSString?,shouldTrim:Bool){
self.init()
self.maximumNumberOfLines=maximumNumberOfLines
self.trimText=trimText
self.shouldtim=shouldtim
}
便利初始化(maximumNumberOfLines:Int,attributedTrimText:NSAttributedString?,shouldTrim:Bool){
self.init()
self.maximumNumberOfLines=maximumNumberOfLines
self.attributedTrimText=attributedTrimText
self.shouldtim=shouldtim
}
@我看得见
var maximumNumberOfLines:Int=0{
didSet{setNeedsLayout()}
}
@我看得见
var-trimText:NSString{
didSet{setNeedsLayout()}
}
var attributedTrimText:NSAttributedString{
didSet{setNeedsLayout()}
}
@我看得见
变量shouldTrim:Bool=false{
didSet{setNeedsLayout()}
}
var trimTextRangePadding:UIEdgeInsets=UIEdgeInsetsZero
var appendTrimTextPrefix:Bool=true
var trimTextPrefix:String=“…”
private var originalText:字符串!
覆盖变量文本:字符串{
迪塞特{
原始文本=文本
originalAttributedText=nil
如果需要strim(){updateText()}
}
}
private var originalAttributedText:NSAttributedString!
重写var attributedText:NSAttributedString{
迪塞特{
originalAttributedText=attributedText
原始文本=零
如果需要strim(){updateText()}
}
}
覆盖func布局子视图(){
super.layoutSubviews()
needsTrim()?updateText():resetText()
}
func needsTrim()->Bool{
返回shouldTrim&&u trimText!=nil
}
func updateText(){
textContainer.maximumNumberOfLines=maximumNumberOfLines
textContainer.size=CGSizeMake(bounds.size.width,CGFloat.max)
let range=rangeToReplaceWithTrimText()
如果range.location!=NSNotFound{
let prefix=appendTrimTextPrefix?trimTextPrefix:“
如果let text=trimText?.mutableCopy()作为?NSMutableString{
text.insertString(“\(前缀)”,索引:0)
textStorage.ReplaceCharactersRange(范围,带字符串:文本作为字符串)
}
否则,如果让text=attributedTrimText?.mutableCopy()作为?NSMutableAttributedString{
text.insertAttributedString(NSAttributedString(字符串:\(前缀)”),索引:0)
textStorage.ReplaceCharactersRange(范围,withAttributedString:text)
}
}
InvalidateIntriseContentSize()无效
}
func resetText(){
textContainer.maximumNumberOfLines=0
如果原始文本!=无{
textStorage.replaceCharactersRange(NSMakeRange(0,countElements(text!)),带字符串:originalText)
打印(“修剪文本”)
}
如果originalAttributedText!=无,则为else{
textStorage.ReplaceCharactersRange(NSMakeRange(0,countElements(text!)),带AttributeString:originalAttributedText)
}
InvalidateIntriseContentSize()无效
//也许这就是我们要找的
}
重写func intrinsicContentSize()->CGSize{
textContainer.size=CGSizeMake(bounds.size.width,CGFloat.max)
var intrinsicContentSize=layoutManager.boundingrectformlyphrange(layoutManager.glyphRangeForTextContainer(textContainer),inTextContainer:textContainer).size
intrinsicContentSize.width=UIViewNoIntrinsicMetric
intrinsicContentSize.height+=(textContainerSet.top+textContainerSet.bottom)
返回intrinsicContentSize
}
覆盖func hitTest(点:CGPoint,withEvent事件:UIEvent?->UIView{
如果需要strim()&&pointInTrimTextRange(点){
shouldTrim=false
maximumNumberOfLines=0
}
返回super.hitTest(point,withEvent:event)
}
//标记:私有方法
私有变量trimText:NSString{
得到{
返回trimText??attributedTrimText?字符串
}
}
专用变量trimTextPrefixLength:Int{
得到{
返回appendTrimTextPrefix?countElements(trimTextPrefix)+1:1
}
}
private var_originalTextLength:Int{
得到{
如果原始文本!=无{
返回countElements(originalText!)
}
如果originalAttributedText!=无,则为else{
返回originalAttributedText!。长度
}
返回0
}
}
private func rangeToReplaceWithTrimText()->NSRange{
让emptyRange=NSMakeRange(NSNotFound,0)
var rangeToReplace=layoutManager.characterRangeThatFits(textContainer)
如果NSMaxRange(rangeToReplace)=\u originalTextLength{
rangeToReplace=emptyRange
}
否则{
rangeToReplace.location=NSMaxRange(rangeToReplace)-(U trimText!.length-\U trimTextPrefixLen
override func tableView(tableView: UITableView!, heightForRowAtIndexPath indexPath: NSIndexPath!) -> CGFloat {
     // an here use intrinsicContentSize
     return self.intrinsicContentSize().height
}
let eachRow = faqInfo.objectAtIndex(indexPath.row)
eachRow.setValue(53, forKey: "heightCell")
var currentHeght = eachRow["heightCell"] as! CGFloat
//25 default question height
eachRow.setValue(currentHeght + (newQuestionHeight - 25), forKey: "heightCell")

var currentHeght = eachRow["heightCell"] as! CGFloat
eachRow.setValue(currentHeght, forKey: "originalHeight")

let isExpanded = eachRow["isexpanded"] as! Bool
if isExpanded == true {
    increaseTextViewInCell(cell, eachRow: eachRow)
}
func increaseTextViewInCell(cell: FAQTableViewCellController, eachRow: AnyObject) {
        let answer = eachRow["answer"] as? String
        let newAnswerHeight = Utils.heightForView(answer!, font: UIFont(name: "AvenirNextCondensed-Regular", size: CGFloat(15))!, width: cell.textviewAnswer.frame.size.width, xpos: cell.textviewAnswer.frame.origin.x)

        //1 default question height
        let currentHeght = eachRow["heightCell"] as! CGFloat
        eachRow.setValue(currentHeght + (newAnswerHeight - 1) + 40, forKey: "heightCell")
        cell.textviewAnswer.text = answer
    }
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let cell = tableView.cellForRowAtIndexPath(indexPath) as! FAQTableViewCellController
    let eachRow = faqInfo.objectAtIndex(indexPath.row)

    let isExpanded = eachRow["isexpanded"] as! Bool
    if isExpanded == false {

        increaseTextViewInCell(cell, eachRow: eachRow)
        /* unncoment if need unexpand all the others cell
        var i = 0
        for eachInfo in faqInfo {
            let isExpanded = eachInfo["isexpanded"] as! Bool
            if isExpanded == true {
                eachInfo.setValue(0, forKey: "isexpanded")
                tableView.reloadRowsAtIndexPaths([NSIndexPath(forRow: i, inSection: 0)], withRowAnimation: .Fade)
                break
            }
            i += 1
        }
        */
        eachRow.setValue(1, forKey: "isexpanded")

    } else {
        let originalHeight = eachRow["originalHeight"] as! CGFloat
        eachRow.setValue(originalHeight, forKey: "heightCell")

        eachRow.setValue(0, forKey: "isexpanded")
    }

    tableView.beginUpdates()
    tableView.endUpdates()
}
class func heightForView(text:String, font:UIFont, width:CGFloat, xpos:CGFloat) -> CGFloat {
        let label:UILabel = UILabel(frame: CGRectMake(xpos, 0, width, CGFloat.max))
        label.numberOfLines = 0
        label.lineBreakMode = NSLineBreakMode.ByWordWrapping
        label.font = font
        label.text = text

        label.sizeToFit()
        return label.frame.height
    }