ios - 如何根据键盘高度快速更新 y 的文本输入位置

标签 ios swift uitableview uikeyboard ios-autolayout

我正在尝试实现评论 View Controller 。

我想通过 Storyboard使用自动布局。

我的问题是...

当我点击输入文本时..然后键盘将向上移动...但输入文本不会向上移动..

enter image description here

enter image description here

enter image description here

enter image description here

键盘与文本输入重叠..

这里是 TableViewController.swift

import UIKit
import Parse

var commentUUID = [String]()
var commentOwner = [String]()

class CommentViewController: UIViewController, UITextViewDelegate, UITableViewDelegate, UITableViewDataSource{

//UI Objects
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var commentTextView: UITextView!
@IBOutlet weak var sendButton: UIButton!
var refresher = UIRefreshControl()

//values for reseting UI to default
var tableViewHeight : CGFloat = 0
var commentY : CGFloat = 0
var commentHeight : CGFloat = 0

//arryas to hold server data
var usernameArray = [String]()
var profileArray = [PFFile]()
var commentArray = [String]()
var dateArray = [NSDate?]()


//variable to hold keyboard frame
var keyboard = CGRect()

//page size
var page : Int32 = 15

override func viewDidLoad() {

    super.viewDidLoad()

    tableView.backgroundColor = .redColor()

    //title at the top
    self.navigationItem.title = "COMMENTS"
    self.navigationItem.hidesBackButton = true
    let backButton = UIBarButtonItem(title: "back", style: .Plain, target: self, action: #selector(CommentViewController.back(_:)))
    self.navigationItem.leftBarButtonItem=backButton


    //swipe to go back
    let backSwipe = UISwipeGestureRecognizer(target: self, action: #selector(CommentViewController.back(_:)))
    backSwipe.direction=UISwipeGestureRecognizerDirection.Right
    self.view.addGestureRecognizer(backSwipe)

    // catch notification if the keyboard is shown or hidden
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(CommentViewController.keyboardWillShow(_:)), name: UIKeyboardWillShowNotification, object: nil)

    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(CommentViewController.keyboardWillHide(_:)), name: UIKeyboardWillHideNotification, object: nil)


    //disable button from the beginning
    sendButton.enabled = false


    //call function
    alignment()

    loadComments()

}

//I think it is not affect on the layout...
func configureTableView() {
    tableView.rowHeight = UITableViewAutomaticDimension
    tableView.estimatedRowHeight = 160.0
}

// preload func
override func viewWillAppear(animated: Bool) {

    //hide bottom bar
    self.tabBarController?.tabBar.hidden = true


}

// postload func
override func viewWillDisappear(animated: Bool) {
    self.tabBarController?.tabBar.hidden = false

}

//func loading when keyboard is shown
func keyboardWillShow(notification : NSNotification){

    //define keyboard frame size
    keyboard = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey]!.CGRectValue)!

    //move UI up
    UIView.animateWithDuration(0.4){ () -> Void in


         self.tableView.frame.size.height = self.tableViewHeight - self.keyboard.height - self.commentTextView.frame.size.height + self.commentHeight

        print("keyboard show")

        self.commentTextView.frame.origin.y = self.commentY - self.keyboard.height - self.commentTextView.frame.size.height + self.commentHeight

        self.sendButton.frame.origin.y = self.commentTextView.frame.origin.y

        self.commentTextView.frame.origin.y = 250

    }
}

//func loading when keyboard is hidden
func keyboardWillHide(notification : NSNotification){

    //move UI down
    UIView.animateWithDuration(0.4){() -> Void in

        self.tableView.frame.size.height = self.tableViewHeight
        self.commentTextView.frame.origin.y = self.commentY
        self.sendButton.frame.origin.y = self.commentY


    }

}

//alignment function
func alignment(){


    let width = self.view.frame.size.width
    let height = self.view.frame.size.height


    tableView.frame = CGRectMake(0, 0, width, height - self.navigationController!.navigationBar.frame.size.height)


    tableView.rowHeight = UITableViewAutomaticDimension
    tableView.estimatedRowHeight = 160.0

    commentTextView.layer.cornerRadius = commentTextView.frame.size.width / 50

    //delegates
    commentTextView.delegate = self
    tableView.delegate = self
    tableView.dataSource = self


    //assign reseting values
    tableViewHeight = tableView.frame.size.height
    commentHeight = commentTextView.frame.size.height
    commentY = commentTextView.frame.origin.y

}



//while writing something
func textViewDidChange(textView: UITextView) {

    //disable button if entered no text
    let spacing = NSCharacterSet.whitespaceAndNewlineCharacterSet()

    //It shown when user entered type
    if !commentTextView.text.stringByTrimmingCharactersInSet(spacing).isEmpty{
        sendButton.enabled = true
    }else {

        sendButton.enabled = false
    }


    // + paragraph

    if textView.contentSize.height > textView.frame.size.height && textView.frame.height < 130{

        //find difference to add
        let difference = textView.contentSize.height - textView.frame.size.height

        //redefine frame of commentText
        textView.frame.origin.y = textView.frame.origin.y - difference
        textView.frame.size.height = textView.contentSize.height

        //move up tableView
        if textView.contentSize.height + keyboard.height + commentY >= tableView.frame.size.height {
            tableView.frame.size.height = tableView.frame.size.height - difference


        }

    }

    // - parapraph

    else if textView.contentSize.height < textView.frame.size.height {

        //find difference to deduct
        let difference = textView.frame.size.height - textView.contentSize.height

        //redefine frame of commentText
        textView.frame.origin.y = textView.frame.origin.y + difference
        textView.frame.size.height = textView.contentSize.height

        //move down tableview
        if textView.contentSize.height + keyboard.height + commentY > tableView.frame.size.height {

            tableView.frame.size.height = tableView.frame.size.height + difference
        }

    }


}

//load comments function
func loadComments(){

    //STEP 1. Count total comments in order to skip all except page size
    let countQuery = PFQuery(className: "comments")
    countQuery.whereKey("to", equalTo: commentUUID.last!)
    countQuery.countObjectsInBackgroundWithBlock({(count:Int32, error:NSError?) -> Void in

        //if comments on the server for current post are more than (page size 15) implement pull to refresh func
        if self.page < count {
            self.refresher.addTarget(self, action: #selector(CommentViewController.loadMore), forControlEvents: UIControlEvents.ValueChanged)
            self.tableView.addSubview(self.refresher)

        }

        //STEP 2. Request last (page size 15) comments
        let query = PFQuery(className: "comments")
        query.whereKey("to", equalTo: commentUUID.last!)
        query.skip = count - self.page
        query.addAscendingOrder("createdAt")
        query.findObjectsInBackgroundWithBlock({(objects:[PFObject]?, error:NSError?) -> Void in

            if error == nil {
                //clean up
                self.usernameArray.removeAll(keepCapacity: false)
                self.profileArray.removeAll(keepCapacity: false)
                self.commentArray.removeAll(keepCapacity: false)
                self.dateArray.removeAll(keepCapacity: false)

                //find related object
                for object in objects!{

                    self.usernameArray.append(object.objectForKey("username") as! String)
                    self.profileArray.append(object.objectForKey("profileImg") as! PFFile)
                    self.commentArray.append(object.objectForKey("comment") as! String)
                    self.dateArray.append(object.createdAt)
                    self.tableView.reloadData()

                    //scroll to bottom
                    self.tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: self.commentArray.count - 1, inSection: 0), atScrollPosition: UITableViewScrollPosition.Bottom, animated: false)

                }
            }else {
                print(error?.localizedDescription)
            }
        })
    })

}

//Pagenation
func loadMore(){

    //STEP 1. Count total comments in order to skip all except page size
   let countQuery = PFQuery(className: "comments")
    countQuery.whereKey("to", equalTo: commentUUID.last!)
    countQuery.countObjectsInBackgroundWithBlock({(count:Int32, error:NSError?) -> Void in

        //self refresher
        self.refresher.endRefreshing()

        //remove refresher if loaded all comments
        if self.page >= count {

            self.refresher.removeFromSuperview()
        }

        //STEP2. Load more comments
        if self.page < count {

            //increase page to laod 30 as first paging
            self.page = self.page + 15

            //request existing comments from the server
            let query = PFQuery(className: "comments")
            query.whereKey("to", equalTo: commentUUID.last!)
            query.skip = count - self.page
            query.addAscendingOrder("createdAt")
            query.findObjectsInBackgroundWithBlock({(objects:[PFObject]?, error:NSError?) -> Void in

                if error==nil{

                    //clean up
                    self.usernameArray.removeAll(keepCapacity: false)
                    self.profileArray.removeAll(keepCapacity: false)
                    self.commentArray.removeAll(keepCapacity: false)
                    self.dateArray.removeAll(keepCapacity: false)

                    //find related objects
                    for object in objects! {

                        self.usernameArray.append(object.objectForKey("username") as! String)
                        self.profileArray.append(object.objectForKey("profileImg") as! PFFile)
                        self.commentArray.append(object.objectForKey("comments") as! String)
                        self.dateArray.append(object.createdAt)
                        self.tableView.reloadData()


                    }

                }else {
                    print(error?.localizedDescription)

                }

            })

        }


    })

}
//Send Button Tapped
@IBAction func sendButtonTapped(sender: AnyObject) {

    print("send tapped")
    //STEP1. Add row in tableView
    usernameArray.append(PFUser.currentUser()!.username!)
    profileArray.append(PFUser.currentUser()?.objectForKey("profileImg") as! PFFile)
    dateArray.append(NSDate())
    commentArray.append(commentTextView.text.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()))
    tableView.reloadData()

    //STEP2. Send comment to server
    let commentObj = PFObject(className: "comments")
    commentObj["to"] = commentUUID.last
    commentObj["username"] = PFUser.currentUser()?.username
    commentObj["profileImg"] = PFUser.currentUser()?.valueForKey("profileImg")
    commentObj["comment"] = commentTextView.text.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
    commentObj.saveEventually()

    //Scroll to bottom
    self.tableView.scrollToRowAtIndexPath(NSIndexPath(forItem: commentArray.count - 1, inSection: 0), atScrollPosition: UITableViewScrollPosition.Bottom, animated: false)

    //STEP 3. Reset UI
    sendButton.enabled = false
    commentTextView.text = ""
    commentTextView.frame.size.height = commentHeight
    commentTextView.frame.origin.y = sendButton.frame.origin.y
    tableView.frame.size.height = self.tableViewHeight - self.keyboard.height - self.commentTextView.frame.size.height + self.commentHeight

}



//tableview
//cell numb
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return commentArray.count
}

//cell height
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

//Cell config
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    //declaire cell

    let cell = tableView.dequeueReusableCellWithIdentifier("commentCell") as! CommentTableViewCell

    cell.usernameButton.setTitle(usernameArray[indexPath.row], forState: .Normal)
    cell.usernameButton.sizeToFit()

    cell.commentLabel.text = commentArray[indexPath.row]
    profileArray[indexPath.row].getDataInBackgroundWithBlock({(data:NSData?, error:NSError?) -> Void in
        cell.profileImagevView.image = UIImage(data: data!)

    })

    //calculate date
    let from = dateArray[indexPath.row]
    let now = NSDate()
    let components : NSCalendarUnit = [.Second, .Minute, .Hour, .Day, .WeekOfMonth]
    let difference = NSCalendar.currentCalendar().components(components, fromDate: from!, toDate: now, options: [])

    if difference.second <= 0 {
        cell.dateLabel.text = "now"

    }
    if difference.second > 0 && difference.minute == 0 {
        cell.dateLabel.text = "\(difference.second)s"
    }

    if difference.minute > 0 && difference.hour == 0 {

        cell.dateLabel.text = "\(difference.minute)m"
    }

    if difference.hour > 0 && difference.day == 0 {

        cell.dateLabel.text = "\(difference.hour)h"
    }

    if difference.day > 0 && difference.weekOfMonth == 0 {

        cell.dateLabel.text = "\(difference.day)d."
    }

    if difference.weekOfMonth > 0 {

        cell.dateLabel.text = "\(difference.weekOfMonth)w."
    }

    cell.usernameButton.layer.setValue(indexPath, forKey: "index")

    return cell
}


//clicked username button
@IBAction func usernameButtonTapped(sender: AnyObject) {


    //call index of current button
    let i = sender.layer.valueForKey("index") as! NSIndexPath

    //Call cell to call further cell data
    let cell = tableView.cellForRowAtIndexPath(i) as! CommentTableViewCell


    //if user tapped on his username go home, else go guest
    if cell.usernameButton.titleLabel?.text == PFUser.currentUser()?.username {

            let home = self.storyboard?.instantiateViewControllerWithIdentifier("HomeViewController") as! HomeViewController
            self.navigationController?.pushViewController(home, animated: true)

    }else {

        guestname.append(cell.usernameButton.titleLabel!.text!)
        let guest = self.storyboard?.instantiateViewControllerWithIdentifier("GuestHomeViewController") as! GuestHomeViewController

        self.navigationController?.pushViewController(guest, animated: true)

    }

}

//go back
func back(sender : UIBarButtonItem){
    //push back
    self.navigationController?.popViewControllerAnimated(true)

    //clean comment uuid from holding information
    if !commentUUID.isEmpty{

        commentUUID.removeLast()
    }

    //clean comment owner from last holding information
    if !commentOwner.isEmpty{

        commentOwner.removeLast()
    }
}


}

这是我的细胞 Controller

import UIKit

class CommentTableViewCell: UITableViewCell {

@IBOutlet weak var profileImagevView: UIImageView!
@IBOutlet weak var usernameButton: UIButton!
@IBOutlet weak var commentLabel: UILabel!
@IBOutlet weak var dateLabel: UILabel!


//default func
override func awakeFromNib() {
    super.awakeFromNib()


    //round profile
    profileImagevView.layer.cornerRadius = profileImagevView.frame.size.width/2
    profileImagevView.clipsToBounds = true

}
}

最佳答案

两条评论:

  1. 使用 UIKeyboardDidShowNotification 而不是 UIKeyboardWillShowNotification
  2. 在使用自动布局时不要直接修改frame。只需将底部布局约束链接到 Controller ,并在需要时更改常量值即可。

关于ios - 如何根据键盘高度快速更新 y 的文本输入位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38035903/

相关文章:

iphone - 子类化 UIWindow

iphone - 在 iOS 上从横向 View 切换到纵向 View

ios - 无效更新 : Invalid Number of Row in Section 0

ios - 如何在 UITable 中获取 UIButton 或 UILabel 的位置?

uitableview - tableView backgroundView 在 iOS7 中不起作用

ios - 我要求的 Swift : Tableview numberOfRowsInSection didn't return the indexpath. 行

ios - 如何访问所有 NSLog 语句?

html - 使用 Fuzi 使用 swift 从特定标签中抓取文本

ios - 当旋转或放大/缩小 map 时,自定义 MKAnnotationView 位置会发生巨大变化

ios - 如何在没有多部分的情况下获取文件上传进度?