diff options
Diffstat (limited to 'core/java/android/view/View.java')
-rw-r--r-- | core/java/android/view/View.java | 512 |
1 files changed, 429 insertions, 83 deletions
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 7ed2712..0b87536 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -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; @@ -46,7 +47,6 @@ import android.os.SystemClock; import android.os.SystemProperties; import android.util.AttributeSet; import android.util.Config; -import android.util.DisplayMetrics; import android.util.EventLog; import android.util.Log; import android.util.Pool; @@ -59,6 +59,7 @@ import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityEventSource; import android.view.accessibility.AccessibilityManager; import android.view.animation.Animation; +import android.view.animation.AnimationUtils; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; @@ -515,7 +516,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> @@ -572,6 +574,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 @@ -2215,12 +2219,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()); @@ -2264,7 +2284,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); } } @@ -2601,6 +2621,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility if (mOnFocusChangeListener != null) { mOnFocusChangeListener.onFocusChange(this, gainFocus); } + + if (mAttachInfo != null) { + mAttachInfo.mKeyDispatchState.reset(this); + } } /** @@ -2983,6 +3007,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility * @param enabled True if this view is enabled, false otherwise. */ public void setEnabled(boolean enabled) { + if (enabled == isEnabled()) return; + setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK); /* @@ -3608,6 +3634,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility } /** + * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState} + * for this view's window. Returns null if the view is not currently attached + * to the window. Normally you will not need to use this directly, but + * just use the standard high-level event callbacks like {@link #onKeyDown}. + */ + public KeyEvent.DispatcherState getKeyDispatcherState() { + return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null; + } + + /** * Dispatch a key event before it is processed by any input method * associated with the view hierarchy. This can be used to intercept * key events in special situations before the IME consumes them; a @@ -3644,7 +3680,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility return true; } - return event.dispatch(this); + return event.dispatch(this, mAttachInfo != null + ? mAttachInfo.mKeyDispatchState : null, this); } /** @@ -3909,6 +3946,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility } /** + * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent) + * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle + * the event). + */ + public boolean onKeyLongPress(int keyCode, KeyEvent event) { + return false; + } + + /** * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent) * KeyEvent.Callback.onKeyMultiple()}: perform clicking of the view * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or @@ -4646,7 +4692,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility mScrollX = x; mScrollY = y; onScrollChanged(mScrollX, mScrollY, oldX, oldY); - invalidate(); + if (!awakenScrollBars()) { + invalidate(); + } } } @@ -4662,6 +4710,160 @@ 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.</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 #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, true); + } + + /** + * <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. + * </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 #scrollBy(int, int) + * @see #scrollTo(int, int) + * @see #isHorizontalScrollBarEnabled() + * @see #isVerticalScrollBarEnabled() + * @see #setHorizontalScrollBarEnabled(boolean) + * @see #setVerticalScrollBarEnabled(boolean) + */ + protected boolean awakenScrollBars(int startDelay) { + return awakenScrollBars(startDelay, true); + } + + /** + * <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()} if the invalidate parameter + * is set to true; 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. + * </p> + * + * @param startDelay the delay, in milliseconds, after which the animation + * should start; when the delay is 0, the animation starts + * immediately + * + * @param invalidate Wheter this method should call invalidate + * + * @return true if the animation is played, false otherwise + * + * @see #scrollBy(int, int) + * @see #scrollTo(int, int) + * @see #isHorizontalScrollBarEnabled() + * @see #isVerticalScrollBarEnabled() + * @see #setHorizontalScrollBarEnabled(boolean) + * @see #setVerticalScrollBarEnabled(boolean) + */ + protected boolean awakenScrollBars(int startDelay, boolean invalidate) { + final ScrollabilityCache scrollCache = mScrollCache; + + if (scrollCache == null || !scrollCache.fadeScrollBars) { + return false; + } + + if (scrollCache.scrollBar == null) { + scrollCache.scrollBar = new ScrollBarDrawable(); + } + + if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) { + + if (invalidate) { + // 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 = AnimationUtils.currentAnimationTimeMillis() + 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 @@ -4754,8 +4956,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility * invalidate/draw passes. * * @return True if this View is guaranteed to be fully opaque, false otherwise. - * - * @hide Pending API council approval */ @ViewDebug.ExportedProperty public boolean isOpaque() { @@ -5152,7 +5352,34 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility private void recomputePadding() { setPadding(mPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom); } - + + /** + * Define whether scrollbars will fade when the view is not scrolling. + * + * @param fadeScrollbars wheter to enable fading + * + */ + public void setScrollbarFadingEnabled(boolean fadeScrollbars) { + initScrollCache(); + final ScrollabilityCache scrollabilityCache = mScrollCache; + scrollabilityCache.fadeScrollBars = fadeScrollbars; + if (fadeScrollbars) { + scrollabilityCache.state = ScrollabilityCache.OFF; + } else { + scrollabilityCache.state = ScrollabilityCache.ON; + } + } + + /** + * + * Returns true if scrollbars will fade when this view is not scrolling + * + * @return true if scrollbar fading is enabled + */ + public boolean isScrollbarFadingEnabled() { + return mScrollCache != null && mScrollCache.fadeScrollBars; + } + /** * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or * inset. When inset, they add to the padding of the view. And the scrollbars @@ -5319,11 +5546,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) { + protected final 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 = @@ -5342,12 +5607,41 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility size = cache.scrollBarSize; } + final int scrollX = mScrollX; + final int scrollY = mScrollY; + final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0; + + int left, top, right, bottom; + if (drawHorizontalScrollBar) { - onDrawHorizontalScrollBar(canvas, scrollBar, width, height, size); + scrollBar.setParameters(computeHorizontalScrollRange(), + computeHorizontalScrollOffset(), + computeHorizontalScrollExtent(), false); + final int verticalScrollBarGap = drawVerticalScrollBar ? + 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) { - onDrawVerticalScrollBar(canvas, scrollBar, width, height, size); + scrollBar.setParameters(computeVerticalScrollRange(), + computeVerticalScrollOffset(), + computeVerticalScrollExtent(), true); + // TODO: Deal with RTL languages to position scrollbar on left + 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); + } } } } @@ -5367,44 +5661,20 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility * <p>Draw the horizontal scrollbar if * {@link #isHorizontalScrollBarEnabled()} returns true.</p> * - * <p>The length of the scrollbar and its thumb is computed according to the - * values returned by {@link #computeHorizontalScrollRange()}, - * {@link #computeHorizontalScrollExtent()} and - * {@link #computeHorizontalScrollOffset()}. Refer to - * {@link android.widget.ScrollBarDrawable} for more information about how - * these values relate to each other.</p> - * * @param canvas the canvas on which to draw the scrollbar * @param scrollBar the scrollbar's drawable - * @param width the width of the drawing surface - * @param height the height of the drawing surface - * @param size the size of the scrollbar * * @see #isHorizontalScrollBarEnabled() * @see #computeHorizontalScrollRange() * @see #computeHorizontalScrollExtent() * @see #computeHorizontalScrollOffset() * @see android.widget.ScrollBarDrawable + * @hide */ - private void onDrawHorizontalScrollBar(Canvas canvas, ScrollBarDrawable scrollBar, int width, - int height, int size) { - - final int viewFlags = mViewFlags; - final int scrollX = mScrollX; - final int scrollY = mScrollY; - final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0; - final int top = scrollY + height - size - (mUserPaddingBottom & inside); - - final int verticalScrollBarGap = - (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL ? - getVerticalScrollbarWidth() : 0; - - scrollBar.setBounds(scrollX + (mPaddingLeft & inside), top, - scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap, top + size); - scrollBar.setParameters( - computeHorizontalScrollRange(), - computeHorizontalScrollOffset(), - computeHorizontalScrollExtent(), false); + protected void onDrawHorizontalScrollBar(Canvas canvas, + Drawable scrollBar, + int l, int t, int r, int b) { + scrollBar.setBounds(l, t, r, b); scrollBar.draw(canvas); } @@ -5412,40 +5682,20 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()} * returns true.</p> * - * <p>The length of the scrollbar and its thumb is computed according to the - * values returned by {@link #computeVerticalScrollRange()}, - * {@link #computeVerticalScrollExtent()} and - * {@link #computeVerticalScrollOffset()}. Refer to - * {@link android.widget.ScrollBarDrawable} for more information about how - * these values relate to each other.</p> - * * @param canvas the canvas on which to draw the scrollbar * @param scrollBar the scrollbar's drawable - * @param width the width of the drawing surface - * @param height the height of the drawing surface - * @param size the size of the scrollbar * * @see #isVerticalScrollBarEnabled() * @see #computeVerticalScrollRange() * @see #computeVerticalScrollExtent() * @see #computeVerticalScrollOffset() * @see android.widget.ScrollBarDrawable + * @hide */ - private void onDrawVerticalScrollBar(Canvas canvas, ScrollBarDrawable scrollBar, int width, - int height, int size) { - - final int scrollX = mScrollX; - final int scrollY = mScrollY; - final int inside = (mViewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0; - // TODO: Deal with RTL languages to position scrollbar on left - final int left = scrollX + width - size - (mUserPaddingRight & inside); - - scrollBar.setBounds(left, scrollY + (mPaddingTop & inside), - left + size, scrollY + height - (mUserPaddingBottom & inside)); - scrollBar.setParameters( - computeVerticalScrollRange(), - computeVerticalScrollOffset(), - computeVerticalScrollExtent(), true); + protected void onDrawVerticalScrollBar(Canvas canvas, + Drawable scrollBar, + int l, int t, int r, int b) { + scrollBar.setBounds(l, t, r, b); scrollBar.draw(canvas); } @@ -5936,11 +6186,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility } final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor; - final boolean opaque = drawingCacheBackgroundColor != 0 || - (mBGDrawable != null && mBGDrawable.getOpacity() == PixelFormat.OPAQUE); + final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque(); + final boolean translucentWindow = attachInfo != null && attachInfo.mTranslucentWindow; if (width <= 0 || height <= 0 || - (width * height * (opaque ? 2 : 4) > // Projected bitmap size in bytes + // Projected bitmap size in bytes + (width * height * (opaque && !translucentWindow ? 2 : 4) > ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize())) { destroyDrawingCache(); return; @@ -5951,7 +6202,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility (mUnscaledDrawingCache == null ? null : mUnscaledDrawingCache.get()); if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) { - Bitmap.Config quality; if (!opaque) { switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) { @@ -5969,7 +6219,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility break; } } else { - quality = Bitmap.Config.RGB_565; + // Optimization for translucent windows + // If the window is translucent, use a 32 bits bitmap to benefit from memcpy() + quality = translucentWindow ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565; } // Try to cleanup memory @@ -5983,6 +6235,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility } else { mUnscaledDrawingCache = new SoftReference<Bitmap>(bitmap); } + if (opaque && translucentWindow) bitmap.setHasAlpha(false); } catch (OutOfMemoryError e) { // If there is not enough memory to create the bitmap cache, just // ignore the issue as bitmap caches are not required to draw the @@ -6057,16 +6310,22 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility * some form of this public, but should think about the API. */ Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor) { - final int width = mRight - mLeft; - final int height = mBottom - mTop; + int width = mRight - mLeft; + int height = mBottom - mTop; - Bitmap bitmap = Bitmap.createBitmap(width, height, quality); + final AttachInfo attachInfo = mAttachInfo; + final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f; + width = (int) ((width * scale) + 0.5f); + height = (int) ((height * scale) + 0.5f); + + Bitmap bitmap = Bitmap.createBitmap(width > 0 ? width : 1, height > 0 ? height : 1, quality); if (bitmap == null) { throw new OutOfMemoryError(); } + bitmap.setDensity(getResources().getDisplayMetrics().densityDpi); + Canvas canvas; - final AttachInfo attachInfo = mAttachInfo; if (attachInfo != null) { canvas = attachInfo.mCanvas; if (canvas == null) { @@ -6089,6 +6348,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility computeScroll(); final int restoreCount = canvas.save(); + canvas.scale(scale, scale); canvas.translate(-mScrollX, -mScrollY); // Temporarily remove the dirty mask @@ -6911,7 +7171,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility /** * Set the background to a given resource. The resource should refer to - * a Drawable object. + * a Drawable object or 0 to remove the background. * @param resid The identifier of the resource. * @attr ref android.R.styleable#View_background */ @@ -8087,6 +8347,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility } /** + * This needs to be a better API (NOT ON VIEW) before it is exposed. If + * it is ever exposed at all. + * @hide + */ + public void onCloseSystemDialogs(String reason) { + } + + /** * Given a Drawable whose bounds have been set to draw into this view, * update a Region being computed for {@link #gatherTransparentRegion} so * that any non-transparent parts of the Drawable are removed from the @@ -8554,6 +8822,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility int mWindowTop; /** + * Indicates whether the window is translucent/transparent + */ + boolean mTranslucentWindow; + + /** * For windows that are full-screen but using insets to layout inside * of the screen decorations, these are the current insets for the * content of the window. @@ -8584,6 +8857,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility */ final ArrayList<View> mScrollContainers = new ArrayList<View>(); + final KeyEvent.DispatcherState mKeyDispatchState + = new KeyEvent.DispatcherState(); + /** * Indicates whether the view's window currently has the focus. */ @@ -8709,21 +8985,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 = ViewConfiguration.getScrollDefaultDelay(); + scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration(); paint = new Paint(); matrix = new Matrix(); @@ -8733,6 +9050,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) { @@ -8740,12 +9058,40 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility mLastColor = color; color |= 0xFF000000; - shader = new LinearGradient(0, 0, 0, 1, color, 0, Shader.TileMode.CLAMP); + shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000, + color & 0x00FFFFFF, Shader.TileMode.CLAMP); paint.setShader(shader); // Restore the default transfer mode (src_over) paint.setXfermode(null); } } + + public void run() { + long now = AnimationUtils.currentAnimationTimeMillis(); + 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(); + } + } + } } |