Loading core/java/android/view/View.java +273 −25 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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> Loading Loading @@ -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 Loading Loading @@ -2214,11 +2218,27 @@ 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 ScrollabilityCache scrollabilityCache = mScrollCache; 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, Loading Loading @@ -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); } } Loading Loading @@ -4671,9 +4691,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility mScrollX = x; mScrollY = y; onScrollChanged(mScrollX, mScrollY, oldX, oldY); if (!awakenScrollBars()) { invalidate(); } } } /** * Move the scrolled position of your view. This will cause a call to Loading @@ -4686,6 +4708,120 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility scrollTo(mScrollX + x, mScrollY + y); } /** * <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. Loading Loading @@ -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 = Loading @@ -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); 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) { Loading @@ -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); } } } } Loading Loading @@ -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(); Loading @@ -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) { Loading @@ -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(); } } } } core/java/android/view/ViewConfiguration.java +24 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,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 */ Loading Loading @@ -220,6 +230,20 @@ public class ViewConfiguration { return mScrollbarSize; } /** * @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 * Loading core/java/android/webkit/WebView.java +2 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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(); } Loading core/java/android/widget/AbsListView.java +4 −1 Original line number Diff line number Diff line Loading @@ -2444,7 +2444,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te if (spaceAbove >= absIncrementalDeltaY && spaceBelow >= absIncrementalDeltaY) { hideSelector(); offsetChildrenTopAndBottom(incrementalDeltaY); if (!awakenScrollBars()) { invalidate(); } mMotionViewNewTop = mMotionViewOriginalTop + deltaY; } else { final int firstPosition = mFirstPosition; Loading Loading @@ -2527,6 +2529,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mBlockLayoutRequests = false; invokeOnItemScrollListener(); awakenScrollBars(); } } Loading core/java/android/widget/GridView.java +24 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -1471,6 +1486,7 @@ public class GridView extends AbsListView { if (nextPage >= 0) { setSelectionInt(nextPage); invokeOnItemScrollListener(); awakenScrollBars(); return true; } Loading Loading @@ -1498,6 +1514,10 @@ public class GridView extends AbsListView { moved = true; } if (moved) { awakenScrollBars(); } return moved; } Loading Loading @@ -1563,6 +1583,10 @@ public class GridView extends AbsListView { invokeOnItemScrollListener(); } if (moved) { awakenScrollBars(); } return moved; } Loading Loading
core/java/android/view/View.java +273 −25 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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> Loading Loading @@ -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 Loading Loading @@ -2214,11 +2218,27 @@ 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 ScrollabilityCache scrollabilityCache = mScrollCache; 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, Loading Loading @@ -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); } } Loading Loading @@ -4671,9 +4691,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility mScrollX = x; mScrollY = y; onScrollChanged(mScrollX, mScrollY, oldX, oldY); if (!awakenScrollBars()) { invalidate(); } } } /** * Move the scrolled position of your view. This will cause a call to Loading @@ -4686,6 +4708,120 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility scrollTo(mScrollX + x, mScrollY + y); } /** * <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. Loading Loading @@ -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 = Loading @@ -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); 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) { Loading @@ -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); } } } } Loading Loading @@ -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(); Loading @@ -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) { Loading @@ -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(); } } } }
core/java/android/view/ViewConfiguration.java +24 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,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 */ Loading Loading @@ -220,6 +230,20 @@ public class ViewConfiguration { return mScrollbarSize; } /** * @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 * Loading
core/java/android/webkit/WebView.java +2 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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(); } Loading
core/java/android/widget/AbsListView.java +4 −1 Original line number Diff line number Diff line Loading @@ -2444,7 +2444,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te if (spaceAbove >= absIncrementalDeltaY && spaceBelow >= absIncrementalDeltaY) { hideSelector(); offsetChildrenTopAndBottom(incrementalDeltaY); if (!awakenScrollBars()) { invalidate(); } mMotionViewNewTop = mMotionViewOriginalTop + deltaY; } else { final int firstPosition = mFirstPosition; Loading Loading @@ -2527,6 +2529,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mBlockLayoutRequests = false; invokeOnItemScrollListener(); awakenScrollBars(); } } Loading
core/java/android/widget/GridView.java +24 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -1471,6 +1486,7 @@ public class GridView extends AbsListView { if (nextPage >= 0) { setSelectionInt(nextPage); invokeOnItemScrollListener(); awakenScrollBars(); return true; } Loading Loading @@ -1498,6 +1514,10 @@ public class GridView extends AbsListView { moved = true; } if (moved) { awakenScrollBars(); } return moved; } Loading Loading @@ -1563,6 +1583,10 @@ public class GridView extends AbsListView { invokeOnItemScrollListener(); } if (moved) { awakenScrollBars(); } return moved; } Loading