Merge "Implement issue #3201795: Improve transition when keyboard comes up"

This commit is contained in:
Dianne Hackborn
2010-12-01 11:02:04 -08:00
committed by Android (Google) Code Review
4 changed files with 126 additions and 17 deletions

View File

@@ -94,13 +94,18 @@ public abstract class HardwareRenderer {
*/
abstract void setup(int width, int height);
interface HardwareDrawCallbacks {
void onHardwarePreDraw(Canvas canvas);
void onHardwarePostDraw(Canvas canvas);
}
/**
* Draws the specified view.
*
* @param view The view to draw.
* @param attachInfo AttachInfo tied to the specified view.
*/
abstract void draw(View view, View.AttachInfo attachInfo, int yOffset);
abstract void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks);
/**
* Creates a new display list that can be used to record batches of
@@ -456,7 +461,7 @@ public abstract class HardwareRenderer {
}
@Override
void draw(View view, View.AttachInfo attachInfo, int yOffset) {
void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks) {
if (canDraw()) {
attachInfo.mDrawingTime = SystemClock.uptimeMillis();
attachInfo.mIgnoreDirtyState = true;
@@ -473,11 +478,12 @@ public abstract class HardwareRenderer {
Canvas canvas = mCanvas;
int saveCount = canvas.save();
canvas.translate(0, -yOffset);
callbacks.onHardwarePreDraw(canvas);
try {
view.draw(canvas);
} finally {
callbacks.onHardwarePostDraw(canvas);
canvas.restoreToCount(saveCount);
}

View File

@@ -25,7 +25,9 @@ import android.content.pm.PackageManager;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.PointF;
@@ -57,6 +59,8 @@ import android.util.TypedValue;
import android.view.View.MeasureSpec;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import android.widget.Scroller;
@@ -79,7 +83,8 @@ import java.util.ArrayList;
* {@hide}
*/
@SuppressWarnings({"EmptyCatchBlock", "PointlessBooleanExpression"})
public final class ViewRoot extends Handler implements ViewParent, View.AttachInfo.Callbacks {
public final class ViewRoot extends Handler implements ViewParent,
View.AttachInfo.Callbacks, HardwareRenderer.HardwareDrawCallbacks {
private static final String TAG = "ViewRoot";
private static final boolean DBG = false;
private static final boolean SHOW_FPS = false;
@@ -213,6 +218,10 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
int mScrollY;
int mCurScrollY;
Scroller mScroller;
Bitmap mResizeBitmap;
long mResizeBitmapStartTime;
int mResizeBitmapDuration;
static final Interpolator mResizeInterpolator = new AccelerateDecelerateInterpolator();
final ViewConfiguration mViewConfiguration;
@@ -626,6 +635,13 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
return mAppVisible ? mView.getVisibility() : View.GONE;
}
void disposeResizeBitmap() {
if (mResizeBitmap != null) {
mResizeBitmap.recycle();
mResizeBitmap = null;
}
}
private void performTraversals() {
// cache mView since it is used so much below...
final View host = mView;
@@ -734,6 +750,48 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
ensureTouchModeLocally(mAddedTouchMode);
} else {
if (!mAttachInfo.mContentInsets.equals(mPendingContentInsets)) {
if (mWidth > 0 && mHeight > 0 &&
mSurface != null && mSurface.isValid() &&
mAttachInfo.mHardwareRenderer != null &&
mAttachInfo.mHardwareRenderer.isEnabled() &&
lp != null && !PixelFormat.formatHasAlpha(lp.format)) {
disposeResizeBitmap();
boolean completed = false;
try {
mResizeBitmap = Bitmap.createBitmap(mWidth, mHeight,
Bitmap.Config.ARGB_8888);
mResizeBitmap.setHasAlpha(false);
Canvas canvas = new Canvas(mResizeBitmap);
int yoff;
final boolean scrolling = mScroller != null
&& mScroller.computeScrollOffset();
if (scrolling) {
yoff = mScroller.getCurrY();
mScroller.abortAnimation();
} else {
yoff = mScrollY;
}
canvas.translate(0, -yoff);
if (mTranslator != null) {
mTranslator.translateCanvas(canvas);
}
canvas.setScreenDensity(mAttachInfo.mScalingRequired
? DisplayMetrics.DENSITY_DEVICE : 0);
mView.draw(canvas);
mResizeBitmapStartTime = SystemClock.uptimeMillis();
mResizeBitmapDuration = mView.getResources().getInteger(
com.android.internal.R.integer.config_mediumAnimTime);
completed = true;
} catch (OutOfMemoryError e) {
Log.w(TAG, "Not enough memory for content change anim buffer", e);
} finally {
if (!completed) {
mResizeBitmap = null;
}
}
}
mAttachInfo.mContentInsets.set(mPendingContentInsets);
host.fitSystemWindows(mAttachInfo.mContentInsets);
insetsChanged = true;
@@ -787,7 +845,6 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
// Maybe we can just try the next size up, and see if that reduces
// the height?
if (host.getWidth() <= baseSize /*&& host.getHeight() <= maxHeight*/) {
Log.v(TAG, "Good!");
goodMeasure = true;
} else {
// Didn't fit in that size... try expanding a bit.
@@ -972,6 +1029,7 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
if (mScroller != null) {
mScroller.abortAnimation();
}
disposeResizeBitmap();
}
} catch (RemoteException e) {
}
@@ -1310,6 +1368,22 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
return measureSpec;
}
int mHardwareYOffset;
int mResizeAlpha;
final Paint mResizePaint = new Paint();
public void onHardwarePreDraw(Canvas canvas) {
canvas.translate(0, -mHardwareYOffset);
}
public void onHardwarePostDraw(Canvas canvas) {
if (mResizeBitmap != null) {
canvas.translate(0, mHardwareYOffset);
mResizePaint.setAlpha(mResizeAlpha);
canvas.drawBitmap(mResizeBitmap, 0, 0, mResizePaint);
}
}
private void draw(boolean fullRedrawNeeded) {
Surface surface = mSurface;
if (surface == null || !surface.isValid()) {
@@ -1334,8 +1408,8 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
}
int yoff;
final boolean scrolling = mScroller != null && mScroller.computeScrollOffset();
if (scrolling) {
boolean animating = mScroller != null && mScroller.computeScrollOffset();
if (animating) {
yoff = mScroller.getCurrY();
} else {
yoff = mScrollY;
@@ -1347,10 +1421,29 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
float appScale = mAttachInfo.mApplicationScale;
boolean scalingRequired = mAttachInfo.mScalingRequired;
int resizeAlpha = 0;
if (mResizeBitmap != null) {
long deltaTime = SystemClock.uptimeMillis() - mResizeBitmapStartTime;
if (deltaTime < mResizeBitmapDuration) {
float amt = deltaTime/(float)mResizeBitmapDuration;
amt = mResizeInterpolator.getInterpolation(amt);
animating = true;
resizeAlpha = 255 - (int)(amt*255);
} else {
disposeResizeBitmap();
}
}
Rect dirty = mDirty;
if (mSurfaceHolder != null) {
// The app owns the surface, we won't draw.
dirty.setEmpty();
if (animating) {
if (mScroller != null) {
mScroller.abortAnimation();
}
disposeResizeBitmap();
}
return;
}
@@ -1363,10 +1456,12 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
if (!dirty.isEmpty() || mIsAnimating) {
mIsAnimating = false;
dirty.setEmpty();
mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, yoff);
mHardwareYOffset = yoff;
mResizeAlpha = resizeAlpha;
mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, this);
}
if (scrolling) {
if (animating) {
mFullRedrawNeeded = true;
scheduleTraversals();
}
@@ -1486,7 +1581,7 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
Log.v(TAG, "Surface " + surface + " unlockCanvasAndPost");
}
if (scrolling) {
if (animating) {
mFullRedrawNeeded = true;
scheduleTraversals();
}
@@ -1600,7 +1695,7 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
if (scrollY != mScrollY) {
if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Pan scroll changed: old="
+ mScrollY + " , new=" + scrollY);
if (!immediate) {
if (!immediate && mResizeBitmap == null) {
if (mScroller == null) {
mScroller = new Scroller(mView.getContext());
}

View File

@@ -122,7 +122,9 @@ class ScreenRotationAnimation {
mSurface.unlockCanvasAndPost(c);
Surface.closeTransaction();
screenshot.recycle();
if (screenshot != null) {
screenshot.recycle();
}
}
static int deltaRotation(int oldRotation, int newRotation) {

View File

@@ -6848,6 +6848,8 @@ public class WindowManagerService extends IWindowManager.Stub
}
if (!mParentFrame.equals(pf)) {
//Slog.i(TAG, "Window " + this + " content frame from " + mParentFrame
// + " to " + pf);
mParentFrame.set(pf);
mContentChanged = true;
}
@@ -7734,12 +7736,10 @@ public class WindowManagerService extends IWindowManager.Stub
* sense to call from performLayoutAndPlaceSurfacesLockedInner().)
*/
boolean shouldAnimateMove() {
return mContentChanged && !mAnimating && !mLastHidden && !mDisplayFrozen
return mContentChanged && !mExiting && !mLastHidden && !mDisplayFrozen
&& (mFrame.top != mLastFrame.top
|| mFrame.left != mLastFrame.left)
&& (mAttachedWindow == null
|| (mAttachedWindow.mAnimation == null
&& !mAttachedWindow.shouldAnimateMove()))
&& (mAttachedWindow == null || !mAttachedWindow.shouldAnimateMove())
&& mPolicy.isScreenOn();
}
@@ -9223,6 +9223,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (!gone || !win.mHaveFrame) {
if (!win.mLayoutAttached) {
if (initial) {
//Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
win.mContentChanged = false;
}
mPolicy.layoutWindowLw(win, win.mAttrs, null);
@@ -9257,6 +9258,7 @@ public class WindowManagerService extends IWindowManager.Stub
if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
|| !win.mHaveFrame) {
if (initial) {
//Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
win.mContentChanged = false;
}
mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow);
@@ -9455,7 +9457,6 @@ public class WindowManagerService extends IWindowManager.Stub
w.setAnimation(a);
animDw = w.mLastFrame.left - w.mFrame.left;
animDh = w.mLastFrame.top - w.mFrame.top;
w.mContentChanged = false;
}
// Execute animation.
@@ -10242,6 +10243,11 @@ public class WindowManagerService extends IWindowManager.Stub
w.mOrientationChanging = false;
}
if (w.mContentChanged) {
//Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
w.mContentChanged = false;
}
final boolean canBeSeen = w.isDisplayedLw();
if (someoneLosingFocus && w == mCurrentFocus && canBeSeen) {