summaryrefslogtreecommitdiffstats
path: root/core/java/android/view/View.java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android/view/View.java')
-rw-r--r--core/java/android/view/View.java512
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();
+ }
+ }
+
}
}