• (一三〇)UITextField的光标操作扩展


    简介

    在iOS开发中,有时候需要完全自主的定义键盘,用于完整的单词输入,例如计算机应用中,需要一次性的输入sin(,在移动光标时要完整的跳过sin(,在删除时也要完整的删除,这就需要对光标的位置进行精确控制,而iOS并没有相关的函数可以直接操作光标,只给出了选择某个区域的功能,本文将介绍基于区域选择设计的UITextField扩展,用于获取光标位置以及移动光标。

    实现原理

    • 光标位置的获取
      在textField中,有一个属性称之为selectedTextRange,这个属性为UITextRange类型,包含[start,end)两个值,通过实验我们可以发现,在没有文字被选取时,start代表当前光标的位置,而end=0;当有区域被选择时,start和end分别是选择的头和尾的光标位置,从0开始,并且不包含end,例如选择了0~3的位置,则start=0,end=4。

    • 光标的移动
      通过setSelectedTextRange:方法可以设置选取范围,我们只要设置一个选取单个字符的范围,即可移动光标而不选中。

    关键属性

    // 内容为[start,end),无论是否有选取区域,start都描述了光标的位置。
    @property (nullable, readwrite, copy) UITextRange *selectedTextRange;
    // 文首和文尾的位置
    @property (nonatomic, readonly) UITextPosition *beginningOfDocument;
    @property (nonatomic, readonly) UITextPosition *endOfDocument;

    关键方法

    // 获取以from为基准的to的偏移,例如abcde,光标在c后,则光标相对文尾的偏移为-2- (NSInteger)offsetFromPosition:(UITextPosition *)from toPosition:(UITextPosition *)toPosition;
    // 获取以from为基准偏移offset的光标位置。
    - (nullable UITextPosition *)positionFromPosition:(UITextPosition *)position offset:(NSInteger)offset;
    // 创建一个UITextRange
    - (nullable UITextRange *)textRangeFromPosition:(UITextPosition *)fromPosition toPosition:(UITextPosition *)toPosition;

    具体实现

    • 下面的代码为UITextField创建了一个分类(Category),包含三个方法,分别用于获取光标位置、从当前位置偏移、从头偏移。
    #import <UIKit/UIKit.h>
    
    @interface UITextField (Extension)
    
    - (NSInteger)curOffset;
    - (void)makeOffset:(NSInteger)offset;
    - (void)makeOffsetFromBeginning:(NSInteger)offset;
    
    @end
    #import "UITextField+Extension.h"
    
    @implementation UITextField (Extension)
    
    - (NSInteger)curOffset{
    
        // 基于文首计算出到光标的偏移数值。
        return [self offsetFromPosition:self.beginningOfDocument toPosition:self.selectedTextRange.start];
    
    }
    
    - (void)makeOffset:(NSInteger)offset{
    
        // 实现原理是先获取一个基于文尾的偏移,然后加上要施加的偏移,再重新根据文尾计算位置,最后利用选取来实现光标定位。
        UITextRange *selectedRange = [self selectedTextRange];
        NSInteger currentOffset = [self offsetFromPosition:self.endOfDocument toPosition:selectedRange.end];
        currentOffset += offset;
        UITextPosition *newPos = [self positionFromPosition:self.endOfDocument offset:currentOffset];
        self.selectedTextRange = [self textRangeFromPosition:newPos toPosition:newPos];
    
    }
    
    - (void)makeOffsetFromBeginning:(NSInteger)offset{
    
        // 先把光标移动到文首,然后再调用上面实现的偏移函数。
        UITextPosition *begin = self.beginningOfDocument;
        UITextPosition *start = [self positionFromPosition:begin offset:0];
        UITextRange *range = [self textRangeFromPosition:start toPosition:start];
        [self setSelectedTextRange:range];
        [self makeOffset:offset];
    
    }
    
    @end
  • 相关阅读:
    MyBatis学习 之 三、动态SQL语句
    MyBatis学习 之 三、动态SQL语句
    MyBatis学习 之 二、SQL语句映射文件(2)增删改查、参数、缓存
    MyBatis学习 之 二、SQL语句映射文件(2)增删改查、参数、缓存
    Spring3 MVC使用@ResponseBody的乱码问题及解决办法
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
  • 原文地址:https://www.cnblogs.com/aiwz/p/6154024.html
Copyright © 2020-2023  润新知