Snap for 7339742 from 7ef5456182 to sc-v2-release
Change-Id: Ibb4e00821b01b0cb46d14b2bb2828115aa4f4154
This commit is contained in:
@@ -103,16 +103,40 @@
|
||||
android:clearTaskOnLaunch="true"
|
||||
android:exported="false"/>
|
||||
|
||||
<!--
|
||||
Activity for gesture nav onboarding.
|
||||
It's protected by android.permission.REBOOT to ensure that only system apps can start it
|
||||
(setup wizard already has this permission)
|
||||
-->
|
||||
<activity android:name="com.android.quickstep.interaction.GestureSandboxActivity"
|
||||
android:autoRemoveFromRecents="true"
|
||||
android:excludeFromRecents="true"
|
||||
android:screenOrientation="portrait"
|
||||
android:exported="true">
|
||||
android:autoRemoveFromRecents="true"
|
||||
android:excludeFromRecents="true"
|
||||
android:screenOrientation="portrait"
|
||||
android:permission="android.permission.REBOOT"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="com.android.quickstep.action.GESTURE_SANDBOX"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<!--
|
||||
Activity following gesture nav onboarding.
|
||||
It's protected by android.permission.REBOOT to ensure that only system apps can start it
|
||||
(setup wizard already has this permission)
|
||||
-->
|
||||
<activity android:name="com.android.quickstep.interaction.AllSetActivity"
|
||||
android:autoRemoveFromRecents="true"
|
||||
android:excludeFromRecents="true"
|
||||
android:screenOrientation="portrait"
|
||||
android:permission="android.permission.REBOOT"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="com.android.quickstep.action.GESTURE_ONBOARDING_ALL_SET"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".hybridhotseat.HotseatEduActivity"
|
||||
android:theme="@android:style/Theme.NoDisplay"
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="42dp"
|
||||
android:height="40dp"
|
||||
android:viewportWidth="42"
|
||||
android:viewportHeight="40">
|
||||
<path
|
||||
android:pathData="M38,14H25.38L27.28,4.86L27.34,4.22C27.34,3.4 27,2.64 26.46,2.1L24.34,0C24.34,0 10.16,13.7 10,14H0V40H32C33.66,40 35.08,39 35.68,37.56L41.72,23.46C41.9,23 42,22.52 42,22V18C42,15.8 40.2,14 38,14ZM10,36H4V18H10V36ZM38,22L32,36H14V16L22.68,7.32L20,18H38V22Z"
|
||||
android:fillColor="#FFFFFF"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,80 @@
|
||||
<?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.
|
||||
-->
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingStart="@dimen/allset_page_margin_horizontal"
|
||||
android:paddingEnd="@dimen/allset_page_margin_horizontal"
|
||||
android:layoutDirection="locale"
|
||||
android:textDirection="locale"
|
||||
android:background="?android:attr/colorBackground">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_gravity="start"
|
||||
android:gravity="start"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/allset_title_icon_margin_top"
|
||||
android:src="@drawable/ic_all_set"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
style="@style/TextAppearance.GestureTutorial.Feedback.Title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/allset_title_margin_top"
|
||||
android:gravity="start"
|
||||
android:text="@string/allset_title"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/subtitle"
|
||||
style="@style/TextAppearance.GestureTutorial.Feedback.Subtitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/allset_subtitle_margin_top"
|
||||
android:gravity="start"
|
||||
android:text="@string/allset_description"/>
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/navigation_settings"
|
||||
style="@style/TextAppearance.GestureTutorial.Feedback.Subtitle"
|
||||
android:textSize="14sp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@+id/hint"
|
||||
android:gravity="center_horizontal"
|
||||
android:layout_marginBottom="72dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@id/hint"
|
||||
style="@style/TextAppearance.GestureTutorial.Feedback.Subtitle"
|
||||
android:textSize="14sp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="@dimen/allset_hint_margin_bottom"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:text="@string/allset_hint"/>
|
||||
</RelativeLayout>
|
||||
@@ -15,12 +15,6 @@
|
||||
-->
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<com.android.quickstep.views.SplitPlaceholderView
|
||||
android:id="@+id/split_placeholder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/split_placeholder_size"
|
||||
android:background="@android:color/darker_gray"
|
||||
android:visibility="gone" />
|
||||
|
||||
<com.android.quickstep.views.LauncherRecentsView
|
||||
android:id="@+id/overview_panel"
|
||||
@@ -31,6 +25,13 @@
|
||||
android:clipToPadding="false"
|
||||
android:visibility="invisible" />
|
||||
|
||||
<com.android.quickstep.views.SplitPlaceholderView
|
||||
android:id="@+id/split_placeholder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/split_placeholder_size"
|
||||
android:background="@android:color/darker_gray"
|
||||
android:visibility="gone" />
|
||||
|
||||
<include
|
||||
android:id="@+id/overview_actions_view"
|
||||
layout="@layout/overview_actions_container" />
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<?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.
|
||||
-->
|
||||
<resources>
|
||||
<declare-styleable name="AllSetLinkSpan">
|
||||
<attr name="android:textSize"/>
|
||||
<attr name="android:fontFamily"/>
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
@@ -99,6 +99,13 @@
|
||||
<dimen name="gesture_tutorial_feedback_margin_start_end">24dp</dimen>
|
||||
<dimen name="gesture_tutorial_button_margin_start_end">18dp</dimen>
|
||||
|
||||
<!-- All Set page -->
|
||||
<dimen name="allset_page_margin_horizontal">40dp</dimen>
|
||||
<dimen name="allset_title_margin_top">28dp</dimen>
|
||||
<dimen name="allset_title_icon_margin_top">80dp</dimen>
|
||||
<dimen name="allset_hint_margin_bottom">52dp</dimen>
|
||||
<dimen name="allset_subtitle_margin_top">24dp</dimen>
|
||||
|
||||
<!-- All Apps Education tutorial -->
|
||||
<dimen name="swipe_edu_padding">8dp</dimen>
|
||||
<dimen name="swipe_edu_circle_size">64dp</dimen>
|
||||
|
||||
@@ -177,6 +177,15 @@
|
||||
<!-- Feedback subtext displaying the current step and the total number of steps for the tutorial. [CHAR LIMIT=30] -->
|
||||
<string name="gesture_tutorial_step">Tutorial <xliff:g id="current">%1$d</xliff:g>/<xliff:g id="total">%2$d</xliff:g></string>
|
||||
|
||||
<!-- Title of "All Set" page [CHAR LIMIT=NONE] -->
|
||||
<string name="allset_title">All set!</string>
|
||||
<!-- Hint string at the bottom of "All Set" page [CHAR LIMIT=NONE] -->
|
||||
<string name="allset_hint">Swipe up to go home</string>
|
||||
<!-- Description of "All Set" page [CHAR LIMIT=NONE] -->
|
||||
<string name="allset_description">You\u2019re ready to start using your phone</string>
|
||||
<!-- String linking to navigation settings on "All Set" page [CHAR LIMIT=NONE] -->
|
||||
<string name="allset_navigation_settings"><annotation id="link">Navigation settings for accessibility</annotation></string>
|
||||
|
||||
<!-- ******* Overview ******* -->
|
||||
<!-- Label for a button that causes the current overview app to be shared. [CHAR_LIMIT=40] -->
|
||||
<string name="action_share">Share</string>
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
parent="TextAppearance.GestureTutorial">
|
||||
<item name="android:gravity">start</item>
|
||||
<item name="android:textColor">?android:attr/textColorPrimary</item>
|
||||
<item name="android:fontFamily">google-sans</item>
|
||||
<item name="android:fontFamily">google-sans-text</item>
|
||||
<item name="android:letterSpacing">0.03</item>
|
||||
<item name="android:textSize">18sp</item>
|
||||
<item name="android:lineHeight">24sp</item>
|
||||
@@ -99,6 +99,11 @@
|
||||
<item name="android:textColor">@color/gesture_tutorial_primary_color</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.GestureTutorial.LinkText"
|
||||
parent="TextAppearance.GestureTutorial.Feedback.Subtitle">
|
||||
<item name="android:textSize">14sp</item>
|
||||
</style>
|
||||
|
||||
<!--
|
||||
Can be applied to views to color things like ripples and list highlights the workspace text
|
||||
color.
|
||||
|
||||
@@ -22,12 +22,12 @@ import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FA
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_MODAL;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW;
|
||||
import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET;
|
||||
import static com.android.quickstep.views.RecentsView.RECENTS_GRID_PROGRESS;
|
||||
import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY;
|
||||
import static com.android.quickstep.views.RecentsView.TASK_PRIMARY_TRANSLATION;
|
||||
import static com.android.quickstep.views.RecentsView.TASK_PRIMARY_SPLIT_TRANSLATION;
|
||||
import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_SPLIT_TRANSLATION;
|
||||
import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION;
|
||||
|
||||
import android.util.FloatProperty;
|
||||
@@ -97,10 +97,10 @@ public abstract class BaseRecentsViewStateController<T extends RecentsView>
|
||||
PagedOrientationHandler orientationHandler =
|
||||
((RecentsView) mLauncher.getOverviewPanel()).getPagedOrientationHandler();
|
||||
FloatProperty taskViewsFloat = orientationHandler.getSplitSelectTaskOffset(
|
||||
TASK_PRIMARY_TRANSLATION, TASK_SECONDARY_TRANSLATION, mLauncher.getDeviceProfile());
|
||||
TASK_PRIMARY_SPLIT_TRANSLATION, TASK_SECONDARY_SPLIT_TRANSLATION,
|
||||
mLauncher.getDeviceProfile());
|
||||
setter.setFloat(mRecentsView, taskViewsFloat,
|
||||
toState.getOverviewSecondaryTranslation(mLauncher),
|
||||
config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, LINEAR));
|
||||
toState.getOverviewSecondaryTranslation(mLauncher), LINEAR);
|
||||
|
||||
setter.setFloat(mRecentsView, getContentAlphaProperty(), toState.overviewUi ? 1 : 0,
|
||||
config.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT));
|
||||
|
||||
+7
-1
@@ -36,11 +36,13 @@ import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_F
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.SKIP_ALL_ANIMATIONS;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.SKIP_SCRIM;
|
||||
import static com.android.launcher3.touch.BothAxesSwipeDetector.DIRECTION_RIGHT;
|
||||
import static com.android.launcher3.touch.BothAxesSwipeDetector.DIRECTION_UP;
|
||||
import static com.android.launcher3.util.DisplayController.getSingleFrameMs;
|
||||
import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
|
||||
import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET;
|
||||
import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
|
||||
import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
|
||||
import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY;
|
||||
import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION;
|
||||
@@ -207,7 +209,7 @@ public class NoButtonQuickSwitchTouchController implements TouchController,
|
||||
/** Create state animation to control non-overview components. */
|
||||
private void updateNonOverviewAnim(LauncherState toState, StateAnimationConfig config) {
|
||||
config.duration = (long) (Math.max(mXRange, mYRange) * 2);
|
||||
config.animFlags |= SKIP_OVERVIEW;
|
||||
config.animFlags |= SKIP_OVERVIEW | SKIP_SCRIM;
|
||||
mNonOverviewAnim = mLauncher.getStateManager()
|
||||
.createAnimationToNewWorkspace(toState, config);
|
||||
mNonOverviewAnim.getTarget().addListener(mClearStateOnCancelListener);
|
||||
@@ -229,10 +231,14 @@ public class NoButtonQuickSwitchTouchController implements TouchController,
|
||||
// As we drag right, animate the following properties:
|
||||
// - RecentsView translationX
|
||||
// - OverviewScrim
|
||||
// - RecentsView fade (if it's empty)
|
||||
PendingAnimation xAnim = new PendingAnimation((long) (mXRange * 2));
|
||||
xAnim.setFloat(mRecentsView, ADJACENT_PAGE_OFFSET, scaleAndOffset[1], LINEAR);
|
||||
xAnim.setViewBackgroundColor(mLauncher.getScrimView(),
|
||||
toState.getWorkspaceScrimColor(mLauncher), LINEAR);
|
||||
if (mRecentsView.getTaskViewCount() == 0) {
|
||||
xAnim.addFloat(mRecentsView, CONTENT_ALPHA, 0f, 1f, LINEAR);
|
||||
}
|
||||
mXOverviewAnim = xAnim.createPlaybackController();
|
||||
mXOverviewAnim.dispatchOnStart();
|
||||
|
||||
|
||||
@@ -47,7 +47,6 @@ import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
|
||||
import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
|
||||
import static com.android.quickstep.util.SwipePipToHomeAnimator.FRACTION_END;
|
||||
import static com.android.quickstep.util.SwipePipToHomeAnimator.FRACTION_START;
|
||||
import static com.android.quickstep.views.RecentsView.RECENTS_GRID_PROGRESS;
|
||||
import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
|
||||
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
|
||||
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME;
|
||||
@@ -55,7 +54,6 @@ import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACT
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityManager;
|
||||
@@ -464,8 +462,6 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
mDeviceState.getRotationTouchHelper()
|
||||
.onEndTargetCalculated(mGestureState.getEndTarget(),
|
||||
mActivityInterface);
|
||||
|
||||
mRecentsView.onGestureEndTargetCalculated(mGestureState.getEndTarget());
|
||||
});
|
||||
|
||||
notifyGestureStartedAsync();
|
||||
@@ -1133,6 +1129,10 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
}
|
||||
homeAnimFactory.playAtomicAnimation(velocityPxPerMs.y);
|
||||
mLauncherTransitionController = null;
|
||||
|
||||
if (mRecentsView != null) {
|
||||
mRecentsView.onPrepareGestureEndAnimation(null, mGestureState.getEndTarget());
|
||||
}
|
||||
} else {
|
||||
AnimatorSet animatorSet = new AnimatorSet();
|
||||
ValueAnimator windowAnim = mCurrentShift.animateToValue(start, end);
|
||||
@@ -1171,9 +1171,9 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
}
|
||||
});
|
||||
animatorSet.play(windowAnim);
|
||||
S state = mActivityInterface.stateFromGestureEndTarget(mGestureState.getEndTarget());
|
||||
if (mRecentsView != null && state.displayOverviewTasksAsGrid(mDp)) {
|
||||
animatorSet.play(ObjectAnimator.ofFloat(mRecentsView, RECENTS_GRID_PROGRESS, 1));
|
||||
if (mRecentsView != null) {
|
||||
mRecentsView.onPrepareGestureEndAnimation(
|
||||
animatorSet, mGestureState.getEndTarget());
|
||||
}
|
||||
animatorSet.setDuration(duration).setInterpolator(interpolator);
|
||||
animatorSet.start();
|
||||
@@ -1701,7 +1701,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
// No need to apply any transform if there is ongoing swipe-pip-to-home animator since
|
||||
// that animator handles the leash solely.
|
||||
if (mRecentsAnimationTargets != null && !mIsSwipingPipToHome) {
|
||||
if (mRecentsViewScrollLinked) {
|
||||
if (mRecentsViewScrollLinked && mRecentsView != null) {
|
||||
mTaskViewSimulator.setScroll(mRecentsView.getScrollOffset());
|
||||
}
|
||||
mTaskViewSimulator.apply(mTransformParams);
|
||||
|
||||
@@ -163,7 +163,9 @@ public final class FallbackActivityInterface extends
|
||||
|
||||
@Override
|
||||
public boolean isInLiveTileMode() {
|
||||
return false;
|
||||
RecentsActivity activity = getCreatedActivity();
|
||||
return activity != null && activity.getStateManager().getState() == DEFAULT &&
|
||||
activity.isStarted();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -260,6 +260,7 @@ public class LauncherSwipeHandlerV2 extends
|
||||
@Override
|
||||
public void setAnimation(RectFSpringAnim anim) {
|
||||
anim.addAnimatorListener(floatingWidgetView);
|
||||
floatingWidgetView.setOnTargetChangeListener(anim::onTargetPositionChanged);
|
||||
floatingWidgetView.setFastFinishRunnable(anim::end);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,10 +22,13 @@ import static com.android.launcher3.QuickstepTransitionManager.RECENTS_LAUNCH_DU
|
||||
import static com.android.launcher3.QuickstepTransitionManager.STATUS_BAR_TRANSITION_DURATION;
|
||||
import static com.android.launcher3.QuickstepTransitionManager.STATUS_BAR_TRANSITION_PRE_DELAY;
|
||||
import static com.android.launcher3.Utilities.createHomeIntent;
|
||||
import static com.android.launcher3.graphics.SysUiScrim.SYSUI_PROGRESS;
|
||||
import static com.android.launcher3.testing.TestProtocol.OVERVIEW_STATE_ORDINAL;
|
||||
import static com.android.quickstep.TaskUtils.taskIsATargetWithMode;
|
||||
import static com.android.quickstep.TaskViewUtils.createRecentsWindowAnimator;
|
||||
import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
|
||||
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
|
||||
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
@@ -35,6 +38,7 @@ import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.view.SurfaceControl.Transaction;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -47,6 +51,7 @@ import com.android.launcher3.LauncherAnimationRunner.AnimationResult;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.WrappedAnimationRunnerImpl;
|
||||
import com.android.launcher3.WrappedLauncherAnimationRunner;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.compat.AccessibilityManagerCompat;
|
||||
@@ -69,6 +74,7 @@ import com.android.quickstep.fallback.RecentsState;
|
||||
import com.android.quickstep.util.RecentsAtomicAnimationFactory;
|
||||
import com.android.quickstep.util.SplitSelectStateController;
|
||||
import com.android.quickstep.views.OverviewActionsView;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.SplitPlaceholderView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.systemui.shared.system.ActivityOptionsCompat;
|
||||
@@ -90,6 +96,8 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> {
|
||||
|
||||
private Handler mUiHandler = new Handler(Looper.getMainLooper());
|
||||
|
||||
private static final long HOME_APPEAR_DURATION = 250;
|
||||
|
||||
private RecentsDragLayer mDragLayer;
|
||||
private ScrimView mScrimView;
|
||||
private FallbackRecentsView mFallbackRecentsView;
|
||||
@@ -112,6 +120,7 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> {
|
||||
mScrimView = findViewById(R.id.scrim_view);
|
||||
mFallbackRecentsView = findViewById(R.id.overview_panel);
|
||||
mActionsView = findViewById(R.id.overview_actions_view);
|
||||
SYSUI_PROGRESS.set(getRootView().getSysUiScrim(), 0f);
|
||||
|
||||
SplitPlaceholderView splitPlaceholderView = findViewById(R.id.split_placeholder);
|
||||
splitPlaceholderView.init(
|
||||
@@ -291,6 +300,16 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStateSetEnd(RecentsState state) {
|
||||
super.onStateSetEnd(state);
|
||||
|
||||
if (state == RecentsState.DEFAULT) {
|
||||
AccessibilityManagerCompat.sendStateEventToTest(getBaseContext(),
|
||||
OVERVIEW_STATE_ORDINAL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize/update the device profile.
|
||||
*/
|
||||
@@ -329,7 +348,42 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> {
|
||||
}
|
||||
|
||||
public void startHome() {
|
||||
startActivity(createHomeIntent());
|
||||
if (LIVE_TILE.get()) {
|
||||
RecentsView recentsView = getOverviewPanel();
|
||||
recentsView.switchToScreenshot(() -> recentsView.finishRecentsAnimation(true,
|
||||
this::startHomeInternal));
|
||||
} else {
|
||||
startHomeInternal();
|
||||
}
|
||||
}
|
||||
|
||||
private void startHomeInternal() {
|
||||
WrappedLauncherAnimationRunner runner = new WrappedLauncherAnimationRunner(
|
||||
getMainThreadHandler(), this::onCreateAnimationToHome, true);
|
||||
RemoteAnimationAdapterCompat adapterCompat =
|
||||
new RemoteAnimationAdapterCompat(runner, HOME_APPEAR_DURATION, 0);
|
||||
startActivity(createHomeIntent(),
|
||||
ActivityOptionsCompat.makeRemoteAnimation(adapterCompat).toBundle());
|
||||
}
|
||||
|
||||
private void onCreateAnimationToHome(
|
||||
int transit, RemoteAnimationTargetCompat[] appTargets,
|
||||
RemoteAnimationTargetCompat[] wallpaperTargets,
|
||||
RemoteAnimationTargetCompat[] nonAppTargets, AnimationResult result) {
|
||||
AnimatorPlaybackController controller = getStateManager()
|
||||
.createAnimationToNewWorkspace(RecentsState.BG_LAUNCHER, HOME_APPEAR_DURATION);
|
||||
controller.dispatchOnStart();
|
||||
|
||||
RemoteAnimationTargets targets = new RemoteAnimationTargets(
|
||||
appTargets, wallpaperTargets, nonAppTargets, MODE_OPENING);
|
||||
for (RemoteAnimationTargetCompat app : targets.apps) {
|
||||
new Transaction().setAlpha(app.leash.getSurfaceControl(), 1).apply();
|
||||
}
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
anim.play(controller.getAnimationPlayer());
|
||||
anim.setDuration(HOME_APPEAR_DURATION);
|
||||
result.setAnimation(anim, this,
|
||||
() -> getStateManager().goToState(RecentsState.HOME, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -20,6 +20,7 @@ import static com.android.quickstep.fallback.RecentsState.DEFAULT;
|
||||
import static com.android.quickstep.fallback.RecentsState.HOME;
|
||||
import static com.android.quickstep.fallback.RecentsState.MODAL_TASK;
|
||||
|
||||
import android.animation.AnimatorSet;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.content.Context;
|
||||
@@ -27,6 +28,9 @@ import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.statemanager.StateManager.StateListener;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
@@ -67,7 +71,6 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity, RecentsSta
|
||||
@Override
|
||||
public void startHome() {
|
||||
mActivity.startHome();
|
||||
mActivity.getStateManager().goToState(RecentsState.HOME);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,14 +89,17 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity, RecentsSta
|
||||
* to the center.
|
||||
*/
|
||||
@Override
|
||||
public void onGestureEndTargetCalculated(GestureState.GestureEndTarget endTarget) {
|
||||
super.onGestureEndTargetCalculated(endTarget);
|
||||
if (mHomeTaskInfo != null && endTarget == RECENTS) {
|
||||
public void onPrepareGestureEndAnimation(
|
||||
@Nullable AnimatorSet animatorSet, GestureState.GestureEndTarget endTarget) {
|
||||
super.onPrepareGestureEndAnimation(animatorSet, endTarget);
|
||||
if (mHomeTaskInfo != null && endTarget == RECENTS && animatorSet != null) {
|
||||
TaskView tv = getTaskView(mHomeTaskInfo.taskId);
|
||||
if (tv != null) {
|
||||
PendingAnimation pa = createTaskDismissAnimation(tv, true, false, 150);
|
||||
pa.addEndListener(e -> setCurrentTask(-1));
|
||||
runDismissAnimation(pa);
|
||||
AnimatorPlaybackController controller = pa.createPlaybackController();
|
||||
controller.dispatchOnStart();
|
||||
animatorSet.play(controller.getAnimationPlayer());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,15 +39,18 @@ public class RecentsState implements BaseState<RecentsState> {
|
||||
private static final int FLAG_OVERVIEW_ACTIONS = BaseState.getFlag(3);
|
||||
private static final int FLAG_SHOW_AS_GRID = BaseState.getFlag(4);
|
||||
private static final int FLAG_SCRIM = BaseState.getFlag(5);
|
||||
private static final int FLAG_LIVE_TILE = BaseState.getFlag(6);
|
||||
|
||||
public static final RecentsState DEFAULT = new RecentsState(0,
|
||||
FLAG_CLEAR_ALL_BUTTON | FLAG_OVERVIEW_ACTIONS | FLAG_SHOW_AS_GRID | FLAG_SCRIM);
|
||||
FLAG_CLEAR_ALL_BUTTON | FLAG_OVERVIEW_ACTIONS | FLAG_SHOW_AS_GRID | FLAG_SCRIM
|
||||
| FLAG_LIVE_TILE);
|
||||
public static final RecentsState MODAL_TASK = new ModalState(1,
|
||||
FLAG_DISABLE_RESTORE | FLAG_CLEAR_ALL_BUTTON | FLAG_OVERVIEW_ACTIONS | FLAG_MODAL
|
||||
| FLAG_SHOW_AS_GRID | FLAG_SCRIM);
|
||||
| FLAG_SHOW_AS_GRID | FLAG_SCRIM | FLAG_LIVE_TILE);
|
||||
public static final RecentsState BACKGROUND_APP = new BackgroundAppState(2,
|
||||
FLAG_DISABLE_RESTORE | FLAG_NON_INTERACTIVE | FLAG_FULL_SCREEN);
|
||||
public static final RecentsState HOME = new RecentsState(3, 0);
|
||||
public static final RecentsState BG_LAUNCHER = new LauncherState(4, 0);
|
||||
|
||||
public final int ordinal;
|
||||
private final int mFlags;
|
||||
@@ -107,6 +110,13 @@ public class RecentsState implements BaseState<RecentsState> {
|
||||
return hasFlag(FLAG_OVERVIEW_ACTIONS);
|
||||
}
|
||||
|
||||
/**
|
||||
* For this state, whether live tile should be shown.
|
||||
*/
|
||||
public boolean hasLiveTile() {
|
||||
return hasFlag(FLAG_LIVE_TILE);
|
||||
}
|
||||
|
||||
/**
|
||||
* For this state, what color scrim should be drawn behind overview.
|
||||
*/
|
||||
@@ -152,4 +162,15 @@ public class RecentsState implements BaseState<RecentsState> {
|
||||
return getOverviewScaleAndOffsetForBackgroundState(activity);
|
||||
}
|
||||
}
|
||||
|
||||
private static class LauncherState extends RecentsState {
|
||||
LauncherState(int id, int flags) {
|
||||
super(id, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float[] getOverviewScaleAndOffset(RecentsActivity activity) {
|
||||
return new float[] { NO_SCALE, 1 };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package com.android.quickstep.fallback;
|
||||
|
||||
import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
|
||||
|
||||
import com.android.launcher3.uioverrides.touchcontrollers.TaskViewTouchController;
|
||||
import com.android.quickstep.RecentsActivity;
|
||||
|
||||
@@ -26,7 +28,8 @@ public class RecentsTaskController extends TaskViewTouchController<RecentsActivi
|
||||
|
||||
@Override
|
||||
protected boolean isRecentsInteractive() {
|
||||
return mActivity.hasWindowFocus();
|
||||
return mActivity.hasWindowFocus() || (LIVE_TILE.get()
|
||||
&& mActivity.getStateManager().getState().hasLiveTile());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* 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.interaction;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextPaint;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
/**
|
||||
* A page shows after SUW flow to hint users to swipe up from the bottom of the screen to go home
|
||||
* for the gestural system navigation.
|
||||
*/
|
||||
public class AllSetActivity extends Activity {
|
||||
|
||||
private static final String LOG_TAG = "AllSetActivity";
|
||||
private static final String URI_SYSTEM_NAVIGATION_SETTING =
|
||||
"#Intent;action=com.android.settings.SEARCH_RESULT_TRAMPOLINE;S.:settings:fragment_args_key=gesture_system_navigation_input_summary;S.:settings:show_fragment=com.android.settings.gestures.SystemNavigationGestureSettings;end";
|
||||
private static final String EXTRA_ACCENT_COLOR_DARK_MODE = "accent_color_dark_mode";
|
||||
private static final String EXTRA_ACCENT_COLOR_LIGHT_MODE = "accent_color_light_mode";
|
||||
|
||||
private int mAccentColor;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_allset);
|
||||
setTitle(R.string.allset_title);
|
||||
|
||||
final int mode =
|
||||
getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
|
||||
mAccentColor = getIntent().getIntExtra(
|
||||
mode == Configuration.UI_MODE_NIGHT_YES
|
||||
? EXTRA_ACCENT_COLOR_DARK_MODE : EXTRA_ACCENT_COLOR_LIGHT_MODE,
|
||||
/* defValue= */ Color.BLACK);
|
||||
|
||||
((ImageView) findViewById(R.id.icon)).getDrawable().mutate().setTint(mAccentColor);
|
||||
|
||||
TextView navigationSettings = findViewById(R.id.navigation_settings);
|
||||
navigationSettings.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
AnnotationSpan.LinkInfo linkInfo = new AnnotationSpan.LinkInfo(
|
||||
AnnotationSpan.LinkInfo.DEFAULT_ANNOTATION,
|
||||
new AllSetLinkSpan(
|
||||
/* context= */ this,
|
||||
view -> {
|
||||
try {
|
||||
startActivityForResult(
|
||||
Intent.parseUri(URI_SYSTEM_NAVIGATION_SETTING, 0), 0);
|
||||
} catch (URISyntaxException e) {
|
||||
Log.e(LOG_TAG, "Failed to parse system nav settings intent", e);
|
||||
}
|
||||
finish();
|
||||
}));
|
||||
navigationSettings.setText(
|
||||
AnnotationSpan.linkify(getText(R.string.allset_navigation_settings), linkInfo));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasFocus) {
|
||||
super.onWindowFocusChanged(hasFocus);
|
||||
if (hasFocus) {
|
||||
hideSystemUI();
|
||||
}
|
||||
}
|
||||
|
||||
private void hideSystemUI() {
|
||||
getWindow().getDecorView().setSystemUiVisibility(
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||
| View.SYSTEM_UI_FLAG_FULLSCREEN);
|
||||
getWindow().setNavigationBarColor(Color.TRANSPARENT);
|
||||
}
|
||||
|
||||
private final class AllSetLinkSpan extends AnnotationSpan {
|
||||
|
||||
private final String mFontFamily;
|
||||
private final int mTextSize;
|
||||
|
||||
AllSetLinkSpan(Context context, View.OnClickListener listener) {
|
||||
super(listener);
|
||||
TypedArray typedArray =
|
||||
context.obtainStyledAttributes(R.style.TextAppearance_GestureTutorial_LinkText,
|
||||
R.styleable.AllSetLinkSpan);
|
||||
mFontFamily = typedArray.getString(R.styleable.AllSetLinkSpan_android_fontFamily);
|
||||
mTextSize =
|
||||
typedArray.getDimensionPixelSize(
|
||||
R.styleable.AllSetLinkSpan_android_textSize, /* defValue= */ -1);
|
||||
typedArray.recycle();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDrawState(TextPaint ds) {
|
||||
super.updateDrawState(ds);
|
||||
ds.setColor(mAccentColor);
|
||||
ds.setTypeface(Typeface.create(mFontFamily, Typeface.NORMAL));
|
||||
ds.setUnderlineText(false);
|
||||
if (mTextSize != -1) {
|
||||
ds.setTextSize(mTextSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.interaction;
|
||||
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.text.Annotation;
|
||||
import android.text.SpannableString;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.style.URLSpan;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* This class is used to add {@link View.OnClickListener} for the text been wrapped by
|
||||
* annotation.
|
||||
*
|
||||
* Copied from packages/apps/Settings/src/com/android/settings/utils/AnnotationSpan.java.
|
||||
*/
|
||||
public class AnnotationSpan extends URLSpan {
|
||||
|
||||
private final View.OnClickListener mClickListener;
|
||||
|
||||
AnnotationSpan(View.OnClickListener lsn) {
|
||||
super((String) null);
|
||||
mClickListener = lsn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View widget) {
|
||||
if (mClickListener != null) {
|
||||
mClickListener.onClick(widget);
|
||||
}
|
||||
}
|
||||
|
||||
public static CharSequence linkify(CharSequence rawText, LinkInfo... linkInfos) {
|
||||
SpannableString msg = new SpannableString(rawText);
|
||||
Annotation[] spans = msg.getSpans(0, msg.length(), Annotation.class);
|
||||
SpannableStringBuilder builder = new SpannableStringBuilder(msg);
|
||||
for (Annotation annotation : spans) {
|
||||
final String key = annotation.getValue();
|
||||
int start = msg.getSpanStart(annotation);
|
||||
int end = msg.getSpanEnd(annotation);
|
||||
AnnotationSpan link = null;
|
||||
for (LinkInfo linkInfo : linkInfos) {
|
||||
if (linkInfo.mAnnotation.equals(key)) {
|
||||
link = linkInfo.mCustomizedSpan != null ? linkInfo.mCustomizedSpan
|
||||
: new AnnotationSpan(linkInfo.mClickListener);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (link != null) {
|
||||
builder.setSpan(link, start, end, msg.getSpanFlags(link));
|
||||
}
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the text part without having text for link part
|
||||
*/
|
||||
public static CharSequence textWithoutLink(CharSequence encodedText) {
|
||||
SpannableString msg = new SpannableString(encodedText);
|
||||
Annotation[] spans = msg.getSpans(0, msg.length(), Annotation.class);
|
||||
if (spans == null) {
|
||||
return encodedText;
|
||||
}
|
||||
Arrays.sort(spans, Comparator.comparingInt(span -> -msg.getSpanStart(span)));
|
||||
StringBuilder msgWithoutLink = new StringBuilder(msg.toString());
|
||||
for (Annotation span : spans) {
|
||||
msgWithoutLink.delete(msg.getSpanStart(span), msg.getSpanEnd(span));
|
||||
}
|
||||
return msgWithoutLink.toString();
|
||||
}
|
||||
|
||||
/** Data class to store the annotation and the click action. */
|
||||
public static class LinkInfo {
|
||||
public static final String DEFAULT_ANNOTATION = "link";
|
||||
private static final String TAG = "AnnotationSpan.LinkInfo";
|
||||
private final String mAnnotation;
|
||||
private final Boolean mActionable;
|
||||
private final View.OnClickListener mClickListener;
|
||||
private final AnnotationSpan mCustomizedSpan;
|
||||
|
||||
public LinkInfo(String annotation, View.OnClickListener listener) {
|
||||
mAnnotation = annotation;
|
||||
mClickListener = listener;
|
||||
mActionable = true; // assume actionable
|
||||
mCustomizedSpan = null;
|
||||
}
|
||||
|
||||
public LinkInfo(String annotation, AnnotationSpan customizedSpan) {
|
||||
mAnnotation = annotation;
|
||||
mClickListener = null;
|
||||
mActionable = customizedSpan != null;
|
||||
mCustomizedSpan = customizedSpan;
|
||||
}
|
||||
|
||||
public LinkInfo(Context context, String annotation, Intent intent) {
|
||||
mAnnotation = annotation;
|
||||
mCustomizedSpan = null;
|
||||
if (intent != null) {
|
||||
mActionable = context.getPackageManager().resolveActivity(intent, 0) != null;
|
||||
} else {
|
||||
mActionable = false;
|
||||
}
|
||||
if (mActionable) {
|
||||
mClickListener =
|
||||
view -> {
|
||||
try {
|
||||
context.startActivity(intent);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Log.w(TAG, "Activity was not found for intent, " + intent);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
mClickListener = null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isActionable() {
|
||||
return mActionable;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,8 +20,6 @@ import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TI
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.quickstep.OverviewComponentObserver;
|
||||
import com.android.quickstep.RecentsAnimationDeviceState;
|
||||
import com.android.quickstep.SysUINavigationMode;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
@@ -37,7 +35,6 @@ public class NavigationModeFeatureFlag implements
|
||||
private final Supplier<Boolean> mBasePredicate;
|
||||
private final Predicate<SysUINavigationMode.Mode> mModePredicate;
|
||||
private boolean mSupported;
|
||||
private OverviewComponentObserver mObserver;
|
||||
|
||||
private NavigationModeFeatureFlag(Supplier<Boolean> basePredicate,
|
||||
Predicate<SysUINavigationMode.Mode> modePredicate) {
|
||||
@@ -46,17 +43,12 @@ public class NavigationModeFeatureFlag implements
|
||||
}
|
||||
|
||||
public boolean get() {
|
||||
return mBasePredicate.get() && mSupported && mObserver != null
|
||||
&& mObserver.isHomeAndOverviewSame();
|
||||
return mBasePredicate.get() && mSupported;
|
||||
}
|
||||
|
||||
public void initialize(Context context) {
|
||||
onNavigationModeChanged(SysUINavigationMode.INSTANCE.get(context).getMode());
|
||||
SysUINavigationMode.INSTANCE.get(context).addModeChangeListener(this);
|
||||
|
||||
// Temporary solution to disable live tile for the fallback launcher
|
||||
RecentsAnimationDeviceState rads = new RecentsAnimationDeviceState(context);
|
||||
mObserver = new OverviewComponentObserver(context, rads);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,6 +25,7 @@ import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITIO
|
||||
import android.animation.AnimatorSet;
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
@@ -64,6 +65,7 @@ public class SplitSelectStateController {
|
||||
private final SystemUiProxy mSystemUiProxy;
|
||||
private TaskView mInitialTaskView;
|
||||
private SplitPositionOption mInitialPosition;
|
||||
private Rect mInitialBounds;
|
||||
private final Handler mHandler;
|
||||
|
||||
public SplitSelectStateController(Handler handler, SystemUiProxy systemUiProxy) {
|
||||
@@ -74,9 +76,11 @@ public class SplitSelectStateController {
|
||||
/**
|
||||
* To be called after first task selected
|
||||
*/
|
||||
public void setInitialTaskSelect(TaskView taskView, SplitPositionOption positionOption) {
|
||||
public void setInitialTaskSelect(TaskView taskView, SplitPositionOption positionOption,
|
||||
Rect initialBounds) {
|
||||
mInitialTaskView = taskView;
|
||||
mInitialPosition = positionOption;
|
||||
mInitialBounds = initialBounds;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -220,9 +224,14 @@ public class SplitSelectStateController {
|
||||
public void resetState() {
|
||||
mInitialTaskView = null;
|
||||
mInitialPosition = null;
|
||||
mInitialBounds = null;
|
||||
}
|
||||
|
||||
public boolean isSplitSelectActive() {
|
||||
return mInitialTaskView != null;
|
||||
}
|
||||
|
||||
public Rect getInitialBounds() {
|
||||
return mInitialBounds;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import androidx.annotation.NonNull;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.util.TraceHelper;
|
||||
import com.android.quickstep.AnimatedFloat;
|
||||
import com.android.quickstep.BaseActivityInterface;
|
||||
import com.android.quickstep.views.TaskThumbnailView.PreviewPositionHelper;
|
||||
@@ -95,7 +96,9 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
|
||||
mContext = context;
|
||||
mSizeStrategy = sizeStrategy;
|
||||
|
||||
mOrientationState = new RecentsOrientedState(context, sizeStrategy, i -> { });
|
||||
// TODO(b/187074722): Don't create this per-TaskViewSimulator
|
||||
mOrientationState = TraceHelper.allowIpcs("",
|
||||
() -> new RecentsOrientedState(context, sizeStrategy, i -> { }));
|
||||
mOrientationState.setGestureActive(true);
|
||||
mCurrentFullscreenParams = new FullscreenDrawParams(context);
|
||||
mOrientationStateId = mOrientationState.getStateId();
|
||||
|
||||
@@ -100,8 +100,8 @@ final class FloatingWidgetBackgroundView extends View {
|
||||
/** Restores the drawables to the source view. */
|
||||
void finish() {
|
||||
if (isUninitialized()) return;
|
||||
mSourceView.setForeground(mOriginalForeground);
|
||||
mSourceView.setBackground(mOriginalBackground);
|
||||
if (mOriginalForeground != null) mSourceView.setForeground(mOriginalForeground);
|
||||
if (mOriginalBackground != null) mSourceView.setBackground(mOriginalBackground);
|
||||
}
|
||||
|
||||
void recycle() {
|
||||
|
||||
@@ -27,6 +27,7 @@ import android.util.Size;
|
||||
import android.view.GhostView;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
@@ -39,7 +40,8 @@ import com.android.launcher3.widget.RoundedCornerEnforcement;
|
||||
|
||||
/** A view that mimics an App Widget through a launch animation. */
|
||||
@TargetApi(Build.VERSION_CODES.S)
|
||||
public class FloatingWidgetView extends FrameLayout implements AnimatorListener {
|
||||
public class FloatingWidgetView extends FrameLayout implements AnimatorListener,
|
||||
OnGlobalLayoutListener {
|
||||
private static final Matrix sTmpMatrix = new Matrix();
|
||||
|
||||
private final Launcher mLauncher;
|
||||
@@ -54,6 +56,7 @@ public class FloatingWidgetView extends FrameLayout implements AnimatorListener
|
||||
|
||||
private Runnable mEndRunnable;
|
||||
private Runnable mFastFinishRunnable;
|
||||
private Runnable mOnTargetChangeRunnable;
|
||||
|
||||
public FloatingWidgetView(Context context) {
|
||||
this(context, null);
|
||||
@@ -93,6 +96,32 @@ public class FloatingWidgetView extends FrameLayout implements AnimatorListener
|
||||
public void onAnimationRepeat(Animator animator) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
getViewTreeObserver().addOnGlobalLayoutListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
getViewTreeObserver().removeOnGlobalLayoutListener(this);
|
||||
super.onDetachedFromWindow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGlobalLayout() {
|
||||
if (isUninitialized()) return;
|
||||
positionViews();
|
||||
if (mOnTargetChangeRunnable != null) {
|
||||
mOnTargetChangeRunnable.run();
|
||||
}
|
||||
}
|
||||
|
||||
/** Sets a runnable that is called on global layout change. */
|
||||
public void setOnTargetChangeListener(Runnable onTargetChangeListener) {
|
||||
mOnTargetChangeRunnable = onTargetChangeListener;
|
||||
}
|
||||
|
||||
/** Sets a runnable that is called after a call to {@link #fastFinish()}. */
|
||||
public void setFastFinishRunnable(Runnable runnable) {
|
||||
mFastFinishRunnable = runnable;
|
||||
@@ -205,6 +234,7 @@ public class FloatingWidgetView extends FrameLayout implements AnimatorListener
|
||||
private void recycle() {
|
||||
mEndRunnable = null;
|
||||
mFastFinishRunnable = null;
|
||||
mOnTargetChangeRunnable = null;
|
||||
mBackgroundPosition = null;
|
||||
mListenerView.setListener(null);
|
||||
mAppWidgetView = null;
|
||||
|
||||
@@ -245,8 +245,8 @@ public class LauncherRecentsView extends RecentsView<BaseQuickstepLauncher, Laun
|
||||
if (mActivity.isInState(OVERVIEW_SPLIT_SELECT)) {
|
||||
// We want to keep the tasks translations in this temporary state
|
||||
// after resetting the rest above
|
||||
setTaskViewsResistanceTranslation(mTaskViewsSecondaryTranslation);
|
||||
setTaskViewsPrimaryTranslation(mTaskViewsPrimaryTranslation);
|
||||
setTaskViewsPrimarySplitTranslation(mTaskViewsPrimarySplitTranslation);
|
||||
setTaskViewsSecondarySplitTranslation(mTaskViewsSecondarySplitTranslation);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -254,16 +254,29 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
* more specific, we'd want to create a similar FloatProperty just for a TaskView's
|
||||
* offsetX/Y property
|
||||
*/
|
||||
public static final FloatProperty<RecentsView> TASK_PRIMARY_TRANSLATION =
|
||||
new FloatProperty<RecentsView>("taskPrimaryTranslation") {
|
||||
public static final FloatProperty<RecentsView> TASK_PRIMARY_SPLIT_TRANSLATION =
|
||||
new FloatProperty<RecentsView>("taskPrimarySplitTranslation") {
|
||||
@Override
|
||||
public void setValue(RecentsView recentsView, float v) {
|
||||
recentsView.setTaskViewsPrimaryTranslation(v);
|
||||
recentsView.setTaskViewsPrimarySplitTranslation(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float get(RecentsView recentsView) {
|
||||
return recentsView.mTaskViewsPrimaryTranslation;
|
||||
return recentsView.mTaskViewsPrimarySplitTranslation;
|
||||
}
|
||||
};
|
||||
|
||||
public static final FloatProperty<RecentsView> TASK_SECONDARY_SPLIT_TRANSLATION =
|
||||
new FloatProperty<RecentsView>("taskSecondarySplitTranslation") {
|
||||
@Override
|
||||
public void setValue(RecentsView recentsView, float v) {
|
||||
recentsView.setTaskViewsSecondarySplitTranslation(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float get(RecentsView recentsView) {
|
||||
return recentsView.mTaskViewsSecondarySplitTranslation;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -279,7 +292,6 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
view.mLiveTileTaskViewSimulator.recentsViewScale.value = scale;
|
||||
view.updatePageOffsets();
|
||||
view.setTaskViewsResistanceTranslation(view.mTaskViewsSecondaryTranslation);
|
||||
view.setTaskViewsPrimaryTranslation(view.mTaskViewsPrimaryTranslation);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -363,7 +375,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
|
||||
private float mAdjacentPageOffset = 0;
|
||||
protected float mTaskViewsSecondaryTranslation = 0;
|
||||
protected float mTaskViewsPrimaryTranslation = 0;
|
||||
protected float mTaskViewsPrimarySplitTranslation = 0;
|
||||
protected float mTaskViewsSecondarySplitTranslation = 0;
|
||||
// Progress from 0 to 1 where 0 is a carousel and 1 is a 2 row grid.
|
||||
private float mGridProgress = 0;
|
||||
private final IntSet mTopRowIdSet = new IntSet();
|
||||
@@ -1631,7 +1644,16 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
/**
|
||||
* Called when a gesture from an app has finished, and an end target has been determined.
|
||||
*/
|
||||
public void onGestureEndTargetCalculated(GestureState.GestureEndTarget endTarget) {
|
||||
public void onPrepareGestureEndAnimation(
|
||||
@Nullable AnimatorSet animatorSet, GestureState.GestureEndTarget endTarget) {
|
||||
if (mSizeStrategy.stateFromGestureEndTarget(endTarget)
|
||||
.displayOverviewTasksAsGrid(mActivity.getDeviceProfile())) {
|
||||
if (animatorSet == null) {
|
||||
setGridProgress(1);
|
||||
} else {
|
||||
animatorSet.play(ObjectAnimator.ofFloat(this, RECENTS_GRID_PROGRESS, 1));
|
||||
}
|
||||
}
|
||||
mCurrentGestureEndTarget = endTarget;
|
||||
if (endTarget == GestureState.GestureEndTarget.NEW_TASK
|
||||
|| endTarget == GestureState.GestureEndTarget.LAST_TASK) {
|
||||
@@ -1839,15 +1861,28 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
final int boxLength = Math.max(mLastComputedGridTaskSize.width(),
|
||||
mLastComputedGridTaskSize.height());
|
||||
int taskTopMargin = mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx;
|
||||
float heightOffset = (boxLength + taskTopMargin) + mRowSpacing;
|
||||
float taskGridVerticalDiff = mLastComputedGridTaskSize.top - mLastComputedTaskSize.top;
|
||||
|
||||
/*
|
||||
* taskGridVerticalDiff is used to position the top of a task in the top row of the grid
|
||||
* heightOffset is the vertical space one grid task takes + space between top and
|
||||
* bottom row
|
||||
* Summed together they provide the top position for bottom row of grid tasks
|
||||
*/
|
||||
final float taskGridVerticalDiff =
|
||||
mLastComputedGridTaskSize.top - mLastComputedTaskSize.top;
|
||||
final float heightOffset = (boxLength + taskTopMargin) + mRowSpacing;
|
||||
|
||||
int topRowWidth = 0;
|
||||
int bottomRowWidth = 0;
|
||||
float topAccumulatedTranslationX = 0;
|
||||
float bottomAccumulatedTranslationX = 0;
|
||||
|
||||
// Contains whether the child index is in top or bottom of grid (for non-focused task)
|
||||
// Different from mTopRowIdSet, which contains the taskId of what task is in top row
|
||||
IntSet topSet = new IntSet();
|
||||
IntSet bottomSet = new IntSet();
|
||||
|
||||
// Horizontal grid translation for each task
|
||||
float[] gridTranslations = new float[taskCount];
|
||||
|
||||
int focusedTaskIndex = Integer.MAX_VALUE;
|
||||
@@ -1901,7 +1936,6 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
boolean isTopRow = isTaskDismissal ? mTopRowIdSet.contains(taskId)
|
||||
: topRowWidth <= bottomRowWidth;
|
||||
if (isTopRow) {
|
||||
gridTranslations[i] += topAccumulatedTranslationX;
|
||||
topRowWidth += taskWidthAndSpacing;
|
||||
topSet.add(i);
|
||||
mTopRowIdSet.add(taskId);
|
||||
@@ -1917,11 +1951,10 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
widthOffset += getTaskViewAt(j).getLayoutParams().width + mPageSpacing;
|
||||
}
|
||||
|
||||
float gridTranslationX = mIsRtl ? widthOffset : -widthOffset;
|
||||
gridTranslations[i] += gridTranslationX;
|
||||
topAccumulatedTranslationX += gridTranslationX;
|
||||
float currentTaskTranslationX = mIsRtl ? widthOffset : -widthOffset;
|
||||
gridTranslations[i] += topAccumulatedTranslationX + currentTaskTranslationX;
|
||||
topAccumulatedTranslationX += currentTaskTranslationX;
|
||||
} else {
|
||||
gridTranslations[i] += bottomAccumulatedTranslationX;
|
||||
bottomRowWidth += taskWidthAndSpacing;
|
||||
bottomSet.add(i);
|
||||
|
||||
@@ -1937,9 +1970,9 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
widthOffset += getTaskViewAt(j).getLayoutParams().width + mPageSpacing;
|
||||
}
|
||||
|
||||
float gridTranslationX = mIsRtl ? widthOffset : -widthOffset;
|
||||
gridTranslations[i] += gridTranslationX;
|
||||
bottomAccumulatedTranslationX += gridTranslationX;
|
||||
float currentTaskTranslationX = mIsRtl ? widthOffset : -widthOffset;
|
||||
gridTranslations[i] += bottomAccumulatedTranslationX + currentTaskTranslationX;
|
||||
bottomAccumulatedTranslationX += currentTaskTranslationX;
|
||||
}
|
||||
if (taskView == snappedTaskView) {
|
||||
snappedTaskRowWidth = isTopRow ? topRowWidth : bottomRowWidth;
|
||||
@@ -2130,18 +2163,43 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
// Use setFloat instead of setViewAlpha as we want to keep the view visible even when it's
|
||||
// alpha is set to 0 so that it can be recycled in the view pool properly
|
||||
anim.setFloat(taskView, VIEW_ALPHA, 0, ACCEL_2);
|
||||
FloatProperty<TaskView> secondaryViewTranslate =
|
||||
taskView.getSecondaryDissmissTranslationProperty();
|
||||
int secondaryTaskDimension = mOrientationHandler.getSecondaryDimension(taskView);
|
||||
int verticalFactor = mOrientationHandler.getSecondaryTranslationDirectionFactor();
|
||||
SplitSelectStateController splitController = mSplitPlaceholderView.getSplitController();
|
||||
|
||||
ResourceProvider rp = DynamicResource.provider(mActivity);
|
||||
SpringProperty sp = new SpringProperty(SpringProperty.FLAG_CAN_SPRING_ON_START)
|
||||
.setDampingRatio(rp.getFloat(R.dimen.dismiss_task_trans_y_damping_ratio))
|
||||
.setStiffness(rp.getFloat(R.dimen.dismiss_task_trans_y_stiffness));
|
||||
FloatProperty<TaskView> dismissingTaskViewTranslate =
|
||||
taskView.getSecondaryDissmissTranslationProperty();;
|
||||
// TODO(b/186800707) translate entire grid size distance
|
||||
int translateDistance = mOrientationHandler.getSecondaryDimension(taskView);
|
||||
int positiveNegativeFactor = mOrientationHandler.getSecondaryTranslationDirectionFactor();
|
||||
if (splitController.isSplitSelectActive()) {
|
||||
// Have the task translate towards whatever side was just pinned
|
||||
int dir = mOrientationHandler.getSplitTaskViewDismissDirection(splitController
|
||||
.getActiveSplitPositionOption(), mActivity.getDeviceProfile());
|
||||
switch (dir) {
|
||||
case PagedOrientationHandler.SPLIT_TRANSLATE_SECONDARY_NEGATIVE:
|
||||
dismissingTaskViewTranslate = taskView
|
||||
.getSecondaryDissmissTranslationProperty();
|
||||
positiveNegativeFactor = -1;
|
||||
break;
|
||||
|
||||
anim.add(ObjectAnimator.ofFloat(taskView, secondaryViewTranslate,
|
||||
verticalFactor * secondaryTaskDimension).setDuration(duration), LINEAR, sp);
|
||||
case PagedOrientationHandler.SPLIT_TRANSLATE_PRIMARY_POSITIVE:
|
||||
dismissingTaskViewTranslate = taskView.getPrimaryDismissTranslationProperty();
|
||||
positiveNegativeFactor = 1;
|
||||
break;
|
||||
|
||||
case PagedOrientationHandler.SPLIT_TRANSLATE_PRIMARY_NEGATIVE:
|
||||
dismissingTaskViewTranslate = taskView.getPrimaryDismissTranslationProperty();
|
||||
positiveNegativeFactor = -1;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Invalid split task translation: " + dir);
|
||||
}
|
||||
}
|
||||
anim.add(ObjectAnimator.ofFloat(taskView, dismissingTaskViewTranslate,
|
||||
positiveNegativeFactor * translateDistance).setDuration(duration), LINEAR, sp);
|
||||
|
||||
if (LIVE_TILE.get() && taskView.isRunningTask()) {
|
||||
anim.addOnFrameCallback(() -> {
|
||||
@@ -2206,18 +2264,6 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
}
|
||||
}
|
||||
|
||||
// Additional offset for fake landscape, if the pinning happens to the right or
|
||||
// left, we need to scroll all the tasks away from the direction of the splaceholder
|
||||
// view
|
||||
if (isSplitSelectionActive()) {
|
||||
int splitPosition = getSplitPlaceholder().getSplitController()
|
||||
.getActiveSplitPositionOption().mStagePosition;
|
||||
int direction = mOrientationHandler
|
||||
.getSplitTranslationDirectionFactor(splitPosition);
|
||||
int splitOffset = mOrientationHandler.getSplitAnimationTranslation(
|
||||
mSplitPlaceholderView.getHeight(), mActivity.getDeviceProfile());
|
||||
offset += direction * splitOffset;
|
||||
}
|
||||
int scrollDiff = newScroll[i] - oldScroll[i] + offset;
|
||||
if (scrollDiff != 0) {
|
||||
FloatProperty translationProperty = child instanceof TaskView
|
||||
@@ -2249,7 +2295,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
mPendingAnimation.addEndListener(new Consumer<Boolean>() {
|
||||
@Override
|
||||
public void accept(Boolean success) {
|
||||
if (LIVE_TILE.get() && taskView.isRunningTask() && success) {
|
||||
if (LIVE_TILE.get() && mEnableDrawingLiveTile && taskView.isRunningTask()
|
||||
&& success) {
|
||||
finishRecentsAnimation(true /* toHome */, () -> onEnd(success));
|
||||
} else {
|
||||
onEnd(success);
|
||||
@@ -2347,7 +2394,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void runDismissAnimation(PendingAnimation pendingAnim) {
|
||||
private void runDismissAnimation(PendingAnimation pendingAnim) {
|
||||
AnimatorPlaybackController controller = pendingAnim.createPlaybackController();
|
||||
controller.dispatchOnStart();
|
||||
controller.getAnimationPlayer().setInterpolator(FAST_OUT_SLOW_IN);
|
||||
@@ -2759,13 +2806,20 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
mLiveTileTaskViewSimulator.recentsViewSecondaryTranslation.value = translation;
|
||||
}
|
||||
|
||||
protected void setTaskViewsPrimaryTranslation(float translation) {
|
||||
mTaskViewsPrimaryTranslation = translation;
|
||||
protected void setTaskViewsPrimarySplitTranslation(float translation) {
|
||||
mTaskViewsPrimarySplitTranslation = translation;
|
||||
for (int i = 0; i < getTaskViewCount(); i++) {
|
||||
TaskView task = getTaskViewAt(i);
|
||||
task.getPrimaryDismissTranslationProperty().set(task, translation / getScaleY());
|
||||
task.getPrimarySplitTranslationProperty().set(task, translation);
|
||||
}
|
||||
}
|
||||
|
||||
protected void setTaskViewsSecondarySplitTranslation(float translation) {
|
||||
mTaskViewsSecondarySplitTranslation = translation;
|
||||
for (int i = 0; i < getTaskViewCount(); i++) {
|
||||
TaskView task = getTaskViewAt(i);
|
||||
task.getSecondarySplitTranslationProperty().set(task, translation);
|
||||
}
|
||||
mLiveTileTaskViewSimulator.recentsViewPrimaryTranslation.value = translation;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2788,8 +2842,9 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
public void initiateSplitSelect(TaskView taskView, SplitPositionOption splitPositionOption) {
|
||||
mSplitHiddenTaskView = taskView;
|
||||
SplitSelectStateController splitController = mSplitPlaceholderView.getSplitController();
|
||||
splitController.setInitialTaskSelect(taskView,
|
||||
splitPositionOption);
|
||||
Rect initialBounds = new Rect(taskView.getLeft(), taskView.getTop(), taskView.getRight(),
|
||||
taskView.getBottom());
|
||||
splitController.setInitialTaskSelect(taskView, splitPositionOption, initialBounds);
|
||||
mSplitHiddenTaskViewIndex = indexOfChild(taskView);
|
||||
mSplitPlaceholderView.setLayoutParams(
|
||||
splitController.getLayoutParamsForActivePosition(getResources(),
|
||||
@@ -2809,7 +2864,10 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
}
|
||||
|
||||
public PendingAnimation cancelSplitSelect(boolean animate) {
|
||||
mSplitPlaceholderView.getSplitController().resetState();
|
||||
SplitSelectStateController splitController = mSplitPlaceholderView.getSplitController();
|
||||
SplitPositionOption splitOption = splitController.getActiveSplitPositionOption();
|
||||
Rect initialBounds = splitController.getInitialBounds();
|
||||
splitController.resetState();
|
||||
int duration = mActivity.getStateManager().getState().getTransitionDuration(getContext());
|
||||
PendingAnimation pendingAnim = new PendingAnimation(duration);
|
||||
if (!animate) {
|
||||
@@ -2824,8 +2882,6 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
getPageScrolls(oldScroll, false,
|
||||
view -> view.getVisibility() != GONE && view != mSplitHiddenTaskView);
|
||||
|
||||
// x is correct, y is before tasks move up
|
||||
int[] locationOnScreen = mSplitHiddenTaskView.getLocationOnScreen();
|
||||
int[] newScroll = new int[getChildCount()];
|
||||
getPageScrolls(newScroll, false, SIMPLE_SCROLL_LOGIC);
|
||||
|
||||
@@ -2833,20 +2889,42 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
for (int i = mSplitHiddenTaskViewIndex; i >= 0; i--) {
|
||||
View child = getChildAt(i);
|
||||
if (child == mSplitHiddenTaskView) {
|
||||
TaskView taskView = (TaskView) child;
|
||||
|
||||
int left = newScroll[i] + getPaddingStart();
|
||||
int topMargin = mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx;
|
||||
int top = -mSplitHiddenTaskView.getHeight() - locationOnScreen[1];
|
||||
mSplitHiddenTaskView.layout(left, top,
|
||||
left + mSplitHiddenTaskView.getWidth(),
|
||||
top + mSplitHiddenTaskView.getHeight());
|
||||
pendingAnim.add(ObjectAnimator.ofFloat(mSplitHiddenTaskView, TRANSLATION_Y,
|
||||
-top + mSplitPlaceholderView.getHeight() - topMargin));
|
||||
int dir = mOrientationHandler.getSplitTaskViewDismissDirection(splitOption,
|
||||
mActivity.getDeviceProfile());
|
||||
FloatProperty<TaskView> dismissingTaskViewTranslate;
|
||||
Rect hiddenBounds = new Rect(taskView.getLeft(), taskView.getTop(),
|
||||
taskView.getRight(), taskView.getBottom());
|
||||
int distanceDelta = 0;
|
||||
if (dir == PagedOrientationHandler.SPLIT_TRANSLATE_SECONDARY_NEGATIVE) {
|
||||
dismissingTaskViewTranslate = taskView
|
||||
.getSecondaryDissmissTranslationProperty();
|
||||
distanceDelta = initialBounds.top - hiddenBounds.top;
|
||||
taskView.layout(initialBounds.left, hiddenBounds.top, initialBounds.right,
|
||||
hiddenBounds.bottom);
|
||||
} else {
|
||||
dismissingTaskViewTranslate = taskView
|
||||
.getPrimaryDismissTranslationProperty();
|
||||
distanceDelta = initialBounds.left - hiddenBounds.left;
|
||||
taskView.layout(hiddenBounds.left, initialBounds.top, hiddenBounds.right,
|
||||
initialBounds.bottom);
|
||||
if (dir == PagedOrientationHandler.SPLIT_TRANSLATE_PRIMARY_POSITIVE) {
|
||||
distanceDelta *= -1;
|
||||
}
|
||||
}
|
||||
pendingAnim.add(ObjectAnimator.ofFloat(mSplitHiddenTaskView,
|
||||
dismissingTaskViewTranslate,
|
||||
distanceDelta));
|
||||
pendingAnim.add(ObjectAnimator.ofFloat(mSplitHiddenTaskView, ALPHA, 1));
|
||||
} else {
|
||||
// If insertion is on last index (furthest from clear all), we directly add the view
|
||||
// else we translate all views to the right of insertion index further right,
|
||||
// ignore views to left
|
||||
if (showAsGrid()) {
|
||||
// TODO(b/186800707) handle more elegantly for grid
|
||||
continue;
|
||||
}
|
||||
int scrollDiff = newScroll[i] - oldScroll[i];
|
||||
if (scrollDiff != 0) {
|
||||
FloatProperty translationProperty = child instanceof TaskView
|
||||
@@ -2872,6 +2950,12 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
pendingAnim.addListener(new AnimationSuccessListener() {
|
||||
@Override
|
||||
public void onAnimationSuccess(Animator animator) {
|
||||
// TODO(b/186800707) Figure out how to undo for grid view
|
||||
// Need to handle cases where dismissed task is
|
||||
// * Top Row
|
||||
// * Bottom Row
|
||||
// * Focused Task
|
||||
updateGridProperties();
|
||||
resetFromSplitSelectionState();
|
||||
}
|
||||
});
|
||||
@@ -2881,13 +2965,16 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
|
||||
private void resetFromSplitSelectionState() {
|
||||
mSplitHiddenTaskView.setTranslationY(0);
|
||||
int pageToSnapTo = mCurrentPage;
|
||||
if (mSplitHiddenTaskViewIndex <= pageToSnapTo) {
|
||||
pageToSnapTo += 1;
|
||||
} else {
|
||||
pageToSnapTo = mSplitHiddenTaskViewIndex;
|
||||
if (!showAsGrid()) {
|
||||
// TODO(b/186800707)
|
||||
int pageToSnapTo = mCurrentPage;
|
||||
if (mSplitHiddenTaskViewIndex <= pageToSnapTo) {
|
||||
pageToSnapTo += 1;
|
||||
} else {
|
||||
pageToSnapTo = mSplitHiddenTaskViewIndex;
|
||||
}
|
||||
snapToPageImmediately(pageToSnapTo);
|
||||
}
|
||||
snapToPageImmediately(pageToSnapTo);
|
||||
onLayout(false /* changed */, getLeft(), getTop(), getRight(), getBottom());
|
||||
resetTaskVisuals();
|
||||
mSplitHiddenTaskView = null;
|
||||
|
||||
@@ -172,6 +172,32 @@ public class TaskView extends FrameLayout implements Reusable {
|
||||
}
|
||||
};
|
||||
|
||||
private static final FloatProperty<TaskView> SPLIT_SELECT_TRANSLATION_X =
|
||||
new FloatProperty<TaskView>("splitSelectTranslationX") {
|
||||
@Override
|
||||
public void setValue(TaskView taskView, float v) {
|
||||
taskView.setSplitSelectTranslationX(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float get(TaskView taskView) {
|
||||
return taskView.mSplitSelectTranslationX;
|
||||
}
|
||||
};
|
||||
|
||||
private static final FloatProperty<TaskView> SPLIT_SELECT_TRANSLATION_Y =
|
||||
new FloatProperty<TaskView>("splitSelectTranslationY") {
|
||||
@Override
|
||||
public void setValue(TaskView taskView, float v) {
|
||||
taskView.setSplitSelectTranslationY(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float get(TaskView taskView) {
|
||||
return taskView.mSplitSelectTranslationY;
|
||||
}
|
||||
};
|
||||
|
||||
private static final FloatProperty<TaskView> DISMISS_TRANSLATION_X =
|
||||
new FloatProperty<TaskView>("dismissTranslationX") {
|
||||
@Override
|
||||
@@ -345,6 +371,9 @@ public class TaskView extends FrameLayout implements Reusable {
|
||||
// The following grid translations scales with mGridProgress.
|
||||
private float mGridTranslationX;
|
||||
private float mGridTranslationY;
|
||||
// Used when in SplitScreenSelectState
|
||||
private float mSplitSelectTranslationY;
|
||||
private float mSplitSelectTranslationX;
|
||||
|
||||
private ObjectAnimator mIconAndDimAnimator;
|
||||
private float mIconScaleAnimStartProgress = 0;
|
||||
@@ -553,6 +582,7 @@ public class TaskView extends FrameLayout implements Reusable {
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animator) {
|
||||
recentsView.getLiveTileTaskViewSimulator().setDrawsBelowRecents(true);
|
||||
mIsClickableAsLiveTile = true;
|
||||
}
|
||||
});
|
||||
@@ -825,8 +855,10 @@ public class TaskView extends FrameLayout implements Reusable {
|
||||
protected void resetViewTransforms() {
|
||||
// fullscreenTranslation and accumulatedTranslation should not be reset, as
|
||||
// resetViewTransforms is called during Quickswitch scrolling.
|
||||
mDismissTranslationX = mTaskOffsetTranslationX = mTaskResistanceTranslationX = 0f;
|
||||
mDismissTranslationY = mTaskOffsetTranslationY = mTaskResistanceTranslationY = 0f;
|
||||
mDismissTranslationX = mTaskOffsetTranslationX = mTaskResistanceTranslationX =
|
||||
mSplitSelectTranslationX = 0f;
|
||||
mDismissTranslationY = mTaskOffsetTranslationY = mTaskResistanceTranslationY =
|
||||
mSplitSelectTranslationY = 0f;
|
||||
applyTranslationX();
|
||||
applyTranslationY();
|
||||
setTranslationZ(0);
|
||||
@@ -956,6 +988,15 @@ public class TaskView extends FrameLayout implements Reusable {
|
||||
setScaleY(scale);
|
||||
}
|
||||
|
||||
private void setSplitSelectTranslationX(float x) {
|
||||
mSplitSelectTranslationX = x;
|
||||
applyTranslationX();
|
||||
}
|
||||
|
||||
private void setSplitSelectTranslationY(float y) {
|
||||
mSplitSelectTranslationY = y;
|
||||
applyTranslationY();
|
||||
}
|
||||
private void setDismissTranslationX(float x) {
|
||||
mDismissTranslationX = x;
|
||||
applyTranslationX();
|
||||
@@ -1056,12 +1097,12 @@ public class TaskView extends FrameLayout implements Reusable {
|
||||
|
||||
private void applyTranslationX() {
|
||||
setTranslationX(mDismissTranslationX + mTaskOffsetTranslationX + mTaskResistanceTranslationX
|
||||
+ getPersistentTranslationX());
|
||||
+ mSplitSelectTranslationX + getPersistentTranslationX());
|
||||
}
|
||||
|
||||
private void applyTranslationY() {
|
||||
setTranslationY(mDismissTranslationY + mTaskOffsetTranslationY + mTaskResistanceTranslationY
|
||||
+ getPersistentTranslationY());
|
||||
+ mSplitSelectTranslationY + getPersistentTranslationY());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1085,6 +1126,16 @@ public class TaskView extends FrameLayout implements Reusable {
|
||||
+ getGridTrans(mGridTranslationY);
|
||||
}
|
||||
|
||||
public FloatProperty<TaskView> getPrimarySplitTranslationProperty() {
|
||||
return getPagedOrientationHandler().getPrimaryValue(
|
||||
SPLIT_SELECT_TRANSLATION_X, SPLIT_SELECT_TRANSLATION_Y);
|
||||
}
|
||||
|
||||
public FloatProperty<TaskView> getSecondarySplitTranslationProperty() {
|
||||
return getPagedOrientationHandler().getSecondaryValue(
|
||||
SPLIT_SELECT_TRANSLATION_X, SPLIT_SELECT_TRANSLATION_Y);
|
||||
}
|
||||
|
||||
public FloatProperty<TaskView> getPrimaryDismissTranslationProperty() {
|
||||
return getPagedOrientationHandler().getPrimaryValue(
|
||||
DISMISS_TRANSLATION_X, DISMISS_TRANSLATION_Y);
|
||||
@@ -1417,9 +1468,10 @@ public class TaskView extends FrameLayout implements Reusable {
|
||||
}
|
||||
|
||||
private void setColorTint(float amount) {
|
||||
mSnapshotView.setDimAlpha(amount);
|
||||
mIconView.setIconColorTint(mTintingColor, amount);
|
||||
mDigitalWellBeingToast.setBannerColorTint(mTintingColor, amount);
|
||||
mTintAmount = amount;
|
||||
mSnapshotView.setDimAlpha(mTintAmount);
|
||||
mIconView.setIconColorTint(mTintingColor, mTintAmount);
|
||||
mDigitalWellBeingToast.setBannerColorTint(mTintingColor, mTintAmount);
|
||||
}
|
||||
|
||||
private float getColorTint() {
|
||||
|
||||
@@ -221,7 +221,7 @@
|
||||
<!-- Text for wallpaper change button [CHAR LIMIT=30]-->
|
||||
<string name="wallpaper_button_text">Wallpapers</string>
|
||||
<!-- Text for wallpaper change button [CHAR LIMIT=30]-->
|
||||
<string name="styles_wallpaper_button_text">Styles & wallpapers</string>
|
||||
<string name="styles_wallpaper_button_text">Wallpaper & style</string>
|
||||
<!-- Text for settings button [CHAR LIMIT=30]-->
|
||||
<string name="settings_button_text">Home settings</string>
|
||||
<!-- Message shown when a feature is disabled by the administrator -->
|
||||
|
||||
@@ -57,6 +57,22 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
|
||||
|
||||
private final View[] mDragHandles = new View[HANDLE_COUNT];
|
||||
private final List<Rect> mSystemGestureExclusionRects = new ArrayList<>(HANDLE_COUNT);
|
||||
private final OnAttachStateChangeListener mWidgetViewAttachStateChangeListener =
|
||||
new OnAttachStateChangeListener() {
|
||||
@Override
|
||||
public void onViewAttachedToWindow(View view) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewDetachedFromWindow(View view) {
|
||||
// When the app widget view is detached, we should close the resize frame.
|
||||
// An example is when the dragging starts, the widget view is detached from
|
||||
// CellLayout and then reattached to DragLayout.
|
||||
close(false);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private LauncherAppWidgetHostView mWidgetView;
|
||||
private CellLayout mCellLayout;
|
||||
@@ -177,7 +193,11 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
|
||||
private void setupForWidget(LauncherAppWidgetHostView widgetView, CellLayout cellLayout,
|
||||
DragLayer dragLayer) {
|
||||
mCellLayout = cellLayout;
|
||||
if (mWidgetView != null) {
|
||||
mWidgetView.removeOnAttachStateChangeListener(mWidgetViewAttachStateChangeListener);
|
||||
}
|
||||
mWidgetView = widgetView;
|
||||
mWidgetView.addOnAttachStateChangeListener(mWidgetViewAttachStateChangeListener);
|
||||
LauncherAppWidgetProviderInfo info = (LauncherAppWidgetProviderInfo)
|
||||
widgetView.getAppWidgetInfo();
|
||||
mResizeMode = info.resizeMode;
|
||||
@@ -628,6 +648,9 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
|
||||
@Override
|
||||
protected void handleClose(boolean animate) {
|
||||
mDragLayer.removeView(this);
|
||||
if (mWidgetView != null) {
|
||||
mWidgetView.removeOnAttachStateChangeListener(mWidgetViewAttachStateChangeListener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.launcher3;
|
||||
|
||||
import static android.animation.ValueAnimator.areAnimatorsEnabled;
|
||||
|
||||
import static com.android.launcher3.Utilities.getBoundsForViewInDragLayer;
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL_1_5;
|
||||
|
||||
import android.animation.Animator;
|
||||
@@ -193,6 +194,8 @@ public class CellLayout extends ViewGroup {
|
||||
private static final int INVALID_DIRECTION = -100;
|
||||
|
||||
private final Rect mTempRect = new Rect();
|
||||
private final RectF mTempRectF = new RectF();
|
||||
private final float[] mTmpFloatArray = new float[4];
|
||||
|
||||
private static final Paint sPaint = new Paint();
|
||||
|
||||
@@ -1070,11 +1073,16 @@ public class CellLayout extends ViewGroup {
|
||||
// Apply local extracted color if the DragView is an AppWidgetHostViewDrawable.
|
||||
View view = dragObject.dragView.getContentView();
|
||||
if (view instanceof LauncherAppWidgetHostView) {
|
||||
Workspace workspace =
|
||||
Launcher.getLauncher(dragObject.dragView.getContext()).getWorkspace();
|
||||
Launcher launcher = Launcher.getLauncher(dragObject.dragView.getContext());
|
||||
Workspace workspace = launcher.getWorkspace();
|
||||
int screenId = workspace.getIdForScreen(this);
|
||||
int pageId = workspace.getPageIndexForScreenId(screenId);
|
||||
cellToRect(targetCell[0], targetCell[1], spanX, spanY, mTempRect);
|
||||
|
||||
// Now get the rect in drag layer coordinates.
|
||||
getBoundsForViewInDragLayer(launcher.getDragLayer(), workspace, mTempRect, false,
|
||||
mTmpFloatArray, mTempRectF);
|
||||
Utilities.setRect(mTempRectF, mTempRect);
|
||||
((LauncherAppWidgetHostView) view).handleDrag(mTempRect, pageId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.ShortcutInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.database.ContentObserver;
|
||||
import android.graphics.Bitmap;
|
||||
@@ -84,6 +85,7 @@ import com.android.launcher3.shortcuts.ShortcutKey;
|
||||
import com.android.launcher3.shortcuts.ShortcutRequest;
|
||||
import com.android.launcher3.util.IntArray;
|
||||
import com.android.launcher3.util.PackageManagerHelper;
|
||||
import com.android.launcher3.views.BaseDragLayer;
|
||||
import com.android.launcher3.widget.PendingAddShortcutInfo;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
@@ -104,6 +106,8 @@ public final class Utilities {
|
||||
private static final Pattern sTrimPattern =
|
||||
Pattern.compile("^[\\s|\\p{javaSpaceChar}]*(.*)[\\s|\\p{javaSpaceChar}]*$");
|
||||
|
||||
private static final float[] sTmpFloatArray = new float[4];
|
||||
|
||||
private static final int[] sLoc0 = new int[2];
|
||||
private static final int[] sLoc1 = new int[2];
|
||||
private static final Matrix sMatrix = new Matrix();
|
||||
@@ -133,6 +137,15 @@ public final class Utilities {
|
||||
Build.TYPE.toLowerCase(Locale.ROOT).contains("debug") ||
|
||||
Build.TYPE.toLowerCase(Locale.ROOT).equals("eng");
|
||||
|
||||
/**
|
||||
* Returns true if theme is dark.
|
||||
*/
|
||||
public static boolean isDarkTheme(Context context) {
|
||||
Configuration configuration = context.getResources().getConfiguration();
|
||||
int nightMode = configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK;
|
||||
return nightMode == Configuration.UI_MODE_NIGHT_YES;
|
||||
}
|
||||
|
||||
public static boolean isDevelopersOptionsEnabled(Context context) {
|
||||
return Settings.Global.getInt(context.getApplicationContext().getContentResolver(),
|
||||
Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) != 0;
|
||||
@@ -218,6 +231,33 @@ public final class Utilities {
|
||||
return scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns bounds for a child view of DragLayer, in drag layer coordinates.
|
||||
*
|
||||
* see {@link com.android.launcher3.dragndrop.DragLayer}.
|
||||
*
|
||||
* @param viewBounds Bounds of the view wanted in drag layer coordinates, relative to the view
|
||||
* itself. eg. (0, 0, view.getWidth, view.getHeight)
|
||||
* @param ignoreTransform If true, view transform is ignored
|
||||
* @param outRect The out rect where we return the bounds of {@param view} in drag layer coords.
|
||||
*/
|
||||
public static void getBoundsForViewInDragLayer(BaseDragLayer dragLayer, View view,
|
||||
Rect viewBounds, boolean ignoreTransform, float[] recycle, RectF outRect) {
|
||||
float[] points = recycle == null ? new float[4] : recycle;
|
||||
points[0] = viewBounds.left;
|
||||
points[1] = viewBounds.top;
|
||||
points[2] = viewBounds.right;
|
||||
points[3] = viewBounds.bottom;
|
||||
|
||||
Utilities.getDescendantCoordRelativeToAncestor(view, dragLayer, points,
|
||||
false, ignoreTransform);
|
||||
outRect.set(
|
||||
Math.min(points[0], points[2]),
|
||||
Math.min(points[1], points[3]),
|
||||
Math.max(points[0], points[2]),
|
||||
Math.max(points[1], points[3]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverse of {@link #getDescendantCoordRelativeToAncestor(View, View, float[], boolean)}.
|
||||
*/
|
||||
@@ -273,6 +313,16 @@ public final class Utilities {
|
||||
return new int[] {sLoc1[0] - sLoc0[0], sLoc1[1] - sLoc0[1]};
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to set rectOut with rectFSrc.
|
||||
*/
|
||||
public static void setRect(RectF rectFSrc, Rect rectOut) {
|
||||
rectOut.left = (int) rectFSrc.left;
|
||||
rectOut.top = (int) rectFSrc.top;
|
||||
rectOut.right = (int) rectFSrc.right;
|
||||
rectOut.bottom = (int) rectFSrc.bottom;
|
||||
}
|
||||
|
||||
public static void scaleRectFAboutCenter(RectF r, float scale) {
|
||||
if (scale != 1.0f) {
|
||||
float cx = r.centerX();
|
||||
|
||||
@@ -32,6 +32,7 @@ import com.android.launcher3.R;
|
||||
import com.android.launcher3.Workspace;
|
||||
import com.android.launcher3.dragndrop.DragController.DragListener;
|
||||
import com.android.launcher3.dragndrop.DragOptions;
|
||||
import com.android.launcher3.dragndrop.DragView;
|
||||
import com.android.launcher3.folder.Folder;
|
||||
import com.android.launcher3.keyboard.KeyboardDragAndDropView;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
@@ -290,7 +291,12 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate impleme
|
||||
return actions;
|
||||
}
|
||||
|
||||
CellLayout layout = (CellLayout) host.getParent().getParent();
|
||||
CellLayout layout;
|
||||
if (host.getParent() instanceof DragView) {
|
||||
layout = (CellLayout) ((DragView) host.getParent()).getContentViewParent().getParent();
|
||||
} else {
|
||||
layout = (CellLayout) host.getParent().getParent();
|
||||
}
|
||||
if ((providerInfo.resizeMode & AppWidgetProviderInfo.RESIZE_HORIZONTAL) != 0) {
|
||||
if (layout.isRegionVacant(info.cellX + info.spanX, info.cellY, 1, info.spanY) ||
|
||||
layout.isRegionVacant(info.cellX - 1, info.cellY, 1, info.spanY)) {
|
||||
|
||||
@@ -75,7 +75,7 @@ import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip.OnActivePag
|
||||
public class AllAppsContainerView extends SpringRelativeLayout implements DragSource,
|
||||
Insettable, OnDeviceProfileChangeListener, OnActivePageChangedListener {
|
||||
|
||||
private static final float FLING_VELOCITY_MULTIPLIER = 1800f;
|
||||
private static final float FLING_VELOCITY_MULTIPLIER = 1000f;
|
||||
|
||||
// Starts the springs after at least 25% of the animation has passed.
|
||||
private static final float FLING_ANIMATION_THRESHOLD = 0.25f;
|
||||
@@ -611,7 +611,7 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
|
||||
public void onAnimationUpdate(ValueAnimator valueAnimator) {
|
||||
if (shouldSpring
|
||||
&& valueAnimator.getAnimatedFraction() >= FLING_ANIMATION_THRESHOLD) {
|
||||
absorbSwipeUpVelocity(-Math.abs(
|
||||
absorbSwipeUpVelocity(Math.abs(
|
||||
Math.round(velocity * FLING_VELOCITY_MULTIPLIER)));
|
||||
shouldSpring = false;
|
||||
}
|
||||
|
||||
@@ -15,13 +15,15 @@
|
||||
*/
|
||||
package com.android.launcher3.allapps;
|
||||
|
||||
import static com.android.launcher3.LauncherState.ALL_APPS;
|
||||
import static com.android.launcher3.LauncherState.ALL_APPS_CONTENT;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
|
||||
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.DEACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS;
|
||||
import static com.android.launcher3.util.SystemUiController.UI_STATE_ALLAPPS;
|
||||
|
||||
@@ -154,9 +156,9 @@ public class AllAppsTransitionController
|
||||
return;
|
||||
}
|
||||
|
||||
Interpolator interpolator = config.userControlled ? LINEAR : toState == OVERVIEW
|
||||
? config.getInterpolator(ANIM_OVERVIEW_SCALE, FAST_OUT_SLOW_IN)
|
||||
: FAST_OUT_SLOW_IN;
|
||||
Interpolator interpolator = toState.equals(ALL_APPS)
|
||||
? (config.userControlled ? ACCEL_2 : ACCEL_0_75) :
|
||||
(config.userControlled ? DEACCEL_2 : DEACCEL);
|
||||
|
||||
Animator anim = createSpringAnimation(mProgress, targetProgress);
|
||||
anim.setInterpolator(config.getInterpolator(ANIM_VERTICAL_PROGRESS, interpolator));
|
||||
|
||||
@@ -21,7 +21,6 @@ import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
@@ -34,6 +33,7 @@ import android.util.Property;
|
||||
import android.util.SparseArray;
|
||||
import android.view.ContextThemeWrapper;
|
||||
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.icons.FastBitmapDrawable;
|
||||
import com.android.launcher3.icons.GraphicsUtils;
|
||||
@@ -119,9 +119,7 @@ public class PreloadIconDrawable extends FastBitmapDrawable {
|
||||
info,
|
||||
IconPalette.getPreloadProgressColor(context, info.bitmap.color),
|
||||
getPreloadColors(context),
|
||||
(context.getResources().getConfiguration().uiMode
|
||||
& Configuration.UI_MODE_NIGHT_MASK
|
||||
& Configuration.UI_MODE_NIGHT_YES) != 0) /* isDarkMode */;
|
||||
Utilities.isDarkTheme(context));
|
||||
}
|
||||
|
||||
public PreloadIconDrawable(
|
||||
|
||||
@@ -94,6 +94,11 @@ public class SearchActionItemInfo extends ItemInfoWithIcon {
|
||||
"SearchActionItemInfo can only have either an Intent or a PendingIntent");
|
||||
}
|
||||
mIntent = intent;
|
||||
// bandage fix for just one week
|
||||
if (intent != null && "com.android.server.telecom".equals(intent.getPackage())) {
|
||||
intent.setAction(Intent.ACTION_DIAL);
|
||||
intent.setPackage(null);
|
||||
}
|
||||
}
|
||||
|
||||
public PendingIntent getPendingIntent() {
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.android.launcher3.popup;
|
||||
|
||||
import static com.android.launcher3.AbstractFloatingView.getTopOpenViewWithType;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
|
||||
import static com.android.launcher3.popup.PopupPopulator.MAX_SHORTCUTS;
|
||||
|
||||
@@ -31,6 +30,7 @@ import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Outline;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
@@ -41,17 +41,21 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewOutlineProvider;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.InsettableFrameLayout;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherAnimUtils;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.Workspace;
|
||||
import com.android.launcher3.anim.RevealOutlineAnimation;
|
||||
import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
|
||||
import com.android.launcher3.dragndrop.DragLayer;
|
||||
@@ -59,9 +63,11 @@ import com.android.launcher3.shortcuts.DeepShortcutView;
|
||||
import com.android.launcher3.statemanager.StatefulActivity;
|
||||
import com.android.launcher3.util.Themes;
|
||||
import com.android.launcher3.views.BaseDragLayer;
|
||||
import com.android.launcher3.widget.LocalColorExtractor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* A container for shortcuts to deep links and notifications associated with an app.
|
||||
@@ -73,6 +79,9 @@ public abstract class ArrowPopup<T extends StatefulActivity<LauncherState>>
|
||||
|
||||
// +1 for system shortcut view
|
||||
private static final int MAX_NUM_CHILDREN = MAX_SHORTCUTS + 1;
|
||||
// Index used to get background color when using local wallpaper color extraction,
|
||||
private static final int LIGHT_COLOR_EXTRACTION_INDEX = android.R.color.system_accent2_50;
|
||||
private static final int DARK_COLOR_EXTRACTION_INDEX = android.R.color.system_accent2_800;
|
||||
|
||||
private final Rect mTempRect = new Rect();
|
||||
|
||||
@@ -104,8 +113,14 @@ public abstract class ArrowPopup<T extends StatefulActivity<LauncherState>>
|
||||
|
||||
private Runnable mOnCloseCallback = () -> { };
|
||||
|
||||
// The rect string of the view that the arrow is attached to, in screen reference frame.
|
||||
private String mArrowColorRectString;
|
||||
private int mArrowColor;
|
||||
private final int[] mColors;
|
||||
private final HashMap<String, View> mViewForRect = new HashMap<>();
|
||||
|
||||
private final int mColorExtractionIndex;
|
||||
@Nullable private LocalColorExtractor mColorExtractor;
|
||||
|
||||
public ArrowPopup(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
@@ -113,7 +128,9 @@ public abstract class ArrowPopup<T extends StatefulActivity<LauncherState>>
|
||||
mOutlineRadius = Themes.getDialogCornerRadius(context);
|
||||
mLauncher = BaseDraggingActivity.fromContext(context);
|
||||
mIsRtl = Utilities.isRtl(getResources());
|
||||
|
||||
mColorExtractionIndex = Utilities.isDarkTheme(context)
|
||||
? DARK_COLOR_EXTRACTION_INDEX
|
||||
: LIGHT_COLOR_EXTRACTION_INDEX;
|
||||
setClipToOutline(true);
|
||||
setOutlineProvider(new ViewOutlineProvider() {
|
||||
@Override
|
||||
@@ -158,6 +175,10 @@ public abstract class ArrowPopup<T extends StatefulActivity<LauncherState>>
|
||||
mColors[i] =
|
||||
(int) argb.evaluate((i + 1) * step, primaryColor, secondaryColor);
|
||||
}
|
||||
|
||||
if (Utilities.ATLEAST_S) {
|
||||
setupColorExtraction();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,6 +363,15 @@ public abstract class ArrowPopup<T extends StatefulActivity<LauncherState>>
|
||||
// so we centered it instead. In that case we don't want to showDefaultOptions the arrow.
|
||||
mArrow.setVisibility(INVISIBLE);
|
||||
} else {
|
||||
updateArrowColor();
|
||||
}
|
||||
|
||||
mArrow.setPivotX(mArrowWidth / 2.0f);
|
||||
mArrow.setPivotY(mIsAboveIcon ? mArrowHeight : 0);
|
||||
}
|
||||
|
||||
private void updateArrowColor() {
|
||||
if (!Gravity.isVertical(mGravity)) {
|
||||
mArrow.setBackground(new RoundedArrowDrawable(
|
||||
mArrowWidth, mArrowHeight, mArrowPointRadius,
|
||||
mOutlineRadius, getMeasuredWidth(), getMeasuredHeight(),
|
||||
@@ -350,9 +380,6 @@ public abstract class ArrowPopup<T extends StatefulActivity<LauncherState>>
|
||||
mArrowColor));
|
||||
mArrow.setElevation(getElevation());
|
||||
}
|
||||
|
||||
mArrow.setPivotX(mArrowWidth / 2.0f);
|
||||
mArrow.setPivotY(mIsAboveIcon ? mArrowHeight : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -671,6 +698,12 @@ public abstract class ArrowPopup<T extends StatefulActivity<LauncherState>>
|
||||
getPopupContainer().removeView(this);
|
||||
getPopupContainer().removeView(mArrow);
|
||||
mOnCloseCallback.run();
|
||||
mArrowColorRectString = null;
|
||||
mViewForRect.clear();
|
||||
if (mColorExtractor != null) {
|
||||
mColorExtractor.removeLocations();
|
||||
mColorExtractor.setListener(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -680,6 +713,68 @@ public abstract class ArrowPopup<T extends StatefulActivity<LauncherState>>
|
||||
mOnCloseCallback = callback;
|
||||
}
|
||||
|
||||
private void setupColorExtraction() {
|
||||
Workspace workspace = mLauncher.findViewById(R.id.workspace);
|
||||
if (workspace == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
mColorExtractor = LocalColorExtractor.newInstance(mLauncher);
|
||||
mColorExtractor.setListener((rect, extractedColors) -> {
|
||||
String rectString = rect.toShortString();
|
||||
View v = mViewForRect.get(rectString);
|
||||
if (v != null) {
|
||||
int newColor = extractedColors.get(mColorExtractionIndex);
|
||||
setChildColor(v, newColor);
|
||||
if (rectString.equals(mArrowColorRectString)) {
|
||||
mArrowColor = newColor;
|
||||
updateArrowColor();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
|
||||
@Override
|
||||
public boolean onPreDraw() {
|
||||
getViewTreeObserver().removeOnPreDrawListener(this);
|
||||
|
||||
ArrayList<RectF> locations = new ArrayList<>();
|
||||
Rect r = new Rect();
|
||||
|
||||
int count = getChildCount();
|
||||
int numVisibleChild = 0;
|
||||
for (int i = 0; i < count; i++) {
|
||||
View view = getChildAt(i);
|
||||
if (view.getVisibility() == VISIBLE) {
|
||||
RectF rf = new RectF();
|
||||
mColorExtractor.getExtractedRectForView(Launcher.getLauncher(getContext()),
|
||||
workspace.getCurrentPage(), view, rf);
|
||||
if (rf.isEmpty()) {
|
||||
numVisibleChild++;
|
||||
continue;
|
||||
}
|
||||
|
||||
locations.add(rf);
|
||||
String rectString = rf.toShortString();
|
||||
mViewForRect.put(rectString, view);
|
||||
|
||||
// Arrow color matches the first child or the last child.
|
||||
if (!mIsAboveIcon && numVisibleChild == 0) {
|
||||
mArrowColorRectString = rectString;
|
||||
} else if (mIsAboveIcon) {
|
||||
mArrowColorRectString = rectString;
|
||||
}
|
||||
|
||||
numVisibleChild++;
|
||||
}
|
||||
}
|
||||
|
||||
mColorExtractor.addLocation(locations);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected BaseDragLayer getPopupContainer() {
|
||||
return mLauncher.getDragLayer();
|
||||
}
|
||||
|
||||
@@ -159,6 +159,19 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler {
|
||||
return VIEW_TRANSLATE_X;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSplitTaskViewDismissDirection(SplitPositionOption splitPosition,
|
||||
DeviceProfile dp) {
|
||||
// Don't use device profile here because we know we're in fake landscape, only split option
|
||||
// available is top/left
|
||||
if (splitPosition.mStagePosition == STAGE_POSITION_TOP_OR_LEFT) {
|
||||
// Top (visually left) side
|
||||
return SPLIT_TRANSLATE_PRIMARY_NEGATIVE;
|
||||
}
|
||||
throw new IllegalStateException("Invalid split stage position: " +
|
||||
splitPosition.mStagePosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPrimaryScroll(View view) {
|
||||
return view.getScrollY();
|
||||
|
||||
@@ -42,6 +42,10 @@ import java.util.List;
|
||||
*/
|
||||
public interface PagedOrientationHandler {
|
||||
|
||||
int SPLIT_TRANSLATE_PRIMARY_POSITIVE = 0;
|
||||
int SPLIT_TRANSLATE_PRIMARY_NEGATIVE = 1;
|
||||
int SPLIT_TRANSLATE_SECONDARY_NEGATIVE = 2;
|
||||
|
||||
PagedOrientationHandler PORTRAIT = new PortraitPagedViewHandler();
|
||||
PagedOrientationHandler LANDSCAPE = new LandscapePagedViewHandler();
|
||||
PagedOrientationHandler SEASCAPE = new SeascapePagedViewHandler();
|
||||
@@ -71,6 +75,13 @@ public interface PagedOrientationHandler {
|
||||
int getSecondaryDimension(View view);
|
||||
FloatProperty<View> getPrimaryViewTranslate();
|
||||
FloatProperty<View> getSecondaryViewTranslate();
|
||||
|
||||
/**
|
||||
* @param splitPosition The position where the view to be split will go
|
||||
* @return {@link #SPLIT_TRANSLATE_*} constants to indicate which direction the
|
||||
* dismissal should happen
|
||||
*/
|
||||
int getSplitTaskViewDismissDirection(SplitPositionOption splitPosition, DeviceProfile dp);
|
||||
int getPrimaryScroll(View view);
|
||||
float getPrimaryScale(View view);
|
||||
int getChildStart(View view);
|
||||
|
||||
@@ -155,6 +155,25 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler {
|
||||
return VIEW_TRANSLATE_Y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSplitTaskViewDismissDirection(SplitPositionOption splitPosition,
|
||||
DeviceProfile dp) {
|
||||
if (splitPosition.mStagePosition == STAGE_POSITION_TOP_OR_LEFT) {
|
||||
if (dp.isLandscape) {
|
||||
// Left side
|
||||
return SPLIT_TRANSLATE_PRIMARY_NEGATIVE;
|
||||
} else {
|
||||
// Top side
|
||||
return SPLIT_TRANSLATE_SECONDARY_NEGATIVE;
|
||||
}
|
||||
} else if (splitPosition.mStagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT) {
|
||||
// We don't have a bottom option, so should be right
|
||||
return SPLIT_TRANSLATE_PRIMARY_POSITIVE;
|
||||
}
|
||||
throw new IllegalStateException("Invalid split stage position: " +
|
||||
splitPosition.mStagePosition);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPrimaryScroll(View view) {
|
||||
return view.getScrollX();
|
||||
@@ -277,7 +296,7 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler {
|
||||
} else {
|
||||
// Phone Portrait, LargeScreen Landscape/Portrait
|
||||
viewGroup.setOrientation(LinearLayout.HORIZONTAL);
|
||||
lp.width = LinearLayout.LayoutParams.WRAP_CONTENT;
|
||||
lp.width = LinearLayout.LayoutParams.MATCH_PARENT;
|
||||
}
|
||||
|
||||
lp.height = LinearLayout.LayoutParams.WRAP_CONTENT;
|
||||
|
||||
@@ -22,7 +22,6 @@ import static android.app.WallpaperColors.HINT_SUPPORTS_DARK_THEME;
|
||||
import android.app.WallpaperColors;
|
||||
import android.app.WallpaperManager;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorMatrix;
|
||||
@@ -54,16 +53,12 @@ public class Themes {
|
||||
}
|
||||
|
||||
public static int getActivityThemeRes(Context context, int wallpaperColorHints) {
|
||||
Configuration configuration = context.getResources().getConfiguration();
|
||||
int nightMode = configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK;
|
||||
boolean darkTheme = nightMode == Configuration.UI_MODE_NIGHT_YES;
|
||||
|
||||
boolean supportsDarkText = Utilities.ATLEAST_S
|
||||
&& (wallpaperColorHints & HINT_SUPPORTS_DARK_TEXT) != 0;
|
||||
boolean isMainColorDark = Utilities.ATLEAST_S
|
||||
&& (wallpaperColorHints & HINT_SUPPORTS_DARK_THEME) != 0;
|
||||
|
||||
if (darkTheme) {
|
||||
if (Utilities.isDarkTheme(context)) {
|
||||
return supportsDarkText ? R.style.AppTheme_Dark_DarkText
|
||||
: isMainColorDark ? R.style.AppTheme_Dark_DarkMainColor : R.style.AppTheme_Dark;
|
||||
} else {
|
||||
|
||||
@@ -48,7 +48,13 @@ public class UiThreadHelper {
|
||||
WindowInsets rootInsets = launcher.getRootView().getRootWindowInsets();
|
||||
boolean isImeShown = rootInsets != null && rootInsets.isVisible(
|
||||
WindowInsets.Type.ime());
|
||||
if (!isImeShown) return;
|
||||
if (isImeShown) {
|
||||
// this call is already asynchronous
|
||||
launcher.getAppsView().getWindowInsetsController().hide(
|
||||
WindowInsets.Type.ime()
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Message.obtain(HANDLER.get(launcher), MSG_HIDE_KEYBOARD, token).sendToTarget();
|
||||
|
||||
@@ -233,15 +233,8 @@ public class FloatingIconView extends FrameLayout implements
|
||||
outViewBounds.set(0, 0, v.getWidth(), v.getHeight());
|
||||
}
|
||||
|
||||
float[] points = new float[] {outViewBounds.left, outViewBounds.top, outViewBounds.right,
|
||||
outViewBounds.bottom};
|
||||
Utilities.getDescendantCoordRelativeToAncestor(v, launcher.getDragLayer(), points,
|
||||
false, ignoreTransform);
|
||||
outRect.set(
|
||||
Math.min(points[0], points[2]),
|
||||
Math.min(points[1], points[3]),
|
||||
Math.max(points[0], points[2]),
|
||||
Math.max(points[1], points[3]));
|
||||
Utilities.getBoundsForViewInDragLayer(launcher.getDragLayer(), v, outViewBounds,
|
||||
ignoreTransform, null /** recycle */, outRect);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package com.android.launcher3.widget;
|
||||
|
||||
import static com.android.launcher3.Utilities.getBoundsForViewInDragLayer;
|
||||
import static com.android.launcher3.Utilities.setRect;
|
||||
|
||||
import android.appwidget.AppWidgetProviderInfo;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
@@ -25,7 +28,6 @@ import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Handler;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
import android.util.SparseBooleanArray;
|
||||
import android.util.SparseIntArray;
|
||||
import android.view.LayoutInflater;
|
||||
@@ -95,11 +97,12 @@ public class LauncherAppWidgetHostView extends NavigableAppWidgetHostView
|
||||
private RectF mLastLocationRegistered = null;
|
||||
@Nullable private AppWidgetHostViewDragListener mDragListener;
|
||||
|
||||
// Used to store the widget size during onLayout.
|
||||
// Used to store the widget sizes in drag layer coordinates.
|
||||
private final Rect mCurrentWidgetSize = new Rect();
|
||||
private final Rect mWidgetSizeAtDrag = new Rect();
|
||||
|
||||
private final float[] mTmpFloatArray = new float[4];
|
||||
private final RectF mTempRectF = new RectF();
|
||||
private final boolean mIsRtl;
|
||||
private final Rect mEnforcedRectangle = new Rect();
|
||||
private final float mEnforcedCornerRadius;
|
||||
private final ViewOutlineProvider mCornerRadiusEnforcementOutline = new ViewOutlineProvider() {
|
||||
@@ -129,7 +132,6 @@ public class LauncherAppWidgetHostView extends NavigableAppWidgetHostView
|
||||
if (Utilities.ATLEAST_Q && Themes.getAttrBoolean(mLauncher, R.attr.isWorkspaceDarkText)) {
|
||||
setOnLightBackground(true);
|
||||
}
|
||||
mIsRtl = Utilities.isRtl(context.getResources());
|
||||
mColorExtractor = LocalColorExtractor.newInstance(getContext());
|
||||
mColorExtractor.setListener(this);
|
||||
|
||||
@@ -319,13 +321,12 @@ public class LauncherAppWidgetHostView extends NavigableAppWidgetHostView
|
||||
mIsScrollable = checkScrollableRecursively(this);
|
||||
|
||||
if (!mIsInDragMode && getTag() instanceof LauncherAppWidgetInfo) {
|
||||
mCurrentWidgetSize.left = left;
|
||||
mCurrentWidgetSize.top = top;
|
||||
mCurrentWidgetSize.right = right;
|
||||
mCurrentWidgetSize.bottom = bottom;
|
||||
LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) getTag();
|
||||
int pageId = mWorkspace.getPageIndexForScreenId(info.screenId);
|
||||
updateColorExtraction(mCurrentWidgetSize, pageId);
|
||||
getBoundsForViewInDragLayer(mLauncher.getDragLayer(), this, mCurrentWidgetSize, true,
|
||||
mTmpFloatArray, mTempRectF);
|
||||
setRect(mTempRectF, mCurrentWidgetSize);
|
||||
updateColorExtraction(mCurrentWidgetSize,
|
||||
mWorkspace.getPageIndexForScreenId(info.screenId));
|
||||
}
|
||||
|
||||
enforceRoundedCorners();
|
||||
@@ -338,8 +339,8 @@ public class LauncherAppWidgetHostView extends NavigableAppWidgetHostView
|
||||
}
|
||||
|
||||
/** Handles a drag event occurred on a workspace page, {@code pageId}. */
|
||||
public void handleDrag(Rect rect, int pageId) {
|
||||
mWidgetSizeAtDrag.set(rect);
|
||||
public void handleDrag(Rect rectInDragLayer, int pageId) {
|
||||
mWidgetSizeAtDrag.set(rectInDragLayer);
|
||||
updateColorExtraction(mWidgetSizeAtDrag, pageId);
|
||||
}
|
||||
|
||||
@@ -351,53 +352,14 @@ public class LauncherAppWidgetHostView extends NavigableAppWidgetHostView
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
private void updateColorExtraction(Rect widgetLocation, int pageId) {
|
||||
// If the widget hasn't been measured and laid out, we cannot do this.
|
||||
if (widgetLocation.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
int screenWidth = mLauncher.getDeviceProfile().widthPx;
|
||||
int screenHeight = mLauncher.getDeviceProfile().heightPx;
|
||||
int numScreens = mWorkspace.getNumPagesForWallpaperParallax();
|
||||
pageId = mIsRtl ? numScreens - pageId - 1 : pageId;
|
||||
float relativeScreenWidth = 1f / numScreens;
|
||||
float absoluteTop = widgetLocation.top;
|
||||
float absoluteBottom = widgetLocation.bottom;
|
||||
View v = this;
|
||||
while (v.getParent() instanceof View) {
|
||||
v = (View) v.getParent();
|
||||
if (v.getId() != R.id.launcher) {
|
||||
break;
|
||||
}
|
||||
absoluteBottom += v.getTop();
|
||||
absoluteTop += v.getTop();
|
||||
}
|
||||
float xOffset = 0;
|
||||
View parentView = (View) getParent();
|
||||
// The layout depends on the orientation.
|
||||
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||
int parentViewWidth = parentView == null ? 0 : parentView.getWidth();
|
||||
xOffset = screenWidth - mWorkspace.getPaddingRight() - parentViewWidth;
|
||||
} else {
|
||||
int parentViewPaddingLeft = parentView == null ? 0 : parentView.getPaddingLeft();
|
||||
xOffset = mWorkspace.getPaddingLeft() + parentViewPaddingLeft;
|
||||
}
|
||||
// This is the position of the widget relative to the wallpaper, as expected by the
|
||||
// local color extraction of the WallpaperManager.
|
||||
// The coordinate system is such that, on the horizontal axis, each screen has a
|
||||
// distinct range on the [0,1] segment. So if there are 3 screens, they will have the
|
||||
// ranges [0, 1/3], [1/3, 2/3] and [2/3, 1]. The position on the subrange should be
|
||||
// the position of the widget relative to the screen. For the vertical axis, this is
|
||||
// simply the location of the widget relative to the screen.
|
||||
mTempRectF.left = ((widgetLocation.left + xOffset) / screenWidth + pageId)
|
||||
* relativeScreenWidth;
|
||||
mTempRectF.right = ((widgetLocation.right + xOffset) / screenWidth + pageId)
|
||||
* relativeScreenWidth;
|
||||
mTempRectF.top = absoluteTop / screenHeight;
|
||||
mTempRectF.bottom = absoluteBottom / screenHeight;
|
||||
if (mTempRectF.left < 0 || mTempRectF.right > 1 || mTempRectF.top < 0
|
||||
|| mTempRectF.bottom > 1) {
|
||||
Log.e(LOG_TAG, " Error, invalid relative position");
|
||||
/**
|
||||
* @param rectInDragLayer Rect of widget in drag layer coordinates.
|
||||
* @param pageId The workspace page the widget is on.
|
||||
*/
|
||||
private void updateColorExtraction(Rect rectInDragLayer, int pageId) {
|
||||
mColorExtractor.getExtractedRectForViewRect(mLauncher, pageId, rectInDragLayer, mTempRectF);
|
||||
|
||||
if (mTempRectF.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (!mTempRectF.equals(mLastLocationRegistered)) {
|
||||
|
||||
@@ -19,11 +19,14 @@ package com.android.launcher3.widget;
|
||||
import android.app.WallpaperColors;
|
||||
import android.appwidget.AppWidgetHostView;
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.util.SparseIntArray;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.util.ResourceBasedOverride;
|
||||
|
||||
@@ -71,4 +74,33 @@ public class LocalColorExtractor implements ResourceBasedOverride {
|
||||
* Updates the base context to contain the colors override
|
||||
*/
|
||||
public void applyColorsOverride(Context base, WallpaperColors colors) { }
|
||||
|
||||
/**
|
||||
* Takes a view and returns its rect that can be used by the wallpaper local color extractor.
|
||||
*
|
||||
* @param launcher Launcher class class.
|
||||
* @param pageId The page the workspace item is on.
|
||||
* @param v The view.
|
||||
* @param colorExtractionRectOut The location rect, but converted to a format expected by the
|
||||
* wallpaper local color extractor.
|
||||
*/
|
||||
public void getExtractedRectForView(Launcher launcher, int pageId, View v,
|
||||
RectF colorExtractionRectOut) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a rect in drag layer coordinates and returns the rect that can be used by the wallpaper
|
||||
* local color extractor.
|
||||
*
|
||||
* @param launcher Launcher class.
|
||||
* @param pageId The page the workspace item is on.
|
||||
* @param rectInDragLayer The relevant bounds of the view in drag layer coordinates.
|
||||
* @param colorExtractionRectOut The location rect, but converted to a format expected by the
|
||||
* wallpaper local color extractor.
|
||||
*/
|
||||
public void getExtractedRectForViewRect(Launcher launcher, int pageId, Rect rectInDragLayer,
|
||||
RectF colorExtractionRectOut) {
|
||||
// no-op
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user