下面列出了android.graphics.Rect#isEmpty ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private boolean drawGestureTrails(final Canvas offscreenCanvas, final Paint paint,
final Rect dirtyRect) {
// Clear previous dirty rectangle.
if (!dirtyRect.isEmpty()) {
paint.setColor(Color.TRANSPARENT);
paint.setStyle(Paint.Style.FILL);
offscreenCanvas.drawRect(dirtyRect, paint);
}
dirtyRect.setEmpty();
boolean needsUpdatingGestureTrail = false;
// Draw gesture trails to offscreen buffer.
synchronized (mGestureTrails) {
// Trails count == fingers count that have ever been active.
final int trailsCount = mGestureTrails.size();
for (int index = 0; index < trailsCount; index++) {
final GestureTrailDrawingPoints trail = mGestureTrails.valueAt(index);
needsUpdatingGestureTrail |= trail.drawGestureTrail(offscreenCanvas, paint,
mGestureTrailBoundsRect, mDrawingParams);
// {@link #mGestureTrailBoundsRect} has bounding box of the trail.
dirtyRect.union(mGestureTrailBoundsRect);
}
}
return needsUpdatingGestureTrail;
}
private boolean drawGestureTrails(final Canvas offscreenCanvas, final Paint paint,
final Rect dirtyRect) {
// Clear previous dirty rectangle.
if (!dirtyRect.isEmpty()) {
paint.setColor(Color.TRANSPARENT);
paint.setStyle(Paint.Style.FILL);
offscreenCanvas.drawRect(dirtyRect, paint);
}
dirtyRect.setEmpty();
boolean needsUpdatingGestureTrail = false;
// Draw gesture trails to offscreen buffer.
synchronized (mGestureTrails) {
// Trails count == fingers count that have ever been active.
final int trailsCount = mGestureTrails.size();
for (int index = 0; index < trailsCount; index++) {
final GestureTrailDrawingPoints trail = mGestureTrails.valueAt(index);
needsUpdatingGestureTrail |= trail.drawGestureTrail(offscreenCanvas, paint,
mGestureTrailBoundsRect, mDrawingParams);
// {@link #mGestureTrailBoundsRect} has bounding box of the trail.
dirtyRect.union(mGestureTrailBoundsRect);
}
}
return needsUpdatingGestureTrail;
}
private void setupPreviousMountableOutputData(Rect localVisibleRect) {
if (localVisibleRect.isEmpty()) {
return;
}
final List<RenderTreeNode> layoutOutputTops = mInput.getMountableOutputTops();
final List<RenderTreeNode> layoutOutputBottoms = mInput.getMountableOutputBottoms();
final int mountableOutputCount = mInput.getMountableOutputCount();
mPreviousTopsIndex = mInput.getMountableOutputCount();
for (int i = 0; i < mountableOutputCount; i++) {
if (localVisibleRect.bottom <= layoutOutputTops.get(i).getBounds().top) {
mPreviousTopsIndex = i;
break;
}
}
mPreviousBottomsIndex = mInput.getMountableOutputCount();
for (int i = 0; i < mountableOutputCount; i++) {
if (localVisibleRect.top < layoutOutputBottoms.get(i).getBounds().bottom) {
mPreviousBottomsIndex = i;
break;
}
}
}
private void updateDrawMatrix(@NonNull final Rect bounds) {
if (mBitmap == null || bounds.isEmpty()) {
mDrawMatrix.reset();
return;
}
// FIXME mRotationDegreeを考慮して計算しないといけない
MatrixUtils.updateDrawMatrix(MatrixUtils.ScaleType.CENTER_CROP,
mDrawMatrix,
bounds.width(), bounds.height(),
mBitmap.getWidth(), mBitmap.getHeight());
invalidateSelf();
}
/**
* Called to swap out the current view with the one passed in.
*
* @param newContentViewCore The content view that should be swapped into the tab.
* @param deleteOldNativeWebContents Whether to delete the native web
* contents of old view.
* @param didStartLoad Whether
* WebContentsObserver::DidStartProvisionalLoadForFrame() has
* already been called.
* @param didFinishLoad Whether WebContentsObserver::DidFinishLoad() has
* already been called.
*/
public void swapContentViewCore(ContentViewCore newContentViewCore,
boolean deleteOldNativeWebContents, boolean didStartLoad, boolean didFinishLoad) {
int originalWidth = 0;
int originalHeight = 0;
if (mContentViewCore != null) {
originalWidth = mContentViewCore.getViewportWidthPix();
originalHeight = mContentViewCore.getViewportHeightPix();
mContentViewCore.onHide();
}
Rect bounds = new Rect();
if (originalWidth == 0 && originalHeight == 0) {
bounds = ExternalPrerenderHandler.estimateContentSize(
(Application) getApplicationContext(), false);
originalWidth = bounds.right - bounds.left;
originalHeight = bounds.bottom - bounds.top;
}
destroyContentViewCore(deleteOldNativeWebContents);
NativePage previousNativePage = mNativePage;
mNativePage = null;
// Size of the new ContentViewCore is zero at this point. If we don't call onSizeChanged(),
// next onShow() call would send a resize message with the current ContentViewCore size
// (zero) to the renderer process, although the new size will be set soon.
// However, this size fluttering may confuse Blink and rendered result can be broken
// (see http://crbug.com/340987).
newContentViewCore.onSizeChanged(originalWidth, originalHeight, 0, 0);
if (!bounds.isEmpty()) {
nativeOnPhysicalBackingSizeChanged(mNativeTabAndroid,
newContentViewCore.getWebContents(), bounds.right, bounds.bottom);
}
newContentViewCore.onShow();
setContentViewCore(newContentViewCore);
destroyNativePageInternal(previousNativePage);
for (TabObserver observer : mObservers) {
observer.onWebContentsSwapped(this, didStartLoad, didFinishLoad);
}
}
/**
* Updates the display info, calculating and returning the new stack and movement bounds in the
* new orientation of the device if necessary.
*/
boolean onTaskStackBoundsChanged(Rect targetBounds, Rect outBounds) {
synchronized (mService.mWindowMap) {
final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
if (mDisplayInfo.equals(displayInfo)) {
// We are already in the right orientation, ignore
outBounds.setEmpty();
return false;
} else if (targetBounds.isEmpty()) {
// The stack is null, we are just initializing the stack, so just store the display
// info and ignore
mDisplayInfo.copyFrom(displayInfo);
outBounds.setEmpty();
return false;
}
mTmpRect.set(targetBounds);
final Rect postChangeStackBounds = mTmpRect;
// Calculate the snap fraction of the current stack along the old movement bounds
final float snapFraction = getSnapFraction(postChangeStackBounds);
mDisplayInfo.copyFrom(displayInfo);
// Calculate the stack bounds in the new orientation to the same same fraction along the
// rotated movement bounds.
final Rect postChangeMovementBounds = getMovementBounds(postChangeStackBounds,
false /* adjustForIme */, false /* adjustForShelf */);
mSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds,
snapFraction);
if (mIsMinimized) {
applyMinimizedOffset(postChangeStackBounds, postChangeMovementBounds);
}
notifyMovementBoundsChanged(false /* fromImeAdjustment */,
false /* fromShelfAdjustment */);
outBounds.set(postChangeStackBounds);
return true;
}
}
@Override
public int onCalculate(TaskRecord task, ActivityInfo.WindowLayout layout,
ActivityRecord activity, ActivityRecord source, ActivityOptions options,
LaunchParams currentParams, LaunchParams outParams) {
// We only care about figuring out bounds for activities.
if (activity == null) {
return RESULT_SKIP;
}
// Activity must be resizeable in the specified task.
if (!(mSupervisor.canUseActivityOptionsLaunchBounds(options)
&& (activity.isResizeable() || (task != null && task.isResizeable())))) {
return RESULT_SKIP;
}
final Rect bounds = options.getLaunchBounds();
// Bounds weren't valid.
if (bounds == null || bounds.isEmpty()) {
return RESULT_SKIP;
}
outParams.mBounds.set(bounds);
// When this is the most explicit position specification so we should not allow further
// modification of the position.
return RESULT_DONE;
}
@VisibleForTesting
void updateBounds(TaskRecord task, Rect bounds) {
if (bounds.isEmpty()) {
return;
}
final ActivityStack stack = task.getStack();
if (stack != null && stack.resizeStackWithLaunchBounds()) {
mService.resizeStack(stack.mStackId, bounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
} else {
task.updateOverrideConfiguration(bounds);
}
}
@Override
public void draw(@NonNull Canvas canvas) {
Rect bounds = getBounds();
if (bounds.isEmpty() || getAlpha() == 0 || !isVisible()) {
return;
}
shapeDrawable.draw(canvas);
if (hasNumber()) {
drawText(canvas);
}
}
/**
* Update task's override configuration based on the bounds.
* @param bounds The bounds of the task.
* @param insetBounds The bounds used to calculate the system insets, which is used here to
* subtract the navigation bar/status bar size from the screen size reported
* to the application. See {@link IActivityManager#resizeDockedStack}.
* @return True if the override configuration was updated.
*/
boolean updateOverrideConfiguration(Rect bounds, @Nullable Rect insetBounds) {
if (equivalentOverrideBounds(bounds)) {
return false;
}
final Rect currentBounds = getOverrideBounds();
mTmpConfig.setTo(getOverrideConfiguration());
final Configuration newConfig = getOverrideConfiguration();
final boolean matchParentBounds = bounds == null || bounds.isEmpty();
final boolean persistBounds = getWindowConfiguration().persistTaskBounds();
if (matchParentBounds) {
if (!currentBounds.isEmpty() && persistBounds) {
mLastNonFullscreenBounds = currentBounds;
}
setBounds(null);
newConfig.unset();
} else {
mTmpRect.set(bounds);
adjustForMinimalTaskDimensions(mTmpRect);
setBounds(mTmpRect);
if (mStack == null || persistBounds) {
mLastNonFullscreenBounds = getOverrideBounds();
}
computeOverrideConfiguration(newConfig, mTmpRect, insetBounds,
mTmpRect.right != bounds.right, mTmpRect.bottom != bounds.bottom);
}
onOverrideConfigurationChanged(newConfig);
return !mTmpConfig.equals(newConfig);
}
Rect updateOverrideConfigurationFromLaunchBounds() {
final Rect bounds = getLaunchBounds();
updateOverrideConfiguration(bounds);
if (bounds != null && !bounds.isEmpty()) {
// TODO: Review if we actually want to do this - we are setting the launch bounds
// directly here.
bounds.set(getOverrideBounds());
}
return bounds;
}
public static Bitmap asBitmap(Drawable drawable, int minWidth, int minHeight) {
final Rect tmpRect = new Rect();
drawable.copyBounds(tmpRect);
if (tmpRect.isEmpty()) {
tmpRect.set(0, 0, Math.max(minWidth, drawable.getIntrinsicWidth()), Math.max(minHeight, drawable.getIntrinsicHeight()));
drawable.setBounds(tmpRect);
}
Bitmap bitmap = Bitmap.createBitmap(tmpRect.width(), tmpRect.height(), Bitmap.Config.ARGB_8888);
drawable.draw(new Canvas(bitmap));
return bitmap;
}
@Override
public void draw(@SuppressWarnings("NullableProblems") Canvas canvas) {
Rect bounds = getBounds();
Bitmap bitmap = bitmapDrawable.getBitmap();
if (bounds.isEmpty() || bitmap == null || bitmap.isRecycled()) {
return;
}
if (shaper != null && bitmapShader != null) {
shaper.draw(canvas, paint, bounds);
} else {
canvas.drawBitmap(bitmap, !srcRect.isEmpty() ? srcRect : null, bounds, paint);
}
}
protected void keyPressed() {
if (isEnabled() && isClickable()) {
Drawable selector = this.mSelector;
Rect selectorRect = this.mSelectorRect;
if (selector == null) {
return;
}
if ((isFocused() || touchModeDrawsInPressedState()) && !selectorRect.isEmpty()) {
View v = getChildAt(this.mSelectedPosition - this.mFirstPosition);
if (v != null) {
if (!v.hasFocusable()) {
v.setPressed(true);
} else {
return;
}
}
setPressed(true);
boolean longClickable = isLongClickable();
Drawable d = selector.getCurrent();
if (d != null && (d instanceof TransitionDrawable)) {
if (longClickable) {
((TransitionDrawable) d).startTransition(ViewConfiguration.getLongPressTimeout());
} else {
((TransitionDrawable) d).resetTransition();
}
}
if (longClickable && !this.mDataChanged) {
if (this.mPendingCheckForKeyLongPress == null) {
this.mPendingCheckForKeyLongPress = new CheckForKeyLongPress(this, null);
}
this.mPendingCheckForKeyLongPress.rememberWindowAttachCount();
postDelayed(this.mPendingCheckForKeyLongPress, (long) ViewConfiguration.getLongPressTimeout());
}
}
}
}
private void update() {
final Rect bounds = getBounds();
if (bounds.isEmpty()) {
mRadius = 0;
return;
}
final float x = bounds.exactCenterX();
final float y = bounds.exactCenterY();
mRadius = (float) Math.sqrt(x * x + y * y);
if (mRippleRadius <= 0)
mRippleRadius = mMaxCount <= 0 ? mRadius : mRadius / mMaxCount;
}
public Bitmap asBitmap(Drawable drawable, int minWidth, int minHeight) {
final Rect tmpRect = new Rect();
drawable.copyBounds(tmpRect);
if (tmpRect.isEmpty()) {
tmpRect.set(0, 0, Math.max(minWidth, drawable.getIntrinsicWidth()), Math.max(minHeight, drawable.getIntrinsicHeight()));
drawable.setBounds(tmpRect);
}
Bitmap bitmap = Bitmap.createBitmap(tmpRect.width(), tmpRect.height(), Bitmap.Config.ARGB_8888);
drawable.draw(new Canvas(bitmap));
return bitmap;
}
@Override
public void adjustLayout(int startPosition, int endPosition, LayoutManagerHelper helper) {
if (requireLayoutView()) {
View refer = null;
Rect tempRect = new Rect();
final OrientationHelperEx orientationHelper = helper.getMainOrientationHelper();
for (int i = 0; i < helper.getChildCount(); i++) {
refer = helper.getChildAt(i);
int anchorPos = helper.getPosition(refer);
if (getRange().contains(anchorPos)) {
if (refer.getVisibility() == View.GONE) {
tempRect.setEmpty();
} else {
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
refer.getLayoutParams();
if (helper.getOrientation() == VirtualLayoutManager.VERTICAL) {
tempRect.union(helper.getDecoratedLeft(refer) - params.leftMargin,
orientationHelper.getDecoratedStart(refer),
helper.getDecoratedRight(refer) + params.rightMargin,
orientationHelper.getDecoratedEnd(refer));
} else {
tempRect.union(orientationHelper.getDecoratedStart(refer),
helper.getDecoratedTop(refer) - params.topMargin, orientationHelper.getDecoratedEnd(refer),
helper.getDecoratedBottom(refer) + params.bottomMargin);
}
}
}
}
if (!tempRect.isEmpty()) {
mLayoutRegion.set(tempRect.left - mPaddingLeft, tempRect.top - mPaddingTop,
tempRect.right + mPaddingRight, tempRect.bottom + mPaddingBottom);
} else {
mLayoutRegion.setEmpty();
}
if (mLayoutView != null) {
mLayoutView.layout(mLayoutRegion.left, mLayoutRegion.top, mLayoutRegion.right, mLayoutRegion.bottom);
}
}
}
public void adjustLayout(int startPosition, int endPosition, LayoutManagerHelper helper) {
if (!isChildrenEmpty()) {
for (Map.Entry<Range<Integer>, T> entry : mChildren.entrySet()) {
RangeStyle rangeStyle = entry.getValue();
rangeStyle.adjustLayout(startPosition, endPosition, helper);
}
}
if (requireLayoutView()) {
View refer = null;
Rect tempRect = new Rect();
final OrientationHelperEx orientationHelper = helper.getMainOrientationHelper();
for (int i = 0; i < helper.getChildCount(); i++) {
refer = helper.getChildAt(i);
int anchorPos = helper.getPosition(refer);
if (getRange().contains(anchorPos)) {
if (refer.getVisibility() == View.GONE) {
tempRect.setEmpty();
} else {
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
refer.getLayoutParams();
if (helper.getOrientation() == VirtualLayoutManager.VERTICAL) {
tempRect.union(helper.getDecoratedLeft(refer) - params.leftMargin,
orientationHelper.getDecoratedStart(refer),
helper.getDecoratedRight(refer) + params.rightMargin,
orientationHelper.getDecoratedEnd(refer));
} else {
tempRect.union(orientationHelper.getDecoratedStart(refer),
helper.getDecoratedTop(refer) - params.topMargin, orientationHelper.getDecoratedEnd(refer),
helper.getDecoratedBottom(refer) + params.bottomMargin);
}
}
}
}
if (!tempRect.isEmpty()) {
mLayoutRegion.set(tempRect.left - mPaddingLeft, tempRect.top - mPaddingTop,
tempRect.right + mPaddingRight, tempRect.bottom + mPaddingBottom);
} else {
mLayoutRegion.setEmpty();
}
if (mLayoutView != null) {
mLayoutView.layout(mLayoutRegion.left, mLayoutRegion.top, mLayoutRegion.right, mLayoutRegion.bottom);
}
}
}
/**
* Called to swap out the current view with the one passed in.
*
* @param newContentViewCore The content view that should be swapped into the tab.
* @param deleteOldNativeWebContents Whether to delete the native web
* contents of old view.
* @param didStartLoad Whether
* WebContentsObserver::DidStartProvisionalLoadForFrame() has
* already been called.
* @param didFinishLoad Whether WebContentsObserver::DidFinishLoad() has
* already been called.
*/
public void swapContentViewCore(ContentViewCore newContentViewCore,
boolean deleteOldNativeWebContents, boolean didStartLoad, boolean didFinishLoad) {
int originalWidth = 0;
int originalHeight = 0;
if (mContentViewCore != null) {
originalWidth = mContentViewCore.getViewportWidthPix();
originalHeight = mContentViewCore.getViewportHeightPix();
mContentViewCore.onHide();
}
Rect bounds = new Rect();
if (originalWidth == 0 && originalHeight == 0) {
bounds = ExternalPrerenderHandler.estimateContentSize(
(Application) getApplicationContext(), false);
originalWidth = bounds.right - bounds.left;
originalHeight = bounds.bottom - bounds.top;
}
destroyContentViewCore(deleteOldNativeWebContents);
NativePage previousNativePage = mNativePage;
mNativePage = null;
// Size of the new ContentViewCore is zero at this point. If we don't call onSizeChanged(),
// next onShow() call would send a resize message with the current ContentViewCore size
// (zero) to the renderer process, although the new size will be set soon.
// However, this size fluttering may confuse Blink and rendered result can be broken
// (see http://crbug.com/340987).
newContentViewCore.onSizeChanged(originalWidth, originalHeight, 0, 0);
if (!bounds.isEmpty()) {
newContentViewCore.onPhysicalBackingSizeChanged(bounds.right, bounds.bottom);
}
newContentViewCore.onShow();
setContentViewCore(newContentViewCore);
mContentViewCore.attachImeAdapter();
// If the URL has already committed (e.g. prerendering), tell process management logic that
// it can rely on the process visibility signal for binding management.
// TODO: Call ChildProcessLauncher#determinedVisibility() at a more intuitive time.
// See crbug.com/537671
if (!mContentViewCore.getWebContents().getLastCommittedUrl().equals("")) {
ChildProcessLauncher.determinedVisibility(mContentViewCore.getCurrentRenderProcessId());
}
destroyNativePageInternal(previousNativePage);
for (TabObserver observer : mObservers) {
observer.onWebContentsSwapped(this, didStartLoad, didFinishLoad);
}
}
private static int computeRectArea(Rect rect) {
return rect.isEmpty() ? 0 : (rect.width() * rect.height());
}