自适应键盘,自带隐藏键盘的输入框(UITextField)

news2024/11/10 12:46:41

引言

在iOS开发中,输入框占据着举足轻重的地位。与安卓不同,iOS输入框经常面临键盘遮挡的问题,或者无法方便地取消键盘。为了解决这些问题,有许多针对iOS键盘管理的库,如IQKeyboardManager、TPKeyboardAvoiding和KeyboardManager等等。

然而,一些库可能对整个项目的侵入性较大,可能会影响到其他功能。有时,我们可能不希望某些输入框被这些库管理,虽然它们通常也提供了相应的解决方案,但有时会显得有些繁琐。

因此,我们可以考虑自己实现一个输入框,根据项目需求定制输入框的功能。这样做不仅轻量级,而且更加灵活。

实现

本篇博客将通过继承的方式,分别介绍如何自定义实现UITextFiled和UITextView。即使你的项目已经存在一段时间,也可以采用"黑魔法"的方式来实现这些功能。

我们首先明确两个要解决的问题:第一个是解决键盘遮挡输入框的问题,第二个是管理键盘的显示和隐藏。

UITextField

首先继承UITextField创建一个名为LATextField的类,然后通过重写它的init方法来处理上面要解决的两个问题。

解决键盘遮挡

为它添加一个属性,该属性是指当键盘出现时,需要跟随键盘上移的视图,我们可以通过遍历父图层的方式自动获取,也可以使用主动赋值的方式。

但属性一定要使用weak来修饰(子视图不能持有它的父视图)。

代码如下:

class LATextField: UITextField {
    
    /// 滑动的视图
    weak var sliderView:UIView?
    
    override init(frame: CGRect) {
        super.init(frame: frame)

    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

在init方法中添加关于键盘出现和消失的监听,代码如下:

    override init(frame: CGRect) {
        super.init(frame: frame)
        addNotification()
    }
    

    fileprivate func addNotification() {
        // 监听键盘的弹出和收起
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
    }

键盘弹出后,我们可以通过通知的userinfo来获取键盘出现的动画时长,以及键盘的frame。

动画时长对应的key为UIResponder.keyboardAnimationDurationUserInfoKey

键盘frame对一个的key为UIResponder.keyboardFrameEndUserInfoKey

代码如下:

    @objc fileprivate func keyboardWillShow(notification: Notification) {
        let userInfo = notification.userInfo
        let duration = userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as! TimeInterval
        let keyboardFrame = userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as! CGRect
        let keyboardHeight = keyboardFrame.size.height

    }

当我们获取到了键盘的frame就可以判断输入框是否被键盘遮挡。而键盘出现的动画时长可以让我们的上移动画更平滑,像是跟随键盘进行上移和下移,具体代码如下:

        if !self.isFirstResponder {
            return
        }
        guard let sliderView = sliderView else { return }
        // 输入框相对于屏幕的位置
        let textfiledFrame = self.convert(self.bounds, to: UIApplication.shared.keyWindow)
        // 输入框的底部位置
        let textfiledBottom = textfiledFrame.origin.y + textfiledFrame.size.height
        if textfiledBottom > keyboardFrame.origin.y {
            let offsetY = textfiledBottom - keyboardFrame.origin.y
            UIView.animate(withDuration: duration) {
                sliderView.transform = CGAffineTransform(translationX: 0, y: -offsetY)
            }
        }

这里面有两个需要注意的地方:

  1. 首先需要判断该输入框是否是第一响应者,如果不是第一响应者那么就不需要处理它。
  2. 第二我们采用了transform进行移动,而不是直接修改y值,防止移动被累加,也方便还原操作。

当键盘隐藏时,我们只需要设置sliderView的transform为.identity即可,代码如下:

    @objc fileprivate func keyboardWillHide(notification: Notification) {
        let userInfo = notification.userInfo
        let duration = userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as! TimeInterval
//        if !self.isFirstResponder {
//            return
//        }
        guard let sliderView = sliderView else { return }
        UIView.animate(withDuration: duration) {
            sliderView.transform = .identity
        }
    }

这里面就不需要进行判断该键盘是否是第一响应者了,因为键盘消失,那么该输入框明显已经不是第一响应者,如果此处添加了判断会影响页面还原。

解决键盘隐藏

这也是一个场景的问题,我们通常会每个输入框都单独处理,比如通过重写它的回车按钮,或者在页面添加手势点击后隐藏键盘。

在这里我们借助它的一个inputAccessoryView属性,在inputAccessoryView添加一个down按钮,点击后调用resignFirstResponder方法取消输入框的第一响应者身份。

代码如下:

    // 添加默认的输入框附加视图
    fileprivate func addInputAccessoryView() {
        let inputAccessortyView = UIView(frame: CGRect(x: 0, y: 0, width: SCREENWIDTH, height: 40))
        inputAccessortyView.backgroundColor = .clear
        let arrowButton = LADownButton()
        arrowButton.frame = CGRect(x: SCREENWIDTH - 40, y: 8, width: 30, height: 30)
        arrowButton.layer.cornerRadius = 15
        arrowButton.layer.masksToBounds = true
        arrowButton.backgroundColor = .black.withAlphaComponent(0.1)
        inputAccessortyView.addSubview(arrowButton)
        arrowButton.addTarget(self, action: #selector(arrowButtonAction), for: .touchUpInside)
        self.inputAccessoryView = inputAccessortyView
    }
    
    @objc fileprivate func arrowButtonAction() {
        self.resignFirstResponder()
    }

其中LADownButton按钮是一个我们自定义的按钮,不过它里面并没有什么实际的东西只是绘制了一个向下的箭头,你可以使用文案代替,也可以使用图片代替。

借助了UIBezierPath来进行绘制,它的代码如下:

class LADownButton: UIButton {

    override func draw(_ rect: CGRect) {
        // 绘制向下的三角
        let path = UIBezierPath()
        path.move(to: CGPoint(x: rect.width * 0.2, y: rect.height * 0.4))
        path.addLine(to: CGPoint(x: rect.width / 2, y: rect.height * 0.7))
        path.addLine(to: CGPoint(x: rect.width * 0.8, y: rect.height * 0.4))
        UIColor.white.setStroke()
        path.lineWidth = 2.0
        path.lineJoinStyle = .round
        path.stroke()
    }

}

整个输入框效果如下:

结语

在本篇博客中,我们演示了简单的实现方式,已经能够满足大部分需求。进一步优化的话,我们可以定制输入框与键盘之间的距离,还可以自动获取需要上移的视图等功能,这些都可以根据具体需求进行定制和扩展。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1931072.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数仓实践:维度建模标准规范定义

一、引言 指以维度建模作为理论基础,构建总线矩阵,划分和定义数据域、业务过程、维度、度量/原子指标、业务限定、时间周期、统计粒度、派生指标。 规范定义如下: 二、名词术语 名词解释数据域面向业务分析,将业务过程或者维度进行抽象的集合。其中,业务过程可以概括为…

idea中使用maven

默认情况下,idea会自动下载并安装maven,这不便于我们管理。 最好是自行下载maven,然后在idea中指定maven的文件夹路径

鸿蒙开发:Universal Keystore Kit(密钥管理服务)【获取密钥属性(C/C++)】

获取密钥属性(C/C) HUKS提供了接口供业务获取指定密钥的相关属性。在获取指定密钥属性前,需要确保已在HUKS中生成或导入持久化存储的密钥。 在CMake脚本中链接相关动态库 target_link_libraries(entry PUBLIC libhuks_ndk.z.so)开发步骤 构造对应参数。 keyAlias&…

华为OD七日集训第1期 - 按算法分类,由易到难,循序渐进,玩转OD

目录 一、适合人群二、本期训练时间三、如何参加四、7日集训第2期五、精心挑选21道高频100分经典题目,作为入门。第1天、逻辑分析第2天、数组第3天、双指针第4天、数据结构第5天、队列第6天、栈第7天、滑动窗口 六、集训总结 大家好,我是哪吒。 最近一直…

Idea如何快速高效的修改项目的包名

文章目录 前言一、全局替换的快捷键二、弹出如下的界面 前言 当我们有时候在做项目迁移的时候,需要快速的修改项目的包名!那么如何快速高效的修改项目的报名呢? 经过尝试了很多方法!最简单的方法就是利用全局替换来直接替换报名&…

半自动辅助制作数据集【实例分割】

利用yoloV8的实例分割模型,半自动辅助制作数据集 引言:【主要步骤】 步骤1:无人机航拍,收集基础图片 步骤2:将收集到的图片,全部用yoloV8-seg.pt模型进行实例分割【预测之前,将配置文件default.…

图——图的应用02最短路径(Dijkstra算法与Floyd算法详解),拓扑排序及关键路径

前面介绍了图的应用——01最小生成树章节,大家可以通过下面的链接学习: 图——图的应用01最小生成树(Prim算法与Kruskal算法详解) 今天就讲一下图的其他应用——最短路径,拓扑排序及关键路径。 目录 一&#xff0c…

解决Qt6 OpenCV项目编译出现错误undefined reference to symbol ‘cv::cvtColor,无法解析的符号

在一次Qt6 OpenCV项目编译的过程中,出现错误undefined reference to symbol cv::cvtColor,无法解析的符号,问题是查看INCLUDEPATH和LIBS,都已经添加正确。 而且这个函数也可以在头文件中索引到。到底是什么问题呢? 清…

公司政务办理流程分享(北京)

社保增减员: 参保登记——增减员业务这么办_北京市人力资源和社会保障局_社会保险 https://rsj.beijing.gov.cn/yltc/202310/t20231025_3287007.html 公积金增减员: https://dwwsyw.gjj.beijing.gov.cn/

【从零开始实现stm32无刷电机FOC】【实践】【5/6 stm32 adc外设的高级用法】

目录 采样时刻触发采样同步采样 点击查看本文开源的完整FOC工程 本节介绍的adc外设高级用法用于电机电流控制。 从前面几节可知,电机力矩来自于转子的q轴受磁力,而磁场强度与电流成正比,也就是说电机力矩与q轴电流成正相关,控制了…

which 命令在Linux中是一个快速查找可执行文件位置的工具

文章目录 0、概念1、which --help2、which命令解释 0、概念 which命令用于查找命令的可执行文件的路径which 命令在 Linux 中用于查找可执行命令的完整路径。当你在 shell 中输入一个命令时,shell 会在环境变量 $PATH 定义的目录列表中查找这个命令。which 命令可以…

数据结构——单链表详解(超详细)(2)

前言: 上一篇文章小编简单的介绍了单链表的概念和一些函数的实现,不过为了保证文章的简洁,小编把它分成了两篇来写,这一篇小编紧接上一篇文章继续写单链表函数功能的实现: 目录: 1.单链表剩余函数的编写 1.…

Spring Security Oauth2源码分析

Spring Security Oauth2源码分析 前言一:客户端OAuth2授权请求的入口1、DefaultOAuth2AuthorizationRequestResolver类OAuth2AuthorizationRequest类authorizationRequestUri 的构建机制redirectUri 3、OAuth2AuthorizationRequestRedirectFilter类 二:O…

hiphop音乐风格分类有几种 怎么使用FL Studio制作Hip Hop音乐 hiphop音乐制作教程

Hip Hop音乐是一类新潮的音乐风格,融合了许多不同的文化元素和音乐表达方式。嘻哈(hip hop)诞生于美国贫民区街头的一种文化形式,一般的说法认为它诞生于美国纽约布朗克斯。嘻哈首先在纽约市北部布朗克斯市区的非裔及拉丁裔青年之…

kali进行host碰撞实验

目录 在kali上安装docker,完成环境搭建,进行host碰撞实验 更新软件包列表 下载阿里云的镜像源 添加 GPG 密钥并添加更新源 安装 Docker 安装成功检验 开启docker 检查docker状态 拉取镜像 在kali访问ip(加端口) 下载压缩…

京东超级18活动入口!京东超级18活动怎么玩?

京东推出新活动,低价的持续性项目“京东超级18”。 活动入口: 京东超级18,领60元大额补贴! 口令直达:14:/京东超级18¥NF5fuBPWIIaHRiMr¥,↗鯨○Dσσδng。 手机京东搜索&#xf…

Claude 3.5 Sonnet模型发布,对比ChatGPT4o孰强孰弱

Anthropic 这家生而为打击 OpenAI 安全问题的公司,正式发布了Claude 3.5 Sonnet模型! 用官网的话就是: 今天,我们推出了 Claude 3.5 Sonnet,这是我们即将推出的 Claude 3.5 型号系列中的第一个版本。Claude 3.5 Sonne…

vscode 打开远程bug vscode Failed to parse remote port from server output

vscode 打开远程bug vscode Failed to parse remote port from server output 原因如图: 解决:

02 Git环境搭建

第2章:Git环境搭建 一、Git下载和安装 ​ 官网:Git (git-scm.com) 一)安装主程序 ​ 准备安装包,双击安装 ​ 开始安装 ​ 选择安装位置 ​ 选择需要安装的组件(默认) ​ 选择文件夹菜单 ​ 选择编辑器&…

Word参考文献交叉引用

前言 Word自带交叉引用功能,可在正文位置引用文档内自动编号的段落,同时创建超链接,适用于参考文献的引用。使用此方法对参考文献进行引用后,当参考文献的编号发生变化时,只需要更新域即可与正文中的引用相对应。下文…