xcode 在点击键盘上方移动文本字段的逻辑
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9135248/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Logic For Moving Text Field Above Keyboard On Tap
提问by JTApps
Right now, I have basic code for moving the textfield above the keyboard when you start editing. However, the size of the textfield varies based on device and orientation. So, I wrote a crude way of doing it, which doesn't stay consistently right above the keyboard, but instead will go up further when you rotate it, and so it doesn't look as professional as I would like.
现在,当您开始编辑时,我有用于在键盘上方移动文本字段的基本代码。但是,文本字段的大小因设备和方向而异。所以,我写了一个粗略的方法,它不会一直保持在键盘正上方,而是当你旋转它时会进一步上升,所以它看起来不像我想要的那么专业。
The basic sense of my question is if there is a logic for getting the size of the keyboard based on device and orientation and using that value automatically and hopefully faster than this.
我的问题的基本意义是,是否存在根据设备和方向获取键盘大小并自动使用该值并希望比这更快的逻辑。
If that is the best way, please let me know. Otherwise, please provide input. Here is the code that I have. (This is just the move-up code, not the move down code, in order to prevent taking up too much space)
如果这是最好的方法,请告诉我。否则,请提供输入。这是我拥有的代码。(这里只是上移代码,不是下移代码,以免占用太多空间)
- (void)textFieldDidBeginEditing:(UITextField *)textField {
//Get Device Type
NSString *deviceType = [[UIDevice currentDevice] model];
//Animate Text Field
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:0.4];
[UIView setAnimationBeginsFromCurrentState:YES];
if ([deviceType isEqualToString:@"iPhone"]) {
//Size For iPhone
googleBar.frame = CGRectMake(googleBar.frame.origin.x - 62.0, (googleBar.frame.origin.y - 210.0), googleBar.frame.size.width + 120.0, googleBar.frame.size.height);
} else if ([deviceType isEqualToString:@"iPad"]) {
//Size for iPad
googleBar.frame = CGRectMake(googleBar.frame.origin.x - 62.0, (googleBar.frame.origin.y - 320.0), googleBar.frame.size.width + 120.0, googleBar.frame.size.height);
} else if ([deviceType isEqualToString:@"iPod touch"]) {
//Size For iPod Touch
googleBar.frame = CGRectMake(googleBar.frame.origin.x - 62.0, (googleBar.frame.origin.y - 210.0), googleBar.frame.size.width + 120.0, googleBar.frame.size.height);
}
[UIView commitAnimations];
}
回答by Carl Veazey
What you really want to do is observe the UIKeyboard(Did|Will)(Show|Hide) notifications. They contain in their userInfo dictionaries the beginning and ending frame, as well as the correct animation curve and durations.
您真正想要做的是观察 UIKeyboard(Did|Will)(Show|Hide) 通知。它们在 userInfo 字典中包含开始和结束帧,以及正确的动画曲线和持续时间。
So after observing this notification, when it's posted move your text field based on the size of the frame passed in the notification, according to the animation hints provided.
因此,在观察到此通知后,根据提供的动画提示,在发布时根据通知中传递的帧的大小移动您的文本字段。
You can see more information in the UIWindow class reference's "notifications" section: https://developer.apple.com/library/ios/#documentation/uikit/reference/UIWindow_Class/UIWindowClassReference/UIWindowClassReference.html
您可以在 UIWindow 类参考的“通知”部分看到更多信息:https: //developer.apple.com/library/ios/#documentation/uikit/reference/UIWindow_Class/UIWindowClassReference/UIWindowClassReference.html
Below is a sample view controller implementation. The nib for this view controller was just a single text field, with an outlet connected to it, and the text field's delegate set to the view controller.
下面是一个示例视图控制器实现。这个视图控制器的笔尖只是一个单独的文本字段,有一个连接到它的插座,文本字段的委托设置为视图控制器。
@interface ViewController ()
- (void)viewControllerInit;
@end
@implementation ViewController
@synthesize textField;
- (id)initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder];
if (self) {
[self viewControllerInit];
}
return self;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])
{
[self viewControllerInit];
}
return self;
}
- (void)viewControllerInit
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark - Notification Handlers
- (void)keyboardWillShow:(NSNotification *)notification
{
// I'll try to make my text field 20 pixels above the top of the keyboard
// To do this first we need to find out where the keyboard will be.
NSValue *keyboardEndFrameValue = [[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey];
CGRect keyboardEndFrame = [keyboardEndFrameValue CGRectValue];
// When we move the textField up, we want to match the animation duration and curve that
// the keyboard displays. So we get those values out now
NSNumber *animationDurationNumber = [[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey];
NSTimeInterval animationDuration = [animationDurationNumber doubleValue];
NSNumber *animationCurveNumber = [[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey];
UIViewAnimationCurve animationCurve = [animationCurveNumber intValue];
// UIView's block-based animation methods anticipate not a UIVieAnimationCurve but a UIViewAnimationOptions.
// We shift it according to the docs to get this curve.
UIViewAnimationOptions animationOptions = animationCurve << 16;
// Now we set up our animation block.
[UIView animateWithDuration:animationDuration
delay:0.0
options:animationOptions
animations:^{
// Now we just animate the text field up an amount according to the keyboard's height,
// as we mentioned above.
CGRect textFieldFrame = self.textField.frame;
textFieldFrame.origin.y = keyboardEndFrame.origin.y - textFieldFrame.size.height - 40; //I don't think the keyboard takes into account the status bar
self.textField.frame = textFieldFrame;
}
completion:^(BOOL finished) {}];
}
- (void)keyboardWillHide:(NSNotification *)notification
{
NSNumber *animationDurationNumber = [[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey];
NSTimeInterval animationDuration = [animationDurationNumber doubleValue];
NSNumber *animationCurveNumber = [[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey];
UIViewAnimationCurve animationCurve = [animationCurveNumber intValue];
UIViewAnimationOptions animationOptions = animationCurve << 16;
[UIView animateWithDuration:animationDuration
delay:0.0
options:animationOptions
animations:^{
self.textField.frame = CGRectMake(20, 409, 280, 31); //just some hard coded value
}
completion:^(BOOL finished) {}];
}
#pragma mark - View lifecycle
- (void)viewDidUnload
{
[self setTextField:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
#pragma mark - UITextFieldDelegate
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[self.textField resignFirstResponder];
return YES;
}
@end
回答by Jans
Using notification keyboard register , you can place your textfield inside a scroll and manage the content offset of scroll to turn the actual first responder above keyboard if it's neccesary.
使用通知键盘 register ,您可以将文本字段放在滚动中并管理滚动的内容偏移量,以便在必要时将实际的第一响应者置于键盘上方。
so after register controller to keybard appear , you must to obtain the gap between keyboard origin and scroll origin relative to parent.
因此,在将控制器注册到键盘出现后,您必须获得键盘原点和滚动原点相对于父级之间的差距。
you must know if an specific first responder can change content offset of scroll, therefore is neccesary to know the possible bounds between keyboard origin and first responder.
您必须知道特定的第一响应者是否可以更改滚动的内容偏移量,因此有必要了解键盘原点和第一响应者之间的可能界限。
by the way you need to know the gap betwen the scroll content offset and the first responder for place your first responder in specific position.
顺便说一下,您需要知道滚动内容偏移量和第一响应者之间的差距,以便将第一响应者放置在特定位置。
@interface MainViewController : UIViewController
@property (strong, nonatomic) IBOutlet UIScrollView *scroll;
@end
@interface MainViewController ()
{
CGPoint scrollOffset;
}
@end
@implementation MainViewController
@synthesize scroll
-(void)viewWillAppear:(BOOL)animated
{
[[ NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillAppear:) name:UIKeyboardDidShowNotification object:nil];
[[ NSNotificationCenter defaultCenter ] addObserver:self selector:@selector(keyboardWillDisAppear:) name:UIKeyboardDidHideNotification object:nil];
}
-(void)viewWillDisappear:(BOOL)animated
{
[[ NSNotificationCenter defaultCenter ] removeObserver:self ];
}
-(void)keyboardWillAppear:(NSNotification*) note
{
const CGFloat default_gap = 25.0f;
NSValue *keyBoardEndFrameValue = [[ note userInfo ] objectForKey:UIKeyboardFrameEndUserInfoKey ];
CGRect keyBoardFrame = [ keyBoardEndFrameValue CGRectValue ];
offset = scroll.contentOffset;
UIWindow *window = [[ UIApplication sharedApplication ] keyWindow];
UITextField *textField = (UITextField*)[ window performSelector:@selector(firstResponder) ];
//Gap between keyboard origin and the scroll origin, relative to parent.
CGFloat distanceRelativeToParent = keyBoardFrame.origin.y - scroll.frame.origin.y;
//Distance between superview to textfield inside scroll. to determine if it's necesary to scroll.
CGFloat bound = (textField.frame.origin.y + textField.frame.size.height)+scroll.frame.origin.y;
CGFloat gapScroll = textField.frame.size.height+default_gap;
if( bound >= keyBoardFrame.origin.y )
{
[ UIView animateWithDuration:.3 delay:0.0 options:UIViewAnimationCurveEaseOut
animations:^{
[ scroll setContentOffset:CGPointMake(0, textField.frame.origin.y - distanceRelativeToParent + gapScroll ) animated:YES ];
}
completion:^(BOOL finished){
}];
}
}
-(void) keyboardWillDisAppear:(NSNotification*) note
{
[ scroll setContentOffset:offset animated:YES ];
}
@end
回答by brandonbocklund
UIViewControllers have a property called interfaceOrientation and the function UIInterfaceOrientationIsPortrait/Landscape so essentially you can do:
UIViewControllers 有一个名为 interfaceOrientation 的属性和函数 UIInterfaceOrientationIsPortrait/Landscape 所以基本上你可以这样做:
if(UIInterfaceOrientationIsPortrait(self.interfaceOrientation){
//portrait logic
}
else{
//landcapeLogic
}
inside for each the iPhone and iPad in your view controller. From there you can do your pixel measurement way as you had done before, because as far as I know that's the simplest way to do it.
视图控制器中的每个 iPhone 和 iPad。从那里您可以像以前一样进行像素测量,因为据我所知,这是最简单的方法。
P.S. There is a function to check for landscape checker too, but if the first if statement is false meaning the device is not in portrait, then it must be in landscape hence the plain else.
PS 也有一个检查横向检查器的功能,但是如果第一个 if 语句是假的,这意味着设备不是纵向的,那么它必须是横向的,因此是普通的 else。