文件夹展开动画集都写在 FolderAnimationManager.java中,所以可以将隐藏Workspace、Hotseat、PageIndicatorDots的动画写在里面,仿造源码中getAnimator()写的动画,添加对应的即可。
app/src/main/java/com/android/launcher3/folder/FolderAnimationManager.java
/**
* Prepares the Folder for animating between open / closed states.
*/
public AnimatorSet getAnimator() {
......
for (BubbleTextView icon : mFolder.getItemsOnPage(mFolder.mContent.getCurrentPage())) {
if (mIsOpening) {
icon.setTextVisibility(false);
}
ObjectAnimator anim = icon.createTextAlphaAnimator(mIsOpening);
anim.addListener(colorResetListener);
play(a, anim);
}
play(a, getAnimator(mFolder, View.TRANSLATION_X, xDistance, 0f));
play(a, getAnimator(mFolder, View.TRANSLATION_Y, yDistance, 0f));
play(a, getAnimator(mFolder, SCALE_PROPERTY, initialScale, finalScale));
play(a, mFolderIcon.mFolderName.createTextAlphaAnimator(!mIsOpening));
+ play(a, getAnimator(mLauncher.getHotseat(), View.ALPHA, 1.0f, 0.0f));
+ play(a, getAnimator(mLauncher.getWorkspace(), View.ALPHA, 1.0f, 0.0f));
+ play(a, getAnimator(mLauncher.getWorkspace().getPageIndicator(), View.ALPHA, 1.0f, 0.0f));
......
}
其中 Workspace、Hotseat、PageIndicatorDots 的View可以使用如下对应获取到
mLauncher.getWorkspace() mLauncher.getHotseat() mLauncher.getWorkspace().getPageIndicator()
在 Folder.java中没有动画的时候,会去执行closeComplete()方法,逻辑如下
app/src/main/java/com/android/launcher3/folder/Folder.java
@Override
protected void handleClose(boolean animate) {
mIsOpen = false;
if (isEditingName()) {
mFolderName.dispatchBackKey();
}
if (mFolderIcon != null) {
mFolderIcon.clearLeaveBehindIfExists();
}
//在animate为false的时候不会走到原来关闭动画的方法,所以需要在closeComplete()方法里面做显示的操作
if (animate) {
animateClosed();
} else {
closeComplete(false);
post(this::announceAccessibilityChanges);
}
......
}
添加显示方法
private void closeComplete(boolean wasAnimated) {
......
if (getItemCount() <= 1) {
if (!mDragInProgress && !mSuppressFolderDeletion) {
replaceFolderWithFinalItem();
} else if (mDragInProgress) {
mDeleteFolderOnDropCompleted = true;
}
}
mSuppressFolderDeletion = false;
clearDragInfo();
mState = STATE_SMALL;
mContent.setCurrentPage(0);
+ displayView(mLauncher.getWorkspace().getPageIndicator());
+ displayView(mLauncher.getWorkspace());
+ displayView(mLauncher.getHotseat());
......
}
+ private void displayView(View view) {
+ view.setVisibility(VISIBLE);
+ view.setAlpha(1.0f);
+ }
遇到一个问题:当在文件夹展开然后拖动应用时PageIndicatorDots会显示出来。
排查发现是workspace的过度动画里面会去设置PageIndicatorDots的显示。
在WorkspaceStateTransitionAnimation.java的setWorkspaceProperty()方法中会去setViewAlpha设置PageIndicatorDots透明度。
解决:在文件夹打开时,不去设置PageIndicatorDots透明度为1。
app/src/main/java/com/android/launcher3/WorkspaceStateTransitionAnimation.java
/**
* Starts a transition animation for the workspace.
*/
private void setWorkspaceProperty(LauncherState state, PropertySetter propertySetter,
AnimatorSetBuilder builder, AnimationConfig config) {
float[] scaleAndTranslation = state.getWorkspaceScaleAndTranslation(mLauncher);
mNewScale = scaleAndTranslation[0];
PageAlphaProvider pageAlphaProvider = state.getWorkspacePageAlphaProvider(mLauncher);
final int childCount = mWorkspace.getChildCount();
for (int i = 0; i < childCount; i++) {
applyChildState(state, (CellLayout) mWorkspace.getChildAt(i), i, pageAlphaProvider,
propertySetter, builder, config);
}
int elements = state.getVisibleElements(mLauncher);
Interpolator fadeInterpolator = builder.getInterpolator(ANIM_WORKSPACE_FADE,
pageAlphaProvider.interpolator);
boolean playAtomicComponent = config.playAtomicComponent();
if (playAtomicComponent) {
Interpolator scaleInterpolator = builder.getInterpolator(ANIM_WORKSPACE_SCALE, ZOOM_OUT);
propertySetter.setFloat(mWorkspace, SCALE_PROPERTY, mNewScale, scaleInterpolator);
float hotseatIconsAlpha = (elements & HOTSEAT_ICONS) != 0 ? 1 : 0;
propertySetter.setViewAlpha(mLauncher.getHotseat().getLayout(), hotseatIconsAlpha,
fadeInterpolator);
//当文件夹打开时,不去设置mLauncher.getWorkspace().getPageIndicator()的显示效果
+ AbstractFloatingView openFolder = AbstractFloatingView.getOpenView(mLauncher, AbstractFloatingView.TYPE_FOLDER);
+ if (openFolder == null) {
+ propertySetter.setViewAlpha(mLauncher.getWorkspace().getPageIndicator(),
+ hotseatIconsAlpha, fadeInterpolator);
+ }
......
}
其中
AbstractFloatingView.getOpenView(mLauncher, AbstractFloatingView.TYPE_FOLDER)可以判断打开的是否是文件夹view。 完成。