Adding an empty page in Recents view corresponding to workspace
The page is aligned to the workspace card and shows a widgets button in the empty region Change-Id: I479c47a2fbac4b3ef1aaf833d9fe82b5d7e10ddc
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
**
|
||||
** Copyright 2017, The Android Open Source Project
|
||||
**
|
||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||
** you may not use this file except in compliance with the License.
|
||||
** You may obtain a copy of the License at
|
||||
**
|
||||
** http://www.apache.org/licenses/LICENSE-2.0
|
||||
**
|
||||
** Unless required by applicable law or agreed to in writing, software
|
||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
** See the License for the specific language governing permissions and
|
||||
** limitations under the License.
|
||||
*/
|
||||
-->
|
||||
|
||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:color="?android:attr/colorControlHighlight">
|
||||
<item android:id="@android:id/mask">
|
||||
<color android:color="#ffffffff" />
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<color android:color="#77FFFFFF" />
|
||||
</item>
|
||||
</ripple>
|
||||
@@ -22,4 +22,36 @@
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:alpha="0.0"
|
||||
android:visibility="invisible" />
|
||||
android:visibility="invisible" >
|
||||
|
||||
<com.android.launcher3.uioverrides.WorkspaceCard
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingTop="@dimen/task_thumbnail_top_margin" >
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/workspace_click_target" />
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/widget_button"
|
||||
android:background="@drawable/bg_workspace_card_button" >
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/widget_button_text"
|
||||
android:drawableStart="@drawable/ic_widget"
|
||||
android:textColor="?attr/workspaceTextColor"
|
||||
android:drawableTint="?attr/workspaceTextColor"
|
||||
android:gravity="center"
|
||||
android:layout_gravity="center"
|
||||
android:drawablePadding="20dp" />
|
||||
</FrameLayout>
|
||||
|
||||
</com.android.launcher3.uioverrides.WorkspaceCard>
|
||||
|
||||
</com.android.quickstep.RecentsView>
|
||||
@@ -22,6 +22,7 @@ import android.view.View;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.Workspace;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.quickstep.RecentsView;
|
||||
@@ -31,8 +32,9 @@ import com.android.quickstep.RecentsView;
|
||||
*/
|
||||
public class OverviewState extends LauncherState {
|
||||
|
||||
private static final int STATE_FLAGS = FLAG_SHOW_SCRIM
|
||||
| FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED;
|
||||
public static final float WORKSPACE_SCALE_ON_SCROLL = 0.9f;
|
||||
|
||||
private static final int STATE_FLAGS = FLAG_SHOW_SCRIM | FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED;
|
||||
|
||||
public OverviewState(int id) {
|
||||
super(id, ContainerType.WORKSPACE, OVERVIEW_TRANSITION_MS, 1f, STATE_FLAGS);
|
||||
@@ -42,18 +44,15 @@ public class OverviewState extends LauncherState {
|
||||
public float[] getWorkspaceScaleAndTranslation(Launcher launcher) {
|
||||
Rect pageRect = new Rect();
|
||||
RecentsView.getPageRect(launcher, pageRect);
|
||||
Workspace ws = launcher.getWorkspace();
|
||||
float childWidth = ws.getNormalChildWidth();
|
||||
if (childWidth <= 0 || pageRect.isEmpty()) {
|
||||
if (launcher.getWorkspace().getNormalChildWidth() <= 0 || pageRect.isEmpty()) {
|
||||
return super.getWorkspaceScaleAndTranslation(launcher);
|
||||
}
|
||||
|
||||
Rect insets = launcher.getDragLayer().getInsets();
|
||||
float scale = pageRect.width() / childWidth;
|
||||
|
||||
float halfHeight = ws.getHeight() / 2;
|
||||
float childTop = halfHeight - scale * (halfHeight - ws.getPaddingTop() - insets.top);
|
||||
return new float[] {scale, pageRect.top - childTop};
|
||||
RecentsView rv = launcher.getOverviewPanel();
|
||||
if (rv.getCurrentPage() >= rv.getFirstTaskIndex()) {
|
||||
Utilities.scaleRectAboutCenter(pageRect, WORKSPACE_SCALE_ON_SCROLL);
|
||||
}
|
||||
return getScaleAndTranslationForPageRect(launcher, pageRect);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -77,4 +76,16 @@ public class OverviewState extends LauncherState {
|
||||
public View getFinalFocus(Launcher launcher) {
|
||||
return launcher.getOverviewPanel();
|
||||
}
|
||||
|
||||
public static float[] getScaleAndTranslationForPageRect(Launcher launcher, Rect pageRect) {
|
||||
Workspace ws = launcher.getWorkspace();
|
||||
float childWidth = ws.getNormalChildWidth();
|
||||
|
||||
Rect insets = launcher.getDragLayer().getInsets();
|
||||
float scale = pageRect.width() / childWidth;
|
||||
|
||||
float halfHeight = ws.getHeight() / 2;
|
||||
float childTop = halfHeight - scale * (halfHeight - ws.getPaddingTop() - insets.top);
|
||||
return new float[] {scale, pageRect.top - childTop};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,10 +30,13 @@ import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.quickstep.AnimatedFloat;
|
||||
import com.android.quickstep.RecentsView;
|
||||
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
|
||||
public class RecentsViewStateController implements StateHandler {
|
||||
|
||||
private final Launcher mLauncher;
|
||||
private final RecentsView mRecentsView;
|
||||
private final WorkspaceCard mWorkspaceCard;
|
||||
|
||||
private final AnimatedFloat mTransitionProgress = new AnimatedFloat(this::applyProgress);
|
||||
// The fraction representing the visibility of the RecentsView. This allows delaying the
|
||||
@@ -44,24 +47,40 @@ public class RecentsViewStateController implements StateHandler {
|
||||
mLauncher = launcher;
|
||||
mRecentsView = launcher.getOverviewPanel();
|
||||
mRecentsView.setStateController(this);
|
||||
|
||||
mWorkspaceCard = (WorkspaceCard) mRecentsView.getChildAt(0);
|
||||
mWorkspaceCard.setup(launcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setState(LauncherState state) {
|
||||
setVisibility(state == LauncherState.OVERVIEW);
|
||||
setTransitionProgress(state == LauncherState.OVERVIEW ? 1 : 0);
|
||||
mWorkspaceCard.setWorkspaceScrollingEnabled(state == OVERVIEW);
|
||||
setVisibility(state == OVERVIEW);
|
||||
setTransitionProgress(state == OVERVIEW ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStateWithAnimation(LauncherState toState,
|
||||
public void setStateWithAnimation(final LauncherState toState,
|
||||
AnimatorSetBuilder builder, AnimationConfig config) {
|
||||
ObjectAnimator progressAnim =
|
||||
mTransitionProgress.animateToValue(toState == LauncherState.OVERVIEW ? 1 : 0);
|
||||
mTransitionProgress.animateToValue(toState == OVERVIEW ? 1 : 0);
|
||||
progressAnim.setDuration(config.duration);
|
||||
progressAnim.setInterpolator(Interpolators.LINEAR);
|
||||
progressAnim.addListener(new AnimationSuccessListener() {
|
||||
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
mWorkspaceCard.setWorkspaceScrollingEnabled(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationSuccess(Animator animator) {
|
||||
mWorkspaceCard.setWorkspaceScrollingEnabled(toState == OVERVIEW);
|
||||
}
|
||||
});
|
||||
builder.play(progressAnim);
|
||||
|
||||
ObjectAnimator visibilityAnim = animateVisibility(toState == LauncherState.OVERVIEW);
|
||||
ObjectAnimator visibilityAnim = animateVisibility(toState == OVERVIEW);
|
||||
visibilityAnim.setDuration(config.duration);
|
||||
visibilityAnim.setInterpolator(Interpolators.LINEAR);
|
||||
builder.play(visibilityAnim);
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.launcher3.uioverrides;
|
||||
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.uioverrides.OverviewState.WORKSPACE_SCALE_ON_SCROLL;
|
||||
import static com.android.quickstep.RecentsView.SCROLL_TYPE_WORKSPACE;
|
||||
|
||||
import android.animation.FloatArrayEvaluator;
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.Workspace;
|
||||
import com.android.launcher3.widget.WidgetsFullSheet;
|
||||
import com.android.quickstep.RecentsView;
|
||||
import com.android.quickstep.RecentsView.PageCallbacks;
|
||||
import com.android.quickstep.RecentsView.ScrollState;
|
||||
|
||||
public class WorkspaceCard extends FrameLayout implements PageCallbacks, OnClickListener {
|
||||
|
||||
private final Rect mTempRect = new Rect();
|
||||
private final float[] mEvaluatedFloats = new float[2];
|
||||
private final FloatArrayEvaluator mEvaluator = new FloatArrayEvaluator(mEvaluatedFloats);
|
||||
|
||||
// UI related information
|
||||
private float[] mScaleAndTranslatePage0, mScaleAndTranslatePage1;
|
||||
private boolean mUIDataValid = false;
|
||||
|
||||
private Launcher mLauncher;
|
||||
private Workspace mWorkspace;
|
||||
|
||||
private boolean mIsWorkspaceScrollingEnabled;
|
||||
|
||||
private View mWorkspaceClickTarget;
|
||||
private View mWidgetsButton;
|
||||
|
||||
public WorkspaceCard(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public WorkspaceCard(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public WorkspaceCard(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
|
||||
mWorkspaceClickTarget = findViewById(R.id.workspace_click_target);
|
||||
mWidgetsButton = findViewById(R.id.widget_button);
|
||||
|
||||
mWorkspaceClickTarget.setOnClickListener(this);
|
||||
mWidgetsButton.setOnClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
// We measure the dimensions of the PagedView to be larger than the pages so that when we
|
||||
// zoom out (and scale down), the view is still contained in the parent
|
||||
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
|
||||
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
|
||||
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
|
||||
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
|
||||
|
||||
if (widthMode == MeasureSpec.UNSPECIFIED || heightMode == MeasureSpec.UNSPECIFIED) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
return;
|
||||
}
|
||||
|
||||
// Return early if we aren't given a proper dimension
|
||||
if (widthSize <= 0 || heightSize <= 0) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
return;
|
||||
}
|
||||
|
||||
int childWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY);
|
||||
|
||||
int pageHeight = mWorkspace.getNormalChildHeight() * widthSize /
|
||||
mWorkspace.getNormalChildWidth();
|
||||
mWorkspaceClickTarget.measure(childWidthSpec,
|
||||
MeasureSpec.makeMeasureSpec(pageHeight, MeasureSpec.EXACTLY));
|
||||
|
||||
int buttonHeight = heightSize - pageHeight - getPaddingTop() - getPaddingBottom();
|
||||
mWidgetsButton.measure(childWidthSpec,
|
||||
MeasureSpec.makeMeasureSpec(buttonHeight, MeasureSpec.EXACTLY));
|
||||
|
||||
setMeasuredDimension(widthSize, heightSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
int y1 = getPaddingTop();
|
||||
int y2 = y1 + mWorkspaceClickTarget.getMeasuredHeight();
|
||||
|
||||
mWorkspaceClickTarget.layout(getPaddingLeft(), y1,
|
||||
mWorkspaceClickTarget.getMeasuredWidth(), y2);
|
||||
|
||||
mWidgetsButton.layout(getPaddingLeft(), y2, mWidgetsButton.getMeasuredWidth(),
|
||||
mWidgetsButton.getMeasuredHeight() + y2);
|
||||
|
||||
mUIDataValid = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if (view == mWorkspaceClickTarget) {
|
||||
mLauncher.getStateManager().goToState(NORMAL);
|
||||
} else if (view == mWidgetsButton) {
|
||||
WidgetsFullSheet.show(mLauncher, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
mUIDataValid = false;
|
||||
}
|
||||
|
||||
public void setup(Launcher launcher) {
|
||||
mLauncher = launcher;
|
||||
mWorkspace = mLauncher.getWorkspace();
|
||||
}
|
||||
|
||||
public void setWorkspaceScrollingEnabled(boolean isEnabled) {
|
||||
mIsWorkspaceScrollingEnabled = isEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onPageScroll(ScrollState scrollState) {
|
||||
setTranslationX(scrollState.distanceFromScreenCenter);
|
||||
|
||||
float factor = scrollState.linearInterpolation;
|
||||
float scale = factor * WORKSPACE_SCALE_ON_SCROLL + (1 - factor);
|
||||
setScaleX(scale);
|
||||
setScaleY(scale);
|
||||
|
||||
if (mIsWorkspaceScrollingEnabled) {
|
||||
initUiData();
|
||||
|
||||
mEvaluator.evaluate(factor, mScaleAndTranslatePage0, mScaleAndTranslatePage1);
|
||||
mWorkspace.setScaleX(mEvaluatedFloats[0]);
|
||||
mWorkspace.setScaleY(mEvaluatedFloats[0]);
|
||||
mWorkspace.setTranslationY(mEvaluatedFloats[1]);
|
||||
}
|
||||
return SCROLL_TYPE_WORKSPACE;
|
||||
}
|
||||
|
||||
private void initUiData() {
|
||||
if (mUIDataValid && mScaleAndTranslatePage0 != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
RecentsView.getPageRect(mLauncher, mTempRect);
|
||||
mScaleAndTranslatePage0 = OverviewState
|
||||
.getScaleAndTranslationForPageRect(mLauncher, mTempRect);
|
||||
Rect scaledDown = new Rect(mTempRect);
|
||||
Utilities.scaleRectAboutCenter(scaledDown, WORKSPACE_SCALE_ON_SCROLL);
|
||||
mScaleAndTranslatePage1 = OverviewState
|
||||
.getScaleAndTranslationForPageRect(mLauncher, scaledDown);
|
||||
mUIDataValid = true;
|
||||
}
|
||||
}
|
||||
@@ -250,6 +250,7 @@ public class NavBarSwipeInteractionHandler extends InternalStateHandler {
|
||||
|
||||
private void setTaskPlanToUi() {
|
||||
mRecentsView.update(mLoadPlan);
|
||||
mRecentsView.initToPage(mRecentsView.getFirstTaskIndex());
|
||||
ObjectAnimator anim = mStateController.animateVisibility(true /* isVisible */)
|
||||
.setDuration(RECENTS_VIEW_VISIBILITY_DURATION);
|
||||
anim.addListener(new AnimationSuccessListener() {
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package com.android.quickstep;
|
||||
|
||||
import android.animation.LayoutTransition;
|
||||
import android.animation.TimeInterpolator;
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.util.AttributeSet;
|
||||
@@ -47,17 +46,11 @@ import java.util.ArrayList;
|
||||
*/
|
||||
public class RecentsView extends PagedView {
|
||||
|
||||
/** Designates how "curvy" the carousel is from 0 to 1, where 0 is a straight line. */
|
||||
private static final float CURVE_FACTOR = 0.25f;
|
||||
/** A circular curve of x from 0 to 1, where 0 is the center of the screen and 1 is the edge. */
|
||||
private static final TimeInterpolator CURVE_INTERPOLATOR
|
||||
= x -> (float) (1 - Math.sqrt(1 - Math.pow(x, 2)));
|
||||
/**
|
||||
* The alpha of a black scrim on a page in the carousel as it leaves the screen.
|
||||
* In the resting position of the carousel, the adjacent pages have about half this scrim.
|
||||
*/
|
||||
private static final float MAX_PAGE_SCRIM_ALPHA = 0.8f;
|
||||
public static final int SCROLL_TYPE_NONE = 0;
|
||||
public static final int SCROLL_TYPE_TASK = 1;
|
||||
public static final int SCROLL_TYPE_WORKSPACE = 2;
|
||||
|
||||
private final ScrollState mScrollState = new ScrollState();
|
||||
private boolean mOverviewStateEnabled;
|
||||
private boolean mTaskStackListenerRegistered;
|
||||
private LayoutTransition mLayoutTransition;
|
||||
@@ -65,7 +58,7 @@ public class RecentsView extends PagedView {
|
||||
private TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
|
||||
@Override
|
||||
public void onTaskSnapshotChanged(int taskId, ThumbnailData snapshot) {
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
for (int i = mFirstTaskIndex; i < getChildCount(); i++) {
|
||||
final TaskView taskView = (TaskView) getChildAt(i);
|
||||
if (taskView.getTask().key.id == taskId) {
|
||||
taskView.getThumbnail().setThumbnail(snapshot);
|
||||
@@ -76,6 +69,7 @@ public class RecentsView extends PagedView {
|
||||
};
|
||||
|
||||
private RecentsViewStateController mStateController;
|
||||
private int mFirstTaskIndex;
|
||||
|
||||
public RecentsView(Context context) {
|
||||
this(context, null);
|
||||
@@ -87,10 +81,12 @@ public class RecentsView extends PagedView {
|
||||
|
||||
public RecentsView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
setWillNotDraw(false);
|
||||
setPageSpacing((int) getResources().getDimension(R.dimen.recents_page_spacing));
|
||||
setPageSpacing(getResources().getDimensionPixelSize(R.dimen.recents_page_spacing));
|
||||
enableFreeScroll(true);
|
||||
setClipChildren(true);
|
||||
setupLayoutTransition();
|
||||
|
||||
mScrollState.isRtl = mIsRtl;
|
||||
}
|
||||
|
||||
private void setupLayoutTransition() {
|
||||
@@ -110,6 +106,8 @@ public class RecentsView extends PagedView {
|
||||
|
||||
Rect padding = getPadding(Launcher.getLauncher(getContext()));
|
||||
setPadding(padding.left, padding.top, padding.right, padding.bottom);
|
||||
|
||||
mFirstTaskIndex = getPageCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -130,6 +128,10 @@ public class RecentsView extends PagedView {
|
||||
updateTaskStackListenerState();
|
||||
}
|
||||
|
||||
public int getFirstTaskIndex() {
|
||||
return mFirstTaskIndex;
|
||||
}
|
||||
|
||||
public void setStateController(RecentsViewStateController stateController) {
|
||||
mStateController = stateController;
|
||||
}
|
||||
@@ -145,10 +147,6 @@ public class RecentsView extends PagedView {
|
||||
|
||||
public void update(RecentsTaskLoadPlan loadPlan) {
|
||||
final RecentsTaskLoader loader = TouchInteractionService.getRecentsTaskLoader();
|
||||
setCurrentPage(0);
|
||||
if (getPageAt(mCurrentPage) instanceof TaskView) {
|
||||
((TaskView) getPageAt(mCurrentPage)).setIconScale(0);
|
||||
}
|
||||
TaskStack stack = loadPlan != null ? loadPlan.getTaskStack() : null;
|
||||
if (stack == null) {
|
||||
removeAllViews();
|
||||
@@ -160,11 +158,13 @@ public class RecentsView extends PagedView {
|
||||
final LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||
final ArrayList<Task> tasks = stack.getTasks();
|
||||
setLayoutTransition(null);
|
||||
for (int i = getChildCount(); i < tasks.size(); i++) {
|
||||
int requiredChildCount = tasks.size() + mFirstTaskIndex;
|
||||
|
||||
for (int i = getChildCount(); i < requiredChildCount; i++) {
|
||||
final TaskView taskView = (TaskView) inflater.inflate(R.layout.task, this, false);
|
||||
addView(taskView);
|
||||
}
|
||||
while (getChildCount() > tasks.size()) {
|
||||
while (getChildCount() > requiredChildCount) {
|
||||
final TaskView taskView = (TaskView) getChildAt(getChildCount() - 1);
|
||||
removeView(taskView);
|
||||
loader.unloadTaskData(taskView.getTask());
|
||||
@@ -174,14 +174,21 @@ public class RecentsView extends PagedView {
|
||||
// Rebind all task views
|
||||
for (int i = tasks.size() - 1; i >= 0; i--) {
|
||||
final Task task = tasks.get(i);
|
||||
final TaskView taskView = (TaskView) getChildAt(tasks.size() - i - 1);
|
||||
final TaskView taskView = (TaskView) getChildAt(tasks.size() - i - 1 + mFirstTaskIndex);
|
||||
taskView.bind(task);
|
||||
loader.loadTaskData(task);
|
||||
}
|
||||
}
|
||||
|
||||
public void initToPage(int pageNo) {
|
||||
setCurrentPage(pageNo);
|
||||
if (getPageAt(mCurrentPage) instanceof TaskView) {
|
||||
((TaskView) getPageAt(mCurrentPage)).setIconScale(0);
|
||||
}
|
||||
}
|
||||
|
||||
public void launchTaskWithId(int taskId) {
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
for (int i = mFirstTaskIndex; i < getChildCount(); i++) {
|
||||
final TaskView taskView = (TaskView) getChildAt(i);
|
||||
if (taskView.getTask().key.id == taskId) {
|
||||
taskView.launchTask(false /* animate */);
|
||||
@@ -245,35 +252,50 @@ public class RecentsView extends PagedView {
|
||||
}
|
||||
final int halfScreenWidth = getMeasuredWidth() / 2;
|
||||
final int screenCenter = halfScreenWidth + getScrollX();
|
||||
final int pageSpacing = getResources().getDimensionPixelSize(R.dimen.recents_page_spacing);
|
||||
final int pageSpacing = mPageSpacing;
|
||||
final int halfPageWidth = mScrollState.halfPageWidth = getNormalChildWidth() / 2;
|
||||
mScrollState.lastScrollType = SCROLL_TYPE_NONE;
|
||||
|
||||
final int pageCount = getPageCount();
|
||||
for (int i = 0; i < pageCount; i++) {
|
||||
View page = getPageAt(i);
|
||||
int pageWidth = page.getMeasuredWidth();
|
||||
int halfPageWidth = pageWidth / 2;
|
||||
int pageCenter = page.getLeft() + halfPageWidth;
|
||||
float distanceFromScreenCenter = Math.abs(pageCenter - screenCenter);
|
||||
mScrollState.distanceFromScreenCenter = screenCenter - pageCenter;
|
||||
float distanceToReachEdge = halfScreenWidth + halfPageWidth + pageSpacing;
|
||||
float linearInterpolation = Math.min(1, distanceFromScreenCenter / distanceToReachEdge);
|
||||
float curveInterpolation = CURVE_INTERPOLATOR.getInterpolation(linearInterpolation);
|
||||
float scale = 1 - curveInterpolation * CURVE_FACTOR;
|
||||
page.setScaleX(scale);
|
||||
page.setScaleY(scale);
|
||||
// Make sure the biggest card (i.e. the one in front) shows on top of the adjacent ones.
|
||||
page.setTranslationZ(scale);
|
||||
page.setTranslationX((screenCenter - pageCenter) * curveInterpolation * CURVE_FACTOR);
|
||||
if (page instanceof TaskView) {
|
||||
TaskThumbnailView thumbnail = ((TaskView) page).getThumbnail();
|
||||
thumbnail.setDimAlpha(1 - curveInterpolation * MAX_PAGE_SCRIM_ALPHA);
|
||||
}
|
||||
mScrollState.linearInterpolation = Math.min(1,
|
||||
Math.abs(mScrollState.distanceFromScreenCenter) / distanceToReachEdge);
|
||||
mScrollState.lastScrollType = ((PageCallbacks) page).onPageScroll(mScrollState);
|
||||
}
|
||||
}
|
||||
|
||||
public void onTaskDismissed(TaskView taskView) {
|
||||
ActivityManagerWrapper.getInstance().removeTask(taskView.getTask().key.id);
|
||||
removeView(taskView);
|
||||
if (getChildCount() == 0) {
|
||||
if (getChildCount() == mFirstTaskIndex) {
|
||||
Launcher.getLauncher(getContext()).getStateManager().goToState(LauncherState.NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
public interface PageCallbacks {
|
||||
|
||||
/**
|
||||
* Updates the page UI based on scroll params and returns the type of scroll
|
||||
* effect performed.
|
||||
*
|
||||
* @see #SCROLL_TYPE_NONE
|
||||
* @see #SCROLL_TYPE_TASK
|
||||
* @see #SCROLL_TYPE_WORKSPACE
|
||||
*/
|
||||
int onPageScroll(ScrollState scrollState);
|
||||
}
|
||||
|
||||
public static class ScrollState {
|
||||
|
||||
public boolean isRtl;
|
||||
public int lastScrollType;
|
||||
|
||||
public int halfPageWidth;
|
||||
public float distanceFromScreenCenter;
|
||||
public float linearInterpolation;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,13 @@
|
||||
|
||||
package com.android.quickstep;
|
||||
|
||||
import static com.android.quickstep.RecentsView.SCROLL_TYPE_TASK;
|
||||
import static com.android.quickstep.RecentsView.SCROLL_TYPE_WORKSPACE;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.TimeInterpolator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.Context;
|
||||
@@ -35,6 +39,8 @@ import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.touch.SwipeDetector;
|
||||
import com.android.quickstep.RecentsView.PageCallbacks;
|
||||
import com.android.quickstep.RecentsView.ScrollState;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
import com.android.systemui.shared.recents.model.Task.TaskCallbacks;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
@@ -49,7 +55,20 @@ import java.util.List;
|
||||
/**
|
||||
* A task in the Recents view.
|
||||
*/
|
||||
public class TaskView extends FrameLayout implements TaskCallbacks, SwipeDetector.Listener {
|
||||
public class TaskView extends FrameLayout implements TaskCallbacks, SwipeDetector.Listener,
|
||||
PageCallbacks {
|
||||
|
||||
/** Designates how "curvy" the carousel is from 0 to 1, where 0 is a straight line. */
|
||||
private static final float CURVE_FACTOR = 0.25f;
|
||||
/** A circular curve of x from 0 to 1, where 0 is the center of the screen and 1 is the edge. */
|
||||
private static final TimeInterpolator CURVE_INTERPOLATOR
|
||||
= x -> (float) (1 - Math.sqrt(1 - Math.pow(x, 2)));
|
||||
|
||||
/**
|
||||
* The alpha of a black scrim on a page in the carousel as it leaves the screen.
|
||||
* In the resting position of the carousel, the adjacent pages have about half this scrim.
|
||||
*/
|
||||
private static final float MAX_PAGE_SCRIM_ALPHA = 0.8f;
|
||||
|
||||
private static final int SWIPE_DIRECTIONS = SwipeDetector.DIRECTION_POSITIVE;
|
||||
|
||||
@@ -288,4 +307,35 @@ public class TaskView extends FrameLayout implements TaskCallbacks, SwipeDetecto
|
||||
mIconView.setScaleY(mIconScale);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onPageScroll(ScrollState scrollState) {
|
||||
float curveInterpolation =
|
||||
CURVE_INTERPOLATOR.getInterpolation(scrollState.linearInterpolation);
|
||||
float scale = 1 - curveInterpolation * CURVE_FACTOR;
|
||||
setScaleX(scale);
|
||||
setScaleY(scale);
|
||||
|
||||
// Make sure the biggest card (i.e. the one in front) shows on top of the adjacent ones.
|
||||
setTranslationZ(scale);
|
||||
|
||||
mSnapshotView.setDimAlpha(1 - curveInterpolation * MAX_PAGE_SCRIM_ALPHA);
|
||||
|
||||
float translation =
|
||||
scrollState.distanceFromScreenCenter * curveInterpolation * CURVE_FACTOR;
|
||||
setTranslationX(translation);
|
||||
|
||||
if (scrollState.lastScrollType == SCROLL_TYPE_WORKSPACE) {
|
||||
// Make sure that the task cards do not overlap with the workspace card
|
||||
float min = scrollState.halfPageWidth * (1 - scale);
|
||||
if (scrollState.isRtl) {
|
||||
setTranslationX(Math.min(translation, min));
|
||||
} else {
|
||||
setTranslationX(Math.max(translation, -min));
|
||||
}
|
||||
} else {
|
||||
setTranslationX(translation);
|
||||
}
|
||||
return SCROLL_TYPE_TASK;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,10 @@
|
||||
android:layout_gravity="bottom|left"
|
||||
android:background="@drawable/all_apps_handle_landscape" />
|
||||
|
||||
<include layout="@layout/overview_panel"
|
||||
android:id="@+id/overview_panel"
|
||||
android:visibility="gone" />
|
||||
|
||||
<com.android.launcher3.views.AllAppsScrim
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
@@ -68,10 +72,6 @@
|
||||
android:id="@+id/drop_target_bar"
|
||||
layout="@layout/drop_target_bar_vert" />
|
||||
|
||||
<include layout="@layout/overview_panel"
|
||||
android:id="@+id/overview_panel"
|
||||
android:visibility="gone" />
|
||||
|
||||
<include layout="@layout/all_apps"
|
||||
android:id="@+id/apps_view"
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -44,6 +44,10 @@
|
||||
launcher:pageIndicator="@+id/page_indicator">
|
||||
</com.android.launcher3.Workspace>
|
||||
|
||||
<include layout="@layout/overview_panel"
|
||||
android:id="@+id/overview_panel"
|
||||
android:visibility="gone" />
|
||||
|
||||
<com.android.launcher3.views.AllAppsScrim
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
@@ -57,10 +61,6 @@
|
||||
android:layout_height="match_parent"
|
||||
launcher:layout_ignoreInsets="true" />
|
||||
|
||||
<include layout="@layout/overview_panel"
|
||||
android:id="@+id/overview_panel"
|
||||
android:visibility="gone" />
|
||||
|
||||
<!-- Keep these behind the workspace so that they are not visible when
|
||||
we go into AllApps -->
|
||||
<include layout="@layout/page_indicator"
|
||||
|
||||
@@ -43,6 +43,10 @@
|
||||
launcher:pageIndicator="@id/page_indicator">
|
||||
</com.android.launcher3.Workspace>
|
||||
|
||||
<include layout="@layout/overview_panel"
|
||||
android:id="@+id/overview_panel"
|
||||
android:visibility="gone" />
|
||||
|
||||
<com.android.launcher3.views.AllAppsScrim
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
@@ -60,10 +64,6 @@
|
||||
android:id="@+id/drop_target_bar"
|
||||
layout="@layout/drop_target_bar_horz" />
|
||||
|
||||
<include layout="@layout/overview_panel"
|
||||
android:id="@+id/overview_panel"
|
||||
android:visibility="gone" />
|
||||
|
||||
<!-- Keep these behind the workspace so that they are not visible when
|
||||
we go into AllApps -->
|
||||
<include layout="@layout/page_indicator"
|
||||
|
||||
@@ -106,7 +106,7 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler {
|
||||
final PreviewBackground mFolderLeaveBehind = new PreviewBackground();
|
||||
|
||||
private static final int[] BACKGROUND_STATE_ACTIVE = new int[] { android.R.attr.state_active };
|
||||
private static final int[] BACKGROUND_STATE_DEFAULT = new int[0];
|
||||
private static final int[] BACKGROUND_STATE_DEFAULT = EMPTY_STATE_SET;
|
||||
private final Drawable mBackground;
|
||||
|
||||
// These values allow a fixed measurement to be set on the CellLayout.
|
||||
|
||||
@@ -106,7 +106,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
|
||||
protected LauncherScroller mScroller;
|
||||
private Interpolator mDefaultInterpolator;
|
||||
private VelocityTracker mVelocityTracker;
|
||||
@Thunk int mPageSpacing = 0;
|
||||
protected int mPageSpacing = 0;
|
||||
|
||||
private float mParentDownMotionX;
|
||||
private float mParentDownMotionY;
|
||||
|
||||
@@ -20,8 +20,6 @@ import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.support.v4.graphics.ColorUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
@@ -41,7 +39,7 @@ public class AllAppsScrim extends View implements WallpaperColorInfo.OnChangeLis
|
||||
private static final int MIN_ALPHA_PORTRAIT = 100;
|
||||
private static final int MIN_ALPHA_LANDSCAPE = MAX_ALPHA;
|
||||
|
||||
private final WallpaperColorInfo mWallpaperColorInfo;
|
||||
protected final WallpaperColorInfo mWallpaperColorInfo;
|
||||
private final Paint mFillPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
|
||||
private final float mRadius;
|
||||
|
||||
@@ -57,7 +57,7 @@ public class WidgetsBottomSheet extends BaseWidgetSheet implements Insettable {
|
||||
mInsets = new Rect();
|
||||
|
||||
mGradientView = (GradientView) mLauncher.getLayoutInflater().inflate(
|
||||
R.layout.gradient_bg, mLauncher.getDragLayer(), false);
|
||||
R.layout.widgets_bottom_sheet_scrim, mLauncher.getDragLayer(), false);
|
||||
mGradientView.setProgress(1, false);
|
||||
mContent = this;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user