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