Merge "Folder polish - update color extraction, fix contrast issues." into sc-dev
diff --git a/go/quickstep/res/values/config.xml b/go/quickstep/res/values/config.xml
index 402bf9a..796d14d 100644
--- a/go/quickstep/res/values/config.xml
+++ b/go/quickstep/res/values/config.xml
@@ -16,8 +16,6 @@
<resources>
<!-- The component to receive app sharing Intents -->
<string name="app_sharing_component" translatable="false"/>
- <!-- The package to receive Listen, Translate, and Search Intents -->
- <string name="niu_actions_package" translatable="false"/>
<!-- Feature Flags -->
<bool name="enable_niu_actions">true</bool>
diff --git a/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java b/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
index 65cdcf0..3a6e9b5 100644
--- a/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
+++ b/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java
@@ -21,6 +21,7 @@
import android.annotation.SuppressLint;
import android.app.assist.AssistContent;
+import android.content.ActivityNotFoundException;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -29,10 +30,10 @@
import android.os.UserManager;
import android.provider.Settings;
import android.text.TextUtils;
+import android.util.Log;
import androidx.annotation.VisibleForTesting;
-import com.android.launcher3.R;
import com.android.quickstep.util.AssistContentRequester;
import com.android.quickstep.views.OverviewActionsView;
import com.android.quickstep.views.TaskThumbnailView;
@@ -90,9 +91,7 @@
public void initOverlay(Task task, ThumbnailData thumbnail, Matrix matrix,
boolean rotated) {
getActionsView().updateDisabledFlags(DISABLED_NO_THUMBNAIL, thumbnail == null);
- mNIUPackageName =
- mApplicationContext.getString(R.string.niu_actions_package);
-
+ checkSettings();
if (thumbnail == null || TextUtils.isEmpty(mNIUPackageName)) {
return;
}
@@ -105,7 +104,6 @@
getActionsView().setCallbacks(new OverlayUICallbacksGoImpl(isAllowedByPolicy, task));
mTaskPackageName = task.key.getPackageName();
- checkPermissions();
if (!mAssistPermissionsEnabled) {
return;
}
@@ -137,7 +135,11 @@
mImageApi.shareAsDataWithExplicitIntent(/* crop */ null, intent);
} else {
intent.putExtra(ACTIONS_ERROR_CODE, ERROR_PERMISSIONS);
- mApplicationContext.startActivity(intent);
+ try {
+ mApplicationContext.startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ Log.e(TAG, "No activity found to receive permission error intent");
+ }
}
}
@@ -160,13 +162,17 @@
* Checks whether the Assistant has screen context permissions
*/
@VisibleForTesting
- public void checkPermissions() {
+ public void checkSettings() {
ContentResolver contentResolver = mApplicationContext.getContentResolver();
boolean structureEnabled = Settings.Secure.getInt(contentResolver,
Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1) != 0;
boolean screenshotEnabled = Settings.Secure.getInt(contentResolver,
Settings.Secure.ASSIST_SCREENSHOT_ENABLED, 1) != 0;
mAssistPermissionsEnabled = structureEnabled && screenshotEnabled;
+
+ String assistantPackage =
+ Settings.Secure.getString(contentResolver, Settings.Secure.ASSISTANT);
+ mNIUPackageName = assistantPackage.split("/", 2)[0];
}
protected class OverlayUICallbacksGoImpl extends OverlayUICallbacksImpl
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index 6852642..0e85ec3 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -353,7 +353,8 @@
public void startHome() {
if (LIVE_TILE.get()) {
RecentsView recentsView = getOverviewPanel();
- recentsView.switchToScreenshotAndFinishAnimationToRecents(this::startHomeInternal);
+ recentsView.switchToScreenshot(() -> recentsView.finishRecentsAnimation(true,
+ this::startHomeInternal));
} else {
startHomeInternal();
}
diff --git a/quickstep/src/com/android/quickstep/util/ImageActionUtils.java b/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
index 2285d74..de7dbd6 100644
--- a/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
+++ b/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
@@ -26,6 +26,7 @@
import android.app.Activity;
import android.app.ActivityOptions;
import android.app.prediction.AppTarget;
+import android.content.ActivityNotFoundException;
import android.content.ClipData;
import android.content.ClipDescription;
import android.content.ComponentName;
@@ -68,6 +69,7 @@
private static final long FILE_LIFE = 1000L /*ms*/ * 60L /*s*/ * 60L /*m*/ * 24L /*h*/;
private static final String SUB_FOLDER = "Overview";
private static final String BASE_NAME = "overview_image_";
+ private static final String TAG = "ImageActionUtils";
/**
* Saves screenshot to location determine by SystemUiProxy
@@ -154,11 +156,15 @@
Intent intent, BiFunction<Uri, Intent, Intent[]> uriToIntentMap, String tag) {
Intent[] intents = uriToIntentMap.apply(getImageUri(bitmap, crop, context, tag), intent);
- // Work around b/159412574
- if (intents.length == 1) {
- context.startActivity(intents[0]);
- } else {
- context.startActivities(intents);
+ try {
+ // Work around b/159412574
+ if (intents.length == 1) {
+ context.startActivity(intents[0]);
+ } else {
+ context.startActivities(intents);
+ }
+ } catch (ActivityNotFoundException e) {
+ Log.e(TAG, "No activity found to receive image intent");
}
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 7991614..df7f8b5 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -2357,7 +2357,8 @@
public void accept(Boolean success) {
if (LIVE_TILE.get() && mEnableDrawingLiveTile && taskView.isRunningTask()
&& success) {
- finishRecentsAnimation(true /* toHome */, () -> onEnd(success));
+ finishRecentsAnimation(true /* toRecents */, false /* shouldPip */,
+ () -> onEnd(success));
} else {
onEnd(success);
}
@@ -2368,7 +2369,8 @@
if (success) {
if (shouldRemoveTask) {
if (taskView.getTask() != null) {
- switchToScreenshotAndFinishAnimationToRecents(() -> {
+ finishRecentsAnimation(true /* toRecents */, false /* shouldPip */,
+ () -> {
UI_HELPER_EXECUTOR.getHandler().postDelayed(() ->
ActivityManagerWrapper.getInstance().removeTask(
taskView.getTask().key.id),
@@ -2478,7 +2480,7 @@
mPendingAnimation.addEndListener(isSuccess -> {
if (isSuccess) {
// Remove all the task views now
- switchToScreenshotAndFinishAnimationToRecents(() -> {
+ finishRecentsAnimation(true /* toRecents */, false /* shouldPip */, () -> {
UI_HELPER_EXECUTOR.getHandler().postDelayed(
ActivityManagerWrapper.getInstance()::removeAllRecentTasks,
REMOVE_TASK_WAIT_FOR_APP_STOP_MS);
@@ -2639,7 +2641,9 @@
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (LIVE_TILE.get() && mEnableDrawingLiveTile && newConfig.orientation != mOrientation) {
- switchToScreenshotAndFinishAnimationToRecents(this::updateRecentsRotation);
+ switchToScreenshot(
+ () -> finishRecentsAnimation(true /* toRecents */, false /* showPip */,
+ this::updateRecentsRotation));
mEnableDrawingLiveTile = false;
} else {
updateRecentsRotation();
@@ -3632,10 +3636,6 @@
}
}
- public void switchToScreenshotAndFinishAnimationToRecents(Runnable onFinishRunnable) {
- switchToScreenshot(() -> finishRecentsAnimation(true /* toRecents */, onFinishRunnable));
- }
-
/**
* Switch the current running task view to static snapshot mode,
* capturing the snapshot at the same time.
diff --git a/res/drawable/work_apps_toggle_background.xml b/res/drawable/work_apps_toggle_background.xml
index a04d269..cb8b8e2 100644
--- a/res/drawable/work_apps_toggle_background.xml
+++ b/res/drawable/work_apps_toggle_background.xml
@@ -24,7 +24,7 @@
<item>
<shape android:shape="rectangle">
<corners android:radius="@dimen/work_fab_radius" />
- <solid android:color="?android:attr/colorAccent" />
+ <solid android:color="@color/all_apps_tab_bg" />
<padding android:left="@dimen/work_fab_radius" android:right="@dimen/work_fab_radius" />
</shape>
</item>
diff --git a/res/drawable/work_card.xml b/res/drawable/work_card.xml
new file mode 100644
index 0000000..0e4b054
--- /dev/null
+++ b/res/drawable/work_card.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ 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.
+ -->
+
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:shape="rectangle">
+ <solid android:color="?androidprv:attr/colorSurface" />
+ <corners android:radius="@dimen/work_edu_card_margin" />
+ <padding
+ android:left="@dimen/work_fab_radius"
+ android:right="@dimen/work_fab_radius" />
+</shape>
+
diff --git a/res/drawable/work_card_btn.xml b/res/drawable/work_card_btn.xml
new file mode 100644
index 0000000..3c93919
--- /dev/null
+++ b/res/drawable/work_card_btn.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ 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.
+ -->
+
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:shape="rectangle">
+ <corners android:radius="@dimen/work_edu_card_margin" />
+ <stroke android:width="1dp" android:color="?androidprv:attr/colorAccentPrimaryVariant" />
+ <padding
+ android:left="@dimen/work_fab_radius"
+ android:right="@dimen/work_fab_radius" />
+</shape>
+
diff --git a/res/layout/work_apps_edu.xml b/res/layout/work_apps_edu.xml
new file mode 100644
index 0000000..2c58907
--- /dev/null
+++ b/res/layout/work_apps_edu.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2020 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.
+-->
+
+<com.android.launcher3.allapps.WorkEduCard xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="@dimen/work_edu_card_margin"
+ android:orientation="vertical"
+ android:background="@drawable/work_card"
+ android:gravity="center">
+
+ <TextView
+ style="@style/PrimaryHeadline"
+ android:textColor="?android:attr/textColorPrimary"
+ android:id="@+id/work_apps_paused_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:layout_marginBottom="8dp"
+ android:text="@string/work_profile_edu_work_apps"
+ android:textAlignment="center"
+ android:textSize="20sp" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/action_btn"
+ android:textColor="?attr/workProfileOverlayTextColor"
+ android:text="@string/work_profile_edu_accept"
+ android:textAlignment="center"
+ android:background="@drawable/work_card_btn"
+ android:textSize="14sp" />
+</com.android.launcher3.allapps.WorkEduCard>
\ No newline at end of file
diff --git a/res/layout/work_mode_fab.xml b/res/layout/work_mode_fab.xml
index 21f269f..4209192 100644
--- a/res/layout/work_mode_fab.xml
+++ b/res/layout/work_mode_fab.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2017 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.
@@ -13,8 +12,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<com.android.launcher3.allapps.WorkModeSwitch
- xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.launcher3.allapps.WorkModeSwitch xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/work_mode_toggle"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
@@ -22,8 +20,8 @@
android:layout_width="wrap_content"
android:gravity="center"
android:includeFontPadding="false"
- android:drawableTint="@android:color/white"
- android:textColor="@android:color/white"
+ android:drawableTint="@color/all_apps_tab_text"
+ android:textColor="@color/all_apps_tab_text"
android:background="@drawable/work_apps_toggle_background"
android:drawablePadding="16dp"
android:drawableStart="@drawable/ic_corp_off"
diff --git a/res/layout/work_mode_switch.xml b/res/layout/work_mode_switch.xml
deleted file mode 100644
index 538a180..0000000
--- a/res/layout/work_mode_switch.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2017 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.
--->
-<com.android.launcher3.allapps.WorkModeSwitch xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- style="@style/PrimaryHeadline"
- android:id="@+id/work_mode_toggle"
- android:drawableStart="@drawable/ic_corp"
- android:drawablePadding="16dp"
- android:drawableTint="?attr/workProfileOverlayTextColor"
- android:textColor="?attr/workProfileOverlayTextColor"
- android:layout_alignParentBottom="true"
- android:ellipsize="end"
- android:elevation="10dp"
- android:gravity="start"
- android:lines="1"
- android:showText="false"
- android:textSize="@dimen/work_profile_footer_text_size"
- android:background="?attr/allAppsScrimColor"
- android:text="@string/work_profile_toggle_label"
- android:paddingBottom="@dimen/work_profile_footer_padding"
- android:paddingLeft="@dimen/work_profile_footer_padding"
- android:paddingRight="@dimen/work_profile_footer_padding"
- android:paddingTop="@dimen/work_profile_footer_padding" />
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 06bdd49..430a1ab 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -122,8 +122,10 @@
<dimen name="work_fab_margin">18dp</dimen>
<dimen name="work_profile_footer_padding">20dp</dimen>
<dimen name="work_profile_footer_text_size">16sp</dimen>
+ <dimen name="work_edu_card_margin">16dp</dimen>
-<!-- Widget tray -->
+
+ <!-- Widget tray -->
<dimen name="widget_cell_vertical_padding">8dp</dimen>
<dimen name="widget_cell_horizontal_padding">16dp</dimen>
<dimen name="widget_cell_font_size">14sp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 9cfe69a..9823df3 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -389,7 +389,7 @@
<!-- This string is in the work profile tab when a user has All Apps open on their phone. This is a label for a toggle to turn the work profile on and off. "Work profile" means a separate profile on a user's phone that's specifically for their work apps and managed by their company. "Work" is used as an adjective.-->
<string name="work_profile_toggle_label">Work profile</string>
<!--- User onboarding title for work profile apps -->
- <string name="work_profile_edu_work_apps">Work apps are badged andare visible to your IT admin</string>
+ <string name="work_profile_edu_work_apps">Work apps are badged and visible to your IT admin</string>
<!-- Action label to finish work profile edu-->
<string name="work_profile_edu_accept">Got it</string>
diff --git a/src/com/android/launcher3/ShortcutAndWidgetContainer.java b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
index 2c24c3a..4579705 100644
--- a/src/com/android/launcher3/ShortcutAndWidgetContainer.java
+++ b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
@@ -18,6 +18,9 @@
import static android.view.MotionEvent.ACTION_DOWN;
+import static com.android.launcher3.CellLayout.FOLDER;
+import static com.android.launcher3.CellLayout.WORKSPACE;
+
import android.app.WallpaperManager;
import android.content.Context;
import android.graphics.Rect;
@@ -124,21 +127,27 @@
public void measureChild(View child) {
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
- final DeviceProfile profile = mActivity.getDeviceProfile();
+ final DeviceProfile dp = mActivity.getDeviceProfile();
if (child instanceof LauncherAppWidgetHostView) {
- ((LauncherAppWidgetHostView) child).getWidgetInset(profile, mTempRect);
+ ((LauncherAppWidgetHostView) child).getWidgetInset(dp, mTempRect);
lp.setup(mCellWidth, mCellHeight, invertLayoutHorizontally(), mCountX, mCountY,
- profile.appWidgetScale.x, profile.appWidgetScale.y, mBorderSpacing, mTempRect);
+ dp.appWidgetScale.x, dp.appWidgetScale.y, mBorderSpacing, mTempRect);
} else {
lp.setup(mCellWidth, mCellHeight, invertLayoutHorizontally(), mCountX, mCountY,
mBorderSpacing, null);
// Center the icon/folder
int cHeight = getCellContentHeight();
int cellPaddingY = (int) Math.max(0, ((lp.height - cHeight) / 2f));
- int cellPaddingX = mContainerType == CellLayout.WORKSPACE
- ? profile.workspaceCellPaddingXPx
- : (int) (profile.edgeMarginPx / 2f);
+
+ // No need to add padding when cell layout border spacing is present.
+ boolean noPadding = (dp.cellLayoutBorderSpacingPx > 0 && mContainerType == WORKSPACE)
+ || (dp.folderCellLayoutBorderSpacingPx > 0 && mContainerType == FOLDER);
+ int cellPaddingX = noPadding
+ ? 0
+ : mContainerType == WORKSPACE
+ ? dp.workspaceCellPaddingXPx
+ : (int) (dp.edgeMarginPx / 2f);
child.setPadding(cellPaddingX, cellPaddingY, cellPaddingX, 0);
}
int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 7249aaf..d749e02 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -50,7 +50,6 @@
import androidx.annotation.VisibleForTesting;
import androidx.core.graphics.ColorUtils;
import androidx.core.os.BuildCompat;
-import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@@ -127,6 +126,7 @@
private Rect mInsets = new Rect();
private SearchAdapterProvider mSearchAdapterProvider;
+ private WorkAdapterProvider mWorkAdapterProvider;
private final int mScrimColor;
private final int mHeaderProtectionColor;
private final float mHeaderThreshold;
@@ -159,6 +159,11 @@
Selection.setSelection(mSearchQueryBuilder, 0);
mAH = new AdapterHolder[2];
+ mWorkAdapterProvider = new WorkAdapterProvider(mLauncher, () -> {
+ if (mAH[AdapterHolder.WORK] != null) {
+ mAH[AdapterHolder.WORK].appsList.updateAdapterItems();
+ }
+ });
mAH[AdapterHolder.MAIN] = new AdapterHolder(false /* isWork */);
mAH[AdapterHolder.WORK] = new AdapterHolder(true /* isWork */);
@@ -228,8 +233,9 @@
}
private void resetWorkProfile() {
- mWorkModeSwitch.updateCurrentState(!mAllAppsStore.hasModelFlag(FLAG_QUIET_MODE_ENABLED));
- mAH[AdapterHolder.WORK].setupOverlay();
+ boolean isEnabled = !mAllAppsStore.hasModelFlag(FLAG_QUIET_MODE_ENABLED);
+ mWorkModeSwitch.updateCurrentState(isEnabled);
+ mWorkAdapterProvider.updateCurrentState(isEnabled);
mAH[AdapterHolder.WORK].applyPadding();
}
@@ -392,7 +398,6 @@
mAH[i].padding.bottom = insets.bottom;
mAH[i].padding.left = mAH[i].padding.right = leftRightPadding;
mAH[i].applyPadding();
- mAH[i].setupOverlay();
}
ViewGroup.MarginLayoutParams mlp = (MarginLayoutParams) getLayoutParams();
@@ -539,6 +544,9 @@
&& mAllAppsStore.hasModelFlag(
FLAG_HAS_SHORTCUT_PERMISSION | FLAG_QUIET_MODE_CHANGE_PERMISSION));
}
+ if (mSearchUiManager != null && mSearchUiManager.getEditText() != null) {
+ mSearchUiManager.getEditText().hideKeyboard();
+ }
}
// Used by tests only
@@ -719,9 +727,15 @@
AdapterHolder(boolean isWork) {
mIsWork = isWork;
- appsList = new AlphabeticalAppsList(mLauncher, mAllAppsStore, isWork);
+ appsList = new AlphabeticalAppsList(mLauncher, mAllAppsStore,
+ isWork ? mWorkAdapterProvider : null);
+
+ BaseAdapterProvider[] adapterProviders =
+ isWork ? new BaseAdapterProvider[]{mSearchAdapterProvider, mWorkAdapterProvider}
+ : new BaseAdapterProvider[]{mSearchAdapterProvider};
+
adapter = new AllAppsGridAdapter(mLauncher, getLayoutInflater(), appsList,
- mSearchAdapterProvider);
+ adapterProviders);
appsList.setAdapter(adapter);
layoutManager = adapter.getLayoutManager();
}
@@ -743,38 +757,11 @@
adapter.setIconFocusListener(focusedItemDecorator.getFocusListener());
applyVerticalFadingEdgeEnabled(verticalFadingEdge);
applyPadding();
- setupOverlay();
if (FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
recyclerView.addItemDecoration(mSearchAdapterProvider.getDecorator());
}
}
- void setupOverlay() {
- if (!mIsWork || recyclerView == null) return;
- boolean workDisabled = mAllAppsStore.hasModelFlag(FLAG_QUIET_MODE_ENABLED);
- if (mWorkDisabled == workDisabled) return;
- recyclerView.setContentDescription(workDisabled ? mLauncher.getString(
- R.string.work_apps_paused_content_description) : null);
- View overlayView = getOverlayView();
- recyclerView.setItemAnimator(new DefaultItemAnimator());
- if (workDisabled) {
- overlayView.setAlpha(0);
- recyclerView.addAutoSizedOverlay(overlayView);
- overlayView.animate().alpha(1).withEndAction(
- () -> {
- appsList.updateItemFilter((info, cn) -> false);
- recyclerView.setItemAnimator(null);
- }).start();
- } else if (mInfoMatcher != null) {
- appsList.updateItemFilter(mInfoMatcher);
- overlayView.animate().alpha(0).withEndAction(() -> {
- recyclerView.setItemAnimator(null);
- recyclerView.clearAutoSizedOverlays();
- }).start();
- }
- mWorkDisabled = workDisabled;
- }
-
void applyPadding() {
if (recyclerView != null) {
Resources res = getResources();
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index 70588ea..874fe80 100644
--- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
+++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
@@ -41,10 +41,10 @@
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.R;
-import com.android.launcher3.allapps.search.SearchAdapterProvider;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.util.PackageManagerHelper;
+import java.util.Arrays;
import java.util.List;
/**
@@ -72,7 +72,8 @@
public static final int VIEW_TYPE_MASK_DIVIDER = VIEW_TYPE_ALL_APPS_DIVIDER;
public static final int VIEW_TYPE_MASK_ICON = VIEW_TYPE_ICON;
- private final SearchAdapterProvider mSearchAdapterProvider;
+
+ private final BaseAdapterProvider[] mAdapterProviders;
/**
* ViewHolder for each icon.
@@ -242,9 +243,12 @@
int totalSpans = mGridLayoutMgr.getSpanCount();
if (isIconViewType(viewType)) {
return totalSpans / mAppsPerRow;
- } else if (mSearchAdapterProvider.isSearchView(viewType)) {
- return totalSpans / mSearchAdapterProvider.getItemsPerRow(viewType, mAppsPerRow);
} else {
+ BaseAdapterProvider adapterProvider = getAdapterProvider(viewType);
+ if (adapterProvider != null) {
+ return totalSpans / adapterProvider.getItemsPerRow(viewType, mAppsPerRow);
+ }
+
// Section breaks span the full width
return totalSpans;
}
@@ -270,7 +274,7 @@
private Intent mMarketSearchIntent;
public AllAppsGridAdapter(BaseDraggingActivity launcher, LayoutInflater inflater,
- AlphabeticalAppsList apps, SearchAdapterProvider searchAdapterProvider) {
+ AlphabeticalAppsList apps, BaseAdapterProvider[] adapterProviders) {
Resources res = launcher.getResources();
mLauncher = launcher;
mApps = apps;
@@ -282,16 +286,18 @@
mOnIconClickListener = launcher.getItemOnClickListener();
- mSearchAdapterProvider = searchAdapterProvider;
+ mAdapterProviders = adapterProviders;
setAppsPerRow(mLauncher.getDeviceProfile().numShownAllAppsColumns);
}
public void setAppsPerRow(int appsPerRow) {
mAppsPerRow = appsPerRow;
int totalSpans = mAppsPerRow;
- for (int itemPerRow : mSearchAdapterProvider.getSupportedItemsPerRowArray()) {
- if (totalSpans % itemPerRow != 0) {
- totalSpans *= itemPerRow;
+ for (BaseAdapterProvider adapterProvider : mAdapterProviders) {
+ for (int itemPerRow : adapterProvider.getSupportedItemsPerRowArray()) {
+ if (totalSpans % itemPerRow != 0) {
+ totalSpans *= itemPerRow;
+ }
}
}
mGridLayoutMgr.setSpanCount(totalSpans);
@@ -363,9 +369,9 @@
return new ViewHolder(mLayoutInflater.inflate(
R.layout.all_apps_divider, parent, false));
default:
- if (mSearchAdapterProvider.isSearchView(viewType)) {
- return mSearchAdapterProvider.onCreateViewHolder(mLayoutInflater, parent,
- viewType);
+ BaseAdapterProvider adapterProvider = getAdapterProvider(viewType);
+ if (adapterProvider != null) {
+ return adapterProvider.onCreateViewHolder(mLayoutInflater, parent, viewType);
}
throw new RuntimeException("Unexpected view type");
}
@@ -399,7 +405,10 @@
// nothing to do
break;
default:
- mSearchAdapterProvider.onBindView(holder, position);
+ BaseAdapterProvider adapterProvider = getAdapterProvider(holder.getItemViewType());
+ if (adapterProvider != null) {
+ adapterProvider.onBindView(holder, position);
+ }
}
}
@@ -424,4 +433,11 @@
AdapterItem item = mApps.getAdapterItems().get(position);
return item.viewType;
}
+
+ @Nullable
+ private BaseAdapterProvider getAdapterProvider(int viewType) {
+ return Arrays.stream(mAdapterProviders).filter(
+ adapterProvider -> adapterProvider.isViewSupported(viewType)).findFirst().orElse(
+ null);
+ }
}
diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
index 88d95fa..ce5c589 100644
--- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
@@ -44,6 +44,7 @@
private static final int FAST_SCROLL_FRACTION_DISTRIBUTE_BY_NUM_SECTIONS = 1;
private final int mFastScrollDistributionMode = FAST_SCROLL_FRACTION_DISTRIBUTE_BY_NUM_SECTIONS;
+ private final WorkAdapterProvider mWorkAdapterProvider;
/**
* Info about a fast scroller section, depending if sections are merged, the fast scroller
@@ -75,8 +76,6 @@
private final ArrayList<AdapterItem> mAdapterItems = new ArrayList<>();
// The set of sections that we allow fast-scrolling to (includes non-merged sections)
private final List<FastScrollSectionInfo> mFastScrollerSections = new ArrayList<>();
- // Is it the work profile app list.
- private final boolean mIsWork;
// The of ordered component names as a result of a search query
private ArrayList<AdapterItem> mSearchResults;
@@ -86,11 +85,12 @@
private int mNumAppRowsInAdapter;
private ItemInfoMatcher mItemFilter;
- public AlphabeticalAppsList(Context context, AllAppsStore appsStore, boolean isWork) {
+ public AlphabeticalAppsList(Context context, AllAppsStore appsStore,
+ WorkAdapterProvider adapterProvider) {
mAllAppsStore = appsStore;
mLauncher = BaseDraggingActivity.fromContext(context);
mAppNameComparator = new AppInfoComparator(context);
- mIsWork = isWork;
+ mWorkAdapterProvider = adapterProvider;
mNumAppsPerRow = mLauncher.getDeviceProfile().inv.numColumns;
mAllAppsStore.addUpdateListener(this);
}
@@ -265,7 +265,7 @@
* Updates the set of filtered apps with the current filter. At this point, we expect
* mCachedSectionNames to have been calculated for the set of all apps in mApps.
*/
- private void updateAdapterItems() {
+ public void updateAdapterItems() {
refillAdapterItems();
refreshRecyclerView();
}
@@ -292,6 +292,12 @@
if (!hasFilter()) {
mAccessibilityResultsCount = mApps.size();
+ if (mWorkAdapterProvider != null) {
+ position += mWorkAdapterProvider.addWorkItems(mAdapterItems);
+ if (!mWorkAdapterProvider.shouldShowWorkApps()) {
+ return;
+ }
+ }
for (AppInfo info : mApps) {
String sectionName = info.sectionName;
@@ -303,7 +309,8 @@
}
// Create an app item
- AdapterItem appItem = AdapterItem.asApp(position++, sectionName, info, appIndex++);
+ AdapterItem appItem = AdapterItem.asApp(position++, sectionName, info,
+ appIndex++);
if (lastFastScrollerSectionInfo.fastScrollToItem == null) {
lastFastScrollerSectionInfo.fastScrollToItem = appItem;
}
diff --git a/src/com/android/launcher3/allapps/BaseAdapterProvider.java b/src/com/android/launcher3/allapps/BaseAdapterProvider.java
new file mode 100644
index 0000000..308294c
--- /dev/null
+++ b/src/com/android/launcher3/allapps/BaseAdapterProvider.java
@@ -0,0 +1,56 @@
+/*
+ * 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.launcher3.allapps;
+
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+
+/**
+ * A UI expansion wrapper providing for providing dynamic recyclerview items
+ */
+public abstract class BaseAdapterProvider {
+
+ /**
+ * Returns whether or not viewType can be handled by searchProvider
+ */
+ public abstract boolean isViewSupported(int viewType);
+
+ /**
+ * Called from RecyclerView.Adapter#onBindViewHolder
+ */
+ public abstract void onBindView(AllAppsGridAdapter.ViewHolder holder, int position);
+
+ /**
+ * Called from RecyclerView.Adapter#onCreateViewHolder
+ */
+ public abstract AllAppsGridAdapter.ViewHolder onCreateViewHolder(LayoutInflater layoutInflater,
+ ViewGroup parent, int viewType);
+
+ /**
+ * Returns supported item per row combinations supported
+ */
+ public int[] getSupportedItemsPerRowArray() {
+ return new int[]{};
+ }
+
+ /**
+ * Returns how many cells a view should span
+ */
+ public int getItemsPerRow(int viewType, int appsPerRow) {
+ return appsPerRow;
+ }
+
+}
diff --git a/src/com/android/launcher3/allapps/WorkAdapterProvider.java b/src/com/android/launcher3/allapps/WorkAdapterProvider.java
new file mode 100644
index 0000000..13444dd
--- /dev/null
+++ b/src/com/android/launcher3/allapps/WorkAdapterProvider.java
@@ -0,0 +1,106 @@
+/*
+ * 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.launcher3.allapps;
+
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+
+import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+
+import java.util.ArrayList;
+
+/**
+ * A UI expansion wrapper providing for providing work profile specific views
+ */
+public class WorkAdapterProvider extends BaseAdapterProvider {
+
+ public static final String KEY_WORK_EDU_STEP = "showed_work_profile_edu";
+
+ private static final int VIEW_TYPE_WORK_EDU_CARD = 1 << 20;
+ private static final int VIEW_TYPE_WORK_DISABLED_CARD = 1 << 21;
+ private final Runnable mRefreshCB;
+ private final BaseDraggingActivity mLauncher;
+ private boolean mEnabled;
+
+ WorkAdapterProvider(BaseDraggingActivity launcher, Runnable refreshCallback) {
+ mLauncher = launcher;
+ mRefreshCB = refreshCallback;
+ }
+
+ @Override
+ public void onBindView(AllAppsGridAdapter.ViewHolder holder, int position) {
+ if (holder.itemView instanceof WorkEduCard) {
+ ((WorkEduCard) holder.itemView).setPosition(position);
+ }
+ }
+
+ @Override
+ public AllAppsGridAdapter.ViewHolder onCreateViewHolder(LayoutInflater layoutInflater,
+ ViewGroup parent, int viewType) {
+ int viewId = viewType == VIEW_TYPE_WORK_DISABLED_CARD ? R.layout.work_apps_paused
+ : R.layout.work_apps_edu;
+ return new AllAppsGridAdapter.ViewHolder(layoutInflater.inflate(viewId, parent, false));
+ }
+
+ /**
+ * returns whether or not work apps should be visible in work tab.
+ */
+ public boolean shouldShowWorkApps() {
+ return mEnabled;
+ }
+
+ /**
+ * Adds work profile specific adapter items to adapterItems and returns number of items added
+ */
+ public int addWorkItems(ArrayList<AllAppsGridAdapter.AdapterItem> adapterItems) {
+ if (!mEnabled) {
+ //add disabled card here.
+ AllAppsGridAdapter.AdapterItem disabledCard = new AllAppsGridAdapter.AdapterItem();
+ disabledCard.viewType = VIEW_TYPE_WORK_DISABLED_CARD;
+ adapterItems.add(disabledCard);
+ } else if (!isEduSeen()) {
+ AllAppsGridAdapter.AdapterItem eduCard = new AllAppsGridAdapter.AdapterItem();
+ eduCard.viewType = VIEW_TYPE_WORK_EDU_CARD;
+ adapterItems.add(eduCard);
+ }
+
+ return adapterItems.size();
+ }
+
+ /**
+ * Sets the current state of work profile
+ */
+ public void updateCurrentState(boolean isEnabled) {
+ mEnabled = isEnabled;
+ mRefreshCB.run();
+ }
+
+ @Override
+ public boolean isViewSupported(int viewType) {
+ return viewType == VIEW_TYPE_WORK_DISABLED_CARD || viewType == VIEW_TYPE_WORK_EDU_CARD;
+ }
+
+ @Override
+ public int getItemsPerRow(int viewType, int appsPerRow) {
+ return 1;
+ }
+
+ private boolean isEduSeen() {
+ return Utilities.getPrefs(mLauncher).getInt(KEY_WORK_EDU_STEP, 0) != 0;
+ }
+}
diff --git a/src/com/android/launcher3/allapps/WorkEduCard.java b/src/com/android/launcher3/allapps/WorkEduCard.java
new file mode 100644
index 0000000..29a42f8
--- /dev/null
+++ b/src/com/android/launcher3/allapps/WorkEduCard.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2020 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.launcher3.allapps;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.widget.LinearLayout;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.R;
+
+/**
+ * Work profile toggle switch shown at the bottom of AllApps work tab
+ */
+public class WorkEduCard extends LinearLayout implements View.OnClickListener,
+ Animation.AnimationListener {
+
+ private final Launcher mLauncher;
+ Animation mDismissAnim;
+ private int mPosition = -1;
+
+ public WorkEduCard(Context context) {
+ this(context, null, 0);
+ }
+
+ public WorkEduCard(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public WorkEduCard(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ mLauncher = Launcher.getLauncher(getContext());
+ mDismissAnim = AnimationUtils.loadAnimation(context, android.R.anim.fade_out);
+ mDismissAnim.setDuration(500);
+ mDismissAnim.setAnimationListener(this);
+ }
+
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ findViewById(R.id.action_btn).setOnClickListener(this);
+ }
+
+ @Override
+ public void onClick(View view) {
+ startAnimation(mDismissAnim);
+ mLauncher.getSharedPrefs().edit().putInt(WorkAdapterProvider.KEY_WORK_EDU_STEP, 1).apply();
+ }
+
+ @Override
+ public void onAnimationEnd(Animation animation) {
+ removeCard();
+ }
+
+ @Override
+ public void onAnimationRepeat(Animation animation) {
+
+ }
+
+ @Override
+ public void onAnimationStart(Animation animation) {
+
+ }
+
+ private void removeCard() {
+ if (mPosition == -1) {
+ if (getParent() != null) ((ViewGroup) getParent()).removeView(WorkEduCard.this);
+ } else {
+ AllAppsRecyclerView rv = mLauncher.getAppsView()
+ .mAH[AllAppsContainerView.AdapterHolder.WORK].recyclerView;
+ rv.getApps().getAdapterItems().remove(mPosition);
+ rv.getAdapter().notifyItemRemoved(mPosition);
+ }
+ }
+
+ public void setPosition(int position) {
+ mPosition = position;
+ }
+
+}
diff --git a/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java b/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java
index ef62da4..7abd555 100644
--- a/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java
+++ b/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java
@@ -57,7 +57,7 @@
}
@Override
- public boolean isSearchView(int viewType) {
+ public boolean isViewSupported(int viewType) {
return false;
}
diff --git a/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java b/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java
index cefb8cb..7af0406 100644
--- a/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java
+++ b/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java
@@ -17,20 +17,18 @@
package com.android.launcher3.allapps.search;
import android.net.Uri;
-import android.view.LayoutInflater;
import android.view.View;
-import android.view.ViewGroup;
import androidx.recyclerview.widget.RecyclerView;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.allapps.AllAppsContainerView;
-import com.android.launcher3.allapps.AllAppsGridAdapter;
+import com.android.launcher3.allapps.BaseAdapterProvider;
/**
* A UI expansion wrapper providing for search results
*/
-public abstract class SearchAdapterProvider {
+public abstract class SearchAdapterProvider extends BaseAdapterProvider {
protected final BaseDraggingActivity mLauncher;
@@ -39,42 +37,12 @@
}
/**
- * Called from RecyclerView.Adapter#onBindViewHolder
- */
- public abstract void onBindView(AllAppsGridAdapter.ViewHolder holder, int position);
-
- /**
* Called from LiveSearchManager to notify slice status updates.
*/
public void onSliceStatusUpdate(Uri sliceUri) {
}
/**
- * Returns whether or not viewType can be handled by searchProvider
- */
- public abstract boolean isSearchView(int viewType);
-
- /**
- * Called from RecyclerView.Adapter#onCreateViewHolder
- */
- public abstract AllAppsGridAdapter.ViewHolder onCreateViewHolder(LayoutInflater layoutInflater,
- ViewGroup parent, int viewType);
-
- /**
- * Returns supported item per row combinations supported
- */
- public int[] getSupportedItemsPerRowArray() {
- return new int[]{};
- }
-
- /**
- * Returns how many cells a view should span
- */
- public int getItemsPerRow(int viewType, int appsPerRow) {
- return appsPerRow;
- }
-
- /**
* Handles selection event on search adapter item. Returns false if provider can not handle
* event
*/
diff --git a/src/com/android/launcher3/anim/AnimatorPlaybackController.java b/src/com/android/launcher3/anim/AnimatorPlaybackController.java
index f6d1651..7d8b82a 100644
--- a/src/com/android/launcher3/anim/AnimatorPlaybackController.java
+++ b/src/com/android/launcher3/anim/AnimatorPlaybackController.java
@@ -290,7 +290,10 @@
callAnimatorCommandRecursively(mAnim, a -> a.setInterpolator(interpolator));
}
- private static void callListenerCommandRecursively(
+ /**
+ * Recursively calls a command on all the listeners of the provided animation
+ */
+ public static void callListenerCommandRecursively(
Animator anim, BiConsumer<AnimatorListener, Animator> command) {
callAnimatorCommandRecursively(anim, a-> {
for (AnimatorListener l : nonNullList(a.getListeners())) {
diff --git a/src/com/android/launcher3/statemanager/StateManager.java b/src/com/android/launcher3/statemanager/StateManager.java
index 03b6853..13d6568 100644
--- a/src/com/android/launcher3/statemanager/StateManager.java
+++ b/src/com/android/launcher3/statemanager/StateManager.java
@@ -18,6 +18,7 @@
import static android.animation.ValueAnimator.areAnimatorsEnabled;
+import static com.android.launcher3.anim.AnimatorPlaybackController.callListenerCommandRecursively;
import static com.android.launcher3.states.StateAnimationConfig.SKIP_ALL_ANIMATIONS;
import android.animation.Animator;
@@ -514,8 +515,15 @@
playbackController.getAnimationPlayer().cancel();
playbackController.dispatchOnCancel();
} else if (currentAnimation != null) {
- currentAnimation.setDuration(0);
- currentAnimation.cancel();
+ AnimatorSet anim = currentAnimation;
+ anim.setDuration(0);
+ if (!anim.isStarted()) {
+ // If the animation is not started the listeners do not get notified,
+ // notify manually.
+ callListenerCommandRecursively(anim, AnimatorListener::onAnimationCancel);
+ callListenerCommandRecursively(anim, AnimatorListener::onAnimationEnd);
+ }
+ anim.cancel();
}
currentAnimation = null;