iPad split-tastatură

Creez o aplicație similară cu aplicația iMessage a iPad-ului care face mesageria. Deci, există o vizualizare de intrare ancorată în partea inferioară a vederii mesajului și vizualizarea accesoriilor de intrare atunci când este afișată tastatura. De asemenea, vizualizarea mesajului trebuie să fie redimensionată corespunzător atunci când tastatura este afișată în timp ce este andocată.

Problema pe care o am este că datele de notificare care apar de la UIKeyboardWillChangeFrameNotification nu sunt coerente.

În primul rând, există 3 moduri în care utilizatorul poate dezactiva tastatura:

  1. Apăsați și țineți apăsată tasta din dreapta jos, apoi glisați în sus
  2. Apăsați și țineți apăsată tasta din dreapta jos, când apare meniul, selectați "decupa"
  3. Apăsați-și țineți apăsată tasta din dreapta jos, când apare meniul, selectați "split" (Divizat)

Pentru cazul # 1, datele de notificare de la UIKeyboardWillChangeFrameNotification sunt coerente. Iată datele:

userInfo = {
    UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 0}, {768, 304}}";
}

Pentru cazul # 2 și # 3 datele sunt inconsistente, iată ce primesc:

userInfo = {
    UIKeyboardAnimationCurveUserInfoKey = 0;
    UIKeyboardAnimationDurationUserInfoKey = "0.25";
    UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {768, 304}}";
    UIKeyboardCenterBeginUserInfoKey = "NSPoint: {384, 872}";
    UIKeyboardCenterEndUserInfoKey = "NSPoint: {384, 1136}";
    UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 0}, {768, 304}}";
    UIKeyboardFrameChangedByUserInteraction = 0;
    UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, -264}, {768, 304}}";
}

Ceea ce este ciudat aici este că atunci când ascult pentru UIKeyboardDidChangeFrameNotification în cazul # 2 sau # 3, datele se introduc așa cum era de așteptat:

userInfo = {
    UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 0}, {768, 304}}";
}

De ce sunt diferite datele de notificare? A găsit cineva o modalitate clară de a detecta evenimentele cu tastatură split?

9

2 răspunsuri

Nu există o metodă clară.

am rezolvat această problemă în pașii următori:

  1. Obțineți orientarea curentă.
  2. Dacă orientarea este Peisaj, atunci obțin înălțime din UIKeyboardFrameEndUserInfoKey. el trebuie să fie egal cu 216. Aceasta înseamnă că tastatura este modul Split, altfel nu;
  3. Dacă orientarea este Portret, atunci primesc înălțime din UIKeyboardFrameEndUserInfoKey. el trebuie să fie egal cu 216. Aceasta înseamnă că tastatura este modul Split, altfel nu;

Actualizez de exemplu. Cu metoda convertRect.

3
adăugat
Feriți-vă, aceasta nu este o soluție bună. Vârstele de la tastatură se modifică în funcție de locație, versiunea și dispozitivul.
adăugat autor capikaw, sursa
nicio diferenta. 216 nu este pixeli, parametrul său punct independent de rezoluție. Dar acest lucru nu funcționează cu iPhone 4s și 5. Și iPhone nu are tastatură divizată. Schimbă factorul de formă.
adăugat autor Bimawa, sursa
@capikaw 216 nu este param static, un număr vine cu tasta UIKeyboardFrameEndUserInfoKey .
adăugat autor Bimawa, sursa
Acest lucru va face mai greu de la introducerea iPad Mini. Nici măcar nu am atins iOS 7 ...
adăugat autor Takeshi Kaga, sursa

Aceasta este o metodă oarecum hacked, dar de încredere pentru a determina dacă tastatura este împărțită.

NSArray *classPath = @[
  @"KeyboardAutomatic",
  @"KeyboardImpl",
  @"KeyboardLayoutStar",
  @"KBKeyplaneView",
  @"KBSplitImageView"
];
UIView *splitView = textField.inputAccessoryView.superview;
for (NSString *className in classPath) {
  for (UIView *subview in splitView.subviews) {
    if ([NSStringFromClass([subview class]) rangeOfString:className].location != NSNotFound) {
      splitView = subview;
      break;
    }
  }
}
BOOL isSplit = [splitView.subviews count] > 1;

Evident, pentru ca acest lucru să funcționeze, aveți nevoie de un UITextField/UITextView cu un inputAccessoryView (nu puteți folosi doar o vizualizare goală pentru asta).

Note: The behavior of textField.inputAccessoryView.superview is quite finicky, and usually depends on the keyboard having been displayed once before calling superview. Also to pass the App Store submission process I removed the 'UI' prefix from the private class names. That's not a guarantee Apple will not flag your app, but this approach has been used successfully before.

Am testat-o ​​doar pe iOS7, dar dacă nu funcționează și pe alte versiuni de iOS, ar putea fi utilizate abordări similare.

1
adăugat
acest lucru ar putea funcționa, dar de ce accesați subviews 0 0 1 0?
adăugat autor Daij-Djan, sursa
care ar trebui să fie făcut folosind numele de clasă, cel puțin așa că nu doar crash
adăugat autor Daij-Djan, sursa
Nu. puteți .. numele arent considerate într-adevăr limite - simbolurile sunt. Eu fac N aplicații și am făcut-o de ani de zile
adăugat autor Daij-Djan, sursa
astfel încât ceva ca în cazul în care (view.className rangeOfString: @ "Splitview" sau className hasPrefix: @ "UIButtton" ...
adăugat autor Daij-Djan, sursa
Aș prefera acest lucru pentru a compara dimensiunile punctelor așa cum se vede aboce Cred că ...
adăugat autor Daij-Djan, sursa
Pentru că trece prin ierarhia de vizualizare în căutarea unei clase private care reda tastatura. Am folosit Reveal pentru a vedea cum se găsește starea ecranului tastaturii. Consultați aici .
adăugat autor cagey, sursa
Este clar o idee proastă de a folosi acest cod exact în producție, dar sperăm că răspunsul poate fi în continuare util pentru unii oameni.
adăugat autor cagey, sursa
Nu puteți folosi nume de clasă deoarece acestea sunt private, astfel încât acestea nu vor fi permise în App Store. Evident, dacă implementați acest lucru în codul de producție, acesta trebuie scris mai în siguranță decât răspunsul meu scurt. Modul în care UIKit generează tastatura este consistent de fiecare dată, astfel încât această metodă funcționează în mod fiabil.
adăugat autor cagey, sursa
Oh! În acest caz, cred că ați putea trece cu mai multă siguranță prin fiecare dintre copii pentru a vă asigura că trageți exact vederea de care aveți nevoie. Voi actualiza răspunsul în acest sens.
adăugat autor cagey, sursa