【问题标题】:View shifting up视图向上移动
【发布时间】:2018-08-20 03:37:56
【问题描述】:

我有一个ViewController,其中有一个ScrollViewScrollView 内有一个视图。视图由多个TextFields 组成。还有一个NavigationContoller。当我单击TextField 并再次单击屏幕时,键盘会消失,但视图会向上移动,并且一些文本字段会隐藏。请帮我解决这个问题

这是我的代码:

class EODViewController: UIViewController, UIScrollViewDelegate, UITextFieldDelegate {

@IBOutlet weak var views: UIView!
@IBOutlet weak var scrollView: UIScrollView!
@IBOutlet weak var inc50: UITextField!
@IBOutlet weak var out50: UITextField!
@IBOutlet weak var dec50: UITextField!

@IBOutlet weak var savebutton: UIButton!

var activeField: UITextField?
let button = UIButton(type: UIButtonType.custom)

override func viewDidLoad() {
    super.viewDidLoad()
    self.navigationItem.title = "Before EOD"

    //For Back button task
    self.navigationItem.hidesBackButton = true

    //to dismiss keyboard on click anywhere on screen
    let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(ViewController.dismissKeyboard))
    view.addGestureRecognizer(tap)

    // to get keyboard notifications
    registerForKeyboardNotifications()

    //textfield delegates
    self.inc50.delegate = self
    self.out50.delegate = self
    self.end50.delegate = self
    self.dec50.delegate = self

}


override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    self.view.endEditing(true)
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    let allowedCharacters = CharacterSet.decimalDigits
    let characterSet = CharacterSet(charactersIn: string)
    return allowedCharacters.isSuperset(of: characterSet)

}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {

    self.out50.resignFirstResponder()
    self.end50.resignFirstResponder()
    self.str50.resignFirstResponder()
    self.inc50.resignFirstResponder()
    self.dec50.resignFirstResponder()

    if textField == self.out50 {

        if self.out50.text?.isEmpty ?? true
        {
            self.out50.attributedPlaceholder = NSAttributedString(string: "Enter Value", attributes: [NSForegroundColorAttributeName : UIColor.red])
            return false
        }
        if end50.isUserInteractionEnabled == false
        {
            if checkValue(textvalue: out50, deno: 50, errorText: error50) == false
            {
                return false
            }
            if error50.text != "Enter multiple of 50"
            {
            editProcessBeforeoneOut(str: str50, inc: inc50, dec: dec50, out: out50, end: end50,terror: error50)
            self.out100.becomeFirstResponder()
            }
        }
        else{
        self.end50.becomeFirstResponder()
        if error50.isHidden == false
        {
        }
        }
    }
    if textField == self.str50
    {
        if self.str50.text?.isEmpty ?? true
        {
            self.str50.attributedPlaceholder = NSAttributedString(string: "Enter Value", attributes: [NSForegroundColorAttributeName : UIColor.red])
            return false
        }
       if checkValue(textvalue: str50, deno: 50, errorText: error50) == false
       {
        self.str50.becomeFirstResponder()
        return false
        }
        if error50.text != "Enter multiple of 50"
        {
            editProcessBeforeoneOut(str: str50, inc: inc50, dec: dec50, out: out50, end: end50,terror: error50)
        self.inc50.becomeFirstResponder()
        }
    }
    if textField == self.inc50
    {
        if self.inc50.text?.isEmpty ?? true
        {
            self.inc50.attributedPlaceholder = NSAttributedString(string: "Enter Value", attributes: [NSForegroundColorAttributeName : UIColor.red])
            return false
        }
        if checkValue(textvalue: str50, deno: 50, errorText: error50) == false
        {
            return false
        }
        if error50.text != "Enter multiple of 50"
        {
            editProcessBeforeoneOut(str: str50, inc: inc50, dec: dec50, out: out50, end: end50,terror: error50)
        self.dec50.becomeFirstResponder()
        }
    }


    return true
}

func validate() -> Bool
{
    var valid : Bool = true
    if self.str50.text?.isEmpty ?? true
    {
        str50.attributedPlaceholder = NSAttributedString(string: "Enter value", attributes: [NSForegroundColorAttributeName : UIColor.red])
        valid = false
    }

    return valid

}


func registerForKeyboardNotifications(){

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)

}

func deregisterFromKeyboardNotifications(){
    //Removing notifies on keyboard appearing
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

func keyboardWasShown(notification: NSNotification){
    //Need to calculate keyboard exact size due to Apple suggestions
    self.scrollView.isScrollEnabled = true
    var info = notification.userInfo!
    let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
    let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize!.height, 0.0)

    self.scrollView.contentInset = contentInsets
    self.scrollView.scrollIndicatorInsets = contentInsets

    var aRect : CGRect = self.view.frame
    aRect.size.height -= keyboardSize!.height
    if let activeField = self.activeField {
        if (!aRect.contains(activeField.frame.origin)){
           // self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
        }
    }
}

func keyboardWillBeHidden(notification: NSNotification){
    //Once keyboard disappears, restore original positions

    self.view.endEditing(true)
    self.scrollView.isScrollEnabled = true
}

func textFieldDidBeginEditing(_ textField: UITextField){
    activeField = textField
      NotificationCenter.default.addObserver(self, selector: #selector(EODViewController.keyboardWillShow(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
}

func textFieldDidEndEditing(_ textField: UITextField){
    activeField = nil
}

func dismissKeyboard() {
    view.endEditing(true)
}

func back(sender: UIBarButtonItem) {
    // Perform your custom actions
    // ...
    // Go back to the previous ViewController
    _ = navigationController?.popViewController(animated: true)


}

override func viewWillAppear(_ animated: Bool) {

    button.setTitle("Return", for: UIControlState())
    button.setTitleColor(UIColor.black, for: UIControlState())
    button.frame = CGRect(x: 0, y: 163, width: 106, height: 53)
    button.adjustsImageWhenHighlighted = false
    button.addTarget(self, action: #selector(ViewController.Done(_:)), for: UIControlEvents.touchUpInside)

}


func keyboardWillShow(_ note : Notification) -> Void{
    DispatchQueue.main.async { () -> Void in
        self.button.isHidden = false

        self.scrollView.isScrollEnabled = true

        var info = note.userInfo!
        let keyBoardWindow = UIApplication.shared.windows.last
        self.button.frame = CGRect(x: 0, y: (keyBoardWindow?.frame.size.height)!-53, width: 106, height: 53)
        keyBoardWindow?.addSubview(self.button)
        keyBoardWindow?.bringSubview(toFront: self.button)
         let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
        let contentInsets : UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize!.height, 0.0)

        self.scrollView.contentInset = contentInsets
        self.scrollView.scrollIndicatorInsets = contentInsets

        var aRect : CGRect = self.view.frame
        aRect.size.height -= keyboardSize!.height
        if let activeField = self.activeField {
            if (!aRect.contains(activeField.frame.origin)){
                self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
            }
        }


        UIView.animate(withDuration: (((note.userInfo! as NSDictionary).object(forKey: UIKeyboardAnimationCurveUserInfoKey) as AnyObject).doubleValue)!, delay: 0, options: UIViewAnimationOptions.curveEaseIn, animations: { () -> Void in
            self.view.frame = self.view.frame.offsetBy(dx: 0, dy: 0)
        }, completion: { (complete) -> Void in

        })

    }

}

func Done(_ sender : UIButton){

    DispatchQueue.main.async { () -> Void in

        self.textFieldShouldReturn(self.activeField!)
    }

}

}

【问题讨论】:

  • 提供一些截图
  • 向我们展示您的代码逻辑。
  • 把你的概念从ScrollView换成uitableview,很容易搞定
  • 显示你尝试过的代码
  • @Anbu.karthik 我添加了代码

标签: ios swift3 uiscrollview


【解决方案1】:

您应该在UIViewController 中尝试UITableViewUITableView 自动管理比UIScrollView 更好。您所有的文本字段都可以放在UIView 中,它设置为TableView 标题视图。

let headerView = UIView()
headerView.translatesAutoresizingMaskIntoConstraints = false
headerView.height(header_height)
tableView.tableHeaderView = UIView()
tableView.tableHeaderView?.frame.size.height = header_height
tableView.tableHeaderView?.addSubview(headerView)

// set autolayout for headerView to fill the tableView.tableHeaderView here

【讨论】:

  • 或者使用tableview的add subview
  • @Anbu.karthik 无法将子视图添加到 tableView。我们无法控制子视图。另一种解决方案是将每个文本字段添加到一个单元格中,静态 TableView 和单元格在 table:cellForRowAt 调用之前创建
  • 我现在不能使用TableView..所有的设计都准备好了,很难改变一切
  • @Priyanka 没有添加你的用户界面图像和核心逻辑,没有人可以帮助你。
【解决方案2】:

您可能想要使用UITableView 而不是UIScrollView。当UITableView 中有多个UITextFields 时,有一个非常稳定的库来处理键盘。查看TPKeyboardAvoiding。我一直在我的几个应用中使用它,效果非常好。

【讨论】:

    猜你喜欢
    • 2014-04-20
    • 2016-01-27
    • 2020-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-21
    • 1970-01-01
    相关资源
    最近更新 更多