2014-05-12 13 views
5

Mam TextView z tekstem "Hello World!" zdefiniowane w układzie xmlZachowanie dziwne: Typ klasy obiektu dodany przez metodę getText() zmian TextView po utworzeniu AccessibilityNodeInfo z TextView

TextView textView = (TextView)findViewById(R.id.textView); 

metoda TextView za getText() zwraca obiekt klasy java.lang.String

//Returns object of String class 
Toast.makeText(getApplicationContext(), textView.getText().getClass().getName(), Toast.LENGTH_LONG).show(); 

Jeśli ta sama nazywa po utworzeniu AccessibilityNodeInfo, zwraca obiekt android.text.SpannableString

//Creating AccessibilityNodeInfo 
AccessibilityNodeInfo info = textView.createAccessibilityNodeInfo(); 

//Returns object of SpannableString 
Toast.makeText(getApplicationContext(), "After creating AccessibilityNodeInfo: " + textView.getText().getClass().getName(), Toast.LENGTH_LONG).show(); 

W jaki sposób tworzony jest AccessibilityNodeInfo w odniesieniu do obiektu zwróconego przez metodę getText()?

Uwaga:Dzieje się tak tylko w Android 4.3 i wyżej

+0

Ważniejsze pytanie brzmi: dlaczego Cię to obchodzi? 'getText()' określa, że ​​zwraca 'CharSequence' ... nic więcej, nic mniej. Rzeczywistym typem zwrotów może być dowolna implementacja 'CharSequence', a ty nigdy nie powinieneś liczyć na to, że jest to coś innego. –

+0

Cóż, nie mogę tutaj opisać pełnych wymagań. Mogę tylko wspomnieć, że mam do czynienia z innym kodem dewelopera i tworzenie AccessiblityNodeInfo łamie ich kod. I jestem tylko ciekawy wiedzieć, w jaki sposób jest zwracany typ metody getText() istotne dla AccessiblityNodeInfo węzła? –

+0

Czuję się dla ciebie. 90% mojej pracy to radzenie sobie z ultra-podekscytowanym kodem stron trzecich, zamiast wykonywać jakąkolwiek prawdziwą pracę własną. Najlepszą praktyką jest * nie * dokumentowanie odpowiedzi na pytania, które zadajesz, więc ... powodzenia. Być może będziesz musiał zanurkować w kodzie Androida, a nawet jeśli znajdziesz odpowiedź, możesz nie być w stanie nic z tym zrobić. –

Odpowiedz

3

Wynika to z nowymi funkcjami, takimi jak select, cut, copy, paste funkcje dodane do AccessibilityNodeInfo. Został wprowadzony w systemie Android 4.3 i jest udokumentowany here.

Zaznacz tekst i kopiuj/wklej

AccessibilityNodeInfo teraz udostępnia API, które umożliwiają osobie AccessibilityService wybrać, wycinanie, kopiowanie i wklejanie tekstu w węźle.

Aby określić zaznaczenie tekstu do wycięcia lub skopiowania, usługa dostępność mogą korzystać z nowych działań, ACTION_SET_SELECTION, przechodząc z nim początku wybór i zakończenia z ACTION_ARGUMENT_SELECTION_START_INT i ACTION_ARGUMENT_SELECTION_END_INT.Alternatywnie możesz zaznaczyć tekst , manipulując pozycją kursora, używając istniejącej akcji, ACTION_NEXT_AT_MOVEMENT_GRANULARITY (poprzednio tylko do przemieszczania pozycji kursora ) i dodając argument ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN.

Następnie można wyciąć lub skopiować za pomocą ACTION_CUT, ACTION_COPY, a następnie wkleić za pomocą ACTION_PASTE.

Uwaga: Te nowe interfejsy API są również dostępne w poprzednich wersjach systemu Android za pośrednictwem biblioteki pomocy systemu Android, z klasą AccessibilityNodeInfoCompat.

Aby wdrożyć funkcję select, że styleable/markup obiekty muszą być dołączone do tekstu bazowego. W związku z tym tekst zmienia się z String na SpannableString. Jest to kod View.java, który wprowadził tę funkcję. Poniższy kod zmienia typ na SpannableString.

@Override 
public CharSequence getIterableTextForAccessibility() { 
    if (!(mText instanceof Spannable)) { 
     setText(mText, BufferType.SPANNABLE); 
    } 
    return mText; 
} 
2

Od patrząc na źródle View i TextView (przynajmniej na poziomie API 19), można stwierdzić, że „winowajcą” jest TextView.getIterableTextForAccessibility(). W klasie TextView, jest zdefiniowana jako:

/** 
* @hide 
*/ 
@Override 
public CharSequence getIterableTextForAccessibility() { 
    if (!(mText instanceof Spannable)) { 
     setText(mText, BufferType.SPANNABLE); 
    } 
    return mText; 
} 

Metoda ta nazywana jest w ramach sekwencji createAccessibilityNodeInfo(), zwłaszcza View.onInitializeAccessibilityNodeInfoInternal().

Ponieważ nie jest to udokumentowane, trudno jest dokładnie określić, dlaczego (a nawet, jeśli był zamierzony lub po prostu efekt uboczny), ale jasne jest, że tekst będzie musiał ostatecznie być Spannable, nawet jeśli nie był jednym przed.

Od history of TextView.java w zwierciadle GitHub w repozytorium AOSP wydaje się, że the commit, która wprowadziła tę logikę, zostało wykonane przez Svetoslav Ganov. Bez pytania, nie jestem pewien, co jeszcze możesz zrobić, aby dowiedzieć się więcej. :)

Co do "dlaczego miałbyś znać ten" bok całej sprawy (poza ciekawością), dokładna klasa tekstu TextView nie powinna być istotna ... Zakładam dziedzictwo kod robił coś w rodzaju String x = (String)textView.getText(). Jeśli potrzebujesz String zamiast CharSequence, zastąpienie tych połączeń przez getText().toString() powinno wystarczyć.

+0

Bingo! Kod źródłowy używa operacji rzucania zamiast używania metody toString(), która początkowo prowadzi do tego. W pewnym sensie rozwijam bibliotekę, a moja biblioteka nie wie, w jaki sposób programiści używają interfejsów API. Westchnienie! –