iOS实现输入框跟随键盘自动上移的实例代码

场景还原

有些时候在包含输入框的页面中,点击输入框输入会因键盘弹起而遮挡住一部分输入框,影响用户体验。iOS在默认情况下并不会处理这种问题,不过我们可以自己实现键盘弹起输入框自动上移的效果。

实现思路

观察键盘的弹起与收回,当弹起的键盘会遮挡住输入框时,将输入框跟随键盘一并上移合适的距离,当键盘收回时,输入框回到原始状态。

具体方案

1. 注册两个观察者,观察键盘的弹起与收回

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];

2. 在上面的keyboardWillShow和keyboardWillHide方法中分别实现输入框的上移和还原

上移

当弹起的键盘遮住了页面上的输入框时,我们应该将输入框移至键盘之上,而键盘没有遮到输入框时,并不需要操作。因此在ios的坐标系下,我们可以分别获取键盘弹起后上端的Y坐标和输入框下端的Y坐标,通过做差可以判断出键盘是否遮住了输入框。上移我们可以采用view的transform属性进行平移变换,而不是直接去操作view的frame,这样做的好处是当我们要还原view的状态时可以直接将transform重置为0,而不需要再关心计算下移时的距离。

还原(下移至原始状态)

根据前面所说,我们只要在恰当的时机操作view的transform属性就可以实现了。

- (void)keyboardWillShow:(NSNotification *)notification
{
  //获取处于焦点中的view
  NSArray *textFields = @[phoneNemberText, verifyCodeText];
  UIView *focusView = nil;
  for (UITextField *view in textFields) {
    if ([view isFirstResponder]) {
      focusView = view;
      break;
    }
  }
  if (focusView) {
    //获取键盘弹出的时间
    double duration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    //获取键盘上端Y坐标
    CGFloat keyboardY = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue].origin.y;
    //获取输入框下端相对于window的Y坐标
    CGRect rect = [focusView convertRect:focusView.bounds toView:[[[UIApplication sharedApplication] delegate] window]];
    CGPoint tmp = rect.origin;
    CGFloat inputBoxY = tmp.y + focusView.frame.size.height;
    //计算二者差值
    CGFloat ty = keyboardY - inputBoxY;
    NSLog(@"position keyboard: %f, inputbox: %f, ty: %f", keyboardY, inputBoxY, ty);
    //差值小于0,做平移变换
    [UIView animateWithDuration:duration animations:^{
      if (ty < 0) {
        self.view.transform = CGAffineTransformMakeTranslation(0, ty);
      }
    }];
  }
}

- (void)keyboardWillHide:(NSNotification *)notification
{
  //获取键盘弹出的时间
  double duration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
  //还原
  [UIView animateWithDuration:duration animations:^{
    self.view.transform = CGAffineTransformMakeTranslation(0, 0);
  }];
}

看上去这样已经完美实现了输入框随键盘自动上移,我们也可以喝杯茶稍微休息一下了。没错,在iOS 8及之后的系统中,确实可以正常的工作,然而如果你的应用需要适配iOS 7并且要支持横屏,那么上面的方式在iOS7上,并不能按照我们的期望正确移动。

原因:在ios7上,键盘的frame,系统是按照竖屏状态下window坐标系来计算的,并不考虑旋转的因素,因此在横屏下得到的键盘frame是错误的。受此影响的还有横屏时获取屏幕宽高[UIScreen mainScreen].bounds,也会有这样的问题。这种情况我们不仅无法正确得到键盘的frame,而且输入框相对于window的坐标计算结果也是错误的。

因此在ios7上,键盘上端的Y坐标以及输入框下端相对于window的Y坐标需要单独处理。键盘上端的Y坐标可以通过屏幕高度减键盘高度得到。我们通过下面的方法获取键盘上端的Y坐标。

- (CGFloat)getKeyboardY:(NSDictionary *)userInfo
{
  CGFloat screenHeight;
  CGFloat keyboardY = 0;
  CGFloat keyboardHeight = 0;
  UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
  if (( [[[UIDevice currentDevice] systemVersion] floatValue]<8) && UIInterfaceOrientationIsLandscape(orientation))
  {
    screenHeight = [[UIScreen mainScreen] bounds].size.width;
    keyboardHeight = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue].size.width;
    keyboardY = screenHeight - keyboardHeight;
  }
  else if (( [[[UIDevice currentDevice] systemVersion] floatValue]<8) && UIInterfaceOrientationIsPortrait(orientation)) {
    screenHeight = [[UIScreen mainScreen] bounds].size.height;
    keyboardHeight = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;
    keyboardY = screenHeight - keyboardHeight;
  }
  else {
    keyboardY = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue].origin.y;
  }
  return keyboardY;
}

输入框下端相对于window的坐标如何计算呢?我们首先获得的其实是基于竖屏状态下坐标系中的Y值,而我们期望的是横屏下得到横屏状态下坐标系中的Y值,根据两个坐标系的关系,可以将第一次转换得到的坐标再做一次转换,计算得出横屏坐标系下的Y坐标值。我们通过下面的方法获取输入框下端的Y坐标。

- (CGPoint)getViewOriginPointToWindow:(UIView *)view
{
  CGPoint origin;
  if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8) {
    CGPoint focusViewPoint = [view convertPoint:CGPointZero toView:nil];
    UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
    if (orientation == UIInterfaceOrientationLandscapeLeft) {
      origin.y = focusViewPoint.x;
      origin.x = [[[UIApplication sharedApplication] delegate] window].bounds.size.height - focusViewPoint.y;
    }
    else if (orientation == UIInterfaceOrientationLandscapeRight) {
      origin.y = [[[UIApplication sharedApplication] delegate] window].bounds.size.width - focusViewPoint.x;
      origin.x = focusViewPoint.y;
    }
    else if (orientation == UIInterfaceOrientationPortraitUpsideDown) {
      origin.y = [[[UIApplication sharedApplication] delegate] window].bounds.size.height - focusViewPoint.y;
      origin.x = [[[UIApplication sharedApplication] delegate] window].bounds.size.width - focusViewPoint.x;
    }
    else {
      origin = focusViewPoint;
    }
  }
  else {
    CGRect rect = [view convertRect:view.bounds toView:[[[UIApplication sharedApplication] delegate] window]];
    origin = rect.origin;
  }
  return origin;
}

因此我们将之前获取两个Y坐标的代码改用下面的方式:

//获取键盘上端Y坐标
CGFloat keyboardY = [self getKeyboardY:notification.userInfo];
//获取输入框下端相对于window的Y坐标
CGPoint tmp = [self getViewOriginPointToWindow:focusView];
CGFloat inputBoxY = tmp.y + focusView.frame.size.height;

这样就完美实现了输入框随键盘自动上移的效果。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • ionic在开发ios系统微信时键盘挡住输入框的解决方法(键盘弹出问题)

    在使用ionic开发IOS系统微信的时候会有一个苦恼的问题,填写表单的时候键盘会挡住输入框,其实并不算什么大问题,只要用户输入一个字就可以立刻看见输入框了. 可惜的是,有些客户是不讲理的,他才不管这个问题,反正就是不行,所以在一天睡觉的时候突然惊醒,想出来这个方案. 我就不仔细讲代码了,直接上图 angular.module('MyApp') .directive('focusInput', ['$ionicScrollDelegate', '$window', '$timeout', '$io

  • IOS 键盘挡住输入框的问题解决办法

    IOS 键盘挡住输入框的问题解决办法 在iOS开发发现一个问题,有时输入框位于低出时,当编辑输入时,弹出的键盘会挡住输入框,令用户看不清楚实时的输入情况,使界面交互极度不友好. 经过查资料终于解决了这个问题. 解决思路: 1. 输入框监听UIControlEventEditingDidBegin事件,当用户开始输入时,将整个view上移. 2. 输入框监听UIControlEventEditingDidEnd事件,当用户结束输入时,将整个view下移,恢复到原位置. 输入框监听事件: [text

  • iOS实现输入框跟随键盘自动上移的实例代码

    场景还原 有些时候在包含输入框的页面中,点击输入框输入会因键盘弹起而遮挡住一部分输入框,影响用户体验.iOS在默认情况下并不会处理这种问题,不过我们可以自己实现键盘弹起输入框自动上移的效果. 实现思路 观察键盘的弹起与收回,当弹起的键盘会遮挡住输入框时,将输入框跟随键盘一并上移合适的距离,当键盘收回时,输入框回到原始状态. 具体方案 1. 注册两个观察者,观察键盘的弹起与收回 [[NSNotificationCenter defaultCenter] addObserver:self selec

  • Swift让输入框跟随键盘弹起避免输入输入法挡住输入框问题

    第一步: 新建Controller 在Xcode选择File → New → File → Cocoa Touch Class 新建LoginViewController继承自UIViewController 第二步:创建两个UITextField passwordInput: UITextField // 密码输入框 accountInput: UITextField // 帐号输入框 第三步:添加键盘KVO 在viewDidLoad方法添加下面两行代码 //当键盘弹起的时候会向系统发出一个通

  • iOS UIScrollView滚动视图/无限循环滚动/自动滚动的实例代码

    我们都知道UIScrollView有一种很流畅的切换效果,结合UIPageControl的辅助展示效果,就可以完成一个很不错的产品介绍功能页面.下面给大家分享iOS UIScrollView滚动视图/无限循环滚动/自动滚动功能,具体代码如下所示: <UIScrollViewDelegate> #define WIDTH [[UIScreen mainScreen] bounds].size.width #define HEIGHT [[UIScreen mainScreen] bounds].

  • Angular 实现输入框中显示文章标签的实例代码

    很多网站发帖的时候标签输入框看起来像是在 <input> 元素中直接显示标签. 比如这种 一开始以为是把 <span> 放在 <input> 中, 看了下 Stack Overflow 和 SegmentFault 的实现方式, 原来是用一个 <div> 把 <span> 和 <input> 包起来, 然后让 <div> 模仿出输入框的样式. 再给 <div> 加上eventListensor, 点击 <

  • IOS NSUserDefault 记住用户名及密码功能的实例代码

    一般的登录界面都会有一个记住密码的选项,要实现这个功能可以使用NSUserDefault,这里只是讲解明文的处理方式,虽然这样是有一定的风险性的但是目前只是了解如何实现这个功能: 首先声明一个NSUserDefault对象: let userDefaults = NSUserDefaults.standardUserDefaults() //本地操作所需 然后根据是否记住密码按钮的状态来判断是否要为用户名和密码设置值,如果是记住密码,那么需要取出需要记住的密码,并且为这两个TextField赋值

  • IOS在SwiftUI中显示模态视图的实例代码

    简介 这里教大家如何弹出一个简单的模态视图.分别有两个页面,ContentView和GCPresentedView,以下对应简称为A和B.我们要做的是在A视图中点击按钮跳转到B视图,然后再从B视图点击按钮返回到A视图. 步骤 在A视图中创建按钮和模态视图代码 struct ContentView: View { @State var isPresented = false var body: some View { Button(action: { self.isPresented = true

  • JavaScript实现的可变动态数字键盘控件方式实例代码

    整理文档,搜刮出一个JavaScript实现的可变动态数字键盘控件方式实例代码,稍微整理精简一下做下分享. @sunRainAmazing JavaScript编写和实现的可变动态键盘密码输入控件,可以动态的生产数字键盘并显示,并且可以实现每次点击后密码键盘重新加载,可以手动刷新功能. 第一种方式,点击查看: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&qu

  • Automapper实现自动映射的实例代码

    出于安全考虑,在后台与前台进行数据传输时,往往不会直接传输实体模型,而是使用Dto(Data transfer object 数据传输对象),这样在后台往前台传递数据时可以省略不必要的信息,只保留必要的信息,大大增强数据安全性. 下面给出两个相互对应的关系模型User.UserDto public class User { private const int NameMaxLength = 20; private const int PassWordMaxLength = 16; [Key] p

  • iOS中创建表格类视图WBDataGridView的实例代码

    项目中创建表格, 引用头文件 #import "WBDataGridView.h" - (void)viewDidLoad{ [superviewDidLoad]; // Do any additional setup after loading the view. self.view.backgroundColor = [UIColorwhiteColor]; CGFloat margin = 10.f; CGFloat width = self.view.frame.size.wi

  • iOS开发中Swift 指纹验证功能模块实例代码

    iOS调用TouchID代码: override func viewDidLoad() { super.viewDidLoad() let context = LAContext() var error: NSError? = nil let canEvaluatePolicy = context.canEvaluatePolicy(LAPolicy.deviceOwnerAuthenticationWithBiometrics, error: &error) as Bool if error

随机推荐