OSDN Git Service

Fading scrollbars return. But you have to opt in.
authorMike Cleron <mcleron@google.com>
Mon, 28 Sep 2009 02:14:12 +0000 (19:14 -0700)
committerMike Cleron <mcleron@google.com>
Mon, 28 Sep 2009 17:47:04 +0000 (10:47 -0700)
12 files changed:
core/java/android/view/View.java
core/java/android/view/ViewConfiguration.java
core/java/android/webkit/WebView.java
core/java/android/widget/AbsListView.java
core/java/android/widget/GridView.java
core/java/android/widget/HorizontalScrollView.java
core/java/android/widget/ListView.java
core/java/android/widget/ScrollView.java
core/java/android/widget/TextView.java
core/res/res/values/attrs.xml
core/res/res/values/public.xml
core/res/res/values/themes.xml

index 642f0fa..9e18418 100644 (file)
@@ -24,6 +24,7 @@ import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.Interpolator;
 import android.graphics.LinearGradient;
 import android.graphics.Matrix;
 import android.graphics.Paint;
@@ -514,7 +515,8 @@ import java.util.WeakHashMap;
  * The framework provides basic support for views that wish to internally
  * scroll their content. This includes keeping track of the X and Y scroll
  * offset as well as mechanisms for drawing scrollbars. See
- * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)} for more details.
+ * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and 
+ * {@link #awakenScrollBars()} for more details.
  * </p>
  *
  * <a name="Tags"></a>
@@ -571,6 +573,8 @@ import java.util.WeakHashMap;
  * @attr ref android.R.styleable#View_scrollbarSize
  * @attr ref android.R.styleable#View_scrollbarStyle
  * @attr ref android.R.styleable#View_scrollbars
+ * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
+ * @attr ref android.R.styleable#View_scrollbarFadeDuration
  * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
  * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
  * @attr ref android.R.styleable#View_scrollbarThumbVertical
@@ -2214,12 +2218,28 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
     protected void initializeScrollbars(TypedArray a) {
         initScrollCache();
 
-        if (mScrollCache.scrollBar == null) {
-            mScrollCache.scrollBar = new ScrollBarDrawable();
-        }
-
         final ScrollabilityCache scrollabilityCache = mScrollCache;
+        
+        if (scrollabilityCache.scrollBar == null) {
+            scrollabilityCache.scrollBar = new ScrollBarDrawable();
+        }
+        
+        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, false);
 
+        if (!fadeScrollbars) {
+            scrollabilityCache.state = ScrollabilityCache.ON;
+        }
+        scrollabilityCache.fadeScrollBars = fadeScrollbars;
+        
+        
+        scrollabilityCache.scrollBarFadeDuration = a.getInt(
+                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
+                        .getScrollBarFadeDuration());
+        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
+                R.styleable.View_scrollbarDefaultDelayBeforeFade,
+                ViewConfiguration.getScrollDefaultDelay());
+
+                
         scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
                 com.android.internal.R.styleable.View_scrollbarSize,
                 ViewConfiguration.get(mContext).getScaledScrollBarSize());
@@ -2263,7 +2283,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
      */
     private void initScrollCache() {
         if (mScrollCache == null) {
-            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext));
+            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
         }
     }
 
@@ -4671,7 +4691,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
             mScrollX = x;
             mScrollY = y;
             onScrollChanged(mScrollX, mScrollY, oldX, oldY);
-            invalidate();
+            if (!awakenScrollBars()) {
+                invalidate();
+            }
         }
     }
 
@@ -4687,6 +4709,120 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
     }
 
     /**
+     * <p>Trigger the scrollbars to draw. When invoked this method starts an
+     * animation to fade the scrollbars out after a default delay. If a subclass
+     * provides animated scrolling, the start delay should equal the duration
+     * of the scrolling animation.</p>
+     *
+     * <p>The animation starts only if at least one of the scrollbars is
+     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
+     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
+     * this method returns true, and false otherwise. If the animation is
+     * started, this method calls {@link #invalidate()}; in that case the
+     * caller should not call {@link #invalidate()}.</p>
+     *
+     * <p>This method should be invoked every time a subclass directly updates
+     * the scroll parameters. (See {@link #mScrollX} and {@link #mScrollY})</p>
+     *
+     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
+     * and {@link #scrollTo(int, int)}.</p>
+     *
+     * @return true if the animation is played, false otherwise
+     *
+     * @see #awakenScrollBars(int)
+     * @see #mScrollX
+     * @see #mScrollY
+     * @see #scrollBy(int, int)
+     * @see #scrollTo(int, int)
+     * @see #isHorizontalScrollBarEnabled()
+     * @see #isVerticalScrollBarEnabled()
+     * @see #setHorizontalScrollBarEnabled(boolean)
+     * @see #setVerticalScrollBarEnabled(boolean)
+     */
+    protected boolean awakenScrollBars() {
+        return mScrollCache != null &&
+                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade);
+    }
+
+    /**
+     * <p>
+     * Trigger the scrollbars to draw. When invoked this method starts an
+     * animation to fade the scrollbars out after a fixed delay. If a subclass
+     * provides animated scrolling, the start delay should equal the duration of
+     * the scrolling animation.
+     * </p>
+     * 
+     * <p>
+     * The animation starts only if at least one of the scrollbars is enabled,
+     * as specified by {@link #isHorizontalScrollBarEnabled()} and
+     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
+     * this method returns true, and false otherwise. If the animation is
+     * started, this method calls {@link #invalidate()}; in that case the caller
+     * should not call {@link #invalidate()}.
+     * </p>
+     * 
+     * <p>
+     * This method should be invoked everytime a subclass directly updates the
+     * scroll parameters. (See {@link #mScrollX} and {@link #mScrollY})
+     * </p>
+     * 
+     * @param startDelay the delay, in milliseconds, after which the animation
+     *        should start; when the delay is 0, the animation starts
+     *        immediately
+     * @return true if the animation is played, false otherwise
+     * 
+     * @see #mScrollX
+     * @see #mScrollY
+     * @see #scrollBy(int, int)
+     * @see #scrollTo(int, int)
+     * @see #isHorizontalScrollBarEnabled()
+     * @see #isVerticalScrollBarEnabled()
+     * @see #setHorizontalScrollBarEnabled(boolean)
+     * @see #setVerticalScrollBarEnabled(boolean)
+     */
+    protected boolean awakenScrollBars(int startDelay) {
+        final ScrollabilityCache scrollCache = mScrollCache;
+        
+        if (scrollCache == null || !scrollCache.fadeScrollBars) {
+            return false;
+        }
+
+        if (scrollCache.scrollBar == null) {
+            scrollCache.scrollBar = new ScrollBarDrawable();
+        }
+
+        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
+
+            // Invalidate to show the scrollbars
+            invalidate();
+
+            if (scrollCache.state == ScrollabilityCache.OFF) {
+                // FIXME: this is copied from WindowManagerService.
+                // We should get this value from the system when it
+                // is possible to do so.
+                final int KEY_REPEAT_FIRST_DELAY = 750;
+                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
+            }
+
+            // Tell mScrollCache when we should start fading. This may
+            // extend the fade start time if one was already scheduled
+            long fadeStartTime = SystemClock.uptimeMillis() + startDelay;
+            scrollCache.fadeStartTime = fadeStartTime;
+            scrollCache.state = ScrollabilityCache.ON;
+
+            // Schedule our fader to run, unscheduling any old ones first
+            if (mAttachInfo != null) {
+                mAttachInfo.mHandler.removeCallbacks(scrollCache);
+                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
+            }
+
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
      * Mark the the area defined by dirty as needing to be drawn. If the view is
      * visible, {@link #onDraw} will be called at some point in the future.
      * This must be called from a UI thread. To call from a non-UI thread, call
@@ -5344,11 +5480,49 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
      * scrollbars are painted only if they have been awakened first.</p>
      *
      * @param canvas the canvas on which to draw the scrollbars
+     * 
+     * @see #awakenScrollBars(int)
      */
     private void onDrawScrollBars(Canvas canvas) {
         // scrollbars are drawn only when the animation is running
         final ScrollabilityCache cache = mScrollCache;
         if (cache != null) {
+            
+            int state = cache.state;
+            
+            if (state == ScrollabilityCache.OFF) {
+                return;
+            }
+            
+            boolean invalidate = false;
+            
+            if (state == ScrollabilityCache.FADING) {
+                // We're fading -- get our fade interpolation
+                if (cache.interpolatorValues == null) {
+                    cache.interpolatorValues = new float[1];
+                }
+                
+                float[] values = cache.interpolatorValues;
+                
+                // Stops the animation if we're done
+                if (cache.scrollBarInterpolator.timeToValues(values) ==
+                        Interpolator.Result.FREEZE_END) {
+                    cache.state = ScrollabilityCache.OFF;
+                } else {
+                    cache.scrollBar.setAlpha(Math.round(values[0]));
+                }
+                
+                // This will make the scroll bars inval themselves after 
+                // drawing. We only want this when we're fading so that
+                // we prevent excessive redraws
+                invalidate = true;
+            } else {
+                // We're just on -- but we may have been fading before so
+                // reset alpha
+                cache.scrollBar.setAlpha(255);
+            }
+
+            
             final int viewFlags = mViewFlags;
 
             final boolean drawHorizontalScrollBar =
@@ -5371,19 +5545,22 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
                 final int scrollY = mScrollY;
                 final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
 
+                int left, top, right, bottom;
+                
                 if (drawHorizontalScrollBar) {
-                    scrollBar.setParameters(
-                                            computeHorizontalScrollRange(),
+                    scrollBar.setParameters(computeHorizontalScrollRange(),
                                             computeHorizontalScrollOffset(),
                                             computeHorizontalScrollExtent(), false);
-                    final int top = scrollY + height - size - (mUserPaddingBottom & inside);
                     final int verticalScrollBarGap = drawVerticalScrollBar ?
-                                                getVerticalScrollbarWidth() : 0;
-                    onDrawHorizontalScrollBar(canvas, scrollBar,
-                        scrollX + (mPaddingLeft & inside),
-                        top,
-                        scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap,
-                        top + size);
+                            getVerticalScrollbarWidth() : 0;
+                    top = scrollY + height - size - (mUserPaddingBottom & inside);                         
+                    left = scrollX + (mPaddingLeft & inside);
+                    right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
+                    bottom = top + size;
+                    onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
+                    if (invalidate) {
+                        invalidate(left, top, right, bottom);
+                    }
                 }
 
                 if (drawVerticalScrollBar) {
@@ -5391,12 +5568,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
                                             computeVerticalScrollOffset(),
                                             computeVerticalScrollExtent(), true);
                     // TODO: Deal with RTL languages to position scrollbar on left
-                    final int left = scrollX + width - size - (mUserPaddingRight & inside);
-                    onDrawVerticalScrollBar(canvas, scrollBar,
-                             left,
-                             scrollY + (mPaddingTop & inside),
-                             left + size,
-                             scrollY + height - (mUserPaddingBottom & inside));
+                    left = scrollX + width - size - (mUserPaddingRight & inside);
+                    top = scrollY + (mPaddingTop & inside);
+                    right = left + size;
+                    bottom = scrollY + height - (mUserPaddingBottom & inside);
+                    onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
+                    if (invalidate) {
+                        invalidate(left, top, right, bottom);
+                    }
                 }
             }
         }
@@ -5424,7 +5603,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
      * @see #computeHorizontalScrollExtent()
      * @see #computeHorizontalScrollOffset()
      * @see android.widget.ScrollBarDrawable
-     *  @hide
+     * @hide
      */
     protected void onDrawHorizontalScrollBar(Canvas canvas,
                                              Drawable scrollBar,
@@ -8731,21 +8910,62 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
      * is supported. This avoids keeping too many unused fields in most
      * instances of View.</p>
      */
-    private static class ScrollabilityCache {
+    private static class ScrollabilityCache implements Runnable {
+                
+        /**
+         * Scrollbars are not visible
+         */
+        public static final int OFF = 0;
+
+        /**
+         * Scrollbars are visible
+         */
+        public static final int ON = 1;
+
+        /**
+         * Scrollbars are fading away
+         */
+        public static final int FADING = 2;
+
+        public boolean fadeScrollBars;
+        
         public int fadingEdgeLength;
+        public int scrollBarDefaultDelayBeforeFade;
+        public int scrollBarFadeDuration;
 
         public int scrollBarSize;
         public ScrollBarDrawable scrollBar;
+        public float[] interpolatorValues;
+        public View host;
 
         public final Paint paint;
         public final Matrix matrix;
         public Shader shader;
 
+        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
+
+        private final float[] mOpaque = {255.0f};
+        private final float[] mTransparent = {0.0f};
+        
+        /**
+         * When fading should start. This time moves into the future every time
+         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
+         */
+        public long fadeStartTime;
+
+
+        /**
+         * The current state of the scrollbars: ON, OFF, or FADING
+         */
+        public int state = OFF;
+
         private int mLastColor;
 
-        public ScrollabilityCache(ViewConfiguration configuration) {
+        public ScrollabilityCache(ViewConfiguration configuration, View host) {
             fadingEdgeLength = configuration.getScaledFadingEdgeLength();
             scrollBarSize = configuration.getScaledScrollBarSize();
+            scrollBarDefaultDelayBeforeFade = configuration.getScrollDefaultDelay();
+            scrollBarFadeDuration = configuration.getScrollBarFadeDuration();
 
             paint = new Paint();
             matrix = new Matrix();
@@ -8755,6 +8975,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
 
             paint.setShader(shader);
             paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
+            this.host = host;
         }
 
         public void setFadeColor(int color) {
@@ -8770,5 +8991,32 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
                 paint.setXfermode(null);
             }
         }
+        
+        public void run() {
+            long now = SystemClock.uptimeMillis();
+            if (now >= fadeStartTime) {
+
+                // the animation fades the scrollbars out by changing
+                // the opacity (alpha) from fully opaque to fully
+                // transparent
+                int nextFrame = (int) now;
+                int framesCount = 0;
+
+                Interpolator interpolator = scrollBarInterpolator;
+
+                // Start opaque
+                interpolator.setKeyFrame(framesCount++, nextFrame, mOpaque);
+
+                // End transparent
+                nextFrame += scrollBarFadeDuration;
+                interpolator.setKeyFrame(framesCount, nextFrame, mTransparent);
+
+                state = FADING;
+
+                // Kick off the fade animation
+                host.invalidate();
+            }
+        }
+
     }
 }
index 3776463..993048f 100644 (file)
@@ -31,6 +31,16 @@ public class ViewConfiguration {
     private static final int SCROLL_BAR_SIZE = 10;
 
     /**
+     * Duration of the fade when scrollbars fade away in milliseconds
+     */
+    private static final int SCROLL_BAR_FADE_DURATION = 250;
+
+    /**
+     * Default delay before the scrollbars fade in milliseconds
+     */
+    private static final int SCROLL_BAR_DEFAULT_DELAY = 300;
+
+    /**
      * Defines the length of the fading edges in pixels
      */
     private static final int FADING_EDGE_LENGTH = 12;
@@ -221,6 +231,20 @@ public class ViewConfiguration {
     }
 
     /**
+     * @return Duration of the fade when scrollbars fade away in milliseconds
+     */
+    public static int getScrollBarFadeDuration() {
+        return SCROLL_BAR_FADE_DURATION;
+    }
+
+    /**
+     * @return Default delay before the scrollbars fade in milliseconds
+     */
+    public static int getScrollDefaultDelay() {
+        return SCROLL_BAR_DEFAULT_DELAY;
+    }
+    
+    /**
      * @return the length of the fading edges in pixels
      *
      * @deprecated Use {@link #getScaledFadingEdgeLength()} instead.
index 0b84848..603f67a 100644 (file)
@@ -2480,6 +2480,7 @@ public class WebView extends AbsoluteLayout
             //        Log.d(LOGTAG, "startScroll: " + dx + " " + dy);
             mScroller.startScroll(mScrollX, mScrollY, dx, dy,
                     animationDuration > 0 ? animationDuration : computeDuration(dx, dy));
+            awakenScrollBars(mScroller.getDuration());
             invalidate();
         } else {
             abortAnimation(); // just in case
@@ -4326,6 +4327,7 @@ public class WebView extends AbsoluteLayout
         // resume the webcore update.
         final int time = mScroller.getDuration();
         mPrivateHandler.sendEmptyMessageDelayed(RESUME_WEBCORE_UPDATE, time);
+        awakenScrollBars(time);
         invalidate();
     }
 
index b242b58..165794a 100644 (file)
@@ -2444,7 +2444,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
         if (spaceAbove >= absIncrementalDeltaY && spaceBelow >= absIncrementalDeltaY) {
             hideSelector();
             offsetChildrenTopAndBottom(incrementalDeltaY);
-            invalidate();
+            if (!awakenScrollBars()) {
+                invalidate();
+            }
             mMotionViewNewTop = mMotionViewOriginalTop + deltaY;
         } else {
             final int firstPosition = mFirstPosition;
@@ -2527,6 +2529,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
             mBlockLayoutRequests = false;
 
             invokeOnItemScrollListener();
+            awakenScrollBars();
         }
     }
 
index 33e83c3..ce07f7a 100644 (file)
@@ -1340,8 +1340,23 @@ public class GridView extends AbsListView {
      */
     @Override
     void setSelectionInt(int position) {
+        int previousSelectedPosition = mNextSelectedPosition;
+
         setNextSelectedPositionInt(position);
         layoutChildren();
+        
+        final int next = mStackFromBottom ? mItemCount - 1  - mNextSelectedPosition : 
+            mNextSelectedPosition;
+        final int previous = mStackFromBottom ? mItemCount - 1
+                - previousSelectedPosition : previousSelectedPosition;
+
+        final int nextRow = next / mNumColumns;
+        final int previousRow = previous / mNumColumns;
+
+        if (nextRow != previousRow) {
+            awakenScrollBars();
+        }
+
     }
 
     @Override
@@ -1471,6 +1486,7 @@ public class GridView extends AbsListView {
         if (nextPage >= 0) {
             setSelectionInt(nextPage);
             invokeOnItemScrollListener();
+            awakenScrollBars();
             return true;
         }
 
@@ -1497,6 +1513,10 @@ public class GridView extends AbsListView {
             invokeOnItemScrollListener();
             moved = true;
         }
+        
+        if (moved) {
+            awakenScrollBars();
+        }
 
         return moved;
     }
@@ -1563,6 +1583,10 @@ public class GridView extends AbsListView {
             invokeOnItemScrollListener();
         }
 
+        if (moved) {
+            awakenScrollBars();
+        }
+        
         return moved;
     }
 
index 46e514c..52f56a7 100644 (file)
@@ -829,6 +829,7 @@ public class HorizontalScrollView extends FrameLayout {
         long duration = AnimationUtils.currentAnimationTimeMillis() - mLastScroll;
         if (duration > ANIMATED_SCROLL_GAP) {
             mScroller.startScroll(mScrollX, mScrollY, dx, dy);
+            awakenScrollBars(mScroller.getDuration());
             invalidate();
         } else {
             if (!mScroller.isFinished()) {
@@ -1172,6 +1173,7 @@ public class HorizontalScrollView extends FrameLayout {
                 mScrollViewMovedFocus = false;
             }
     
+            awakenScrollBars(mScroller.getDuration());
             invalidate();
         }
     }
index 41c9267..37208b3 100644 (file)
@@ -1818,13 +1818,29 @@ public class ListView extends AbsListView {
 
     /**
      * Makes the item at the supplied position selected.
-     *
+     * 
      * @param position the position of the item to select
      */
     @Override
     void setSelectionInt(int position) {
         setNextSelectedPositionInt(position);
+        boolean awakeScrollbars = false;
+
+        final int selectedPosition = mSelectedPosition;
+
+        if (selectedPosition >= 0) {
+            if (position == selectedPosition - 1) {
+                awakeScrollbars = true;
+            } else if (position == selectedPosition + 1) {
+                awakeScrollbars = true;
+            }
+        }
+
         layoutChildren();
+
+        if (awakeScrollbars) {
+            awakenScrollBars();
+        }
     }
 
     /**
@@ -2084,7 +2100,9 @@ public class ListView extends AbsListView {
 
                 setSelectionInt(position);
                 invokeOnItemScrollListener();
-                invalidate();
+                if (!awakenScrollBars()) {
+                    invalidate();
+                }
 
                 return true;
             }
@@ -2125,7 +2143,8 @@ public class ListView extends AbsListView {
             }
         }
 
-        if (moved) {
+        if (moved && !awakenScrollBars()) {
+            awakenScrollBars();
             invalidate();
         }
 
@@ -2270,7 +2289,9 @@ public class ListView extends AbsListView {
                 positionSelector(selectedView);
                 mSelectedTop = selectedView.getTop();
             }
-            invalidate();
+            if (!awakenScrollBars()) {
+                invalidate();
+            }
             invokeOnItemScrollListener();
             return true;
         }
index 31c7814..24d97a5 100644 (file)
@@ -832,6 +832,7 @@ public class ScrollView extends FrameLayout {
         long duration = AnimationUtils.currentAnimationTimeMillis() - mLastScroll;
         if (duration > ANIMATED_SCROLL_GAP) {
             mScroller.startScroll(mScrollX, mScrollY, dx, dy);
+            awakenScrollBars(mScroller.getDuration());
             invalidate();
         } else {
             if (!mScroller.isFinished()) {
@@ -1175,6 +1176,7 @@ public class ScrollView extends FrameLayout {
                 mScrollViewMovedFocus = false;
             }
     
+            awakenScrollBars(mScroller.getDuration());
             invalidate();
         }
     }
index 3c61c1c..10f86f2 100644 (file)
@@ -5572,6 +5572,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
 
                 if (duration > ANIMATED_SCROLL_GAP) {
                     mScroller.startScroll(mScrollX, mScrollY, dx, dy);
+                    awakenScrollBars(mScroller.getDuration());
                     invalidate();
                 } else {
                     if (!mScroller.isFinished()) {
index f5b8ab6..6f109df 100644 (file)
              set, else it will be false. -->
         <attr name="isScrollContainer" format="boolean" />
 
+          <!-- Defines whether to fade out scrollbars when they are not in use. -->
+         <attr name="fadeScrollbars" format="boolean" />
+         <!-- Defines the delay in milliseconds that a scrollbar takes to fade out. -->
+         <attr name="scrollbarFadeDuration" format="integer" />
+         <!-- Defines the delay in milliseconds that a scrollbar waits before fade out. -->
+        <attr name="scrollbarDefaultDelayBeforeFade" format="integer" />
         <!-- Sets the width of vertical scrollbars and height of horizontal scrollbars. -->
         <attr name="scrollbarSize" format="dimension" />
         <!-- Defines the horizontal scrollbar thumb drawable. -->
index 257e0f2..97fb80a 100644 (file)
   <public type="attr" name="thumbnail" />
   <public type="attr" name="detachWallpaper" />
   <public type="attr" name="finishOnCloseSystemDialogs" />
-
+  <public type="attr" name="scrollbarFadeDuration" />
+  <public type="attr" name="scrollbarDefaultDelayBeforeFade" />
+  <public type="attr" name="fadeScrollbars" />
+  
   <public type="style" name="Theme.Wallpaper" />
   <public type="style" name="Theme.Wallpaper.NoTitleBar" />
   <public type="style" name="Theme.Wallpaper.NoTitleBar.Fullscreen" />
index c0ca21b..5ddbce2 100644 (file)
         <item name="panelTextAppearance">?android:attr/textAppearanceInverse</item>
 
         <!-- Scrollbar attributes -->
+        <item name="scrollbarFadeDuration">250</item>
+        <item name="scrollbarDefaultDelayBeforeFade">300</item> 
         <item name="scrollbarSize">10dip</item>
         <item name="scrollbarThumbHorizontal">@android:drawable/scrollbar_handle_horizontal</item>
         <item name="scrollbarThumbVertical">@android:drawable/scrollbar_handle_vertical</item>