List of usage examples for android.animation ValueAnimator addUpdateListener
public void addUpdateListener(AnimatorUpdateListener listener)
From source file:com.android.systemui.statusbar.phone.NotificationPanelView.java
private void animateKeyguardStatusBarOut() { ValueAnimator anim = ValueAnimator.ofFloat(mKeyguardStatusBar.getAlpha(), 0f); anim.addUpdateListener(mStatusBarAnimateAlphaListener); anim.setStartDelay(mStatusBar.isKeyguardFadingAway() ? mStatusBar.getKeyguardFadingAwayDelay() : 0); anim.setDuration(mStatusBar.isKeyguardFadingAway() ? mStatusBar.getKeyguardFadingAwayDuration() / 2 : StackStateAnimator.ANIMATION_DURATION_STANDARD); anim.setInterpolator(mDozeAnimationInterpolator); anim.addListener(new AnimatorListenerAdapter() { @Override/* w ww . j a v a 2s . c o m*/ public void onAnimationEnd(Animator animation) { mAnimateKeyguardStatusBarInvisibleEndRunnable.run(); } }); anim.start(); }
From source file:org.secuso.privacyfriendlypasswordgenerator.helpers.SwipeableRecyclerViewTouchListener.java
@TargetApi(Build.VERSION_CODES.HONEYCOMB) private void performDismiss(final View dismissView, final int dismissPosition) { // Animate the dismissed list item to zero-height and fire the dismiss callback when // all dismissed list item animations have completed. This triggers layout on each animation // frame; in the future we may want to do something smarter and more performant. final ViewGroup.LayoutParams lp = dismissView.getLayoutParams(); final int originalLayoutParamsHeight = lp.height; final int originalHeight = dismissView.getHeight(); ValueAnimator animator = ValueAnimator.ofInt(originalHeight, 1).setDuration(mAnimationTime); animator.addListener(new AnimatorListenerAdapter() { @Override/*from w w w .j a va2 s. com*/ public void onAnimationEnd(Animator animation) { --mDismissAnimationRefCount; if (mDismissAnimationRefCount == 0) { // No active animations, process all pending dismisses. // Sort by descending position Collections.sort(mPendingDismisses); int[] dismissPositions = new int[mPendingDismisses.size()]; for (int i = mPendingDismisses.size() - 1; i >= 0; i--) { dismissPositions[i] = mPendingDismisses.get(i).position; } if (mFinalDelta < 0) { mSwipeListener.onDismissedBySwipeLeft(mRecyclerView, dismissPositions); // } else { // mSwipeListener.onDismissedBySwipeRight(mRecyclerView, dismissPositions); } // Reset mDownPosition to avoid MotionEvent.ACTION_UP trying to start a dismiss // animation with a stale position mDownPosition = ListView.INVALID_POSITION; ViewGroup.LayoutParams lp; for (PendingDismissData pendingDismiss : mPendingDismisses) { // Reset view presentation pendingDismiss.view.setAlpha(mAlpha); pendingDismiss.view.setTranslationX(0); lp = pendingDismiss.view.getLayoutParams(); lp.height = originalLayoutParamsHeight; pendingDismiss.view.setLayoutParams(lp); } // Send a cancel event long time = SystemClock.uptimeMillis(); MotionEvent cancelEvent = MotionEvent.obtain(time, time, MotionEvent.ACTION_CANCEL, 0, 0, 0); mRecyclerView.dispatchTouchEvent(cancelEvent); mPendingDismisses.clear(); mAnimatingPosition = ListView.INVALID_POSITION; } } }); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { lp.height = (Integer) valueAnimator.getAnimatedValue(); dismissView.setLayoutParams(lp); } }); mPendingDismisses.add(new PendingDismissData(dismissPosition, dismissView)); animator.start(); }
From source file:com.android.leanlauncher.Workspace.java
Animator getChangeStateAnimation(final State state, boolean animated, int delay, ArrayList<View> layerViews) { if (mState == state) { return null; }/* ww w. java2 s . c om*/ AnimatorSet anim = animated ? LauncherAnimUtils.createAnimatorSet() : null; // We only want a single instance of a workspace animation to be running at once, so // we cancel any incomplete transition. if (mStateAnimator != null) { mStateAnimator.cancel(); } mStateAnimator = anim; final State oldState = mState; final boolean oldStateIsNormal = (oldState == State.NORMAL); final boolean oldStateIsOverview = (oldState == State.OVERVIEW); setState(state); final boolean stateIsNormal = (state == State.NORMAL); final boolean stateIsSpringLoaded = (state == State.SPRING_LOADED); final boolean stateIsNormalHidden = (state == State.NORMAL_HIDDEN); final boolean stateIsOverviewHidden = (state == State.OVERVIEW_HIDDEN); final boolean stateIsOverview = (state == State.OVERVIEW); float finalBackgroundAlpha = (stateIsSpringLoaded || stateIsOverview) ? 1.0f : 0f; float finalOverviewPanelAlpha = stateIsOverview ? 1f : 0f; float finalWorkspaceTranslationY = stateIsOverview || stateIsOverviewHidden ? getOverviewModeTranslationY() : 0; boolean workspaceToAllApps = (oldStateIsNormal && stateIsNormalHidden); boolean overviewToAllApps = (oldStateIsOverview && stateIsOverviewHidden); boolean allAppsToWorkspace = (stateIsNormalHidden && stateIsNormal); boolean workspaceToOverview = (oldStateIsNormal && stateIsOverview); boolean overviewToWorkspace = (oldStateIsOverview && stateIsNormal); mNewScale = 1.0f; if (state != State.NORMAL) { if (stateIsSpringLoaded) { mNewScale = mSpringLoadedShrinkFactor; } else if (stateIsOverview || stateIsOverviewHidden) { mNewScale = mOverviewModeShrinkFactor; } } final int duration; if (workspaceToAllApps || overviewToAllApps) { duration = HIDE_WORKSPACE_DURATION; //getResources().getInteger(R.integer.config_workspaceUnshrinkTime); } else if (workspaceToOverview || overviewToWorkspace) { duration = getResources().getInteger(R.integer.config_overviewTransitionTime); } else { duration = getResources().getInteger(R.integer.config_appsCustomizeWorkspaceShrinkTime); } final CellLayout cl = mWorkspace; float initialAlpha = cl.getShortcutsAndWidgets().getAlpha(); float finalAlpha; if (stateIsNormalHidden || stateIsOverviewHidden) { finalAlpha = 0f; } else { finalAlpha = 1f; } // If we are animating to/from the small state, then hide the side pages and fade the // current page in if (!mIsSwitchingState) { if (workspaceToAllApps || allAppsToWorkspace) { if (allAppsToWorkspace) { initialAlpha = 0f; } cl.setShortcutAndWidgetAlpha(initialAlpha); } } float oldAlpha = initialAlpha; float newAlpha = finalAlpha; if (animated) { mOldBackgroundAlpha = cl.getBackgroundAlpha(); mNewBackgroundAlpha = finalBackgroundAlpha; } else { cl.setBackgroundAlpha(finalBackgroundAlpha); cl.setShortcutAndWidgetAlpha(finalAlpha); } final View overviewPanel = mLauncher.getOverviewPanel(); if (animated) { LauncherViewPropertyAnimator scale = new LauncherViewPropertyAnimator(this); scale.scaleX(mNewScale).scaleY(mNewScale).translationY(finalWorkspaceTranslationY).setDuration(duration) .setInterpolator(mZoomInInterpolator); anim.play(scale); float currentAlpha = cl.getShortcutsAndWidgets().getAlpha(); if (oldAlpha == 0 && newAlpha == 0) { cl.setBackgroundAlpha(mNewBackgroundAlpha); cl.setShortcutAndWidgetAlpha(newAlpha); } else { if (layerViews != null) { layerViews.add(cl); } if (oldAlpha != newAlpha || currentAlpha != newAlpha) { LauncherViewPropertyAnimator alphaAnim = new LauncherViewPropertyAnimator( cl.getShortcutsAndWidgets()); alphaAnim.alpha(newAlpha).setDuration(duration).setInterpolator(mZoomInInterpolator); anim.play(alphaAnim); } if (mOldBackgroundAlpha != 0 || mNewBackgroundAlpha != 0) { ValueAnimator bgAnim = LauncherAnimUtils.ofFloat(cl, 0f, 1f); bgAnim.setInterpolator(mZoomInInterpolator); bgAnim.setDuration(duration); bgAnim.addUpdateListener(new LauncherAnimatorUpdateListener() { public void onAnimationUpdate(float a, float b) { cl.setBackgroundAlpha(a * mOldBackgroundAlpha + b * mNewBackgroundAlpha); } }); anim.play(bgAnim); } } Animator overviewPanelAlpha = new LauncherViewPropertyAnimator(overviewPanel) .alpha(finalOverviewPanelAlpha).withLayer(); overviewPanelAlpha.addListener(new AlphaUpdateListener(overviewPanel)); // For animation optimations, we may need to provide the Launcher transition // with a set of views on which to force build layers in certain scenarios. overviewPanel.setLayerType(View.LAYER_TYPE_HARDWARE, null); if (layerViews != null) { layerViews.add(overviewPanel); } if (workspaceToOverview) { overviewPanelAlpha.setInterpolator(null); } else if (overviewToWorkspace) { overviewPanelAlpha.setInterpolator(new DecelerateInterpolator(2)); } overviewPanelAlpha.setDuration(duration); anim.play(overviewPanelAlpha); anim.setStartDelay(delay); anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mStateAnimator = null; } }); } else { overviewPanel.setAlpha(finalOverviewPanelAlpha); AlphaUpdateListener.updateVisibility(overviewPanel); setScaleX(mNewScale); setScaleY(mNewScale); setTranslationY(finalWorkspaceTranslationY); } if (stateIsNormal) { animateBackgroundGradient(0f, animated); } else { animateBackgroundGradient(getResources().getInteger(R.integer.config_workspaceScrimAlpha) / 100f, animated); } return anim; }
From source file:com.marlonjones.voidlauncher.CellLayout.java
public boolean animateChildToPosition(final View child, int cellX, int cellY, int duration, int delay, boolean permanent, boolean adjustOccupied) { ShortcutAndWidgetContainer clc = getShortcutsAndWidgets(); if (clc.indexOfChild(child) != -1) { final LayoutParams lp = (LayoutParams) child.getLayoutParams(); final ItemInfo info = (ItemInfo) child.getTag(); // We cancel any existing animations if (mReorderAnimators.containsKey(lp)) { mReorderAnimators.get(lp).cancel(); mReorderAnimators.remove(lp); }/*from www. j a v a2 s.c o m*/ final int oldX = lp.x; final int oldY = lp.y; if (adjustOccupied) { GridOccupancy occupied = permanent ? mOccupied : mTmpOccupied; occupied.markCells(lp.cellX, lp.cellY, lp.cellHSpan, lp.cellVSpan, false); occupied.markCells(cellX, cellY, lp.cellHSpan, lp.cellVSpan, true); } lp.isLockedToGrid = true; if (permanent) { lp.cellX = info.cellX = cellX; lp.cellY = info.cellY = cellY; } else { lp.tmpCellX = cellX; lp.tmpCellY = cellY; } clc.setupLp(lp); lp.isLockedToGrid = false; final int newX = lp.x; final int newY = lp.y; lp.x = oldX; lp.y = oldY; // Exit early if we're not actually moving the view if (oldX == newX && oldY == newY) { lp.isLockedToGrid = true; return true; } ValueAnimator va = LauncherAnimUtils.ofFloat(child, 0f, 1f); va.setDuration(duration); mReorderAnimators.put(lp, va); va.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float r = ((Float) animation.getAnimatedValue()).floatValue(); lp.x = (int) ((1 - r) * oldX + r * newX); lp.y = (int) ((1 - r) * oldY + r * newY); child.requestLayout(); } }); va.addListener(new AnimatorListenerAdapter() { boolean cancelled = false; public void onAnimationEnd(Animator animation) { // If the animation was cancelled, it means that another animation // has interrupted this one, and we don't want to lock the item into // place just yet. if (!cancelled) { lp.isLockedToGrid = true; child.requestLayout(); } if (mReorderAnimators.containsKey(lp)) { mReorderAnimators.remove(lp); } } public void onAnimationCancel(Animator animation) { cancelled = true; } }); va.setStartDelay(delay); va.start(); return true; } return false; }
From source file:cc.flydev.launcher.Page.java
public void onFlingToDelete(PointF vel) { final long startTime = AnimationUtils.currentAnimationTimeMillis(); // NOTE: Because it takes time for the first frame of animation to actually be // called and we expect the animation to be a continuation of the fling, we have // to account for the time that has elapsed since the fling finished. And since // we don't have a startDelay, we will always get call to update when we call // start() (which we want to ignore). final TimeInterpolator tInterpolator = new TimeInterpolator() { private int mCount = -1; private long mStartTime; private float mOffset; /* Anonymous inner class ctor */ { mStartTime = startTime;//w w w . ja va2s . c om } @Override public float getInterpolation(float t) { if (mCount < 0) { mCount++; } else if (mCount == 0) { mOffset = Math.min(0.5f, (float) (AnimationUtils.currentAnimationTimeMillis() - mStartTime) / FLING_TO_DELETE_FADE_OUT_DURATION); mCount++; } return Math.min(1f, mOffset + t); } }; final Rect from = new Rect(); final View dragView = mDragView; from.left = (int) dragView.getTranslationX(); from.top = (int) dragView.getTranslationY(); AnimatorUpdateListener updateCb = new FlingAlongVectorAnimatorUpdateListener(dragView, vel, from, startTime, FLING_TO_DELETE_FRICTION); final Runnable onAnimationEndRunnable = createPostDeleteAnimationRunnable(dragView); // Create and start the animation ValueAnimator mDropAnim = new ValueAnimator(); mDropAnim.setInterpolator(tInterpolator); mDropAnim.setDuration(FLING_TO_DELETE_FADE_OUT_DURATION); mDropAnim.setFloatValues(0f, 1f); mDropAnim.addUpdateListener(updateCb); mDropAnim.addListener(new AnimatorListenerAdapter() { public void onAnimationEnd(Animator animation) { onAnimationEndRunnable.run(); } }); mDropAnim.start(); mDeferringForDelete = true; }
From source file:saftyos.android.launcher3.Page.java
public void onFlingToDelete(PointF vel) { final long startTime = AnimationUtils.currentAnimationTimeMillis(); // NOTE: Because it takes time for the first frame of animation to actually be // called and we expect the animation to be a continuation of the fling, we have // to account for the time that has elapsed since the fling finished. And since // we don't have a startDelay, we will always get call to update when we call // start() (which we want to ignore). final TimeInterpolator tInterpolator = new TimeInterpolator() { private int mCount = -1; private long mStartTime; private float mOffset; /* Anonymous inner class ctor */ { mStartTime = startTime;//from w w w . j a v a 2 s .com } @Override public float getInterpolation(float t) { if (mCount < 0) { mCount++; } else if (mCount == 0) { mOffset = Math.min(0.5f, (float) (AnimationUtils.currentAnimationTimeMillis() - mStartTime) / FLING_TO_DELETE_FADE_OUT_DURATION); mCount++; } return Math.min(1f, mOffset + t); } }; final Rect from = new Rect(); final View dragView = mDragView; from.left = (int) dragView.getTranslationX(); from.top = (int) dragView.getTranslationY(); AnimatorUpdateListener updateCb = new FlingAlongVectorAnimatorUpdateListener(dragView, vel, from, startTime, FLING_TO_DELETE_FRICTION); final Runnable onAnimationEndRunnable = createPostDeleteAnimationRunnable(dragView); // Create and start the animation ValueAnimator mDropAnim = new ValueAnimator(); mDropAnim.setInterpolator(tInterpolator); mDropAnim.setDuration(FLING_TO_DELETE_FADE_OUT_DURATION); mDropAnim.setFloatValues(0f, 1f); mDropAnim.addUpdateListener(updateCb); mDropAnim.addListener(new AnimatorListenerAdapter() { public void onAnimationEnd(Animator animation) { onAnimationEndRunnable.run(); } }); mDropAnim.start(); mDeferringForDelete = true; }
From source file:com.android.systemui.statusbar.phone.NotificationPanelView.java
private void flingSettings(float vel, boolean expand, final Runnable onFinishRunnable, boolean isClick) { float target = expand ? mQsMaxExpansionHeight : mQsMinExpansionHeight; if (target == mQsExpansionHeight) { mScrollYOverride = -1;//www. j a v a2s .co m if (onFinishRunnable != null) { onFinishRunnable.run(); } return; } boolean belowFalsingThreshold = isBelowFalsingThreshold(); if (belowFalsingThreshold) { vel = 0; } mScrollView.setBlockFlinging(true); ValueAnimator animator = ValueAnimator.ofFloat(mQsExpansionHeight, target); if (isClick) { animator.setInterpolator(mTouchResponseInterpolator); animator.setDuration(368); } else { mFlingAnimationUtils.apply(animator, mQsExpansionHeight, target, vel); } if (belowFalsingThreshold) { animator.setDuration(350); } animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { setQsExpansion((Float) animation.getAnimatedValue()); } }); animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mScrollView.setBlockFlinging(false); mScrollYOverride = -1; mQsExpansionAnimator = null; if (onFinishRunnable != null) { onFinishRunnable.run(); } } }); animator.start(); mQsExpansionAnimator = animator; mQsAnimatorExpand = expand; }
From source file:com.n2hsu.launcher.Page.java
public void onFlingToDelete(PointF vel) { final long startTime = AnimationUtils.currentAnimationTimeMillis(); // NOTE: Because it takes time for the first frame of animation to // actually be // called and we expect the animation to be a continuation of the fling, // we have/*from w w w.jav a 2s. c o m*/ // to account for the time that has elapsed since the fling finished. // And since // we don't have a startDelay, we will always get call to update when we // call // start() (which we want to ignore). final TimeInterpolator tInterpolator = new TimeInterpolator() { private int mCount = -1; private long mStartTime; private float mOffset; /* Anonymous inner class ctor */ { mStartTime = startTime; } @Override public float getInterpolation(float t) { if (mCount < 0) { mCount++; } else if (mCount == 0) { mOffset = Math.min(0.5f, (float) (AnimationUtils.currentAnimationTimeMillis() - mStartTime) / FLING_TO_DELETE_FADE_OUT_DURATION); mCount++; } return Math.min(1f, mOffset + t); } }; final Rect from = new Rect(); final View dragView = mDragView; from.left = (int) dragView.getTranslationX(); from.top = (int) dragView.getTranslationY(); AnimatorUpdateListener updateCb = new FlingAlongVectorAnimatorUpdateListener(dragView, vel, from, startTime, FLING_TO_DELETE_FRICTION); final Runnable onAnimationEndRunnable = createPostDeleteAnimationRunnable(dragView); // Create and start the animation ValueAnimator mDropAnim = new ValueAnimator(); mDropAnim.setInterpolator(tInterpolator); mDropAnim.setDuration(FLING_TO_DELETE_FADE_OUT_DURATION); mDropAnim.setFloatValues(0f, 1f); mDropAnim.addUpdateListener(updateCb); mDropAnim.addListener(new AnimatorListenerAdapter() { public void onAnimationEnd(Animator animation) { onAnimationEndRunnable.run(); } }); mDropAnim.start(); mDeferringForDelete = true; }
From source file:com.android.launcher3.CellLayout.java
public boolean animateChildToPosition(final View child, int cellX, int cellY, int duration, int delay, boolean permanent, boolean adjustOccupied) { ShortcutAndWidgetContainer clc = getShortcutsAndWidgets(); boolean[][] occupied = mOccupied; if (!permanent) { occupied = mTmpOccupied;// w ww . j a v a 2 s . c om } if (clc.indexOfChild(child) != -1) { final LayoutParams lp = (LayoutParams) child.getLayoutParams(); final ItemInfo info = (ItemInfo) child.getTag(); // We cancel any existing animations if (mReorderAnimators.containsKey(lp)) { mReorderAnimators.get(lp).cancel(); mReorderAnimators.remove(lp); } final int oldX = lp.x; final int oldY = lp.y; if (adjustOccupied) { occupied[lp.cellX][lp.cellY] = false; occupied[cellX][cellY] = true; } lp.isLockedToGrid = true; if (permanent) { lp.cellX = info.cellX = cellX; lp.cellY = info.cellY = cellY; } else { lp.tmpCellX = cellX; lp.tmpCellY = cellY; } clc.setupLp(lp); lp.isLockedToGrid = false; final int newX = lp.x; final int newY = lp.y; lp.x = oldX; lp.y = oldY; // Exit early if we're not actually moving the view if (oldX == newX && oldY == newY) { lp.isLockedToGrid = true; return true; } ValueAnimator va = LauncherAnimUtils.ofFloat(child, 0f, 1f); va.setDuration(duration); mReorderAnimators.put(lp, va); va.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float r = ((Float) animation.getAnimatedValue()).floatValue(); lp.x = (int) ((1 - r) * oldX + r * newX); lp.y = (int) ((1 - r) * oldY + r * newY); child.requestLayout(); } }); va.addListener(new AnimatorListenerAdapter() { boolean cancelled = false; public void onAnimationEnd(Animator animation) { // If the animation was cancelled, it means that another animation // has interrupted this one, and we don't want to lock the item into // place just yet. if (!cancelled) { lp.isLockedToGrid = true; child.requestLayout(); } if (mReorderAnimators.containsKey(lp)) { mReorderAnimators.remove(lp); } } public void onAnimationCancel(Animator animation) { cancelled = true; } }); va.setStartDelay(delay); va.start(); return true; } return false; }
From source file:com.guodong.sun.guodong.widget.ZoomImageView.java
private void startTransform(final int state) { if (mTransfrom == null) { return;/*w ww . j a v a 2s. c o m*/ } ValueAnimator valueAnimator = new ValueAnimator(); valueAnimator.setDuration(300); valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator()); if (state == STATE_TRANSFORM_IN) { PropertyValuesHolder scaleHolder = PropertyValuesHolder.ofFloat("scale", mTransfrom.startScale, mTransfrom.endScale); PropertyValuesHolder leftHolder = PropertyValuesHolder.ofFloat("left", mTransfrom.startRect.left, mTransfrom.endRect.left); PropertyValuesHolder topHolder = PropertyValuesHolder.ofFloat("top", mTransfrom.startRect.top, mTransfrom.endRect.top); PropertyValuesHolder widthHolder = PropertyValuesHolder.ofFloat("width", mTransfrom.startRect.width, mTransfrom.endRect.width); PropertyValuesHolder heightHolder = PropertyValuesHolder.ofFloat("height", mTransfrom.startRect.height, mTransfrom.endRect.height); PropertyValuesHolder alphaHolder = PropertyValuesHolder.ofInt("alpha", 0, 255); valueAnimator.setValues(scaleHolder, leftHolder, topHolder, widthHolder, heightHolder, alphaHolder); } else { PropertyValuesHolder scaleHolder = PropertyValuesHolder.ofFloat("scale", mTransfrom.endScale, mTransfrom.startScale); PropertyValuesHolder leftHolder = PropertyValuesHolder.ofFloat("left", mTransfrom.endRect.left, mTransfrom.startRect.left); PropertyValuesHolder topHolder = PropertyValuesHolder.ofFloat("top", mTransfrom.endRect.top, mTransfrom.startRect.top); PropertyValuesHolder widthHolder = PropertyValuesHolder.ofFloat("width", mTransfrom.endRect.width, mTransfrom.startRect.width); PropertyValuesHolder heightHolder = PropertyValuesHolder.ofFloat("height", mTransfrom.endRect.height, mTransfrom.startRect.height); PropertyValuesHolder alphaHolder = PropertyValuesHolder.ofInt("alpha", 255, 0); valueAnimator.setValues(scaleHolder, leftHolder, topHolder, widthHolder, heightHolder, alphaHolder); } valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public synchronized void onAnimationUpdate(ValueAnimator animation) { mTransfrom.scale = (Float) animation.getAnimatedValue("scale"); mTransfrom.rect.left = (Float) animation.getAnimatedValue("left"); mTransfrom.rect.top = (Float) animation.getAnimatedValue("top"); mTransfrom.rect.width = (Float) animation.getAnimatedValue("width"); mTransfrom.rect.height = (Float) animation.getAnimatedValue("height"); mBgAlpha = (Integer) animation.getAnimatedValue("alpha"); invalidate(); ((Activity) getContext()).getWindow().getDecorView().invalidate(); } }); valueAnimator.addListener(new ValueAnimator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { /* * ???center_cropout??center_crop? * ???out???Normal???bug */ // TODO ??? if (state == STATE_TRANSFORM_IN) { mState = STATE_NORMAL; } if (mTransformListener != null) { mTransformListener.onTransformComplete(state); } } @Override public void onAnimationCancel(Animator animation) { } }); valueAnimator.start(); }