简体   繁体   English

如何快速更新y的文本输入位置,具体取决于键盘高度

[英]How do I update text input position of the y depending on keyboard height in swift

I'm trying to implement the comment view controller. 我正在尝试实现评论视图控制器。

I want using the auto layout via the storyboard. 我想通过情节提要使用自动布局。

My question is... 我的问题是

When I tap the input text..then keyboard will move up...but input text is not move up.. 当我点击输入文本..然后键盘将向上移动...但是输入文本没有向上移动..

在此处输入图片说明

在此处输入图片说明

在此处输入图片说明

在此处输入图片说明

Keyboard is overlapping the text input.. 键盘与文本输入重叠。

Here is TableViewController.swift 这是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()
    }
}


}

And It is my cell 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

}
}

Two comments: 两条评论:

  1. Use UIKeyboardDidShowNotification instead of UIKeyboardWillShowNotification 使用UIKeyboardDidShowNotification代替UIKeyboardWillShowNotification
  2. Do not modify frame directly when you're using auto layout. 使用自动布局时,请勿直接修改frame Just link your bottom layout constraint to the controller and change a constant value when needed. 只需将底部布局约束链接到控制器,并在需要时更改一个恒定值。

Try this: 尝试这个:

    self.tableView.frame.size.height = self.view.frame.height - keyboard.height - self.tableView.frame.size.height

    print("keyboard show")

    self.commentTextView.frame = CGRect(self.commentTextView.frame.minX, self.commentTextView.frame.minY - keyboard.height, self.commentTextView.frame.width, self.commentTextView.frame.height)

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

Edit 编辑

@Arsen's Answer makes much more sense and probably much easier, by the way :P But this should work the same. 顺便说一句,@ Arsen的答案更有意义,也可能更容易:P但这应该是一样的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Swift:如何在UILabel中找到字母的位置(x,y)? - Swift : How do I find the position(x,y) of a letter in a UILabel? 如何使 Swift 中的图像与旁边的文本高度相同? - How do I make an Image in Swift the same height as the text next to it? 更改UIView高度和子视图y位置[快速] - Change UIView height and subviews y position [Swift] 如何在Swift 3中偏移文本视图等于键盘的高度? - how to offset text view equals height of the keyboard in swift 3? iOS Swift uistackview更新孩子的身高和x,y框架位置值 - ios swift uistackview update children height and x, y frame position values 如何在响应式布局中将按钮放置在没有固定高度和位置的区域中:绝对? (UPDATE) - How do I position a button in a responsive layout, in an area that has no fixed height and position:absolute? (UPDATE) 在Swift中,如何获取UILabel的文本基线的y位置? - In Swift, how to get the y position of a text baseline of a UILabel? 为什么它要求我提供 Y 位置或高度? 我该如何解决? - Why is it asking me for a Y position or a height? How can I fix it? 如何使用Storyboard或Xib将iOS自定义键盘扩展用作Swift中的可编程自定义输入视图 - How do I use a iOS custom keyboard extension as a programmable custom input view in Swift using storyboards or xibs 如何在Swift中移动对象的位置? - How do I move a position of an object in Swift?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM