PageRenderTime 8ms CodeModel.GetById 2ms app.highlight 4ms RepoModel.GetById 1ms app.codeStats 0ms

/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
 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}