Merge "Updating the card size logic" into ub-launcher3-master

This commit is contained in:
TreeHugger Robot
2018-04-09 17:20:31 +00:00
committed by Android (Google) Code Review
9 changed files with 189 additions and 191 deletions
@@ -19,13 +19,11 @@ import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS;
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
import static com.android.launcher3.states.RotationHelper.REQUEST_ROTATE;
import android.graphics.Rect;
import android.view.View;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.Workspace;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.quickstep.views.RecentsView;
@@ -47,14 +45,8 @@ public class OverviewState extends LauncherState {
@Override
public float[] getWorkspaceScaleAndTranslation(Launcher launcher) {
Rect pageRect = new Rect();
RecentsView.getPageRect(launcher.getDeviceProfile(), launcher, pageRect);
if (launcher.getWorkspace().getNormalChildWidth() <= 0 || pageRect.isEmpty()) {
return super.getWorkspaceScaleAndTranslation(launcher);
}
return getScaleAndTranslationForPageRect(launcher, pageRect);
// TODO: provide a valid value
return new float[]{1, 0, -launcher.getDeviceProfile().hotseatBarSizePx / 2};
}
@Override
@@ -93,20 +85,6 @@ public class OverviewState extends LauncherState {
};
}
public static float[] getScaleAndTranslationForPageRect(Launcher launcher, Rect pageRect) {
Workspace ws = launcher.getWorkspace();
float childWidth = ws.getNormalChildWidth();
float scale = pageRect.width() / childWidth;
Rect insets = launcher.getDragLayer().getInsets();
float halfHeight = ws.getExpectedHeight() / 2;
float childTop = halfHeight - scale * (halfHeight - ws.getPaddingTop() - insets.top);
float translationY = pageRect.top - childTop;
return new float[] {scale, 0, translationY};
}
@Override
public int getVisibleElements(Launcher launcher) {
if (launcher.getDeviceProfile().isVerticalBarLayout()) {
@@ -44,6 +44,7 @@ import com.android.launcher3.util.ViewOnDrawExecutor;
import com.android.quickstep.fallback.FallbackRecentsView;
import com.android.quickstep.util.RemoteAnimationProvider;
import com.android.quickstep.views.LauncherLayoutListener;
import com.android.quickstep.views.LauncherRecentsView;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -122,7 +123,7 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {
@Override
public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect) {
RecentsView.getPageRect(dp, context, outRect);
LauncherRecentsView.getPageRect(dp, context, outRect);
if (dp.isVerticalBarLayout()) {
Rect targetInsets = dp.getInsets();
int hotseatInset = dp.isSeascape() ? targetInsets.left : targetInsets.right;
@@ -271,7 +272,7 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {
@Override
public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect) {
FallbackRecentsView.getCenterPageRect(dp, context, outRect);
FallbackRecentsView.getPageRect(dp, context, outRect);
if (dp.isVerticalBarLayout()) {
Rect targetInsets = dp.getInsets();
int hotseatInset = dp.isSeascape() ? targetInsets.left : targetInsets.right;
@@ -18,15 +18,16 @@ package com.android.quickstep.fallback;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.support.annotation.AnyThread;
import android.util.AttributeSet;
import android.view.View;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Insettable;
import com.android.quickstep.RecentsActivity;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.views.RecentsView;
public class FallbackRecentsView extends RecentsView<RecentsActivity> implements Insettable {
public class FallbackRecentsView extends RecentsView<RecentsActivity> {
public FallbackRecentsView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
@@ -55,31 +56,19 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity> implements
updateEmptyMessage();
}
@Override
public void setInsets(Rect insets) {
mInsets.set(insets);
DeviceProfile dp = mActivity.getDeviceProfile();
Rect padding = getPadding(dp, getContext());
verticalCenter(padding, dp);
setPadding(padding.left, padding.top, padding.right, padding.bottom);
}
private static void verticalCenter(Rect padding, DeviceProfile dp) {
Rect insets = dp.getInsets();
int totalSpace = (padding.top + padding.bottom - insets.top - insets.bottom) / 2;
padding.top = insets.top + totalSpace;
padding.bottom = insets.bottom + totalSpace;
}
public static void getCenterPageRect(DeviceProfile grid, Context context, Rect outRect) {
Rect targetPadding = getPadding(grid, context);
verticalCenter(targetPadding, grid);
getPageRect(grid, context, outRect, targetPadding);
}
@Override
public void draw(Canvas canvas) {
maybeDrawEmptyMessage(canvas);
super.draw(canvas);
}
@Override
protected void getTaskSize(DeviceProfile dp, Rect outRect) {
LayoutUtils.calculateTaskSize(getContext(), dp, 0, outRect);
}
@AnyThread
public static void getPageRect(DeviceProfile grid, Context context, Rect outRect) {
LayoutUtils.calculateTaskSize(context, grid, 0, outRect);
}
}
@@ -0,0 +1,84 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.quickstep.util;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Rect;
import android.graphics.RectF;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
public class LayoutUtils {
public static void calculateLauncherTaskSize(Context context, DeviceProfile dp, Rect outRect) {
float extraSpace = dp.isVerticalBarLayout() ? 0 : dp.hotseatBarSizePx;
calculateTaskSize(context, dp, extraSpace, outRect);
}
public static void calculateTaskSize(Context context, DeviceProfile dp,
float extraVerticalSpace, Rect outRect) {
float taskWidth, taskHeight, paddingHorz;
Resources res = context.getResources();
Rect insets = dp.getInsets();
if (dp.isMultiWindowMode) {
DeviceProfile fullDp = dp.getFullScreenProfile();
// Use availableWidthPx and availableHeightPx instead of widthPx and heightPx to
// account for system insets
taskWidth = fullDp.availableWidthPx;
taskHeight = fullDp.availableHeightPx;
float halfDividerSize = res.getDimension(R.dimen.multi_window_task_divider_size) / 2;
if (fullDp.isLandscape) {
taskWidth = taskWidth / 2 - halfDividerSize;
} else {
taskHeight = taskHeight / 2 - halfDividerSize;
}
paddingHorz = res.getDimension(R.dimen.multi_window_task_card_horz_space);
} else {
taskWidth = dp.availableWidthPx;
taskHeight = dp.availableHeightPx;
paddingHorz = res.getDimension(dp.isVerticalBarLayout()
? R.dimen.landscape_task_card_horz_space
: R.dimen.portrait_task_card_horz_space);
}
float topIconMargin = res.getDimension(R.dimen.task_thumbnail_top_margin);
float paddingVert = res.getDimension(R.dimen.task_card_vert_space);
// Note this should be same as dp.availableWidthPx and dp.availableHeightPx unless
// we override the insets ourselves.
int launcherVisibleWidth = dp.widthPx - insets.left - insets.right;
int launcherVisibleHeight = dp.heightPx - insets.top - insets.bottom;
float availableHeight = launcherVisibleHeight
- topIconMargin - extraVerticalSpace - paddingVert;
float availableWidth = launcherVisibleWidth - paddingHorz;
float scale = Math.min(availableWidth / taskWidth, availableHeight / taskHeight);
float outWidth = scale * taskWidth;
float outHeight = scale * taskHeight;
// Center in the visible space
float x = insets.left + (taskWidth - outWidth) / 2;
float y = insets.top + Math.max(topIconMargin,
(launcherVisibleHeight - extraVerticalSpace - outHeight) / 2);
outRect.set(Math.round(x), Math.round(y),
Math.round(x + outWidth), Math.round(y + outHeight));
}
}
@@ -27,22 +27,22 @@ import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.os.Build;
import android.support.annotation.AnyThread;
import android.util.AttributeSet;
import android.util.FloatProperty;
import android.view.View;
import android.view.ViewDebug;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Insettable;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.quickstep.util.LayoutUtils;
/**
* {@link RecentsView} used in Launcher activity
*/
@TargetApi(Build.VERSION_CODES.O)
public class LauncherRecentsView extends RecentsView<Launcher> implements Insettable {
public class LauncherRecentsView extends RecentsView<Launcher> {
public static final FloatProperty<LauncherRecentsView> TRANSLATION_Y_FACTOR =
new FloatProperty<LauncherRecentsView>("translationYFactor") {
@@ -61,8 +61,6 @@ public class LauncherRecentsView extends RecentsView<Launcher> implements Insett
@ViewDebug.ExportedProperty(category = "launcher")
private float mTranslationYFactor;
private Rect mPagePadding = new Rect();
public LauncherRecentsView(Context context) {
this(context, null);
}
@@ -76,16 +74,6 @@ public class LauncherRecentsView extends RecentsView<Launcher> implements Insett
setContentAlpha(0);
}
@Override
public void setInsets(Rect insets) {
mInsets.set(insets);
DeviceProfile dp = mActivity.getDeviceProfile();
Rect padding = getPadding(dp, getContext());
setPadding(padding.left, padding.top, padding.right, padding.bottom);
mPagePadding.set(padding);
mPagePadding.top += getResources().getDimensionPixelSize(R.dimen.task_thumbnail_top_margin);
}
@Override
protected void onAllTasksRemoved() {
mActivity.getStateManager().goToState(NORMAL);
@@ -99,7 +87,7 @@ public class LauncherRecentsView extends RecentsView<Launcher> implements Insett
public void setTranslationYFactor(float translationFactor) {
mTranslationYFactor = translationFactor;
setTranslationY(mTranslationYFactor * (mPagePadding.bottom - mPagePadding.top));
setTranslationY(mTranslationYFactor * (getPaddingBottom() - getPaddingTop()));
}
@Override
@@ -138,4 +126,14 @@ public class LauncherRecentsView extends RecentsView<Launcher> implements Insett
mActivity.getAllAppsController(), ALL_APPS_PROGRESS, allAppsProgressOffscreen));
return anim;
}
@Override
protected void getTaskSize(DeviceProfile dp, Rect outRect) {
LayoutUtils.calculateLauncherTaskSize(getContext(), dp, outRect);
}
@AnyThread
public static void getPageRect(DeviceProfile grid, Context context, Rect outRect) {
LayoutUtils.calculateLauncherTaskSize(context, grid, outRect);
}
}
@@ -53,6 +53,7 @@ import android.view.accessibility.AccessibilityEvent;
import com.android.launcher3.BaseActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Insettable;
import com.android.launcher3.PagedView;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
@@ -75,7 +76,6 @@ import com.android.systemui.shared.recents.model.TaskStack;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.WindowManagerWrapper;
import java.util.ArrayList;
@@ -84,7 +84,9 @@ import java.util.ArrayList;
*/
@TargetApi(Build.VERSION_CODES.P)
public abstract class RecentsView<T extends BaseActivity>
extends PagedView implements OnSharedPreferenceChangeListener {
extends PagedView implements OnSharedPreferenceChangeListener, Insettable {
private final Rect mTempRect = new Rect();
public static final FloatProperty<RecentsView> CONTENT_ALPHA =
new FloatProperty<RecentsView>("contentAlpha") {
@@ -99,8 +101,6 @@ public abstract class RecentsView<T extends BaseActivity>
}
};
public static final FloatProperty<RecentsView> ADJACENT_SCALE =
new FloatProperty<RecentsView>("adjacentScale") {
@Override
@@ -116,8 +116,6 @@ public abstract class RecentsView<T extends BaseActivity>
private static final String PREF_FLIP_RECENTS = "pref_flip_recents";
private static final int DISMISS_TASK_DURATION = 300;
private static final Rect sTempStableInsets = new Rect();
protected final T mActivity;
private final QuickScrubController mQuickScrubController;
private final float mFastFlingVelocity;
@@ -397,69 +395,20 @@ public abstract class RecentsView<T extends BaseActivity>
}
}
protected static Rect getPadding(DeviceProfile profile, Context context) {
WindowManagerWrapper.getInstance().getStableInsets(sTempStableInsets);
Rect padding = new Rect(profile.workspacePadding);
float taskWidth = profile.widthPx - sTempStableInsets.left - sTempStableInsets.right;
float taskHeight = profile.heightPx - sTempStableInsets.top - sTempStableInsets.bottom;
float overviewHeight, overviewWidth;
if (profile.isVerticalBarLayout()) {
float maxPadding = Math.max(padding.left, padding.right);
// Use the same padding on both sides for symmetry.
float availableWidth = taskWidth - 2 * maxPadding;
float availableHeight = profile.availableHeightPx - padding.top - padding.bottom
- sTempStableInsets.top;
float scaledRatio = Math.min(availableWidth / taskWidth, availableHeight / taskHeight);
overviewHeight = taskHeight * scaledRatio;
overviewWidth = taskWidth * scaledRatio;
} else {
overviewHeight = profile.availableHeightPx - padding.top - padding.bottom
- sTempStableInsets.top;
overviewWidth = taskWidth * overviewHeight / taskHeight;
}
padding.bottom = profile.availableHeightPx - padding.top - sTempStableInsets.top
- Math.round(overviewHeight);
padding.left = padding.right = (int) ((profile.availableWidthPx - overviewWidth) / 2);
// If the height ratio is larger than the width ratio, the screenshot will get cropped
// at the bottom when swiping up. In this case, increase the top/bottom padding to make it
// the same aspect ratio.
Rect pageRect = new Rect();
getPageRect(profile, context, pageRect, padding);
float widthRatio = (float) pageRect.width() / taskWidth;
float heightRatio = (float) pageRect.height() / taskHeight;
if (heightRatio > widthRatio) {
float additionalVerticalPadding = pageRect.height() - widthRatio * taskHeight;
additionalVerticalPadding = Math.round(additionalVerticalPadding);
padding.top += additionalVerticalPadding / 2;
padding.bottom += additionalVerticalPadding / 2;
}
return padding;
}
public static void getPageRect(DeviceProfile grid, Context context, Rect outRect) {
Rect targetPadding = getPadding(grid, context);
getPageRect(grid, context, outRect, targetPadding);
}
protected static void getPageRect(DeviceProfile grid, Context context, Rect outRect,
Rect targetPadding) {
Rect insets = grid.getInsets();
outRect.set(
targetPadding.left + insets.left,
targetPadding.top + insets.top,
grid.widthPx - targetPadding.right - insets.right,
grid.heightPx - targetPadding.bottom - insets.bottom);
outRect.top += context.getResources()
@Override
public void setInsets(Rect insets) {
mInsets.set(insets);
DeviceProfile dp = mActivity.getDeviceProfile();
getTaskSize(dp, mTempRect);
mTempRect.top -= getResources()
.getDimensionPixelSize(R.dimen.task_thumbnail_top_margin);
setPadding(mTempRect.left - mInsets.left, mTempRect.top - mInsets.top,
dp.widthPx - mTempRect.right - mInsets.right,
dp.heightPx - mTempRect.bottom - mInsets.bottom);
}
protected abstract void getTaskSize(DeviceProfile dp, Rect outRect);
@Override
protected boolean computeScrollHelper() {
boolean scrolling = super.computeScrollHelper();
@@ -22,12 +22,9 @@ import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ComposeShader;
import android.graphics.LightingColorFilter;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.Rect;
import android.graphics.Shader;
import android.util.AttributeSet;
@@ -50,14 +47,16 @@ public class TaskThumbnailView extends View {
private static final LightingColorFilter[] sDimFilterCache = new LightingColorFilter[256];
private final float mCornerRadius;
private final float mFadeLength;
private final BaseActivity mActivity;
private final TaskOverlay mOverlay;
private final Paint mPaint = new Paint();
private final Paint mLockedPaint = new Paint();
private final Paint mBackgroundPaint = new Paint();
private final Matrix mMatrix = new Matrix();
private float mClipBottom = -1;
private Task mTask;
private ThumbnailData mThumbnailData;
protected BitmapShader mBitmapShader;
@@ -75,10 +74,10 @@ public class TaskThumbnailView extends View {
public TaskThumbnailView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mCornerRadius = getResources().getDimension(R.dimen.task_corner_radius);
mFadeLength = getResources().getDimension(R.dimen.task_fade_length);
mOverlay = TaskOverlayFactory.get(context).createOverlay(this);
mPaint.setFilterBitmap(true);
mLockedPaint.setColor(Color.WHITE);
mBackgroundPaint.setColor(Color.WHITE);
mActivity = BaseActivity.fromContext(context);
}
public void bind() {
@@ -90,7 +89,9 @@ public class TaskThumbnailView extends View {
*/
public void setThumbnail(Task task, ThumbnailData thumbnailData) {
mTask = task;
mPaint.setColor(task == null ? Color.BLACK : task.colorBackground | 0xFF000000);
int color = task == null ? Color.BLACK : task.colorBackground | 0xFF000000;
mPaint.setColor(color);
mBackgroundPaint.setColor(color);
if (thumbnailData != null && thumbnailData.thumbnail != null) {
Bitmap bm = thumbnailData.thumbnail;
@@ -128,8 +129,23 @@ public class TaskThumbnailView extends View {
if (mTask == null) {
return;
}
canvas.drawRoundRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mCornerRadius,
mCornerRadius, mTask.isLocked ? mLockedPaint : mPaint);
int width = getMeasuredWidth();
int height = getMeasuredHeight();
if (mClipBottom > 0 && !mTask.isLocked) {
canvas.save();
canvas.clipRect(0, 0, width, mClipBottom);
canvas.drawRoundRect(0, 0, width, height, mCornerRadius, mCornerRadius, mPaint);
canvas.restore();
canvas.save();
canvas.clipRect(0, mClipBottom, width, height);
canvas.drawRoundRect(0, 0, width, height, mCornerRadius, mCornerRadius,
mBackgroundPaint);
canvas.restore();
} else {
canvas.drawRoundRect(0, 0, width, height, mCornerRadius,
mCornerRadius, mTask.isLocked ? mBackgroundPaint : mPaint);
}
}
private void updateThumbnailPaintFilter() {
@@ -137,7 +153,7 @@ public class TaskThumbnailView extends View {
if (mBitmapShader != null) {
LightingColorFilter filter = getLightingColorFilter(mul);
mPaint.setColorFilter(filter);
mLockedPaint.setColorFilter(filter);
mBackgroundPaint.setColorFilter(filter);
} else {
mPaint.setColorFilter(null);
mPaint.setColor(Color.argb(255, mul, mul, mul));
@@ -147,47 +163,38 @@ public class TaskThumbnailView extends View {
private void updateThumbnailMatrix() {
boolean rotate = false;
mClipBottom = -1;
if (mBitmapShader != null && mThumbnailData != null) {
float scale = mThumbnailData.scale;
Rect thumbnailInsets = mThumbnailData.insets;
float thumbnailWidth = mThumbnailData.thumbnail.getWidth() -
(mThumbnailData.insets.left + mThumbnailData.insets.right) * scale;
(thumbnailInsets.left + thumbnailInsets.right) * scale;
float thumbnailHeight = mThumbnailData.thumbnail.getHeight() -
(mThumbnailData.insets.top + mThumbnailData.insets.bottom) * scale;
(thumbnailInsets.top + thumbnailInsets.bottom) * scale;
final float thumbnailScale;
final DeviceProfile profile = BaseActivity.fromContext(getContext())
.getDeviceProfile();
final DeviceProfile profile = mActivity.getDeviceProfile();
if (getMeasuredWidth() == 0) {
// If we haven't measured , skip the thumbnail drawing and only draw the background
// color
thumbnailScale = 0f;
} else {
final Configuration configuration =
getContext().getApplicationContext().getResources().getConfiguration();
if (configuration.orientation == mThumbnailData.orientation) {
// If we are in the same orientation as the screenshot, just scale it to the
// width of the task view
thumbnailScale = getMeasuredWidth() / thumbnailWidth;
} else {
if (FeatureFlags.OVERVIEW_USE_SCREENSHOT_ORIENTATION) {
rotate = true;
// Scale the height (will be width after rotation) to the width of this view
thumbnailScale = getMeasuredWidth() / thumbnailHeight;
} else {
if (configuration.orientation == Configuration.ORIENTATION_PORTRAIT) {
// Scale the landscape thumbnail up to app size, then scale that to the
// task view size to match other portrait screenshots
thumbnailScale = ((float) getMeasuredWidth() / profile.widthPx);
} else {
// Otherwise, scale the screenshot to fit 1:1 in the current orientation
thumbnailScale = 1;
}
}
}
getContext().getResources().getConfiguration();
// Rotate the screenshot if not in multi-window mode
rotate = FeatureFlags.OVERVIEW_USE_SCREENSHOT_ORIENTATION &&
configuration.orientation != mThumbnailData.orientation &&
!mActivity.isInMultiWindowModeCompat();
// Scale the screenshot to always fit the width of the card.
thumbnailScale = rotate
? getMeasuredWidth() / thumbnailHeight
: getMeasuredWidth() / thumbnailWidth;
}
if (rotate) {
int rotationDir = profile.isVerticalBarLayout() && !profile.isSeascape() ? -1 : 1;
mMatrix.setRotate(90 * rotationDir);
Rect thumbnailInsets = mThumbnailData.insets;
int newLeftInset = rotationDir == 1 ? thumbnailInsets.bottom : thumbnailInsets.top;
int newTopInset = rotationDir == 1 ? thumbnailInsets.left : thumbnailInsets.right;
mMatrix.postTranslate(-newLeftInset * scale, -newTopInset * scale);
@@ -209,27 +216,11 @@ public class TaskThumbnailView extends View {
mMatrix.postScale(thumbnailScale, thumbnailScale);
mBitmapShader.setLocalMatrix(mMatrix);
Shader shader = mBitmapShader;
if (!FeatureFlags.OVERVIEW_USE_SCREENSHOT_ORIENTATION) {
float bitmapHeight = Math.max(thumbnailHeight * thumbnailScale, 0);
if (Math.round(bitmapHeight) < getMeasuredHeight()) {
int color = mPaint.getColor();
LinearGradient fade = new LinearGradient(
0, bitmapHeight - mFadeLength, 0, bitmapHeight,
color & 0x00FFFFFF, color, Shader.TileMode.CLAMP);
shader = new ComposeShader(fade, shader, Mode.DST_OVER);
}
float bitmapWidth = Math.max(thumbnailWidth * thumbnailScale, 0);
if (Math.round(bitmapWidth) < getMeasuredWidth()) {
int color = mPaint.getColor();
LinearGradient fade = new LinearGradient(
bitmapWidth - mFadeLength, 0, bitmapWidth, 0,
color & 0x00FFFFFF, color, Shader.TileMode.CLAMP);
shader = new ComposeShader(fade, shader, Mode.DST_OVER);
}
float bitmapHeight = Math.max(thumbnailHeight * thumbnailScale, 0);
if (Math.round(bitmapHeight) < getMeasuredHeight()) {
mClipBottom = bitmapHeight;
}
mPaint.setShader(shader);
mPaint.setShader(mBitmapShader);
}
if (rotate) {