fré*_*sie 102 iphone cocoa-touch objective-c scrollview ios
我的代码遇到了问题.我正在尝试移动UIScrollView当我正在编辑时UITextField应该被键盘弹出隐藏.
我现在正在移动主框架,因为我不知道如何在代码中"向上滚动".所以,我做了一些代码,它工作正常但是当我编辑一个UItextfield并且我切换到另一个UITextField而没有按下"返回"按钮时,主视图变得非常了不起.
我NSLog()用变量大小,距离和textFieldRect.origin.y 做了一个,如下所示.当我把两个UITextField放在同一个地方(y原点)并且我做这个特别的'开关'(没有按回车)时,我得到相同的数字,而我的代码在第一次UITextField编辑时工作正常但不适用于第二次编辑.
看一下这个:
- (void)textFieldDidBeginEditing:(UITextField *)textField {
{
int size;
CGRect textFieldRect = [self.view.window convertRect:textField.bounds fromView:textField];
size = textFieldRect.origin.y + textFieldRect.size.height;
if (change == FALSE)
{
size = size - distance;
}
if (size < PORTRAIT_KEYBOARD_HEIGHT)
{
distance = 0;
}
else if (size > PORTRAIT_KEYBOARD_HEIGHT)
{
distance = size - PORTRAIT_KEYBOARD_HEIGHT + 5; // +5 px for more visibility
}
NSLog(@"origin %f", textFieldRect.origin.y);
NSLog(@"size %d", size);
NSLog(@"distance %d", distance);
CGRect viewFrame = self.view.frame;
viewFrame.origin.y -= distance;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
[self.view setFrame:viewFrame];
[UIView commitAnimations];
change = FALSE;
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
change = TRUE;
CGRect viewFrame = self.view.frame;
viewFrame.origin.y += distance;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
[self.view setFrame:viewFrame];
[UIView commitAnimations];
}
Run Code Online (Sandbox Code Playgroud)
有任何想法吗 ?
Mas*_*asa 197
从苹果公司推荐的方法是改变contentInset的UIScrollView.这是一个非常优雅的解决方案,因为你不必乱用contentSize.以下代码是从" 键盘编程指南"中复制的,其中解释了此问题的处理.你应该看看它.
// Call this method somewhere in your view controller setup code.
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
}
// Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWasShown:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
// If active text field is hidden by keyboard, scroll it so it's visible
// Your application might not need or want this behavior.
CGRect aRect = self.view.frame;
aRect.size.height -= kbSize.height;
if (!CGRectContainsPoint(aRect, activeField.frame.origin) ) {
CGPoint scrollPoint = CGPointMake(0.0, activeField.frame.origin.y-kbSize.height);
[scrollView setContentOffset:scrollPoint animated:YES];
}
}
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
}
Run Code Online (Sandbox Code Playgroud)
Swift版本:
func registerForKeyboardNotifications() {
NotificationCenter.default.addObserver(self, selector: #selector(onKeyboardAppear(_:)), name: NSNotification.Name.UIKeyboardDidShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(onKeyboardDisappear(_:)), name: NSNotification.Name.UIKeyboardDidHide, object: nil)
}
// Don't forget to unregister when done
deinit {
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardDidShow, object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardDidHide, object: nil)
}
@objc func onKeyboardAppear(_ notification: NSNotification) {
let info = notification.userInfo!
let rect: CGRect = info[UIKeyboardFrameBeginUserInfoKey] as! CGRect
let kbSize = rect.size
let insets = UIEdgeInsetsMake(0, 0, kbSize.height, 0)
scrollView.contentInset = insets
scrollView.scrollIndicatorInsets = insets
// If active text field is hidden by keyboard, scroll it so it's visible
// Your application might not need or want this behavior.
var aRect = self.view.frame;
aRect.size.height -= kbSize.height;
let activeField: UITextField? = [addressTextView, servicePathTextView, usernameTextView, passwordTextView].first { $0.isFirstResponder }
if let activeField = activeField {
if aRect.contains(activeField.frame.origin) {
let scrollPoint = CGPoint(x: 0, y: activeField.frame.origin.y-kbSize.height)
scrollView.setContentOffset(scrollPoint, animated: true)
}
}
}
@objc func onKeyboardDisappear(_ notification: NSNotification) {
scrollView.contentInset = UIEdgeInsets.zero
scrollView.scrollIndicatorInsets = UIEdgeInsets.zero
}
Run Code Online (Sandbox Code Playgroud)
Joh*_*nes 63
我刚刚在Xcode 7(beta 6)上使用Swift 2.0 for iOS9实现了这个,在这里运行正常.
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
registerKeyboardNotifications()
}
func registerKeyboardNotifications() {
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)
}
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
func keyboardWillShow(notification: NSNotification) {
let userInfo: NSDictionary = notification.userInfo!
let keyboardSize = userInfo.objectForKey(UIKeyboardFrameBeginUserInfoKey)!.CGRectValue.size
let contentInsets = UIEdgeInsetsMake(0, 0, keyboardSize.height, 0)
scrollView.contentInset = contentInsets
scrollView.scrollIndicatorInsets = contentInsets
var viewRect = view.frame
viewRect.size.height -= keyboardSize.height
if CGRectContainsPoint(viewRect, textField.frame.origin) {
let scrollPoint = CGPointMake(0, textField.frame.origin.y - keyboardSize.height)
scrollView.setContentOffset(scrollPoint, animated: true)
}
}
func keyboardWillHide(notification: NSNotification) {
scrollView.contentInset = UIEdgeInsetsZero
scrollView.scrollIndicatorInsets = UIEdgeInsetsZero
}
Run Code Online (Sandbox Code Playgroud)
编辑为Swift 3
好像你只需要设置contentInset和scrollIndicatorInset使用Swift 3,滚动/ contentOffset自动完成.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
registerKeyboardNotifications()
}
func registerKeyboardNotifications() {
NotificationCenter.default.addObserver(self,
selector: #selector(keyboardWillShow(notification:)),
name: NSNotification.Name.UIKeyboardWillShow,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(keyboardWillHide(notification:)),
name: NSNotification.Name.UIKeyboardWillHide,
object: nil)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
func keyboardWillShow(notification: NSNotification) {
let userInfo: NSDictionary = notification.userInfo! as NSDictionary
let keyboardInfo = userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue
let keyboardSize = keyboardInfo.cgRectValue.size
let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)
scrollView.contentInset = contentInsets
scrollView.scrollIndicatorInsets = contentInsets
}
func keyboardWillHide(notification: NSNotification) {
scrollView.contentInset = .zero
scrollView.scrollIndicatorInsets = .zero
}
Run Code Online (Sandbox Code Playgroud)
Rob*_*Rob 15
这里的所有答案似乎都忘记了景观的可能性.如果您希望在将设备旋转到横向视图时工作,那么您将面临问题.
这里的诀窍是虽然视图知道方向,但键盘不是.这意味着在Landscape中,键盘宽度实际上是它的高度,反之亦然.
要修改Apples推荐的更改内容插入的方法并使其支持横向,我建议使用以下内容:
// Call this method somewhere in your view controller setup code.
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
}
// Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWasShown:(NSNotification*)aNotification
{
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
CGSize keyboardSize = [[[notif userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
if (orientation == UIDeviceOrientationLandscapeLeft || orientation == UIDeviceOrientationLandscapeRight ) {
CGSize origKeySize = keyboardSize;
keyboardSize.height = origKeySize.width;
keyboardSize.width = origKeySize.height;
}
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0, 0, keyboardSize.height, 0);
scroller.contentInset = contentInsets;
scroller.scrollIndicatorInsets = contentInsets;
// If active text field is hidden by keyboard, scroll it so it's visible
// Your application might not need or want this behavior.
CGRect rect = scroller.frame;
rect.size.height -= keyboardSize.height;
NSLog(@"Rect Size Height: %f", rect.size.height);
if (!CGRectContainsPoint(rect, activeField.frame.origin)) {
CGPoint point = CGPointMake(0, activeField.frame.origin.y - keyboardSize.height);
NSLog(@"Point Height: %f", point.y);
[scroller setContentOffset:point animated:YES];
}
}
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
scrollView.contentInset = contentInsets;
scrollView.scrollIndicatorInsets = contentInsets;
}
Run Code Online (Sandbox Code Playgroud)
这里要注意的部分如下:
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
CGSize keyboardSize = [[[notif userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
if (orientation == UIDeviceOrientationLandscapeLeft || orientation == UIDeviceOrientationLandscapeRight ) {
CGSize origKeySize = keyboardSize;
keyboardSize.height = origKeySize.width;
keyboardSize.width = origKeySize.height;
}
Run Code Online (Sandbox Code Playgroud)
做什么,是检测设备的方向.如果是横向,它将'交换'keyboardSize变量的宽度和高度值,以确保在每个方向使用正确的值.
小智 11
Swift 4解决方案:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
registerKeyboardNotifications()
}
func registerKeyboardNotifications() {
NotificationCenter.default.addObserver(self,
selector: #selector(keyboardWillShow(notification:)),
name: NSNotification.Name.UIKeyboardWillShow,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(keyboardWillHide(notification:)),
name: NSNotification.Name.UIKeyboardWillHide,
object: nil)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self)
}
@objc func keyboardWillShow(notification: NSNotification) {
let userInfo: NSDictionary = notification.userInfo! as NSDictionary
let keyboardInfo = userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue
let keyboardSize = keyboardInfo.cgRectValue.size
let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)
scrollView.contentInset = contentInsets
scrollView.scrollIndicatorInsets = contentInsets
}
@objc func keyboardWillHide(notification: NSNotification) {
scrollView.contentInset = .zero
scrollView.scrollIndicatorInsets = .zero
}
Run Code Online (Sandbox Code Playgroud)
对于这些东西,不需要编写很多代码就像下面的代码一样: -
你的所有文本都在UIBcrollview中来自nib,如下图所示: -

YourViewController.h
@interface cntrInquiryViewController : UIViewController<UIScrollViewDelegate,UITextFieldDelegate>
{
IBOutlet UITextField *txtName;
IBOutlet UITextField *txtEmail;
IBOutlet UIScrollView *srcScrollView;
}
@end
Run Code Online (Sandbox Code Playgroud)
从nib连接IBOutlet,并从NIB连接UItextfiled和scrollview委托的每个委托
-(void)viewWillAppear:(BOOL)animated
{
srcScrollView.contentSize = CGSizeMake(320, 500);
[super viewWillAppear:YES];
}
-(void)textFieldDidBeginEditing:(FMTextField *)textField
{
[srcScrollView setContentOffset:CGPointMake(0,textField.center.y-140) animated:YES];//you can set your y cordinate as your req also
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
[srcScrollView setContentOffset:CGPointMake(0,0) animated:YES];
return YES;
}
Run Code Online (Sandbox Code Playgroud)
注意如果文本字段委托没有连接,那么没有一种方法可以工作,请确保所有iBOulate和委托连接正确
苹果推荐使用Swift +在iOS中使用带有自动布局的UIScrollView进行重新编码(基于以下链接:链接1,链接2,链接3):
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet var t1: UITextField!
@IBOutlet var t2: UITextField!
@IBOutlet var t3: UITextField!
@IBOutlet var t4: UITextField!
@IBOutlet var srcScrollView: UIScrollView!
@IBOutlet var contentView: UIView!
var contentViewCoordinates: CGPoint!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
/* Constraints on content view */
let leftConstraint = NSLayoutConstraint(item:self.contentView,
attribute:NSLayoutAttribute.Leading,
relatedBy:NSLayoutRelation.Equal,
toItem:self.view,
attribute:NSLayoutAttribute.Left,
multiplier:1.0,
constant:0)
self.view.addConstraint(leftConstraint)
let rightConstraint = NSLayoutConstraint(item:self.contentView,
attribute:NSLayoutAttribute.Trailing,
relatedBy:NSLayoutRelation.Equal,
toItem:self.view,
attribute:NSLayoutAttribute.Right,
multiplier:1.0,
constant:0)
self.view.addConstraint(rightConstraint)
/* Tap gesture */
let tapGesture: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "hideKeyboard")
// prevents the scroll view from swallowing up the touch event of child buttons
tapGesture.cancelsTouchesInView = false
srcScrollView.addGestureRecognizer(tapGesture)
/* Save content view coordinates */
contentViewCoordinates = contentView.frame.origin
}
func hideKeyboard() {
t1.resignFirstResponder()
t2.resignFirstResponder()
t3.resignFirstResponder()
t4.resignFirstResponder()
}
var activeField: UITextField?
func textFieldDidBeginEditing(textField: UITextField) {
activeField = textField
}
func textFieldDidEndEditing(textField: UITextField) {
activeField = nil
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
let center = NSNotificationCenter.defaultCenter()
center.addObserver(self, selector: "keyboardOnScreen:", name: UIKeyboardDidShowNotification, object: nil)
center.addObserver(self, selector: "keyboardOffScreen:", name: UIKeyboardDidHideNotification, object: nil)
}
func keyboardOnScreen(notification: NSNotification){
// Retrieve the size and top margin (inset is the fancy word used by Apple)
// of the keyboard displayed.
let info: NSDictionary = notification.userInfo!
let kbSize = info.valueForKey(UIKeyboardFrameEndUserInfoKey)?.CGRectValue().size
let contentInsets: UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize!.height, 0.0)
srcScrollView.contentInset = contentInsets
srcScrollView.scrollIndicatorInsets = contentInsets
var aRect: CGRect = self.view.frame
aRect.size.height -= kbSize!.height
//you may not need to scroll, see if the active field is already visible
if (CGRectContainsPoint(aRect, activeField!.frame.origin) == false) {
let scrollPoint:CGPoint = CGPointMake(0.0, activeField!.frame.origin.y - kbSize!.height)
srcScrollView.setContentOffset(scrollPoint, animated: true)
}
}
// func keyboardOnScreen(aNotification: NSNotification) {
// let info: NSDictionary = aNotification.userInfo!
// let kbSize = info.valueForKey(UIKeyboardFrameEndUserInfoKey)?.CGRectValue().size
//
// var bkgndRect: CGRect! = activeField?.superview?.frame
//
// bkgndRect.size.height += kbSize!.height
//
// activeField?.superview?.frame = bkgndRect
//
// srcScrollView.setContentOffset(CGPointMake(0.0, activeField!.frame.origin.y - kbSize!.height), animated: true)
// }
func keyboardOffScreen(notification: NSNotification){
let contentInsets:UIEdgeInsets = UIEdgeInsetsZero
srcScrollView.contentInset = contentInsets
srcScrollView.scrollIndicatorInsets = contentInsets
self.srcScrollView.setContentOffset(CGPointMake(0, -self.view.frame.origin.y/2), animated: true)
}
}
Run Code Online (Sandbox Code Playgroud)
Swift 4.2解决方案考虑了 UIToolbar 和 UITabBar 的可能高度。
private func setupKeyboardNotifications() {
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: UIControl.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: UIControl.keyboardWillHideNotification, object: nil)
}
@objc func keyboardWillShow(_ notification: Notification) {
let userInfo: NSDictionary = notification.userInfo! as NSDictionary
let keyboardSize = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.size
let tabbarHeight = tabBarController?.tabBar.frame.size.height ?? 0
let toolbarHeight = navigationController?.toolbar.frame.size.height ?? 0
let bottomInset = keyboardSize.height - tabbarHeight - toolbarHeight
scrollView.contentInset.bottom = bottomInset
scrollView.scrollIndicatorInsets.bottom = bottomInset
}
@objc func keyboardWillHide(_ notification: Notification) {
scrollView.contentInset = .zero
scrollView.scrollIndicatorInsets = .zero
}
Run Code Online (Sandbox Code Playgroud)
而且,如果您的目标是 < iOS 9,则必须在某个时候取消注册观察者(感谢Joe)
我会在 Apple 代码中更新的唯一内容是 keyboardWillBeHidden: 方法,以提供平滑过渡。
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
[UIView animateWithDuration:0.4 animations:^{
self.scrollView.contentInset = contentInsets;
}];
self.scrollView.scrollIndicatorInsets = contentInsets;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
104882 次 |
| 最近记录: |