textView Swift 的动态单元格高度

Posted

技术标签:

【中文标题】textView Swift 的动态单元格高度【英文标题】:Dynamic cell height for textView Swift 【发布时间】:2017-04-13 17:59:35 【问题描述】:

我之前使用过一个标签,它工作正常。但我刚刚意识到我需要一个 UITextView 而我似乎无法让它正常工作。

文字一直向右移动,我再也看不到它了。我需要它来调整单元格的动态高度,就像之前使用标签一样。

struct postStruct 
    let username : String!
    let message : String!
    let photoURL : String!
    let timeStamp: String!
    let cellUserId : String!




class GeneralChatroom: UIViewController, UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate 

    @IBOutlet weak var messageTextField: UITextField!
    @IBOutlet weak var tableView: UITableView!

    var generalRoomDataArr = [postStruct]()



    override func viewDidLoad() 
        super.viewDidLoad()



        //Key Board - self delegate for return key
        messageTextField.delegate = self

        //TableView Cell word wrap (Dynamic Text)
        self.tableView.dataSource = self
        self.tableView.delegate = self
        self.tableView.estimatedRowHeight = 78
        self.tableView.rowHeight = UITableViewAutomaticDimension

        //Liquid Loader
        let growColor = UIColor.red
        let lineMatColor = UIColor(red: 11 / 255.0, green: 211 / 255.0, blue: 138 / 255.0, alpha: 1.0)
        let lineMatFrame = CGRect(x: self.view.frame.width * 0.5 - 25, y: 500, width: 50, height: 50)
        let lineMat = LiquidLoader(frame: lineMatFrame, effect: .Line(lineMatColor,4,1.0, growColor))

        //Placement of liquid Loader
        let screenSize = UIScreen.main.bounds
        let screenWidth = screenSize.width
       // let screenHeight = screenSize.height
        lineMat.frame = CGRect(x:screenWidth - 55 , y: 20, width:20 , height: 20)
        view.addSubview(lineMat)


        //Start Here


        let ref = FIRDatabase.database().reference()
        //let userID = FIRAuth.auth()?.currentUser?.uid







        ref.child("general_room").queryOrderedByKey().observe(.childAdded, with: snapshot in

            let snapDict = snapshot.value as? NSDictionary
            let message = snapDict?["Message"] as? String ?? ""
            let username = snapDict?["user_name"] as? String ?? ""
            let userIDString = snapDict?["uid"] as? String ?? ""
            let firebaseUserPhotoURL = snapDict?["photo_url"] as? String ?? ""






//            print("username: " + username)
//            print("message: " + message)
//            print("URL: " + firebaseUserPhotoURL)
//            print("Snapshot" + snapshot.key)

            //Time String from Firbase Database
            let timeString = snapDict?["time_stamp"] as? String ?? "2017-03-06 00:20:51"

            //timeAgoSinceDate - Format and call function to recieve time of post
            let dateFormatter = DateFormatter()
            dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
            let timeStampDate = dateFormatter.date(from: timeString)
            let timeStamp = timeAgoSinceDate(date: timeStampDate!, numericDates: false)


            //Assign array values
            self.generalRoomDataArr.insert(postStruct(username: username, message: message, photoURL: firebaseUserPhotoURL, timeStamp: timeStamp, cellUserId: userIDString), at: 0)
            self.tableView.reloadData()


        )


        //End Here


        self.tableView.reloadData()



    //End ViewDidLoad





    //MARK:                      Buttons (BackButton || Send Button)


    @IBAction func backButtonPressed(_ sender: UIButton) 
        self.performSegue(withIdentifier: "BackToRoom", sender: nil)
    


    //Message Send button is pressed data uploaded to firebase
    @IBAction func sendButtonPressed(_ sender: UIButton) 

        //If a character exists will be uploaded to firebase
        if ((messageTextField.text?.characters.count)! > 0) 

        let message : String = self.messageTextField.text!
        UploadGeneralChatRoom(message: message) //upload to general_room
        self.messageTextField.text = nil
        messageTextField.resignFirstResponder()//Quit keyboard

        self.tableView.reloadData() //Reload tableView
        //UploadUserData() //Update Rank in database

        


    




    //MARK:                     TableView (Cell & Labels)



    //Get Data of current cell that has been tapped
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 

        let userIdentityString = generalRoomDataArr[indexPath.row].cellUserId

        print("Uid of cell Data: " + userIdentityString!)
        print("section: \(indexPath.section)")
        print("row: \(indexPath.row)")

        //1.) If imageView touch is deteected
        //2.) Segua to new view controller by passing in the string UID(userIdentityString) of the cell
        //3.) Get database information based on the UID that is added(look at prevous methods)
        //      -might have to call this function and use separeate function
        //4.) Output data from database Users to represent a user profile



        //All you have to do is pass a UID (Check other Database methods to send UID)

    


    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return generalRoomDataArr.count // your number of cell here
    




    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 


        let cell = tableView.dequeueReusableCell(withIdentifier: "cell")

        //Transform Data From ^ to load at the bottom
        tableView.transform = CGAffineTransform (scaleX: 1,y: -1);
        cell?.contentView.transform = CGAffineTransform (scaleX: 1,y: -1);
        cell?.accessoryView?.transform = CGAffineTransform (scaleX: 1,y: -1);

        //Set username label to display username
        let usernameLabel = cell?.viewWithTag(1) as! UILabel
        usernameLabel.text = generalRoomDataArr[indexPath.row].username


        //Set message label to display message
//        let messageLabel = cell?.viewWithTag(2) as! UILabel
//        messageLabel.text = generalRoomDataArr[indexPath.row].message
//        messageLabel.numberOfLines = 0

        let messageLabel = cell?.viewWithTag(5) as! UITextView
        messageLabel.text = generalRoomDataArr[indexPath.row].message



        //initialize UI Profile Image
        let imageView = cell?.viewWithTag(3) as! UIImageView

        //Make Porfile Image Cirlce
        imageView.layer.cornerRadius = imageView.frame.size.width/2
        imageView.clipsToBounds = true

        //Set timeStampLabel to current time AGO
        let timeStampLabel = cell?.viewWithTag(4) as! UILabel
        timeStampLabel.text = generalRoomDataArr[indexPath.row].timeStamp
        timeStampLabel.numberOfLines = 0


        //Loading and change of Usesrs profile image on chat cell
        let userProfileChatImage = generalRoomDataArr[indexPath.row].photoURL

        //Load profile image(on cell) with URL & Alamofire Library
            let downloadURL = NSURL(string: userProfileChatImage!)
            imageView.af_setImage(withURL: downloadURL as! URL)

        return cell!
    




    //MARK:              KeyBoard close on return button


    // Hide the keyboard when the return key pressed
    func textFieldShouldReturn(_ messageTextField: UITextField) -> Bool 
        messageTextField.resignFirstResponder()
        return true
    




//END CLASS

【问题讨论】:

能否在故事板中显示单元格布局 刚刚添加到帖子中 您是否正确设置了约束?我有一个例子并且工作得很好,唯一需要的调整是禁用可滚动行为,所以我认为你的左右约束可能是错误的,请告诉我 【参考方案1】:

设置 textView 的高度并将其作为 NSLayoutConstraints 连接到视图控制器并通过 textViewDidChange 进行更新。

查看下面的代码,其中 textViewHeight 是 NSLayoutConstraints

func textViewDidChange(_ textView: UITextView) 

    let fixedWidth = textView.frame.size.width
    textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
    let newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
    var newFrame = textView.frame
    newFrame.size = CGSize(width: max(newSize.width, fixedWidth), height: newSize.height)
    textView.frame = newFrame;
    textViewHeight.constant = newFrame.size.height
    tableView.beginUpdates()
    tableView.endUpdates()

【讨论】:

此解决方案不起作用:1)您无权从单元格访问tableView; 2)即使你通过自定义委托方法调用tableView.beginUpdates() + tableView.endUpdates(),它仍然不起作用【参考方案2】:

您是否尝试从 textView 委托方法更改大小?也许是这样的:

func textViewDidChange(_ textView: UITextView) 
    let currentOffset = tableView.contentOffset
    UIView.setAnimationsEnabled(false)
    tableView.beginUpdates()
    tableView.endUpdates()
    UIView.setAnimationsEnabled(true)
    tableView.setContentOffset(currentOffset, animated: false)

当用户在文本视图中键入内容时,我使用此代码来调整单元格的高度。不确定它是否适合您的目的,但请试一试。

【讨论】:

textViewHeight.constant = newFrame.size.height? @Ayush sharma

以上是关于textView Swift 的动态单元格高度的主要内容,如果未能解决你的问题,请参考以下文章

ios swift在textView单元格中显示/隐藏元素并清除其空间

如何在swift ios中调整集合视图单元格的高度?

UITextView 和单元格根据 textview 的内容动态更新高度?

UITableView 单元格的动态高度问题(Swift)

Swift动态表格单元格高度[重复]

如何在 Swift 中动态更改包含 UICollectionView 单元格的 UITableView 单元格的高度?