2015-03-05 11 views
11

Zajmuję się tworzeniem aplikacji do obsługi wiadomości i chcę, aby klawiatura prognostyczna w systemie iOS 8 rozpoznawała, że ​​użytkownik, który tworzy wiadomość, odpowiada na poprzednią wiadomość.Możliwe programowe podawanie kontekstu klawiatury/tekstu źródłowego w systemie iOS?

Chcę więc móc podać ciąg znaków na klawiaturze, aby zapewnić kontekst do prognozowania. Jeśli więc użytkownik zostanie zapytany o pytanie, które można zinterpretować jako polarne (tak/nie), to podpowiedziowa klawiatura powinna być dostępna dla programistów?

Należy pamiętać, że nie mówię o niestandardowej klawiaturze, po prostu karmienie standardowej klawiatury pewnym kontekstem dla jej przewidywań. Nie jestem również zainteresowany faktycznym dostosowywaniem szybkich odpowiedzi typu as in this question. Chcę tylko, żeby klawiatura wiedziała, o czym pisze.

Odpowiedz

8

Ściśle wprowadzanie sugestii do domyślnej klawiatury nie jest możliwe. Jeśli jednak chcesz zapewnić użytkownikom odpowiednią jakość, ukryłbym pasek sugestii iOS przy użyciu myTextView.autocorrectionType = UITextAutocorrectionTypeNo;, a następnie zastąp ten widok moim własnym niestandardowym widokiem, który naśladuje widok sugestii do. Po wpisaniu przez użytkownika znaku lub wybraniu opcji ukryj niestandardowy widok sugestii i ponownie włącz pasek sugestii na iOS.

I Subclassed UIInputView tylko do tego (przezroczystość i przejście jest trochę wyłączona, ale wszystko inne działa ładna dobrze).

#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 

zaimplementować to w UITextField lub UITextView że już podklasy, importować SuggestionView i wdrożenie SuggestionViewDelegate. Następnie w UITextFieldDelegate (lub) metod UITextViewDelegate dodać:

- (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]; 
} 

Następnie, wykonuje SuggestionViewDelegate:

- (void)suggestionSelected:(NSString *)suggestion { 
    [self.messageTextField setText:[NSString stringWithFormat:@"%@%@ ", self.messageTextField.text, suggestion]]; 
    [self removeSuggestionView]; 
} 

Chociaż nie jest to idealne rozwiązanie, że nie tworzy żądany efekt.

+3

Podczas gdy miałem nadzieję, że ktoś wpadnie i powie: "Tak, to możliwe, po prostu zrób XYZ", to jest niesamowita odpowiedź. Dziękuję za udostępnienie Twojego kodu i podejścia - chciałbym tylko, żeby Apple to otworzył, choć przypuszczam, że to mała marchewka do używania Wiadomości zamiast WhatsApp, FB Messenger, Kik, etcetera itd. – sbauch

3

Ponieważ istnieje teraz sposób na znalezienie dalszych informacji na ten temat w oficjalnej dokumentacji Apple, myślę, że to niemożliwe. Jednak masz dwie opcje:

  • Utrzymuj standardowej klawiatury i ręcznie wyświetlić pasek (w instancji UIView) na wierzchu.
  • Utwórz niestandardową klawiaturę od podstaw (znacznie trudniejsze). Możesz read more here.

Można również myśleć o zupełnie innym UX. Na przykład. jeśli użytkownik może wybrać jedną z sugestii, należy tylko przedstawić te sugestie i zachować mały przycisk, aby wprowadzić niestandardowe dane wejściowe (i tutaj zamknąć klawiaturę). Jeśli użytkownik prawdopodobnie wprowadzi dane niestandardowe, zapoznaj się z powyższymi alternatywami.

+0

Co za miła odpowiedź. – Cesare

+0

To jest wspaniała, zwięzła odpowiedź (choć nie ta, którą chciałem usłyszeć!), Więc dziękuję. Nie stworzyłem nagrody, ale czuję się zobowiązany do wyboru drugiej odpowiedzi jako "najbardziej słuszna".Myślę, że zupełnie inny UX nie działa (dla mnie, w tym przypadku), ponieważ świadomie staram się wprowadzić dane wejściowe, które mogłyby być z łatwością 2 przyciskami bardziej z NLP/konwersacji. – sbauch

+0

Nie ma problemu, mam nadzieję, że będziesz w stanie zrobić to, czego potrzebujesz, drugą odpowiedź! –

Powiązane problemy