在 iOS 6 下,当使用外部蓝牙键盘和在模拟器中工作时,UITextView 尊重向上和向下箭头键。在 iOS 7 下,向上和向下箭头键不再做任何事情,尽管向左和向右箭头键仍然移动光标。
在 iOS 7 下,如何在 UITextView 中支持外部键盘的向上和向下箭头键?
在 iOS 6 下,当使用外部蓝牙键盘和在模拟器中工作时,UITextView 尊重向上和向下箭头键。在 iOS 7 下,向上和向下箭头键不再做任何事情,尽管向左和向右箭头键仍然移动光标。
在 iOS 7 下,如何在 UITextView 中支持外部键盘的向上和向下箭头键?
我不知道在 iOS 7 中是否有意省略了向上和向下箭头键支持。这是一种恢复大约 95% 丢失功能的方法。请注意,这个子类UITextView
还纠正了 iOS 7 中滚动文本视图导致其疯狂跳跃的一些问题。我已经看到它从一个长文件的中间跳转到文件的末尾。
我发现这个实现的唯一问题是没有处理重复键操作系统,所以如果你按住向上或向下箭头键,移动光标的代码仍然只调用一次。
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
@implementation ArrowKeyTextView
- (id) initWithFrame: (CGRect) frame {
self = [super initWithFrame:frame];
if (self) {
// This has nothing to do with support for arrow keys, but it does fix a number of issues with scrolling in iOS 7.
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0"))
self.layoutManager.allowsNonContiguousLayout = NO;
}
return self;
}
- (NSArray *) keyCommands {
UIKeyCommand *upArrow = [UIKeyCommand keyCommandWithInput: UIKeyInputUpArrow modifierFlags: 0 action: @selector(upArrow:)];
UIKeyCommand *downArrow = [UIKeyCommand keyCommandWithInput: UIKeyInputDownArrow modifierFlags: 0 action: @selector(downArrow:)];
return [[NSArray alloc] initWithObjects: upArrow, downArrow, nil];
}
- (void) upArrow: (UIKeyCommand *) keyCommand {
UITextRange *range = self.selectedTextRange;
if (range != nil) {
float lineHeight = self.font.lineHeight;
CGRect caret = [self firstRectForRange: range];
if (isinf(caret.origin.y)) {
// Work-around for a bug in iOS 7 that returns bogus values when the caret is at the start of a line.
range = [self textRangeFromPosition: range.start toPosition: [self positionFromPosition: range.start offset: 1]];
caret = [self firstRectForRange: range];
caret.origin.y = caret.origin.y + lineHeight;
}
caret.origin.y = caret.origin.y - lineHeight < 0 ? 0 : caret.origin.y - lineHeight;
caret.size.width = 1;
UITextPosition *position = [self closestPositionToPoint: caret.origin];
self.selectedTextRange = [self textRangeFromPosition: position toPosition: position];
caret = [self firstRectForRange: self.selectedTextRange];
if (isinf(caret.origin.y)) {
// Work-around for a bug in iOS 7 that occurs when the range is set to a position past the end of the last character
// on a line.
NSRange range = {0, 0};
range.location = [self offsetFromPosition: self.beginningOfDocument toPosition: position];
self.selectedRange = range;
}
}
}
- (void) downArrow: (UIKeyCommand *) keyCommand {
UITextRange *range = self.selectedTextRange;
if (range != nil) {
float lineHeight = self.font.lineHeight;
CGRect caret = [self firstRectForRange: range];
if (isinf(caret.origin.y)) {
// Work-around for a bug in iOS 7 that returns bogus values when the caret is at the start of a line.
range = [self textRangeFromPosition: range.start toPosition: [self positionFromPosition: range.start offset: 1]];
caret = [self firstRectForRange: range];
caret.origin.y = caret.origin.y + lineHeight;
}
caret.origin.y = caret.origin.y + lineHeight < 0 ? 0 : caret.origin.y + lineHeight;
caret.size.width = 1;
UITextPosition *position = [self closestPositionToPoint: caret.origin];
self.selectedTextRange = [self textRangeFromPosition: position toPosition: position];
caret = [self firstRectForRange: self.selectedTextRange];
if (isinf(caret.origin.y)) {
// Work-around for a bug in iOS 7 that occurs when the range is set to a position past the end of the last character
// on a line.
NSRange range = {0, 0};
range.location = [self offsetFromPosition: self.beginningOfDocument toPosition: position];
self.selectedRange = range;
}
}
}
@end
这对我有用,除了 downArrow 中的这一部分:
CGRect caret = [self firstRectForRange: range];
if (isinf(caret.origin.y)) {
// Work-around for a bug in iOS 7 that returns bogus values when the caret is at the start of a line.
range = [self textRangeFromPosition: range.start toPosition: [self positionFromPosition: range.start offset: 1]];
caret = [self firstRectForRange: range];
caret.origin.y = caret.origin.y + lineHeight;
}
我不得不删除该if
行:
CGRect caret = [self firstRectForRange: range];
// Work-around for a bug in iOS 7 that returns bogus values when the caret is at the start of a line.
range = [self textRangeFromPosition: range.start toPosition: [self positionFromPosition: range.start offset: 1]];
caret = [self firstRectForRange: range];
caret.origin.y = caret.origin.y + lineHeight;
它就像一个魅力!
似乎该问题已在 iOS 7.0.3 中得到修复,并且箭头键可以按预期移动光标。