Merge "Fixing various layout issues when docking" into nyc-dev

This commit is contained in:
Winson Chung
2016-04-14 17:51:52 +00:00
committed by Android (Google) Code Review
14 changed files with 186 additions and 215 deletions

View File

@@ -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>

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -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.
*/

View File

@@ -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 {

View File

@@ -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);
}
}

View File

@@ -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 */);
}
};

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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

View File

@@ -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. */

View File

@@ -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));
}
}