diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index f4ef1f7e47..c91fa9fd5c 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -22,7 +22,6 @@ import static android.widget.Toast.LENGTH_SHORT; import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER; import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS; -import static com.android.launcher3.QuickstepTransitionManager.RECENTS_LAUNCH_DURATION; import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL; import static com.android.launcher3.anim.Interpolators.DEACCEL; import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2; @@ -97,8 +96,8 @@ import com.android.quickstep.util.ActiveGestureLog; import com.android.quickstep.util.ActivityInitListener; import com.android.quickstep.util.AnimatorControllerWithResistance; import com.android.quickstep.util.InputConsumerProxy; +import com.android.quickstep.util.InputProxyHandlerFactory; import com.android.quickstep.util.MotionPauseDetector; -import com.android.quickstep.util.MultiValueUpdateListener; import com.android.quickstep.util.ProtoTracer; import com.android.quickstep.util.RecentsOrientedState; import com.android.quickstep.util.RectFSpringAnim; @@ -113,12 +112,10 @@ import com.android.systemui.shared.system.InputConsumerController; import com.android.systemui.shared.system.InteractionJankMonitorWrapper; import com.android.systemui.shared.system.LatencyTrackerCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; -import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams; import com.android.systemui.shared.system.TaskInfoCompat; import com.android.systemui.shared.system.TaskStackChangeListener; import java.util.ArrayList; -import java.util.Arrays; import java.util.function.Consumer; /** @@ -255,7 +252,10 @@ public abstract class AbsSwipeUpHandler, mActivityInterface = gestureState.getActivityInterface(); mActivityInitListener = mActivityInterface.createActivityInitListener(this::onActivityInit); mInputConsumerProxy = - new InputConsumerProxy(inputConsumer, this::createNewInputProxyHandler); + new InputConsumerProxy(inputConsumer, () -> { + endRunningWindowAnim(mGestureState.getEndTarget() == HOME /* cancel */); + endLauncherTransitionController(); + }, new InputProxyHandlerFactory(mActivityInterface, mGestureState)); mTaskAnimationManager = taskAnimationManager; mTouchTimeMs = touchTimeMs; mContinuingLastGesture = continuingLastGesture; @@ -783,19 +783,6 @@ public abstract class AbsSwipeUpHandler, handleNormalGestureEnd(endVelocity, isFling, velocity, false /* isCancel */); } - /** - * Called to create a input proxy for the running task - */ - @UiThread - protected InputConsumer createNewInputProxyHandler() { - endRunningWindowAnim(mGestureState.getEndTarget() == HOME /* cancel */); - endLauncherTransitionController(); - - StatefulActivity activity = mActivityInterface.getCreatedActivity(); - return activity == null ? InputConsumer.NO_OP - : new OverviewInputConsumer(mGestureState, activity, null, true); - } - private void endRunningWindowAnim(boolean cancel) { if (mRunningWindowAnim != null) { if (cancel) { @@ -1338,6 +1325,7 @@ public abstract class AbsSwipeUpHandler, mInputConsumerProxy.destroy(); mTaskAnimationManager.setLiveTileCleanUpHandler(null); } + mInputConsumerProxy.unregisterCallback(); endRunningWindowAnim(false /* cancel */); if (mGestureEndCallback != null) { @@ -1502,36 +1490,13 @@ public abstract class AbsSwipeUpHandler, protected abstract void finishRecentsControllerToHome(Runnable callback); - private final TaskStackChangeListener mLiveTileRestartListener = new TaskStackChangeListener() { - @Override - public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task, - boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) { - if (mRecentsView.getRunningTaskIndex() != -1 - && mRecentsView.getRunningTaskId() == task.taskId - && mRecentsAnimationTargets.hasTask(task.taskId)) { - launchOtherTaskInLiveTileMode(task.taskId, mRecentsAnimationTargets.apps); - } - ActivityManagerWrapper.getInstance().unregisterTaskStackListener( - mLiveTileRestartListener); - } - }; - private void setupLauncherUiAfterSwipeUpToRecentsAnimation() { endLauncherTransitionController(); mActivityInterface.onSwipeUpToRecentsComplete(); mRecentsView.onSwipeUpAnimationSuccess(); if (LIVE_TILE.get()) { - mTaskAnimationManager.setLaunchOtherTaskInLiveTileModeHandler( - appearedTaskTarget -> { - RemoteAnimationTargetCompat[] apps = Arrays.copyOf( - mRecentsAnimationTargets.apps, - mRecentsAnimationTargets.apps.length + 1); - apps[apps.length - 1] = appearedTaskTarget; - launchOtherTaskInLiveTileMode(appearedTaskTarget.taskId, apps); - }); mTaskAnimationManager.setLiveTileCleanUpHandler(mInputConsumerProxy::destroy); - ActivityManagerWrapper.getInstance().registerTaskStackListener( - mLiveTileRestartListener); + mTaskAnimationManager.enableLiveTileRestartListener(); } SystemUiProxy.INSTANCE.get(mContext).onOverviewShown(false, TAG); @@ -1539,65 +1504,6 @@ public abstract class AbsSwipeUpHandler, reset(); } - private void launchOtherTaskInLiveTileMode(int taskId, RemoteAnimationTargetCompat[] apps) { - AnimatorSet anim = new AnimatorSet(); - TaskView taskView = mRecentsView.getTaskView(taskId); - if (taskView == null || !mRecentsView.isTaskViewVisible(taskView)) { - // TODO: Refine this animation. - SurfaceTransactionApplier surfaceApplier = - new SurfaceTransactionApplier(mActivity.getDragLayer()); - ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1); - appAnimator.setDuration(RECENTS_LAUNCH_DURATION); - appAnimator.setInterpolator(ACCEL_DEACCEL); - appAnimator.addUpdateListener(new MultiValueUpdateListener() { - @Override - public void onUpdate(float percent) { - SurfaceParams.Builder builder = new SurfaceParams.Builder( - apps[apps.length - 1].leash); - Matrix matrix = new Matrix(); - matrix.postScale(percent, percent); - matrix.postTranslate(mDp.widthPx * (1 - percent) / 2, - mDp.heightPx * (1 - percent) / 2); - builder.withAlpha(percent).withMatrix(matrix); - surfaceApplier.scheduleApply(builder.build()); - } - }); - anim.play(appAnimator); - } else { - TaskViewUtils.composeRecentsLaunchAnimator( - anim, taskView, apps, - mRecentsAnimationTargets.wallpapers, true /* launcherClosing */, - mActivity.getStateManager(), mRecentsView, - mActivityInterface.getDepthController()); - } - anim.addListener(new AnimatorListenerAdapter(){ - - @Override - public void onAnimationEnd(Animator animator) { - cleanUp(false); - } - - @Override - public void onAnimationCancel(Animator animator) { - cleanUp(true); - } - - private void cleanUp(boolean canceled) { - if (mRecentsAnimationController != null) { - mRecentsAnimationController.finish(false /* toRecents */, - null /* onFinishComplete */); - if (canceled) { - mRecentsAnimationController = null; - } else { - mActivityInterface.onLaunchTaskSuccess(); - } - ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", false); - } - } - }); - anim.start(); - } - private static boolean isNotInRecents(RemoteAnimationTargetCompat app) { return app.isNotInRecents || app.activityType == ACTIVITY_TYPE_HOME; diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationTargets.java b/quickstep/src/com/android/quickstep/RecentsAnimationTargets.java index da0a66431e..718c5baa2c 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationTargets.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationTargets.java @@ -41,13 +41,4 @@ public class RecentsAnimationTargets extends RemoteAnimationTargets { public boolean hasTargets() { return unfilteredApps.length != 0; } - - public boolean hasTask(int taskId) { - for (RemoteAnimationTargetCompat target : unfilteredApps) { - if (target.taskId == taskId) { - return true; - } - } - return false; - } } diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java index 9a454f2bd7..b6dad2d385 100644 --- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java +++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java @@ -17,10 +17,11 @@ package com.android.quickstep; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; -import static com.android.quickstep.GestureState.GestureEndTarget.RECENTS; import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_INITIALIZED; import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_STARTED; +import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE; +import android.app.ActivityManager; import android.content.Context; import android.content.Intent; import android.os.Bundle; @@ -31,13 +32,13 @@ import androidx.annotation.UiThread; import com.android.launcher3.Utilities; import com.android.launcher3.config.FeatureFlags; +import com.android.quickstep.views.RecentsView; import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.ActivityOptionsCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; import com.android.systemui.shared.system.RemoteTransitionCompat; - -import java.util.function.Consumer; +import com.android.systemui.shared.system.TaskStackChangeListener; public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAnimationListener { public static final boolean ENABLE_SHELL_TRANSITIONS = @@ -49,10 +50,24 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn // Temporary until we can hook into gesture state events private GestureState mLastGestureState; private RemoteAnimationTargetCompat mLastAppearedTaskTarget; - private Consumer mLaunchOtherTaskHandler; private Runnable mLiveTileCleanUpHandler; private Context mCtx; + private final TaskStackChangeListener mLiveTileRestartListener = new TaskStackChangeListener() { + @Override + public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task, + boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) { + BaseActivityInterface activityInterface = mLastGestureState.getActivityInterface(); + if (LIVE_TILE.get() && activityInterface.isInLiveTileMode() + && activityInterface.getCreatedActivity() != null) { + RecentsView recentsView = activityInterface.getCreatedActivity().getOverviewPanel(); + recentsView.launchSideTaskInLiveTileModeForRestartedApp(task.taskId); + ActivityManagerWrapper.getInstance().unregisterTaskStackListener( + mLiveTileRestartListener); + } + } + }; + TaskAnimationManager(Context ctx) { mCtx = ctx; } @@ -114,9 +129,14 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn @Override public void onTaskAppeared(RemoteAnimationTargetCompat appearedTaskTarget) { - if (mLaunchOtherTaskHandler != null - && mLastGestureState.getEndTarget() == RECENTS) { - mLaunchOtherTaskHandler.accept(appearedTaskTarget); + BaseActivityInterface activityInterface = mLastGestureState.getActivityInterface(); + if (LIVE_TILE.get() && activityInterface.isInLiveTileMode() + && activityInterface.getCreatedActivity() != null) { + RecentsView recentsView = + activityInterface.getCreatedActivity().getOverviewPanel(); + RemoteAnimationTargetCompat[] apps = new RemoteAnimationTargetCompat[1]; + apps[0] = appearedTaskTarget; + recentsView.launchSideTaskInLiveTileMode(appearedTaskTarget.taskId, apps); return; } if (mController != null) { @@ -161,17 +181,12 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn return mCallbacks; } - /** - * The passed-in handler is used to render side task launch animation in recents in live tile - * mode. - */ - public void setLaunchOtherTaskInLiveTileModeHandler( - Consumer handler) { - mLaunchOtherTaskHandler = handler; + public void setLiveTileCleanUpHandler(Runnable cleanUpHandler) { + mLiveTileCleanUpHandler = cleanUpHandler; } - public void setLiveTileCleanUpHandler(Runnable runnable) { - mLiveTileCleanUpHandler = runnable; + public void enableLiveTileRestartListener() { + ActivityManagerWrapper.getInstance().registerTaskStackListener(mLiveTileRestartListener); } /** @@ -215,6 +230,7 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn mLiveTileCleanUpHandler.run(); mLiveTileCleanUpHandler = null; } + ActivityManagerWrapper.getInstance().unregisterTaskStackListener(mLiveTileRestartListener); // Release all the target leashes if (mTargets != null) { @@ -231,7 +247,6 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn mTargets = null; mLastGestureState = null; mLastAppearedTaskTarget = null; - mLaunchOtherTaskHandler = null; } public void dump() { diff --git a/quickstep/src/com/android/quickstep/util/InputConsumerProxy.java b/quickstep/src/com/android/quickstep/util/InputConsumerProxy.java index 3e87f48f02..2e5b33ae24 100644 --- a/quickstep/src/com/android/quickstep/util/InputConsumerProxy.java +++ b/quickstep/src/com/android/quickstep/util/InputConsumerProxy.java @@ -38,7 +38,8 @@ public class InputConsumerProxy { private static final String TAG = "InputConsumerProxy"; private final InputConsumerController mInputConsumerController; - private final Supplier mConsumerSupplier; + private Runnable mCallback; + private Supplier mConsumerSupplier; // The consumer is created lazily on demand. private InputConsumer mInputConsumer; @@ -48,8 +49,9 @@ public class InputConsumerProxy { private boolean mDestroyPending = false; public InputConsumerProxy(InputConsumerController inputConsumerController, - Supplier consumerSupplier) { + Runnable callback, Supplier consumerSupplier) { mInputConsumerController = inputConsumerController; + mCallback = callback; mConsumerSupplier = consumerSupplier; } @@ -64,9 +66,7 @@ public class InputConsumerProxy { if (ev instanceof MotionEvent) { onInputConsumerMotionEvent((MotionEvent) ev); } else if (ev instanceof KeyEvent) { - if (mInputConsumer == null) { - mInputConsumer = mConsumerSupplier.get(); - } + initInputConsumerIfNeeded(); mInputConsumer.onKeyEvent((KeyEvent) ev); return true; } @@ -89,9 +89,7 @@ public class InputConsumerProxy { if (action == ACTION_DOWN) { mTouchInProgress = true; - if (mInputConsumer == null) { - mInputConsumer = mConsumerSupplier.get(); - } + initInputConsumerIfNeeded(); } else if (action == ACTION_CANCEL || action == ACTION_UP) { // Finish any pending actions mTouchInProgress = false; @@ -115,4 +113,18 @@ public class InputConsumerProxy { mDestroyed = true; mInputConsumerController.setInputListener(null); } + + public void unregisterCallback() { + mCallback = null; + } + + private void initInputConsumerIfNeeded() { + if (mInputConsumer == null) { + if (mCallback != null) { + mCallback.run(); + } + mInputConsumer = mConsumerSupplier.get(); + mConsumerSupplier = null; + } + } } diff --git a/quickstep/src/com/android/quickstep/util/InputProxyHandlerFactory.java b/quickstep/src/com/android/quickstep/util/InputProxyHandlerFactory.java new file mode 100644 index 0000000000..8209c09304 --- /dev/null +++ b/quickstep/src/com/android/quickstep/util/InputProxyHandlerFactory.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.quickstep.util; + +import androidx.annotation.UiThread; + +import com.android.launcher3.statemanager.StatefulActivity; +import com.android.quickstep.BaseActivityInterface; +import com.android.quickstep.GestureState; +import com.android.quickstep.InputConsumer; +import com.android.quickstep.inputconsumers.OverviewInputConsumer; + +import java.util.function.Supplier; + +/** + * A factory that creates a input consumer for + * {@link com.android.quickstep.util.InputConsumerProxy}. + */ +public class InputProxyHandlerFactory implements Supplier { + + private final BaseActivityInterface mActivityInterface; + private final GestureState mGestureState; + + @UiThread + public InputProxyHandlerFactory(BaseActivityInterface activityInterface, + GestureState gestureState) { + mActivityInterface = activityInterface; + mGestureState = gestureState; + } + + /** + * Called to create a input proxy for the running task + */ + @Override + public InputConsumer get() { + StatefulActivity activity = mActivityInterface.getCreatedActivity(); + return activity == null ? InputConsumer.NO_OP + : new OverviewInputConsumer(mGestureState, activity, null, true); + } +} diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index d357ebead0..769344080a 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -27,6 +27,7 @@ import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA; import static com.android.launcher3.LauncherState.BACKGROUND_APP; import static com.android.launcher3.LauncherState.OVERVIEW_MODAL_TASK; import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT; +import static com.android.launcher3.QuickstepTransitionManager.RECENTS_LAUNCH_DURATION; import static com.android.launcher3.Utilities.EDGE_NAV_BAR; import static com.android.launcher3.Utilities.mapToRange; import static com.android.launcher3.Utilities.squaredHypot; @@ -34,6 +35,7 @@ import static com.android.launcher3.Utilities.squaredTouchSlop; import static com.android.launcher3.anim.Interpolators.ACCEL; import static com.android.launcher3.anim.Interpolators.ACCEL_0_75; import static com.android.launcher3.anim.Interpolators.ACCEL_2; +import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL; import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_CLEAR_ALL; @@ -50,6 +52,7 @@ import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_RECENTS; import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_TASKS; import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.LayoutTransition; import android.animation.LayoutTransition.TransitionListener; @@ -61,6 +64,7 @@ import android.app.ActivityManager.RunningTaskInfo; import android.content.Context; import android.content.res.Configuration; import android.graphics.Canvas; +import android.graphics.Matrix; import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; @@ -129,8 +133,11 @@ import com.android.quickstep.RecentsModel.TaskVisualsChangeListener; import com.android.quickstep.SystemUiProxy; import com.android.quickstep.TaskOverlayFactory; import com.android.quickstep.TaskThumbnailCache; +import com.android.quickstep.TaskViewUtils; import com.android.quickstep.ViewUtils; +import com.android.quickstep.util.ActiveGestureLog; import com.android.quickstep.util.LayoutUtils; +import com.android.quickstep.util.MultiValueUpdateListener; import com.android.quickstep.util.RecentsOrientedState; import com.android.quickstep.util.SplitScreenBounds; import com.android.quickstep.util.SurfaceTransactionApplier; @@ -142,6 +149,8 @@ import com.android.systemui.shared.recents.model.Task.TaskKey; import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.PackageManagerWrapper; +import com.android.systemui.shared.system.RemoteAnimationTargetCompat; +import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams; import com.android.systemui.shared.system.TaskStackChangeListener; import com.android.wm.shell.pip.IPipAnimationListener; @@ -715,6 +724,72 @@ public abstract class RecentsView extends PagedView super.draw(canvas); } + public void launchSideTaskInLiveTileModeForRestartedApp(int taskId) { + if (mRunningTaskId != -1 && mRunningTaskId == taskId && + getLiveTileParams().getTargetSet().findTask(taskId) != null) { + launchSideTaskInLiveTileMode(taskId, getLiveTileParams().getTargetSet().apps); + } + } + + public void launchSideTaskInLiveTileMode(int taskId, RemoteAnimationTargetCompat[] apps) { + AnimatorSet anim = new AnimatorSet(); + TaskView taskView = getTaskView(taskId); + if (taskView == null || !isTaskViewVisible(taskView)) { + // TODO: Refine this animation. + SurfaceTransactionApplier surfaceApplier = + new SurfaceTransactionApplier(mActivity.getDragLayer()); + ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1); + appAnimator.setDuration(RECENTS_LAUNCH_DURATION); + appAnimator.setInterpolator(ACCEL_DEACCEL); + appAnimator.addUpdateListener(new MultiValueUpdateListener() { + @Override + public void onUpdate(float percent) { + SurfaceParams.Builder builder = new SurfaceParams.Builder( + apps[apps.length - 1].leash); + Matrix matrix = new Matrix(); + matrix.postScale(percent, percent); + matrix.postTranslate(mActivity.getDeviceProfile().widthPx * (1 - percent) / 2, + mActivity.getDeviceProfile().heightPx * (1 - percent) / 2); + builder.withAlpha(percent).withMatrix(matrix); + surfaceApplier.scheduleApply(builder.build()); + } + }); + anim.play(appAnimator); + } else { + TaskViewUtils.composeRecentsLaunchAnimator( + anim, taskView, apps, + mLiveTileParams.getTargetSet().wallpapers, true /* launcherClosing */, + mActivity.getStateManager(), this, + getDepthController()); + } + anim.addListener(new AnimatorListenerAdapter(){ + + @Override + public void onAnimationEnd(Animator animator) { + cleanUp(false); + } + + @Override + public void onAnimationCancel(Animator animator) { + cleanUp(true); + } + + private void cleanUp(boolean canceled) { + if (mRecentsAnimationController != null) { + mRecentsAnimationController.finish(false /* toRecents */, + null /* onFinishComplete */); + if (canceled) { + mRecentsAnimationController = null; + } else { + mSizeStrategy.onLaunchTaskSuccess(); + } + ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", false); + } + } + }); + anim.start(); + } + private void updateTaskStartIndex(View affectingView) { if (!(affectingView instanceof TaskView) && !(affectingView instanceof ClearAllButton)) { int childCount = getChildCount();