Merge "2D Recents: round task thumbnails properly." into nyc-mr2-dev

This commit is contained in:
TreeHugger Robot
2017-01-20 04:05:27 +00:00
committed by Android (Google) Code Review
9 changed files with 210 additions and 16 deletions

View File

@@ -15,5 +15,5 @@
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#61FFFFFF" />
<corners android:radius="8dp"/>
<corners android:radius="@dimen/recents_grid_task_view_rounded_corners_radius"/>
</shape>

View File

@@ -18,7 +18,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="true">
<com.android.systemui.recents.views.TaskViewThumbnail
<com.android.systemui.recents.views.grid.GridTaskViewThumbnail
android:id="@+id/task_view_thumbnail"
android:layout_width="match_parent"
android:layout_height="match_parent" />

View File

@@ -22,5 +22,6 @@
<dimen name="recents_grid_task_view_header_height">44dp</dimen>
<dimen name="recents_grid_task_view_header_button_padding">8dp</dimen>
<dimen name="recents_grid_task_view_focused_frame_thickness">8dp</dimen>
<dimen name="recents_grid_task_view_rounded_corners_radius">8dp</dimen>
</resources>

View File

@@ -30,6 +30,7 @@ import android.graphics.drawable.Drawable;
import android.util.Log;
import com.android.systemui.R;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsConfiguration;
/**
@@ -90,8 +91,10 @@ class FakeShadowDrawable extends Drawable {
mCornerShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
mCornerShadowPaint.setStyle(Paint.Style.FILL);
mCornerShadowPaint.setDither(true);
mCornerRadius = resources.getDimensionPixelSize(
R.dimen.recents_task_view_rounded_corners_radius);
mCornerRadius = Recents.getConfiguration().isGridEnabled ?
resources.getDimensionPixelSize(
R.dimen.recents_grid_task_view_rounded_corners_radius) :
resources.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius);
mCardBounds = new RectF();
mEdgeShadowPaint = new Paint(mCornerShadowPaint);
}

View File

@@ -266,8 +266,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
mStackScroller = new TaskStackViewScroller(context, this, mLayoutAlgorithm);
mTouchHandler = new TaskStackViewTouchHandler(context, this, mStackScroller);
mAnimationHelper = new TaskStackAnimationHelper(context, this);
mTaskCornerRadiusPx = res.getDimensionPixelSize(
R.dimen.recents_task_view_rounded_corners_radius);
mTaskCornerRadiusPx = Recents.getConfiguration().isGridEnabled ?
res.getDimensionPixelSize(R.dimen.recents_grid_task_view_rounded_corners_radius) :
res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius);
mDividerSize = ssp.getDockedDividerSize(context);
mDisplayOrientation = Utilities.getAppConfiguration(mContext).orientation;
mDisplayRect = ssp.getDisplayRect();

View File

@@ -201,7 +201,9 @@ public class TaskViewHeader extends FrameLayout
Resources res = context.getResources();
mLightDismissDrawable = context.getDrawable(R.drawable.recents_dismiss_light);
mDarkDismissDrawable = context.getDrawable(R.drawable.recents_dismiss_dark);
mCornerRadius = res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius);
mCornerRadius = Recents.getConfiguration().isGridEnabled ?
res.getDimensionPixelSize(R.dimen.recents_grid_task_view_rounded_corners_radius) :
res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius);
mHighlightHeight = res.getDimensionPixelSize(R.dimen.recents_task_view_highlight);
mTaskBarViewLightTextColor = context.getColor(R.color.recents_task_bar_light_text_color);
mTaskBarViewDarkTextColor = context.getColor(R.color.recents_task_bar_dark_text_color);

View File

@@ -58,11 +58,11 @@ public class TaskViewThumbnail extends View {
// Drawing
@ViewDebug.ExportedProperty(category="recents")
private Rect mTaskViewRect = new Rect();
protected Rect mTaskViewRect = new Rect();
@ViewDebug.ExportedProperty(category="recents")
private Rect mThumbnailRect = new Rect();
protected Rect mThumbnailRect = new Rect();
@ViewDebug.ExportedProperty(category="recents")
private float mThumbnailScale;
protected float mThumbnailScale;
private float mFullscreenThumbnailScale;
/** The height, in pixels, of the task view's title bar. */
private int mTitleBarHeight;
@@ -70,13 +70,13 @@ public class TaskViewThumbnail extends View {
private boolean mOverlayHeaderOnThumbnailActionBar = true;
private ActivityManager.TaskThumbnailInfo mThumbnailInfo;
private int mCornerRadius;
protected int mCornerRadius;
@ViewDebug.ExportedProperty(category="recents")
private float mDimAlpha;
private Matrix mScaleMatrix = new Matrix();
private Paint mDrawPaint = new Paint();
private Paint mBgFillPaint = new Paint();
private BitmapShader mBitmapShader;
protected Paint mDrawPaint = new Paint();
protected Paint mBgFillPaint = new Paint();
protected BitmapShader mBitmapShader;
private LightingColorFilter mLightingColorFilter = new LightingColorFilter(0xffffffff, 0);
// Clip the top of the thumbnail against the opaque header bar that overlaps this view

View File

@@ -0,0 +1,185 @@
/*
* 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.systemui.recents.views.grid;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Path;
import android.util.AttributeSet;
import com.android.systemui.R;
import com.android.systemui.recents.views.TaskViewThumbnail;
public class GridTaskViewThumbnail extends TaskViewThumbnail {
private Path mThumbnailOutline;
private Path mRestBackgroundOutline;
private Path mFullBackgroundOutline;
// True if either this view's size or thumbnail scale has changed and mThumbnailOutline should
// be updated.
private boolean mUpdateThumbnailOutline = true;
public GridTaskViewThumbnail(Context context) {
this(context, null);
}
public GridTaskViewThumbnail(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public GridTaskViewThumbnail(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
public GridTaskViewThumbnail(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
mCornerRadius = getResources().getDimensionPixelSize(
R.dimen.recents_grid_task_view_rounded_corners_radius);
}
/**
* Called when the task view frame changes, allowing us to move the contents of the header
* to match the frame changes.
*/
public void onTaskViewSizeChanged(int width, int height) {
mUpdateThumbnailOutline = true;
super.onTaskViewSizeChanged(width, height);
}
/**
* Updates the scale of the bitmap relative to this view.
*/
public void updateThumbnailScale() {
mUpdateThumbnailOutline = true;
super.updateThumbnailScale();
}
private void updateThumbnailOutline() {
final int titleHeight = getResources().getDimensionPixelSize(
R.dimen.recents_grid_task_view_header_height);
final int viewWidth = mTaskViewRect.width();
final int viewHeight = mTaskViewRect.height() - titleHeight;
final int thumbnailWidth = Math.min(viewWidth,
(int) (mThumbnailRect.width() * mThumbnailScale));
final int thumbnailHeight = Math.min(viewHeight,
(int) (mThumbnailRect.height() * mThumbnailScale));
// Draw the thumbnail, we only round the bottom corners:
//
// outerLeft outerRight
// <-----------------------> mRestBackgroundOutline
// _________________________ (thumbnailWidth < viewWidth)
// |_______________________| outerTop A ____ B
// | | ↑ | |
// | | | | |
// | | | | |
// | | | | | C
// \_______________________/ ↓ |__/
// mCornerRadius outerBottom E D
//
// mRestBackgroundOutline (thumbnailHeight < viewHeight)
// A _________________________ B
// | | C
// F \_______________________/
// E D
final int outerLeft = 0;
final int outerTop = 0;
final int outerRight = outerLeft + thumbnailWidth;
final int outerBottom = outerTop + thumbnailHeight;
mThumbnailOutline = new Path();
mThumbnailOutline.moveTo(outerLeft, outerTop);
mThumbnailOutline.lineTo(outerRight, outerTop);
mThumbnailOutline.lineTo(outerRight, outerBottom - mCornerRadius);
mThumbnailOutline.arcTo(outerRight - 2 * mCornerRadius, outerBottom - 2 * mCornerRadius,
outerRight, outerBottom, 0, 90, false);
mThumbnailOutline.lineTo(outerLeft + mCornerRadius, outerBottom);
mThumbnailOutline.arcTo(outerLeft, outerBottom - 2 * mCornerRadius,
outerLeft + 2 * mCornerRadius, outerBottom, 90, 90, false);
mThumbnailOutline.lineTo(outerLeft, outerTop);
mThumbnailOutline.close();
if (mBitmapShader != null && thumbnailWidth > 0 && thumbnailHeight > 0) {
if (thumbnailWidth < viewWidth) {
final int l = Math.max(0, outerRight - mCornerRadius);
final int r = outerRight;
final int t = outerTop;
final int b = outerBottom;
mRestBackgroundOutline = new Path();
mRestBackgroundOutline.moveTo(l, t); // A
mRestBackgroundOutline.lineTo(r, t); // B
mRestBackgroundOutline.lineTo(r, b - mCornerRadius); // C
mRestBackgroundOutline.arcTo(r - 2 * mCornerRadius, b - 2 * mCornerRadius, r, b,
0, 90, false); // D
mRestBackgroundOutline.lineTo(l, b); // E
mRestBackgroundOutline.lineTo(l, t); // A
mRestBackgroundOutline.close();
}
if (thumbnailHeight < viewHeight) {
final int l = outerLeft;
final int r = outerRight;
final int t = Math.max(0, thumbnailHeight - mCornerRadius);
final int b = outerBottom;
mRestBackgroundOutline = new Path();
mRestBackgroundOutline.moveTo(l, t); // A
mRestBackgroundOutline.lineTo(r, t); // B
mRestBackgroundOutline.lineTo(r, b - mCornerRadius); // C
mRestBackgroundOutline.arcTo(r - 2 * mCornerRadius, b - 2 * mCornerRadius, r, b,
0, 90, false); // D
mRestBackgroundOutline.lineTo(l + mCornerRadius, b); // E
mRestBackgroundOutline.arcTo(l, b - 2 * mCornerRadius, l + 2 * mCornerRadius, b,
90, 90, false); // F
mRestBackgroundOutline.lineTo(l, t); // A
mRestBackgroundOutline.close();
}
} else {
mFullBackgroundOutline = mThumbnailOutline;
}
}
@Override
protected void onDraw(Canvas canvas) {
final int titleHeight = getResources().getDimensionPixelSize(
R.dimen.recents_grid_task_view_header_height);
final int viewWidth = mTaskViewRect.width();
final int viewHeight = mTaskViewRect.height() - titleHeight;
final int thumbnailWidth = Math.min(viewWidth,
(int) (mThumbnailRect.width() * mThumbnailScale));
final int thumbnailHeight = Math.min(viewHeight,
(int) (mThumbnailRect.height() * mThumbnailScale));
if (mUpdateThumbnailOutline) {
updateThumbnailOutline();
mUpdateThumbnailOutline = false;
}
if (mBitmapShader != null && thumbnailWidth > 0 && thumbnailHeight > 0) {
// Draw the background, there will be some small overdraw with the thumbnail
if (thumbnailWidth < viewWidth) {
// Portrait thumbnail on a landscape task view
canvas.drawPath(mRestBackgroundOutline, mBgFillPaint);
}
if (thumbnailHeight < viewHeight) {
// Landscape thumbnail on a portrait task view
canvas.drawPath(mRestBackgroundOutline, mBgFillPaint);
}
canvas.drawPath(mThumbnailOutline, mDrawPaint);
} else {
canvas.drawPath(mFullBackgroundOutline, mBgFillPaint);
}
}
}

View File

@@ -105,11 +105,13 @@ public class TaskGridLayoutAlgorithm {
if (maxTaskHeight >= maxTaskWidth / mAppAspectRatio + mTitleBarHeight) {
// Width bound.
taskWidth = maxTaskWidth;
taskHeight = (int) (maxTaskWidth / mAppAspectRatio + mTitleBarHeight);
// Here we should round the height to the nearest integer.
taskHeight = (int) (maxTaskWidth / mAppAspectRatio + mTitleBarHeight + 0.5);
} else {
// Height bound.
taskHeight = maxTaskHeight;
taskWidth = (int) ((taskHeight - mTitleBarHeight) * mAppAspectRatio);
// Here we should round the width to the nearest integer.
taskWidth = (int) ((taskHeight - mTitleBarHeight) * mAppAspectRatio + 0.5);
}
size.set(0, 0, taskWidth, taskHeight);