/TalkBack/src/com/google/android/marvin/talkback/formatter/ScrollFormatter.java

http://eyes-free.googlecode.com/ · Java · 87 lines · 45 code · 16 blank · 26 comment · 8 complexity · e26601692918b1c6a3f9f4656e5c96e4 MD5 · raw file

  1. // Copyright 2011 Google Inc. All Rights Reserved.
  2. package com.google.android.marvin.talkback.formatter;
  3. import android.content.Context;
  4. import android.os.Bundle;
  5. import android.text.TextUtils;
  6. import android.view.accessibility.AccessibilityEvent;
  7. import com.google.android.marvin.talkback.AccessibilityEventCompatUtils;
  8. import com.google.android.marvin.talkback.Formatter;
  9. import com.google.android.marvin.talkback.R;
  10. import com.google.android.marvin.talkback.Utils;
  11. import com.google.android.marvin.talkback.Utterance;
  12. /**
  13. * Formatter that returns an utterance to announce scrolling.
  14. *
  15. * @author alanv@google.com (Alan Viverette)
  16. */
  17. public class ScrollFormatter implements Formatter {
  18. @Override
  19. public boolean format(AccessibilityEvent event, Context context, Utterance utterance, Bundle args) {
  20. final CharSequence text = Utils.getEventText(context, event);
  21. if (!TextUtils.isEmpty(text)) {
  22. utterance.getText().append(text);
  23. return true;
  24. }
  25. final float percent = getScrollPercent(event);
  26. final float rate = (float) Math.pow(2.0, (percent / 50.0) - 1);
  27. utterance.getEarcons().add(R.raw.item);
  28. utterance.getMetadata().putFloat(Utterance.KEY_METADATA_EARCON_RATE, rate);
  29. return true;
  30. }
  31. /**
  32. * Returns the percentage scrolled within a scrollable view. The value will
  33. * be in the range {0..100} where 100 is the maximum scroll amount.
  34. *
  35. * @param event The event from which to obtain the scroll position.
  36. * @return The percentage scrolled within a scrollable view.
  37. */
  38. private float getScrollPercent(AccessibilityEvent event) {
  39. final float position = getScrollPosition(event);
  40. return (100.0f * Math.max(0.0f, Math.min(1.0f, position)));
  41. }
  42. /**
  43. * Returns a floating point value representing the scroll position of an
  44. * {@link AccessibilityEvent}. This value may be outside the range {0..1}.
  45. * If there's no valid way to obtain a position, this method returns 0.5.
  46. *
  47. * @param event The event from which to obtain the scroll position.
  48. * @return A floating point value representing the scroll position.
  49. */
  50. private float getScrollPosition(AccessibilityEvent event) {
  51. final int itemCount = event.getItemCount();
  52. final int fromIndex = event.getFromIndex();
  53. // First, attempt to use (fromIndex / itemCount).
  54. if ((fromIndex >= 0) && (itemCount > 0)) {
  55. return (fromIndex / (float) itemCount);
  56. }
  57. final int scrollY = event.getScrollY();
  58. final int maxScrollY = AccessibilityEventCompatUtils.getMaxScrollY(event);
  59. // Next, attempt to use (scrollY / maxScrollY). This will fail if the
  60. // getMaxScrollX() method is not available.
  61. if ((scrollY >= 0) && (maxScrollY > 0)) {
  62. return (scrollY / (float) maxScrollY);
  63. }
  64. // Finally, attempt to use (scrollY / itemCount).
  65. // TODO(alanv): Hack from previous versions -- is it still needed?
  66. if ((scrollY >= 0) && (itemCount > 0) && (scrollY <= itemCount)) {
  67. return (scrollY / (float) itemCount);
  68. }
  69. return 0.5f;
  70. }
  71. }