android - programacion - no puedo activar servicios de accesibilidad
Problemas de implementación de la función de accesibilidad en Android. (2)
Estoy desarrollando una aplicación que ve libros. Hay una pantalla (Actividad) que muestra un libro. Tiene una vista personalizada, algo similar a ViewSwitcher y cada página es un mapa de bits que se representa mediante una vista personalizada.
Ahora debo implementar la función de accesibilidad: el libro debe ser leído por el teléfono (audio).
He leído la sección Accesibilidad aquí https://developer.android.com/guide/topics/ui/accessibility/index.html pero no está lo suficientemente claro.
Utilizo SupportLibrary para la gestión de accesibilidad y ahora tengo este código en ViewGroup (que administra las páginas del libro). Código 1 :
private class EditionPagesViewSwitcherAccessibilityDelegate extends AccessibilityDelegateCompat {
private int mPageCount;
private double[] mPageRange;
@Override
public void onInitializeAccessibilityEvent(final View host, final AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(host, event);
event.setClassName(EditionPagesViewSwitcher.class.getName());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
event.setScrollable(canScroll());
}
if (event.getEventType() == AccessibilityEventCompat.TYPE_VIEW_SCROLLED && updatePageValues()) {
event.setItemCount(mPageCount);
// we use +1 because of user friendly numbers (from 1 not 0)
event.setFromIndex((int) (mPageRange[0] + 1));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
event.setToIndex((int) (mPageRange[1] + 1));
}
}
}
@Override
public void onInitializeAccessibilityNodeInfo(final View host, final AccessibilityNodeInfoCompat info) {
super.onInitializeAccessibilityNodeInfo(host, info);
info.setClassName(EditionPagesViewSwitcher.class.getName());
info.setScrollable(canScroll());
info.setLongClickable(true);
if (canScrollForward()) {
info.addAction(AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD);
}
if (canScrollBackward()) {
info.addAction(AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD);
}
}
@Override
public boolean performAccessibilityAction(final View host, final int action, final Bundle args) {
if (super.performAccessibilityAction(host, action, args)) {
return true;
}
switch (action) {
case AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD: {
if (canScrollForward()) {
showNext();
return true;
}
}
return false;
case AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD: {
if (canScrollBackward()) {
showPrevious();
return true;
}
}
return false;
}
return false;
}
Aquí está el código de la página vista Código 2 :
@Override
public void onInitializeAccessibilityEvent(final View host, final AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(host, event);
event.setClassName(EditionPageView.class.getName());
if (hasText()) {
event.getText().add(getPageRangeText());
final String trimText = mSurfaceUpdateData.getPageText().trim();
if (trimText.length() > MAX_TEXT_LENGTH) {
event.getText().add(trimText.substring(0, MAX_TEXT_LENGTH));
// event.getText().add(trimText.substring(MAX_TEXT_LENGTH, trimText.length()));
}
else {
event.getText().add(trimText);
}
}
}
@Override
public void onInitializeAccessibilityNodeInfo(final View host, final AccessibilityNodeInfoCompat info) {
super.onInitializeAccessibilityNodeInfo(host, info);
info.setClassName(EditionPageView.class.getName());
}
Debido a que los datos de texto de la página se cargan de forma asíncrona, la accesibilidad por primera vez no tiene ningún texto mientras se ejecuta en el código Inicializar Acceso Accesibilidad. Y luego, cuando se han cargado los datos, se activan los eventos AccessibilityEvent.TYPE_VIEW_SELECTED y AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED. Luego onInitializeAccessibilityEvent se ejecuta de nuevo y el teléfono "lee" el texto del libro.
Así que mis preguntas:
- ¿Es correcta mi implementación de accesibilidad? ¿Puede ser que esté mal diseñado? Porque no encontré ningún buen tutorial sobre esta característica.
- ¿Por qué necesito usar las comprobaciones de las versiones del SDK en las implementaciones de Soporte en el Código 1? ¿Por qué la implementación de soporte no lo maneja correctamente?
- ¿Es realmente necesario disparar TYPE_VIEW_SELECTED y TYPE_VIEW_TEXT_CHANGED? ¿O puede ser que algún otro código deba ser implementado?
- La pregunta principal. En el Código 2 hay una línea de código comentada. El texto de la subcadena de esta declaración de código debe ser menor que MAX_TEXT_LENGTH (es 3800) porque si el texto es más grande no se reproduce nada. Nada. ¿Es restricción de accesibilidad? Cualquier otro texto que sea menor a este valor se juega bien.
- ¿Alguien sabe donde puedo encontrar algún buen tutorial? (sí vi muestras).
- ¿Alguien tiene alguna realización personalizada para mirar?
ACTUALIZADO
Bien. Aquí hay algunas respuestas:
- Como puedo ver, los eventos TYPE_VIEW_SELECTED y TYPE_VIEW_TEXT_CHANGED no son necesarios si no desea que este texto se lea tan pronto como lo reciba.
- En Nexus 7, todo el texto grande se reproduce bien (texto de hasta 8000 símbolos), por lo que este problema no se reproduce en él, pero en Samsung Galaxy Tab 10.1 (Android 4.0.4) y Genymotion emulator de Tab 10.1 con Android 4.3 sí. Y esto es extraño ...
4 .. De acuerdo con la documentación de String.substring()
El primer argumento que pasa es el índice de inicio en la cadena original, el segundo argumento es el índice final en la cadena original.
Ejemplo:
String text = "Hello";
partOfText = text.substring(2,text.length() - 1);
partOfText
es igual a "llo" (el primer carácter es el índice 0)
Entonces al poner su constante MAX_TEXT_LENGTH
como primer argumento, comenzaría en el índice 3800 para eliminar la subcadena.
http://developer.android.com/reference/java/lang/String.html#substring(int)
Tienes razón MAX_TEXT_LENGTH es 3800.
Sobre tu duda,
este código:
event.getText().add(trimText.substring(MAX_TEXT_LENGTH, trimText.length()));
}
estás tratando de subscribir "trimText" de MAX_TEXT_LENGTH a trimText.length ()! Suponiendo que trimText = "STACK", trimText.length () = 5, entonces trimText.substring (3800,5) va a ser?
Al principio, esto no tiene sentido, usarlo correctamente sería así: trimText.substring (0,2) = "ST";