Animation.setFillAfter and Animation.setFillBefore的作用

本文详细解释了Android中动画填充效果setFillAfter和setFillBefore的功能。通过实例说明这两个方法的作用仅限于动画本身的表现,并不会真正改变View的位置。为了保持动画结束后的状态,需要额外修改View的属性。

转:http://blog.youkuaiyun.com/yangweigbh/article/details/9788531

setFillAfter(boolean fillAfter)  在Android developer上的文档:

If fillAfter is true, the transformation that this animation performed will persist when it is finished.

但是,animation只是操作View 的位图表示(bitmap representation),而不是真正的改变View的位置

动画结束后,View回到了原来的位置,setFillAfter 和 setFillBefore 并不能解决这个问题,要使View保持动画结束时的状态,必须另外改变View的属性(动画并不会帮助你改变View的属性),setFillAfter 和 setFillBefore 只能改变动画的属性

为什么会有setFillAfter 和 setFillBefore这两个方法:

是因为有动画链的原因,假定你有一个移动的动画紧跟一个淡出的动画,如果你不把移动的动画的setFillAfter置为true,那么移动动画结束后,View会回到原来的位置淡出,如果setFillAfter置为true, 就会在移动动画结束的位置淡出

/*********************************************************** ** Copyright (C), 2020-2030, OPLUS Mobile Comm Corp., Ltd. ** File: - OplusFoldSwitchStateObserver.java ** Description: ** Version: 1.0 ** Date : 2023/6/7 - 14:04 ** Author: LiangHan@WMS ** ** ---------------------Revision History: --------------------- ** <author> <data> <version > <desc> ** LiangHan 2023/6/7 - 14:04 1.0 build this module ****************************************************************/ package com.oplus.foldswitch; import static android.window.TransitionInfo.FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY; import static com.android.wm.shell.startingsurface.OplusShellStartingWindowUtils.typeCasting; import android.content.Context; import android.graphics.Matrix; import android.graphics.Rect; import android.hardware.devicestate.DeviceState; import android.hardware.devicestate.DeviceStateManager; import android.os.Bundle; import android.os.RemoteException; import android.util.Log; import android.view.OplusWindowManager; import android.view.SurfaceControl; import android.view.SurfaceSession; import android.view.WindowManager; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.view.animation.AnimationSet; import android.view.animation.PathInterpolator; import android.view.animation.ScaleAnimation; import android.view.animation.ClipRectAnimation; import android.window.TransitionInfo; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.transition.TransitionAnimationUtil; import com.android.wm.shell.transition.TransitionLog; import com.oplus.foldswitch.ReflectionHelper; import com.oplus.transition.OplusShellLightOSTransition; public class OplusFoldingSwitchAnimationManager { public static final String TAG = "FSS_OplusFoldSwitchStateObserver"; public static final int DEVICE_STATE_CLOSE = 0; public static final int DEVICE_STATE_TENT = 1; public static final int DEVICE_STATE_CLOSE_ALL = 100; public static final int FOLD_SWITCHING_TRANSITION_INVALID = -1; public static final int FOLD_SWITCHING_TRANSITION_CLOSE = 1; public static final int FOLD_SWITCHING_TRANSITION_OPEN = 2; private static final float FOLD_SWITCHING_ANIMATION_SCALE = 1.2f; private static final long RESET_TIME_OUT = 1500L; private static final Object DEVICE_STATE_LOCK = new Object(); private final OplusWindowManager mOplusWindowManager; private final OplusFoldSwitchStateObserver mFoldSwitchStateObserver = new OplusFoldSwitchStateObserver() { @Override public void onFoldingSwitchStateChanged(Bundle bundle) { if (!bundle.containsKey(KEY_DEVICE_FOLDING)) { return; } boolean deviceFolding = bundle.getBoolean(KEY_DEVICE_FOLDING); updateDeviceFolding(deviceFolding); } }; private final DeviceStateManager.DeviceStateCallback mDeviceStateCallback = new DeviceStateManager.DeviceStateCallback() { @Override public void onDeviceStateChanged(DeviceState state) { Log.d(TAG, "onStateChanged: state = " + state); if(state == null) { return; } setDeviceState(state.getIdentifier()); } }; private Context mContext; private ShellExecutor mMainExecutor; private boolean mDeviceFolding = false; private int mDeviceState = DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER; public OplusFoldingSwitchAnimationManager(Context context, ShellExecutor mainExecutor) { mContext = context; mMainExecutor = mainExecutor; mOplusWindowManager = new OplusWindowManager(); registerDeviceStateCallback(); } public void registerOplusFoldSwitchStateObserver() { try { mOplusWindowManager.registerFoldSwitchStateObserver(mFoldSwitchStateObserver); } catch (RemoteException e) { Log.d(TAG, "failed to register fold switch observer, error = " + e); } } public void unregisterOplusFoldSwitchStateObserver() { try { mOplusWindowManager.unregisterFoldSwitchStateObserver(mFoldSwitchStateObserver); } catch (RemoteException e) { Log.d(TAG, "failed to unregister fold switch observer, error = " + e); } } public boolean getDeviceFolding() { Log.d(TAG, "getDeviceFolding: mDeviceFolding = " + mDeviceFolding); return mDeviceFolding; } public boolean getDeviceFolded() { synchronized (DEVICE_STATE_LOCK) { return isFoldedState(mDeviceState); } } public Animation[] getDeviceFoldingRotationAnimations(int delta, int originWidth, int originHeight, int finalWidth, int finalHeight) { TransitionLog.debug("getDeviceFoldingRotationAnimations ==> delta =:" + delta + ",originWidth =:" + originWidth + ",originHeight =:" + originHeight + ",finalWidth =:" + finalWidth + ",finalHeight =:" + finalHeight); int rotateExitDuration = 200; int rotateEnterDuration = 600; PathInterpolator enterAlphaInterpolator = new PathInterpolator(0.3f, 0f, 0.1f, 1f); PathInterpolator enterScaleInterpolator = new PathInterpolator(0.3f, 0f, 0.1f, 1f); float enterScaleNum = FOLD_SWITCHING_ANIMATION_SCALE; Animation[] screenRotateAnimations = new Animation[2]; AnimationSet rotateExitAnim = new AnimationSet(false); rotateExitAnim.setFillBefore(true); rotateExitAnim.setFillAfter(true); rotateExitAnim.setFillEnabled(true); rotateExitAnim.addAnimation(new AlphaAnimation(1, 0) {{ setDuration(rotateExitDuration); }}); rotateExitAnim.setStartOffset(rotateExitDuration); AnimationSet rotateEnterAnim = new AnimationSet(false); rotateEnterAnim.setFillBefore(true); rotateEnterAnim.setFillAfter(true); rotateEnterAnim.setFillEnabled(true); AlphaAnimation enterAlpha = new AlphaAnimation(1, 1); enterAlpha.setDuration(rotateEnterDuration); enterAlpha.setInterpolator(enterAlphaInterpolator); ClipRectAnimation enterClipAnim = new ClipRectAnimation(new Rect(0, 0, finalWidth, finalHeight), new Rect(0, 0, finalWidth, finalHeight)); enterClipAnim.setDuration(rotateEnterDuration); rotateEnterAnim.addAnimation(enterClipAnim); ScaleAnimation enterScale = new ScaleAnimation(enterScaleNum, 1, enterScaleNum, 1, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); enterScale.setDuration(rotateEnterDuration); enterScale.setInterpolator(enterScaleInterpolator); rotateEnterAnim.addAnimation(enterAlpha); if (!getDeviceFolded()) { rotateEnterAnim.addAnimation(enterScale); } TransitionAnimationUtil.setAnimationHasRoundedCorners(rotateExitAnim, !OplusShellLightOSTransition.IS_LIGHTOS); TransitionAnimationUtil.setAnimationHasRoundedCorners(rotateEnterAnim, !OplusShellLightOSTransition.IS_LIGHTOS); screenRotateAnimations[0] = rotateExitAnim; screenRotateAnimations[1] = rotateEnterAnim; return screenRotateAnimations; } public boolean skipDefaultTransitionIfNeed(TransitionInfo info, TransitionInfo.Change change) { int foldChangeType = getFoldChangeType(info); if ((info.getFlags() & WindowManager.TRANSIT_FLAG_INVISIBLE) != 0 && foldChangeType == FOLD_SWITCHING_TRANSITION_OPEN && change.hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY)) { Log.d(TAG, "skip DefaultTransition"); return true; } return false; } public void initAnimLayerWhenFolding(SurfaceControl.Transaction t, SurfaceControl animLeash, TransitionInfo info, int startWidth, int startHeight) { setScale(t, animLeash, info, startWidth, startHeight); } public int getFoldChangeType(TransitionInfo info) { return ReflectionHelper.oplusTransitionExtendedInfoGetFoldChangeType(info); } public boolean cancelAnimationIfNeedWhenFolding(TransitionInfo info) { int foldChangeType = getFoldChangeType(info); Log.d(TAG, "cancelAnimationIfNeedWhenFolding: foldChangeType = " + foldChangeType); if ((info.getFlags() & WindowManager.TRANSIT_FLAG_INVISIBLE) != 0 && (foldChangeType != FOLD_SWITCHING_TRANSITION_OPEN)) { return true; } return foldChangeType == FOLD_SWITCHING_TRANSITION_CLOSE; } private void setScale(SurfaceControl.Transaction t, SurfaceControl animLeash, TransitionInfo info, int startWidth, int startHeight) { if (getFoldChangeType(info) == FOLD_SWITCHING_TRANSITION_OPEN) { final Matrix matrix = new Matrix(); final float[] tmpFloats = new float[9]; matrix.setScale(FOLD_SWITCHING_ANIMATION_SCALE, FOLD_SWITCHING_ANIMATION_SCALE); matrix.getValues(tmpFloats); float x = (1 - FOLD_SWITCHING_ANIMATION_SCALE) / 2 * startWidth; float y = (1 - FOLD_SWITCHING_ANIMATION_SCALE) / 2 * startHeight; Log.d(TAG, "setScale: x = " + x + ", y = " + y + ", startWidth = " + startWidth + ", startHeight = " + startHeight); t.setPosition(animLeash, x, y); t.setMatrix(animLeash, tmpFloats[Matrix.MSCALE_X], tmpFloats[Matrix.MSKEW_Y], tmpFloats[Matrix.MSKEW_X], tmpFloats[Matrix.MSCALE_Y]); } } private void registerDeviceStateCallback() { DeviceStateManager deviceStateManager = (DeviceStateManager) mContext.getSystemService(Context.DEVICE_STATE_SERVICE); deviceStateManager.registerCallback(mMainExecutor, mDeviceStateCallback); } private boolean isFoldedState(int deviceState) { return TransitionAnimationUtil.isFoldDevice() && !TransitionAnimationUtil.isFlipDevice() && isFoldedDeviceState(deviceState); } private boolean isFoldedDeviceState(int deviceState) { return deviceState == DEVICE_STATE_CLOSE || deviceState == DEVICE_STATE_TENT || deviceState == DEVICE_STATE_CLOSE_ALL; } private void setDeviceState(int deviceState) { synchronized (DEVICE_STATE_LOCK) { mDeviceState = deviceState; } } private void updateDeviceFolding(boolean newDeviceFolding) { if (mDeviceFolding == newDeviceFolding) { return; } Log.d(TAG, "updateDeviceFolding old = " + mDeviceFolding + ", new = " + newDeviceFolding); mDeviceFolding = newDeviceFolding; } } 解析以上写好的类和类中方法的作用与含义
07-18
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值