Merge "Fixing various layout issues when docking" into nyc-dev
This commit is contained in:
@@ -18,47 +18,43 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:focusable="true">
|
||||
<FrameLayout
|
||||
android:id="@+id/task_view_content"
|
||||
<com.android.systemui.recents.views.TaskViewThumbnail
|
||||
android:id="@+id/task_view_thumbnail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<com.android.systemui.recents.views.TaskViewThumbnail
|
||||
android:id="@+id/task_view_thumbnail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<include layout="@layout/recents_task_view_header" />
|
||||
<include layout="@layout/recents_task_view_header" />
|
||||
|
||||
<com.android.systemui.statusbar.AlphaOptimizedFrameLayout
|
||||
android:id="@+id/lock_to_app_fab"
|
||||
android:layout_width="@dimen/recents_lock_to_app_size"
|
||||
android:layout_height="@dimen/recents_lock_to_app_size"
|
||||
android:layout_gravity="bottom|right"
|
||||
android:layout_marginRight="15dp"
|
||||
android:layout_marginBottom="15dp"
|
||||
android:translationZ="4dp"
|
||||
android:contentDescription="@string/recents_lock_to_app_button_label"
|
||||
android:background="@drawable/recents_lock_to_task_button_bg"
|
||||
android:visibility="invisible"
|
||||
android:alpha="0">
|
||||
<ImageView
|
||||
android:layout_width="@dimen/recents_lock_to_app_icon_size"
|
||||
android:layout_height="@dimen/recents_lock_to_app_icon_size"
|
||||
android:layout_gravity="center"
|
||||
android:src="@drawable/recents_lock_to_app_pin" />
|
||||
</com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
|
||||
<!-- TODO: Move this into a view stub -->
|
||||
<com.android.systemui.statusbar.AlphaOptimizedFrameLayout
|
||||
android:id="@+id/lock_to_app_fab"
|
||||
android:layout_width="@dimen/recents_lock_to_app_size"
|
||||
android:layout_height="@dimen/recents_lock_to_app_size"
|
||||
android:layout_gravity="bottom|right"
|
||||
android:layout_marginRight="15dp"
|
||||
android:layout_marginBottom="15dp"
|
||||
android:translationZ="4dp"
|
||||
android:contentDescription="@string/recents_lock_to_app_button_label"
|
||||
android:background="@drawable/recents_lock_to_task_button_bg"
|
||||
android:visibility="invisible"
|
||||
android:alpha="0">
|
||||
<ImageView
|
||||
android:layout_width="@dimen/recents_lock_to_app_icon_size"
|
||||
android:layout_height="@dimen/recents_lock_to_app_icon_size"
|
||||
android:layout_gravity="center"
|
||||
android:src="@drawable/recents_lock_to_app_pin" />
|
||||
</com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
|
||||
|
||||
<!-- The incompatible app toast -->
|
||||
<ViewStub android:id="@+id/incompatible_app_toast_stub"
|
||||
android:inflatedId="@+id/incompatible_app_toast"
|
||||
android:layout="@*android:layout/transient_notification"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top|center_horizontal"
|
||||
android:layout_marginTop="48dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp" />
|
||||
</FrameLayout>
|
||||
<!-- The incompatible app toast -->
|
||||
<ViewStub android:id="@+id/incompatible_app_toast_stub"
|
||||
android:inflatedId="@+id/incompatible_app_toast"
|
||||
android:layout="@*android:layout/transient_notification"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top|center_horizontal"
|
||||
android:layout_marginTop="48dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp" />
|
||||
</com.android.systemui.recents.views.TaskView>
|
||||
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
|
||||
|
||||
private RecentsPackageMonitor mPackageMonitor;
|
||||
private long mLastTabKeyEventTime;
|
||||
private int mLastOrientation = Configuration.ORIENTATION_UNDEFINED;
|
||||
private int mLastDeviceOrientation = Configuration.ORIENTATION_UNDEFINED;
|
||||
private boolean mFinishedOnStartup;
|
||||
private boolean mIgnoreAltTabRelease;
|
||||
private boolean mIsVisible;
|
||||
@@ -276,7 +276,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
|
||||
getWindow().getAttributes().privateFlags |=
|
||||
WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
|
||||
|
||||
mLastOrientation = getResources().getConfiguration().orientation;
|
||||
mLastDeviceOrientation = Utilities.getAppConfiguration(this).orientation;
|
||||
mFocusTimerDuration = getResources().getInteger(R.integer.recents_auto_advance_duration);
|
||||
mIterateTrigger = new DozeTrigger(mFocusTimerDuration, new Runnable() {
|
||||
@Override
|
||||
@@ -426,13 +426,12 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
|
||||
|
||||
// Notify of the config change
|
||||
int newOrientation = getResources().getConfiguration().orientation;
|
||||
int newDeviceOrientation = Utilities.getAppConfiguration(this).orientation;
|
||||
int numStackTasks = mRecentsView.getStack().getStackTaskCount();
|
||||
EventBus.getDefault().send(new ConfigurationChangedEvent(false /* fromMultiWindow */,
|
||||
(mLastOrientation != newOrientation), numStackTasks > 0));
|
||||
mLastOrientation = newOrientation;
|
||||
(mLastDeviceOrientation != newDeviceOrientation), numStackTasks > 0));
|
||||
mLastDeviceOrientation = newDeviceOrientation;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -455,7 +454,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
|
||||
int numStackTasks = stack.getStackTaskCount();
|
||||
|
||||
EventBus.getDefault().send(new ConfigurationChangedEvent(true /* fromMultiWindow */,
|
||||
false /* fromOrientationChange */, numStackTasks > 0));
|
||||
false /* fromDeviceOrientationChange */, numStackTasks > 0));
|
||||
|
||||
if (mRecentsView != null) {
|
||||
mRecentsView.updateStack(stack);
|
||||
@@ -777,6 +776,8 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
|
||||
@Override
|
||||
public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
|
||||
super.dump(prefix, fd, writer, args);
|
||||
EventBus.getDefault().dump(prefix, writer);
|
||||
|
||||
String id = Integer.toHexString(System.identityHashCode(this));
|
||||
|
||||
writer.print(prefix); writer.print(TAG);
|
||||
@@ -787,6 +788,5 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
|
||||
if (mRecentsView != null) {
|
||||
mRecentsView.dump(prefix, writer);
|
||||
}
|
||||
EventBus.getDefault().dump(prefix, writer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -689,7 +689,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
|
||||
TaskStackViewScroller stackScroller = stackView.getScroller();
|
||||
|
||||
stackView.updateLayoutAlgorithm(true /* boundScroll */);
|
||||
stackView.updateToInitialState(true /* scrollToInitialState */);
|
||||
stackView.updateToInitialState();
|
||||
|
||||
for (int i = tasks.size() - 1; i >= 0; i--) {
|
||||
Task task = tasks.get(i);
|
||||
@@ -742,7 +742,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
|
||||
|
||||
// Get the transform for the running task
|
||||
stackView.updateLayoutAlgorithm(true /* boundScroll */);
|
||||
stackView.updateToInitialState(true /* scrollToInitialState */);
|
||||
stackView.updateToInitialState();
|
||||
stackView.getStackAlgorithm().getStackTransformScreenCoordinates(launchTask,
|
||||
stackView.getScroller().getStackScroll(), mTmpTransform, null);
|
||||
return mTmpTransform;
|
||||
|
||||
@@ -24,13 +24,13 @@ import com.android.systemui.recents.events.EventBus;
|
||||
public class ConfigurationChangedEvent extends EventBus.AnimatedEvent {
|
||||
|
||||
public final boolean fromMultiWindow;
|
||||
public final boolean fromOrientationChange;
|
||||
public final boolean fromDeviceOrientationChange;
|
||||
public final boolean hasStackTasks;
|
||||
|
||||
public ConfigurationChangedEvent(boolean fromMultiWindow, boolean fromOrientationChange,
|
||||
public ConfigurationChangedEvent(boolean fromMultiWindow, boolean fromDeviceOrientationChange,
|
||||
boolean hasStackTasks) {
|
||||
this.fromMultiWindow = fromMultiWindow;
|
||||
this.fromOrientationChange = fromOrientationChange;
|
||||
this.fromDeviceOrientationChange = fromDeviceOrientationChange;
|
||||
this.hasStackTasks = hasStackTasks;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,11 @@ package com.android.systemui.recents.misc;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.RectEvaluator;
|
||||
import android.annotation.FloatRange;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Rect;
|
||||
@@ -71,7 +74,7 @@ public class Utilities {
|
||||
};
|
||||
|
||||
public static final RectFEvaluator RECTF_EVALUATOR = new RectFEvaluator();
|
||||
|
||||
public static final RectEvaluator RECT_EVALUATOR = new RectEvaluator(new Rect());
|
||||
public static final Rect EMPTY_RECT = new Rect();
|
||||
|
||||
/**
|
||||
@@ -269,6 +272,14 @@ public class Utilities {
|
||||
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the application configuration, which is independent of the activity's current
|
||||
* configuration in multiwindow.
|
||||
*/
|
||||
public static Configuration getAppConfiguration(Context context) {
|
||||
return context.getApplicationContext().getResources().getConfiguration();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a lightweight dump of a rect.
|
||||
*/
|
||||
|
||||
@@ -299,7 +299,7 @@ public class TaskStack {
|
||||
if (bounds != null && !dockAreaOverlay.getBounds().equals(bounds)) {
|
||||
if (animateBounds) {
|
||||
PropertyValuesHolder prop = PropertyValuesHolder.ofObject(
|
||||
Utilities.DRAWABLE_RECT, new RectEvaluator(new Rect()),
|
||||
Utilities.DRAWABLE_RECT, Utilities.RECT_EVALUATOR,
|
||||
dockAreaOverlay.getBounds(), bounds);
|
||||
animators.add(ObjectAnimator.ofPropertyValuesHolder(dockAreaOverlay, prop));
|
||||
} else {
|
||||
|
||||
@@ -88,6 +88,10 @@ public class FixedSizeFrameLayout extends FrameLayout {
|
||||
*/
|
||||
protected void layoutContents(Rect bounds, boolean changed) {
|
||||
super.onLayout(changed, bounds.left, bounds.top, bounds.right, bounds.bottom);
|
||||
|
||||
int width = getMeasuredWidth();
|
||||
int height = getMeasuredHeight();
|
||||
onSizeChanged(width, height, width, height);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -519,7 +519,9 @@ public class RecentsView extends FrameLayout {
|
||||
@Override
|
||||
public void onAnimationStarted() {
|
||||
EventBus.getDefault().send(new DockedFirstAnimationFrameEvent());
|
||||
mTaskStackView.getStack().removeTask(event.task, AnimationProps.IMMEDIATE,
|
||||
// Remove the task and don't bother relaying out, as all the tasks will be
|
||||
// relaid out when the stack changes on the multiwindow change event
|
||||
mTaskStackView.getStack().removeTask(event.task, null,
|
||||
true /* fromDockGesture */);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -297,9 +297,6 @@ public class TaskStackLayoutAlgorithm {
|
||||
private FreePathInterpolator mUnfocusedDimCurveInterpolator;
|
||||
private FreePathInterpolator mFocusedDimCurveInterpolator;
|
||||
|
||||
// Indexed from the front of the stack, the normalized x in the unfocused range for each task
|
||||
private float[] mInitialNormX;
|
||||
|
||||
// The state of the stack focus (0..1), which controls the transition of the stack from the
|
||||
// focused to non-focused state
|
||||
@ViewDebug.ExportedProperty(category="recents")
|
||||
@@ -406,8 +403,10 @@ public class TaskStackLayoutAlgorithm {
|
||||
/**
|
||||
* Sets the system insets.
|
||||
*/
|
||||
public void setSystemInsets(Rect systemInsets) {
|
||||
public boolean setSystemInsets(Rect systemInsets) {
|
||||
boolean changed = mSystemInsets.equals(systemInsets);
|
||||
mSystemInsets.set(systemInsets);
|
||||
return changed;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -545,13 +544,11 @@ public class TaskStackLayoutAlgorithm {
|
||||
} else {
|
||||
mInitialScrollP = Utilities.clamp(launchTaskIndex - 1, mMinScrollP, mMaxScrollP);
|
||||
}
|
||||
mInitialNormX = null;
|
||||
} else if (!ssp.hasFreeformWorkspaceSupport() && mNumStackTasks == 1) {
|
||||
// If there is one stack task, ignore the min/max/initial scroll positions
|
||||
mMinScrollP = 0;
|
||||
mMaxScrollP = 0;
|
||||
mInitialScrollP = 0;
|
||||
mInitialNormX = null;
|
||||
} else {
|
||||
// Set the max scroll to be the point where the front most task is visible with the
|
||||
// stack bottom offset
|
||||
@@ -565,42 +562,50 @@ public class TaskStackLayoutAlgorithm {
|
||||
launchState.launchedViaDockGesture;
|
||||
if (launchState.launchedWithAltTab) {
|
||||
mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
|
||||
mInitialNormX = null;
|
||||
} else if (scrollToFront) {
|
||||
mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
|
||||
mInitialNormX = null;
|
||||
} else {
|
||||
// We are overriding the initial two task positions, so set the initial scroll
|
||||
// position to match the second task (aka focused task) position
|
||||
float initialTopNormX = getNormalizedXFromUnfocusedY(mInitialTopOffset, FROM_TOP);
|
||||
mInitialScrollP = Math.max(mMinScrollP, Math.min(mMaxScrollP, (mNumStackTasks - 2))
|
||||
- Math.max(0, mUnfocusedRange.getAbsoluteX(initialTopNormX)));
|
||||
|
||||
// Set the initial scroll to the predefined state (which differs from the stack)
|
||||
mInitialNormX = new float[] {
|
||||
getNormalizedXFromUnfocusedY(mSystemInsets.bottom + mInitialBottomOffset,
|
||||
FROM_BOTTOM),
|
||||
initialTopNormX
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updateToInitialState(List<Task> tasks) {
|
||||
if (mInitialNormX == null) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Creates task overrides to ensure the initial stack layout if necessary.
|
||||
*/
|
||||
public void setTaskOverridesForInitialState(TaskStack stack) {
|
||||
RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
|
||||
|
||||
mUnfocusedRange.offset(0f);
|
||||
int taskCount = tasks.size();
|
||||
for (int i = taskCount - 1; i >= 0; i--) {
|
||||
int indexFromFront = taskCount - i - 1;
|
||||
if (indexFromFront >= mInitialNormX.length) {
|
||||
break;
|
||||
mTaskIndexOverrideMap.clear();
|
||||
|
||||
boolean scrollToFront = launchState.launchedFromHome ||
|
||||
launchState.launchedViaDockGesture;
|
||||
if (getInitialFocusState() == STATE_UNFOCUSED && mNumStackTasks > 1) {
|
||||
if (!launchState.launchedWithAltTab && !scrollToFront) {
|
||||
// Set the initial scroll to the predefined state (which differs from the stack)
|
||||
float [] initialNormX = new float[] {
|
||||
getNormalizedXFromUnfocusedY(mSystemInsets.bottom + mInitialBottomOffset,
|
||||
FROM_BOTTOM),
|
||||
getNormalizedXFromUnfocusedY(mInitialTopOffset, FROM_TOP)
|
||||
};
|
||||
|
||||
mUnfocusedRange.offset(0f);
|
||||
List<Task> tasks = stack.getStackTasks();
|
||||
int taskCount = tasks.size();
|
||||
for (int i = taskCount - 1; i >= 0; i--) {
|
||||
int indexFromFront = taskCount - i - 1;
|
||||
if (indexFromFront >= initialNormX.length) {
|
||||
break;
|
||||
}
|
||||
float newTaskProgress = mInitialScrollP +
|
||||
mUnfocusedRange.getAbsoluteX(initialNormX[indexFromFront]);
|
||||
mTaskIndexOverrideMap.put(tasks.get(i).key.id, newTaskProgress);
|
||||
}
|
||||
}
|
||||
float newTaskProgress = mInitialScrollP +
|
||||
mUnfocusedRange.getAbsoluteX(mInitialNormX[indexFromFront]);
|
||||
mTaskIndexOverrideMap.put(tasks.get(i).key.id, newTaskProgress);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,11 +28,9 @@ import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.provider.Settings;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
@@ -105,12 +103,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
|
||||
private static final String TAG = "TaskStackView";
|
||||
|
||||
private final static String KEY_SAVED_STATE_SUPER = "saved_instance_state_super";
|
||||
private final static String KEY_SAVED_STATE_LAYOUT_FOCUSED_STATE =
|
||||
"saved_instance_state_layout_focused_state";
|
||||
private final static String KEY_SAVED_STATE_LAYOUT_STACK_SCROLL =
|
||||
"saved_instance_state_layout_stack_scroll";
|
||||
|
||||
// The thresholds at which to show/hide the stack action button.
|
||||
private static final float SHOW_STACK_ACTION_BUTTON_SCROLL_THRESHOLD = 0.3f;
|
||||
private static final float HIDE_STACK_ACTION_BUTTON_SCROLL_THRESHOLD = 0.3f;
|
||||
@@ -350,11 +342,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
/**
|
||||
* Updates this TaskStackView to the initial state.
|
||||
*/
|
||||
public void updateToInitialState(boolean scrollToInitialState) {
|
||||
if (scrollToInitialState) {
|
||||
mStackScroller.setStackScrollToInitialState();
|
||||
mLayoutAlgorithm.updateToInitialState(mStack.getStackTasks());
|
||||
}
|
||||
public void updateToInitialState() {
|
||||
mStackScroller.setStackScrollToInitialState();
|
||||
mLayoutAlgorithm.setTaskOverridesForInitialState(mStack);
|
||||
}
|
||||
|
||||
/** Updates the list of task views */
|
||||
@@ -638,17 +628,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
/**
|
||||
* @see #relayoutTaskViews(AnimationProps, ArraySet<Task.TaskKey>, boolean)
|
||||
*/
|
||||
void relayoutTaskViews(AnimationProps animation) {
|
||||
public void relayoutTaskViews(AnimationProps animation) {
|
||||
relayoutTaskViews(animation, mIgnoreTasks, false /* ignoreTaskOverrides */);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #relayoutTaskViews(AnimationProps, ArraySet<Task.TaskKey>, boolean)
|
||||
*/
|
||||
void relayoutTaskViews(AnimationProps animation, ArraySet<Task.TaskKey> ignoreTasksSet) {
|
||||
relayoutTaskViews(animation, ignoreTasksSet, false /* ignoreTaskOverrides */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Relayout the the visible {@link TaskView}s to their current transforms as specified by the
|
||||
* {@link TaskStackLayoutAlgorithm} with the given {@param animation}. This call cancels any
|
||||
@@ -657,7 +640,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
*
|
||||
* @param ignoreTasksSet the set of tasks to ignore in the relayout
|
||||
*/
|
||||
void relayoutTaskViews(AnimationProps animation, ArraySet<Task.TaskKey> ignoreTasksSet,
|
||||
private void relayoutTaskViews(AnimationProps animation, ArraySet<Task.TaskKey> ignoreTasksSet,
|
||||
boolean ignoreTaskOverrides) {
|
||||
// If we had a deferred animation, cancel that
|
||||
mDeferredTaskViewLayoutAnimation = null;
|
||||
@@ -841,7 +824,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
*
|
||||
* @param ignoreTasksSet the set of tasks to ignore in the relayout
|
||||
*/
|
||||
public void updateLayoutAlgorithm(boolean boundScrollToNewMinMax,
|
||||
private void updateLayoutAlgorithm(boolean boundScrollToNewMinMax,
|
||||
ArraySet<Task.TaskKey> ignoreTasksSet) {
|
||||
// Compute the min and max scroll values
|
||||
mLayoutAlgorithm.update(mStack, ignoreTasksSet);
|
||||
@@ -1097,24 +1080,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Parcelable onSaveInstanceState() {
|
||||
Bundle savedState = new Bundle();
|
||||
savedState.putParcelable(KEY_SAVED_STATE_SUPER, super.onSaveInstanceState());
|
||||
savedState.putInt(KEY_SAVED_STATE_LAYOUT_FOCUSED_STATE, mLayoutAlgorithm.getFocusState());
|
||||
savedState.putFloat(KEY_SAVED_STATE_LAYOUT_STACK_SCROLL, mStackScroller.getStackScroll());
|
||||
return super.onSaveInstanceState();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Parcelable state) {
|
||||
Bundle savedState = (Bundle) state;
|
||||
super.onRestoreInstanceState(savedState.getParcelable(KEY_SAVED_STATE_SUPER));
|
||||
|
||||
mLayoutAlgorithm.setFocusState(savedState.getInt(KEY_SAVED_STATE_LAYOUT_FOCUSED_STATE));
|
||||
mStackScroller.setStackScroll(savedState.getFloat(KEY_SAVED_STATE_LAYOUT_STACK_SCROLL));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getAccessibilityClassName() {
|
||||
return TaskStackView.class.getName();
|
||||
@@ -1181,9 +1146,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
* Updates the system insets.
|
||||
*/
|
||||
public void setSystemInsets(Rect systemInsets) {
|
||||
if (!systemInsets.equals(mLayoutAlgorithm.mSystemInsets)) {
|
||||
mStableLayoutAlgorithm.setSystemInsets(systemInsets);
|
||||
mLayoutAlgorithm.setSystemInsets(systemInsets);
|
||||
boolean changed = false;
|
||||
changed |= mStableLayoutAlgorithm.setSystemInsets(systemInsets);
|
||||
changed |= mLayoutAlgorithm.setSystemInsets(systemInsets);
|
||||
if (changed) {
|
||||
requestLayout();
|
||||
}
|
||||
}
|
||||
@@ -1215,12 +1181,14 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack));
|
||||
mLayoutAlgorithm.initialize(mWindowRect, mStackBounds,
|
||||
TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack));
|
||||
updateLayoutAlgorithm(false /* boundScroll */, mIgnoreTasks);
|
||||
updateLayoutAlgorithm(false /* boundScroll */);
|
||||
|
||||
// If this is the first layout, then scroll to the front of the stack, then update the
|
||||
// TaskViews with the stack so that we can lay them out
|
||||
if (mAwaitingFirstLayout || mInitialState != INITIAL_STATE_UPDATE_NONE) {
|
||||
updateToInitialState(mInitialState != INITIAL_STATE_UPDATE_LAYOUT_ONLY);
|
||||
if (mInitialState != INITIAL_STATE_UPDATE_LAYOUT_ONLY) {
|
||||
updateToInitialState();
|
||||
}
|
||||
if (!mAwaitingFirstLayout) {
|
||||
mInitialState = INITIAL_STATE_UPDATE_NONE;
|
||||
}
|
||||
@@ -1247,16 +1215,16 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
* Measures a TaskView.
|
||||
*/
|
||||
private void measureTaskView(TaskView tv) {
|
||||
Rect padding = new Rect();
|
||||
if (tv.getBackground() != null) {
|
||||
tv.getBackground().getPadding(mTmpRect);
|
||||
} else {
|
||||
mTmpRect.setEmpty();
|
||||
tv.getBackground().getPadding(padding);
|
||||
}
|
||||
Rect taskRect = mStableLayoutAlgorithm.mTaskRect;
|
||||
mTmpRect.set(mStableLayoutAlgorithm.mTaskRect);
|
||||
mTmpRect.union(mLayoutAlgorithm.mTaskRect);
|
||||
tv.measure(
|
||||
MeasureSpec.makeMeasureSpec(taskRect.width() + mTmpRect.left + mTmpRect.right,
|
||||
MeasureSpec.makeMeasureSpec(mTmpRect.width() + padding.left + padding.right,
|
||||
MeasureSpec.EXACTLY),
|
||||
MeasureSpec.makeMeasureSpec(taskRect.height() + mTmpRect.top + mTmpRect.bottom,
|
||||
MeasureSpec.makeMeasureSpec(mTmpRect.height() + padding.top + padding.bottom,
|
||||
MeasureSpec.EXACTLY));
|
||||
}
|
||||
|
||||
@@ -1278,7 +1246,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
}
|
||||
|
||||
// Relayout all of the task views including the ignored ones
|
||||
relayoutTaskViews(AnimationProps.IMMEDIATE, mIgnoreTasks);
|
||||
relayoutTaskViews(AnimationProps.IMMEDIATE);
|
||||
clipTaskViews();
|
||||
|
||||
if (mAwaitingFirstLayout || !mEnterAnimationComplete) {
|
||||
@@ -1293,15 +1261,15 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
*/
|
||||
private void layoutTaskView(boolean changed, TaskView tv) {
|
||||
if (changed) {
|
||||
Rect padding = new Rect();
|
||||
if (tv.getBackground() != null) {
|
||||
tv.getBackground().getPadding(mTmpRect);
|
||||
} else {
|
||||
mTmpRect.setEmpty();
|
||||
tv.getBackground().getPadding(padding);
|
||||
}
|
||||
Rect taskRect = mStableLayoutAlgorithm.mTaskRect;
|
||||
mTmpRect.set(mStableLayoutAlgorithm.mTaskRect);
|
||||
mTmpRect.union(mLayoutAlgorithm.mTaskRect);
|
||||
tv.cancelTransformAnimation();
|
||||
tv.layout(taskRect.left - mTmpRect.left, taskRect.top - mTmpRect.top,
|
||||
taskRect.right + mTmpRect.right, taskRect.bottom + mTmpRect.bottom);
|
||||
tv.layout(mTmpRect.left - padding.left, mTmpRect.top - padding.top,
|
||||
mTmpRect.right + padding.right, mTmpRect.bottom + padding.bottom);
|
||||
} else {
|
||||
// If the layout has not changed, then just lay it out again in-place
|
||||
tv.layout(tv.getLeft(), tv.getTop(), tv.getRight(), tv.getBottom());
|
||||
@@ -1847,7 +1815,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
height -= systemInsets.bottom;
|
||||
systemInsets.bottom = 0;
|
||||
mStackBounds.set(dockState.getDockedTaskStackBounds(getMeasuredWidth(),
|
||||
height, mDividerSize, mLayoutAlgorithm.mSystemInsets,
|
||||
height, mDividerSize, systemInsets,
|
||||
mLayoutAlgorithm, getResources(), mWindowRect));
|
||||
mLayoutAlgorithm.setSystemInsets(systemInsets);
|
||||
mLayoutAlgorithm.initialize(mWindowRect, mStackBounds,
|
||||
@@ -1982,17 +1950,24 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
|
||||
public final void onBusEvent(MultiWindowStateChangedEvent event) {
|
||||
if (!event.inMultiWindow) {
|
||||
// Scroll the stack to the front to see the undocked task
|
||||
mStackScroller.animateScroll(mLayoutAlgorithm.mMaxScrollP, new Runnable() {
|
||||
// Defer until the next frame to ensure that we have received all the system insets, and
|
||||
// initial layout updates
|
||||
post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
List<TaskView> taskViews = getTaskViews();
|
||||
int taskViewCount = taskViews.size();
|
||||
for (int i = 0; i < taskViewCount; i++) {
|
||||
TaskView tv = taskViews.get(i);
|
||||
tv.getHeaderView().rebindToTask(tv.getTask(), tv.mTouchExplorationEnabled,
|
||||
tv.mIsDisabledInSafeMode);
|
||||
}
|
||||
// Scroll the stack to the front to see the undocked task
|
||||
mStackScroller.animateScroll(mLayoutAlgorithm.mMaxScrollP, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
List<TaskView> taskViews = getTaskViews();
|
||||
int taskViewCount = taskViews.size();
|
||||
for (int i = 0; i < taskViewCount; i++) {
|
||||
TaskView tv = taskViews.get(i);
|
||||
tv.getHeaderView().rebindToTask(tv.getTask(),
|
||||
tv.mTouchExplorationEnabled, tv.mIsDisabledInSafeMode);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -2013,9 +1988,12 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
}
|
||||
|
||||
// Trigger a new layout and update to the initial state if necessary
|
||||
if (event.fromMultiWindow || event.fromOrientationChange) {
|
||||
if (event.fromMultiWindow) {
|
||||
mInitialState = INITIAL_STATE_UPDATE_LAYOUT_ONLY;
|
||||
requestLayout();
|
||||
} else if (event.fromDeviceOrientationChange) {
|
||||
mInitialState = INITIAL_STATE_UPDATE_ALL;
|
||||
requestLayout();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2110,7 +2088,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
if (mFocusedTask != null) {
|
||||
writer.print(innerPrefix);
|
||||
writer.print("Focused task: ");
|
||||
mFocusedTask.dump(innerPrefix, writer);
|
||||
mFocusedTask.dump("", writer);
|
||||
}
|
||||
|
||||
mLayoutAlgorithm.dump(innerPrefix, writer);
|
||||
|
||||
@@ -152,7 +152,6 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks
|
||||
private final TaskViewTransform mTargetAnimationTransform = new TaskViewTransform();
|
||||
private ArrayList<Animator> mTmpAnimators = new ArrayList<>();
|
||||
|
||||
View mContent;
|
||||
@ViewDebug.ExportedProperty(deepExport=true, prefix="thumbnail_")
|
||||
TaskViewThumbnail mThumbnailView;
|
||||
@ViewDebug.ExportedProperty(deepExport=true, prefix="header_")
|
||||
@@ -226,9 +225,9 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
// Bind the views
|
||||
mContent = findViewById(R.id.task_view_content);
|
||||
mHeaderView = (TaskViewHeader) findViewById(R.id.task_view_bar);
|
||||
mThumbnailView = (TaskViewThumbnail) findViewById(R.id.task_view_thumbnail);
|
||||
mThumbnailView.updateClipToTaskBar(mHeaderView);
|
||||
mActionButtonView = findViewById(R.id.lock_to_app_fab);
|
||||
mActionButtonView.setOutlineProvider(new ViewOutlineProvider() {
|
||||
@Override
|
||||
@@ -255,6 +254,9 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks
|
||||
if (w > 0 && h > 0) {
|
||||
mHeaderView.onTaskViewSizeChanged(w, h);
|
||||
mThumbnailView.onTaskViewSizeChanged(w, h);
|
||||
|
||||
mActionButtonView.setTranslationX(w - getMeasuredWidth());
|
||||
mActionButtonView.setTranslationY(h - getMeasuredHeight());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,13 +278,11 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks
|
||||
protected void measureContents(int width, int height) {
|
||||
int widthWithoutPadding = width - mPaddingLeft - mPaddingRight;
|
||||
int heightWithoutPadding = height - mPaddingTop - mPaddingBottom;
|
||||
int widthSpec = MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY);
|
||||
int heightSpec = MeasureSpec.makeMeasureSpec(heightWithoutPadding, MeasureSpec.EXACTLY);
|
||||
|
||||
// Measure the content
|
||||
mContent.measure(MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY),
|
||||
MeasureSpec.makeMeasureSpec(heightWithoutPadding, MeasureSpec.EXACTLY));
|
||||
|
||||
// Optimization: Prevent overdraw of the thumbnail under the header view
|
||||
mThumbnailView.updateClipToTaskBar(mHeaderView);
|
||||
measureChildren(widthSpec, heightSpec);
|
||||
|
||||
setMeasuredDimension(width, height);
|
||||
}
|
||||
@@ -346,6 +346,8 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks
|
||||
mActionButtonView.setScaleX(1f);
|
||||
mActionButtonView.setScaleY(1f);
|
||||
mActionButtonView.setAlpha(0f);
|
||||
mActionButtonView.setTranslationX(0f);
|
||||
mActionButtonView.setTranslationY(0f);
|
||||
mActionButtonView.setTranslationZ(mActionButtonTranslationZ);
|
||||
if (mIncompatibleAppToastView != null) {
|
||||
mIncompatibleAppToastView.setVisibility(View.INVISIBLE);
|
||||
|
||||
@@ -350,6 +350,8 @@ public class TaskViewHeader extends FrameLayout
|
||||
}
|
||||
mDismissButton.setVisibility(showDismissIcon ? View.VISIBLE : View.INVISIBLE);
|
||||
mDismissButton.setTranslationX(rightInset);
|
||||
|
||||
setLeftTopRightBottom(0, 0, width, getMeasuredHeight());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -123,6 +123,7 @@ public class TaskViewThumbnail extends View {
|
||||
}
|
||||
|
||||
mTaskViewRect.set(0, 0, width, height);
|
||||
setLeftTopRightBottom(0, 0, width, height);
|
||||
updateThumbnailScale();
|
||||
}
|
||||
|
||||
@@ -148,22 +149,26 @@ public class TaskViewThumbnail extends View {
|
||||
int thumbnailHeight = Math.min(viewHeight,
|
||||
(int) (mThumbnailRect.height() * mThumbnailScale));
|
||||
if (mBitmapShader != null && thumbnailWidth > 0 && thumbnailHeight > 0) {
|
||||
int topOffset = mTaskBar != null
|
||||
? mTaskBar.getHeight() - mCornerRadius
|
||||
: 0;
|
||||
|
||||
// Draw the background, there will be some small overdraw with the thumbnail
|
||||
if (thumbnailWidth < viewWidth) {
|
||||
// Portrait thumbnail on a landscape task view
|
||||
canvas.drawRoundRect(Math.max(0, thumbnailWidth - mCornerRadius), 0,
|
||||
canvas.drawRoundRect(Math.max(0, thumbnailWidth - mCornerRadius), topOffset,
|
||||
viewWidth, viewHeight,
|
||||
mCornerRadius, mCornerRadius, mBgFillPaint);
|
||||
}
|
||||
if (thumbnailHeight < viewHeight) {
|
||||
// Landscape thumbnail on a portrait task view
|
||||
canvas.drawRoundRect(0, Math.max(0, thumbnailHeight - mCornerRadius),
|
||||
canvas.drawRoundRect(0, Math.max(topOffset, thumbnailHeight - mCornerRadius),
|
||||
viewWidth, viewHeight,
|
||||
mCornerRadius, mCornerRadius, mBgFillPaint);
|
||||
}
|
||||
|
||||
// Draw the thumbnail
|
||||
canvas.drawRoundRect(0, 0, thumbnailWidth, thumbnailHeight,
|
||||
canvas.drawRoundRect(0, topOffset, thumbnailWidth, thumbnailHeight,
|
||||
mCornerRadius, mCornerRadius, mDrawPaint);
|
||||
} else {
|
||||
canvas.drawRoundRect(0, 0, viewWidth, viewHeight, mCornerRadius, mCornerRadius,
|
||||
@@ -274,10 +279,7 @@ public class TaskViewThumbnail extends View {
|
||||
/** Updates the clip rect based on the given task bar. */
|
||||
void updateClipToTaskBar(View taskBar) {
|
||||
mTaskBar = taskBar;
|
||||
int top = (int) Math.max(0, taskBar.getTranslationY() +
|
||||
taskBar.getMeasuredHeight() - 1);
|
||||
mClipRect.set(0, top, getMeasuredWidth(), getMeasuredHeight());
|
||||
setClipBounds(mClipRect);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
/** Updates the visibility of the the thumbnail. */
|
||||
|
||||
@@ -19,11 +19,14 @@ package com.android.systemui.recents.views;
|
||||
import android.animation.Animator;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.PropertyValuesHolder;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.util.IntProperty;
|
||||
import android.util.Property;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.systemui.recents.misc.Utilities;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
@@ -31,55 +34,20 @@ import java.util.ArrayList;
|
||||
*/
|
||||
public class TaskViewTransform {
|
||||
|
||||
public static final Property<View, Integer> LEFT =
|
||||
new IntProperty<View>("left") {
|
||||
public static final Property<View, Rect> LTRB =
|
||||
new Property<View, Rect>(Rect.class, "leftTopRightBottom") {
|
||||
|
||||
private Rect mTmpRect = new Rect();
|
||||
|
||||
@Override
|
||||
public void setValue(View object, int v) {
|
||||
object.setLeft(v);
|
||||
public void set(View v, Rect ltrb) {
|
||||
v.setLeftTopRightBottom(ltrb.left, ltrb.top, ltrb.right, ltrb.bottom);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer get(View object) {
|
||||
return object.getLeft();
|
||||
}
|
||||
};
|
||||
|
||||
public static final Property<View, Integer> TOP =
|
||||
new IntProperty<View>("top") {
|
||||
@Override
|
||||
public void setValue(View object, int v) {
|
||||
object.setTop(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer get(View object) {
|
||||
return object.getTop();
|
||||
}
|
||||
};
|
||||
|
||||
public static final Property<View, Integer> RIGHT =
|
||||
new IntProperty<View>("right") {
|
||||
@Override
|
||||
public void setValue(View object, int v) {
|
||||
object.setRight(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer get(View object) {
|
||||
return object.getRight();
|
||||
}
|
||||
};
|
||||
|
||||
public static final Property<View, Integer> BOTTOM =
|
||||
new IntProperty<View>("bottom") {
|
||||
@Override
|
||||
public void setValue(View object, int v) {
|
||||
object.setBottom(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer get(View object) {
|
||||
return object.getBottom();
|
||||
public Rect get(View v) {
|
||||
mTmpRect.set(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
|
||||
return mTmpRect;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -205,11 +173,12 @@ public class TaskViewTransform {
|
||||
animators.add(animation.apply(AnimationProps.ALPHA, anim));
|
||||
}
|
||||
if (hasRectChangedFrom(v)) {
|
||||
Rect fromViewRect = new Rect(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
|
||||
Rect toViewRect = new Rect();
|
||||
rect.round(toViewRect);
|
||||
ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(v,
|
||||
PropertyValuesHolder.ofInt(LEFT, v.getLeft(), (int) rect.left),
|
||||
PropertyValuesHolder.ofInt(TOP, v.getTop(), (int) rect.top),
|
||||
PropertyValuesHolder.ofInt(RIGHT, v.getRight(), (int) rect.right),
|
||||
PropertyValuesHolder.ofInt(BOTTOM, v.getBottom(), (int) rect.bottom));
|
||||
PropertyValuesHolder.ofObject(LTRB, Utilities.RECT_EVALUATOR,
|
||||
fromViewRect, toViewRect));
|
||||
animators.add(animation.apply(AnimationProps.BOUNDS, anim));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user