可以以编程方式提供 iOS 预测键盘上下文/源文本吗?
Posted
技术标签:
【中文标题】可以以编程方式提供 iOS 预测键盘上下文/源文本吗?【英文标题】:Possible to programmatically feed the iOS predictive keyboard context/source text? 【发布时间】:2015-03-05 22:50:44 【问题描述】:我正在开发一个消息应用程序,并且希望 ios 8 中的预测键盘能够识别正在撰写消息的用户正在回复上一条消息。
所以我希望能够向键盘输入一个字符串,以便为其提供预测上下文。因此,如果用户被问到一个可以解释为极坐标(是/否)的问题,那么预测键盘应该有Yes | No | Maybe
这对开发人员可用吗?
请注意,我不是在谈论自定义键盘,只是为标准键盘提供一些上下文以进行预测。我也不关心实际自定义快速类型回复as in this question。我只是想让键盘知道它在输入什么。
【问题讨论】:
【参考方案1】:无法将建议严格输入到默认键盘。但是,如果您想为用户提供同等体验,我会使用 myTextView.autocorrectionType = UITextAutocorrectionTypeNo;
隐藏 iOS 建议栏,然后用我自己的模仿建议视图的自定义视图替换该视图。用户输入字符或选择选项后,隐藏自定义建议视图并重新启用 iOS 建议栏。
为此,我将 UIInputView 子类化了(透明度和过渡效果有些差,但其他一切都相当正常工作)。
#import <UIKit/UIKit.h>
@protocol SuggestionViewDelegate <NSObject>
@required
- (void)suggestionSelected:(NSString *)suggestion;
@end
@interface SuggestionView : UIInputView
- (instancetype)init;
- (instancetype)initWithFrame:(CGRect)frame;
/**
* The list of suggestions being displayed.
* The array contains 0-3 strings.
*
* @return Array of NSString's representing the current suggested strings
*/
- (NSArray *)suggestions;
/**
* Add a suggestion to display in the view.
* If there are already maxSuggestionCount suggestions, the added suggestion will push one of them out.
* If there are already maxSuggestionCount suggestions and the input is 'nil' then the last suggestion will be removed.
*
* @param suggestion String to suggest to the user
*/
- (void)addSuggestion:(NSString *)suggestion;
/**
* Removes the suggestion from the list of displayed suggestions.
* If the string is not in the set then there is no change made.
*
* @param suggestion NSString to remove from the suggested strings
*/
- (void)removeSuggestion:(NSString *)suggestion;
/**
* Takes in either NSArray or NSSet and replaces 'suggestions' with the input.
* Only the first three arguments are recognized.
* Objects should be strings. Undefined behavior otherwise.
*
* @param suggestions NSArray or NSSet with 0-3 NSStrings
*/
- (void)setSuggestions:(NSObject *)suggestions;
@property (weak) id <SuggestionViewDelegate> delegate;
/**
* The maximum number of suggestions allowed. Default is 3.
*/
@property (nonatomic) NSInteger maxSuggestionCount;
@end
#import "SuggestionView.h"
#define kScreenWidth [UIScreen mainScreen].bounds.size.width
@implementation SuggestionView
NSMutableOrderedSet *_suggestions;
NSMutableArray *_suggestionButtons;
- (instancetype)init
self = [self initWithFrame:CGRectMake(0.0f, 0.0f, kScreenWidth, 36.0f)];
if (self)
return self;
- (instancetype)initWithFrame:(CGRect)frame
self = [super initWithFrame:frame inputViewStyle:UIInputViewStyleKeyboard];
if (self)
_suggestions = [[NSMutableOrderedSet alloc] initWithCapacity:3];
self.maxSuggestionCount = 3;
_suggestionButtons = [[NSMutableArray alloc] init];
self.backgroundColor = [UIColor colorWithWhite:0.0f alpha:0.04f];
return self;
#pragma mark - Modifying Suggestions
- (void)addSuggestion:(NSString *)suggestion
if (suggestion)
[_suggestions addObject:suggestion];
while (_suggestions.count > self.maxSuggestionCount)
[_suggestions removeObjectAtIndex:self.maxSuggestionCount];
- (void)removeSuggestion:(NSString *)suggestion
[_suggestions removeObject:suggestion];
- (void)setSuggestions:(NSObject *)suggestions
if ([suggestions respondsToSelector:@selector(countByEnumeratingWithState:objects:count:)])
[_suggestions removeAllObjects];
for (NSString *suggestion in (NSArray *)suggestions)
if (_suggestions.count < self.maxSuggestionCount)
[_suggestions addObject:suggestion];
else
break;
- (NSArray *)suggestions
NSMutableArray *suggestionsArray = [[NSMutableArray alloc] initWithCapacity:_suggestions.count];
for (NSString *suggestion in _suggestions)
[suggestionsArray addObject:suggestion];
return suggestionsArray;
#pragma mark - Visual Layout of Suggestions
- (void)layoutSubviews
[self layoutSuggestions];
- (void)layoutSuggestions
for (UIView *subview in _suggestionButtons)
[subview removeFromSuperview];
[_suggestionButtons removeAllObjects];
for (int i = 0; i < _suggestions.count; i++)
NSString *suggestion = _suggestions[i];
UIButton *suggestionButton = [[UIButton alloc] initWithFrame:CGRectMake(i * self.bounds.size.width/_suggestions.count, 0.0f, self.bounds.size.width/_suggestions.count, self.bounds.size.height)];
[suggestionButton setTitle:suggestion forState:UIControlStateNormal];
suggestionButton.titleLabel.adjustsFontSizeToFitWidth = YES;
suggestionButton.titleLabel.textAlignment = NSTextAlignmentCenter;
[suggestionButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[suggestionButton addTarget:self action:@selector(buttonTouched:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:suggestionButton];
if (i > 0)
UIView *whiteLine = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 0.5f, self.bounds.size.height)];
whiteLine.backgroundColor = [UIColor whiteColor];
[suggestionButton addSubview:whiteLine];
[_suggestionButtons addObject:suggestionButton];
#pragma mark - Selecting a Suggestion
- (void)buttonTouched:(UIButton *)button
NSTimeInterval animationDuration = 0.09f;
[UIView animateWithDuration:animationDuration animations:^
[button setBackgroundColor:[UIColor whiteColor]];
if ([self.delegate respondsToSelector:@selector(suggestionSelected:)])
[self performSelector:@selector(suggestionSelected:) withObject:button.currentTitle afterDelay:animationDuration * 0.9f];
[button performSelector:@selector(setBackgroundColor:) withObject:[UIColor clearColor] afterDelay:animationDuration];
];
- (void)suggestionSelected:(NSString *)suggestion
if ([self.delegate respondsToSelector:@selector(suggestionSelected:)])
[self.delegate suggestionSelected:suggestion];
@end
要将其实现到您已经子类化的UITextField
或UITextView
,请导入 SuggestionView 并实现 SuggestionViewDelegate。然后,在UITextFieldDelegate
(或UITextViewDelegate
)方法中,添加:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
if ([textField isEqual:self.messageTextField])
if (self.suggestionView.suggestions.count > 0 && textField.text.length == 0)
textField.inputAccessoryView = self.suggestionView;
textField.autocorrectionType = UITextAutocorrectionTypeNo;
[textField reloadInputViews];
return YES;
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
if ([textField isEqual:self.messageTextField])
if (string.length > 0)
[self removeSuggestionView];
return YES;
- (void)removeSuggestionView
self.messageTextField.inputAccessoryView = nil;
[self.messageTextField setInputAccessoryView:nil];
self.messageTextField.autocorrectionType = UITextAutocorrectionTypeYes;
[self.messageTextField reloadInputViews];
[self.messageTextField performSelector:@selector(resignFirstResponder) withObject:self afterDelay:0.0f];
[self.messageTextField performSelector:@selector(becomeFirstResponder) withObject:self afterDelay:0.0f];
然后,实现SuggestionViewDelegate
:
- (void)suggestionSelected:(NSString *)suggestion
[self.messageTextField setText:[NSString stringWithFormat:@"%@%@ ", self.messageTextField.text, suggestion]];
[self removeSuggestionView];
虽然这不是一个完美的解决方案,但它确实创造了预期的效果。
【讨论】:
虽然我希望有人会突然说:“是的,有可能,只要做 XYZ”,这是一个令人难以置信的答案。感谢您分享您的代码和方法 - 我只是希望 Apple 能够打开它,尽管我认为使用 Messages 而不是 WhatsApp、FB Messenger、Kik 等是一个小胡萝卜【参考方案2】:由于现在可以在 Apple 官方文档中找到有关如何执行此操作的更多信息,我想这是不可能的。但是你有两个选择:
保留标准键盘并在其顶部手动显示一个栏(在 UIView 实例中)。 从头开始创建您的自定义键盘(要困难得多)。你可以read more here。您还可以考虑完全不同的用户体验。 例如。如果您的用户可能会选择您的建议之一,则仅显示这些建议并保留一个小按钮以输入自定义输入(并在此处关闭键盘)。如果用户可能会输入自定义输入,请参考上述两种选择。
【讨论】:
这是一个伟大而简洁的答案(尽管不是我想听到的答案!啊!!!),所以谢谢。我没有创造赏金,但觉得有义务选择另一个答案作为“最正确的”。我认为完全不同的 UX 不起作用(对我来说,在这种情况下),因为我有意识地尝试做出一个输入,它可以很容易地成为 NLP/对话输入的 2 个按钮。 没问题,希望你能做你需要的其他答案!以上是关于可以以编程方式提供 iOS 预测键盘上下文/源文本吗?的主要内容,如果未能解决你的问题,请参考以下文章