下面列出了android.graphics.Rect#offsetTo ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* Calculates the snapshot frame in window coordinate space from crop.
*
* @param crop rect that is in snapshot coordinate space.
*/
@VisibleForTesting
Rect calculateSnapshotFrame(Rect crop) {
final Rect frame = new Rect(crop);
final float scale = mSnapshot.getScale();
// Rescale the frame from snapshot to window coordinate space
frame.scale(1 / scale);
// By default, offset it to to top/left corner
frame.offsetTo((int) (-crop.left / scale), (int) (-crop.top / scale));
// However, we also need to make space for the navigation bar on the left side.
final int colorViewLeftInset = getColorViewLeftInset(mStableInsets.left,
mContentInsets.left);
frame.offset(colorViewLeftInset, 0);
return frame;
}
public void reset(int offset) {
for (int i = 0; i < mLanes.length; i++) {
final Rect laneRect = mLanes[i];
laneRect.offsetTo(mIsVertical ? laneRect.left : offset,
mIsVertical ? offset : laneRect.top);
if (mIsVertical) {
laneRect.bottom = laneRect.top;
} else {
laneRect.right = laneRect.left;
}
}
invalidateEdges();
}
/**
* Take a screenshot of the wallpaper if it's visible.
*
* @return Bitmap of the wallpaper
*/
Bitmap screenshotWallpaperLocked() {
if (!mService.mPolicy.isScreenOn()) {
if (DEBUG_SCREENSHOT) {
Slog.i(TAG_WM, "Attempted to take screenshot while display was off.");
}
return null;
}
final WindowState wallpaperWindowState = getTopVisibleWallpaper();
if (wallpaperWindowState == null) {
if (DEBUG_SCREENSHOT) {
Slog.i(TAG_WM, "No visible wallpaper to screenshot");
}
return null;
}
final Rect bounds = wallpaperWindowState.getBounds();
bounds.offsetTo(0, 0);
GraphicBuffer wallpaperBuffer = SurfaceControl.captureLayers(
wallpaperWindowState.getSurfaceControl().getHandle(), bounds, 1 /* frameScale */);
if (wallpaperBuffer == null) {
Slog.w(TAG_WM, "Failed to screenshot wallpaper");
return null;
}
return Bitmap.createHardwareBitmap(wallpaperBuffer);
}
@Override
public Animator onDisappear(ViewGroup sceneRoot, View view,
TransitionValues startValues, TransitionValues endValues) {
if (startValues == null) {
return null;
}
Rect bounds = (Rect) startValues.values.get(PROPNAME_SCREEN_BOUNDS);
int viewPosX = bounds.left;
int viewPosY = bounds.top;
float startX = view.getTranslationX();
float startY = view.getTranslationY();
float endX = startX;
float endY = startY;
int[] interruptedPosition = (int[]) startValues.view.getTag(R.id.transitionPosition);
if (interruptedPosition != null) {
// We want to have the end position relative to the interrupted position, not
// the position it was supposed to start at.
endX += interruptedPosition[0] - bounds.left;
endY += interruptedPosition[1] - bounds.top;
bounds.offsetTo(interruptedPosition[0], interruptedPosition[1]);
}
calculateOut(sceneRoot, bounds, mTempLoc);
endX += mTempLoc[0];
endY += mTempLoc[1];
return TranslationAnimationCreator.createAnimation(view, startValues,
viewPosX, viewPosY, startX, startY, endX, endY, sAccelerate, this);
}
protected static Rect getDrawableBounds(Drawable d) {
Rect bounds = new Rect();
d.copyBounds(bounds);
if (bounds.width() == 0 || bounds.height() == 0) {
bounds.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
} else {
bounds.offsetTo(0, 0);
}
return bounds;
}
private static Rect getDrawableBounds(Drawable d) {
Rect bounds = new Rect();
d.copyBounds(bounds);
if (bounds.width() == 0 || bounds.height() == 0) {
bounds.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
} else {
bounds.offsetTo(0, 0);
}
if (d instanceof PreloadIconDrawable) {
int inset = -((PreloadIconDrawable) d).getOutset();
bounds.inset(inset, inset);
}
return bounds;
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES20.glViewport(0, 0, width, height);
final float ratioDisplay = (float) width / height;
Matrix.frustumM(projectionMatrix, 0, -ratioDisplay, ratioDisplay, -1.0f, 1.0f, 1.0f, 10.0f);
this.width = width;
this.height = height;
frameBuffer.setResolution(new Resolution(this.width, this.height));
videoViewport = new Rect();
videoViewport.left = 0;
videoViewport.top = 0;
// Landscape
if (ratioDisplay > 1.0f) {
videoViewport.right = videoCapture.getFrameWidth();
videoViewport.bottom = (int) (videoCapture.getFrameWidth() / ratioDisplay);
} else {
videoViewport.bottom = videoCapture.getFrameHeight();
videoViewport.right = (int) (videoCapture.getFrameHeight() * ratioDisplay);
}
videoViewport.offsetTo((videoCapture.getFrameWidth() - videoViewport.right) / 2, (videoCapture.getFrameHeight() - videoViewport.bottom) / 2);
}
@Override
public Animator onDisappear(@NonNull ViewGroup sceneRoot, @NonNull View view,
@Nullable TransitionValues startValues, @Nullable TransitionValues endValues) {
if (startValues == null) {
return null;
}
Rect bounds = (Rect) startValues.values.get(PROPNAME_SCREEN_BOUNDS);
int viewPosX = bounds.left;
int viewPosY = bounds.top;
float startX = view.getTranslationX();
float startY = view.getTranslationY();
float endX = startX;
float endY = startY;
int[] interruptedPosition = (int[]) startValues.view.getTag(R.id.transitionPosition);
if (interruptedPosition != null) {
// We want to have the end position relative to the interrupted position, not
// the position it was supposed to start at.
endX += interruptedPosition[0] - bounds.left;
endY += interruptedPosition[1] - bounds.top;
bounds.offsetTo(interruptedPosition[0], interruptedPosition[1]);
}
calculateOut(sceneRoot, bounds, mTempLoc);
endX += mTempLoc[0];
endY += mTempLoc[1];
return TranslationAnimationCreator.createAnimation(view, startValues,
viewPosX, viewPosY, startX, startY, endX, endY, sAccelerate, this);
}
public void scrollToPage(int pageNumber)
{
// scroll to bring the page into view
int scrollTime = 400;
// get current viewport
Rect viewport = new Rect();
getGlobalVisibleRect(viewport);
// offset it based on current scroll position
Point viewportOrigin = new Point();
viewportOrigin.set(getScrollX(), getScrollY());
viewport.offsetTo(viewportOrigin.x, viewportOrigin.y);
// get page rect from last layout
DocPageView cv = (DocPageView) getOrCreateChild(pageNumber);
Rect childRect = cv.getChildRect();
// scroll
if ((childRect.height()) > viewport.height())
{
// put the top of the page at the top and the left at 0
smoothScrollBy(getScrollX(), getScrollY() - childRect.top, scrollTime);
}
else
{
// if the whole page is not visible, move the center of the page at the center
if (childRect.top < viewport.top || childRect.bottom > viewport.bottom)
{
if (childRect.top == 0)
smoothScrollBy(0, getScrollY(), scrollTime);
else
smoothScrollBy(0, getScrollY() + viewport.height() / 2 - (childRect.bottom + childRect.top) / 2, scrollTime);
}
}
}
void layout(int x, int y, int max) {
Rect rect = getBounds();
rect.offsetTo(Math.min(x - rect.width() / 2, max - rect.width() - (int)(0.2f * mHeight)), Math.max(0, y - rect.height() / 2));
setBounds(rect);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void updateUIToSelectedTheme(final String themeId, final boolean animate) {
for (final ThemeUiHolder holder : mThemeUiHolders) {
boolean selected = holder.theme.id.equals(themeId);
holder.button.setSelected(selected);
if (holder.selected != selected && selected) {
if (mCurrentRevealAnimator != null) {
mCurrentRevealAnimator.end();
updatePreviewView(mAnimatingTheme, mMainClockContainerView, mMainClockView);
}
if (animate && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mAnimatingTheme = holder.theme;
updatePreviewView(mAnimatingTheme, mAnimateClockContainerView, mAnimateClockView);
Rect buttonRect = new Rect();
Rect clockContainerRect = new Rect();
holder.button.getGlobalVisibleRect(buttonRect);
mMainClockContainerView.getGlobalVisibleRect(clockContainerRect);
int cx = buttonRect.centerX() - clockContainerRect.left;
int cy = buttonRect.centerY() - clockContainerRect.top;
clockContainerRect.offsetTo(0, 0);
mCurrentRevealAnimator = ViewAnimationUtils.createCircularReveal(
mAnimateClockContainerView, cx, cy, 0,
MathUtil.maxDistanceToCorner(clockContainerRect, cx, cy));
mAnimateClockContainerView.setVisibility(View.VISIBLE);
mCurrentRevealAnimator.setDuration(300);
mCurrentRevealAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (mCurrentRevealAnimator == animation) {
mAnimateClockContainerView.setVisibility(View.INVISIBLE);
updatePreviewView(holder.theme, mMainClockContainerView, mMainClockView);
}
}
});
mAnimateClockView.postInvalidateOnAnimation();
mCurrentRevealAnimator.start();
} else {
updatePreviewView(holder.theme, mMainClockContainerView, mMainClockView);
}
}
holder.selected = selected;
}
}
/**
* Use to signal that there's a portion of this view that wants to be
* visible to the user on the screen. This method will place the sub
* view on the screen, and will also place as much of this view as possible
* on the screen. If this view is smaller than the viewable area available, it
* will be fully visible in addition to the subview.
*/
private void requestChildViewOnScreen(View child) {
//Take focus so the user can be prepared to interact with this question, since
//they will need to be fixing the input
acceptFocus();
//Get the rectangle that wants to put itself on the screen
Rect vitalPortion = new Rect();
child.getDrawingRect(vitalPortion);
//Save a reference to it in case we have to manipulate it later.
Rect vitalPortionSaved = new Rect();
child.getDrawingRect(vitalPortionSaved);
//Then get the bounding rectangle for this whole view.
Rect wholeView = new Rect();
this.getDrawingRect(wholeView);
//If we don't know enough about the screen, just default to asking to see the
//subview that was requested.
if (mFrameHeight == -1) {
child.requestRectangleOnScreen(vitalPortion);
return;
}
//If the whole view fits, just request that we display the whole thing.
if (wholeView.height() < mFrameHeight) {
this.requestRectangleOnScreen(wholeView);
return;
}
//The whole view will not fit, we need to scale down our requested focus.
//Trying to construct the "ideal" rectangle here is actually pretty hard
//but the base case is just to see if we can get the view onto the screen from
//the bottom or the top
int topY = wholeView.top;
int bottomY = wholeView.bottom;
//shrink the view to contain only the current frame size.
wholeView.inset(0, (wholeView.height() - mFrameHeight) / 2);
wholeView.offsetTo(wholeView.left, topY);
//The view is now the size of the frame and anchored back at the top.
//Now let's contextualize where the child view actually is in this frame.
this.offsetDescendantRectToMyCoords(child, vitalPortion);
//If the newly transformed view now contains the child portion, we're good
if (wholeView.contains(vitalPortion)) {
this.requestRectangleOnScreen(wholeView);
return;
}
//otherwise, move to the requested frame to be at the bottom of this view
wholeView.offsetTo(wholeView.left, bottomY - wholeView.height());
//now see if the transformed view contains the vital portion
if (wholeView.contains(vitalPortion)) {
this.requestRectangleOnScreen(wholeView);
return;
}
//Otherwise the child is hidden in the frame, so it won't matter which
//we choose.
child.requestRectangleOnScreen(vitalPortionSaved);
}
/**
* Draws the pins and text labels for the nearby list of places.
*
* @param canvas the {@link Canvas} upon which to draw
* @param pixelsPerDegree the size, in pixels, of one degree step
* @param offset the number of pixels to translate the drawing operations by in the horizontal
* direction; used because place names are drawn three times to get proper wraparound
*/
private void drawPlaces(Canvas canvas, float pixelsPerDegree, float offset) {
if (mOrientation.hasLocation() && mNearbyPlaces != null) {
synchronized (mNearbyPlaces) {
Location userLocation = mOrientation.getLocation();
double latitude1 = userLocation.getLatitude();
double longitude1 = userLocation.getLongitude();
mAllBounds.clear();
// Loop over the list of nearby places (those within 10 km of the user's current
// location), and compute the relative bearing from the user's location to the
// place's location. This determines the position on the compass view where the
// pin will be drawn.
for (Place place : mNearbyPlaces) {
double latitude2 = place.getLatitude();
double longitude2 = place.getLongitude();
float bearing = MathUtils.getBearing(latitude1, longitude1, latitude2,
longitude2);
String name = place.getName();
double distanceKm = MathUtils.getDistance(latitude1, longitude1, latitude2,
longitude2);
String text = getContext().getResources().getString(
R.string.place_text_format, name, mDistanceFormat.format(distanceKm));
// Measure the text and offset the text bounds to the location where the text
// will finally be drawn.
Rect textBounds = new Rect();
mPlacePaint.getTextBounds(text, 0, text.length(), textBounds);
textBounds.offsetTo((int) (offset + bearing * pixelsPerDegree
+ PLACE_PIN_WIDTH / 2 + PLACE_TEXT_MARGIN), canvas.getHeight() / 2
- (int) PLACE_TEXT_HEIGHT);
// Extend the bounds rectangle to include the pin icon and a small margin
// to the right of the text, for the overlap calculations below.
textBounds.left -= PLACE_PIN_WIDTH + PLACE_TEXT_MARGIN;
textBounds.right += PLACE_TEXT_MARGIN;
// This loop attempts to find the best vertical position for the string by
// starting at the bottom of the display and checking to see if it overlaps
// with any other labels that were already drawn. If there is an overlap, we
// move up and check again, repeating this process until we find a vertical
// position where there is no overlap, or when we reach the limit on
// overlapping place names.
boolean intersects;
int numberOfTries = 0;
do {
intersects = false;
numberOfTries++;
textBounds.offset(0, (int) -(PLACE_TEXT_HEIGHT + PLACE_TEXT_LEADING));
for (Rect existing : mAllBounds) {
if (Rect.intersects(existing, textBounds)) {
intersects = true;
break;
}
}
} while (intersects && numberOfTries <= MAX_OVERLAPPING_PLACE_NAMES);
// Only draw the string if it would not go high enough to overlap the compass
// directions. This means some places may not be drawn, even if they're nearby.
if (numberOfTries <= MAX_OVERLAPPING_PLACE_NAMES) {
mAllBounds.add(textBounds);
canvas.drawBitmap(mPlaceBitmap, offset + bearing * pixelsPerDegree
- PLACE_PIN_WIDTH / 2, textBounds.top + 2, mPaint);
canvas.drawText(text,
offset + bearing * pixelsPerDegree + PLACE_PIN_WIDTH / 2
+ PLACE_TEXT_MARGIN, textBounds.top + PLACE_TEXT_HEIGHT,
mPlacePaint);
}
}
}
}
}
/**
* Draws the pins and text labels for the nearby list of places.
*
* @param canvas the {@link Canvas} upon which to draw
* @param pixelsPerDegree the size, in pixels, of one degree step
* @param offset the number of pixels to translate the drawing operations by in the horizontal
* direction; used because place names are drawn three times to get proper wraparound
*/
private void drawPlaces(Canvas canvas, float pixelsPerDegree, float offset) {
if (mOrientation.hasLocation() && mNearbyPlaces != null) {
synchronized (mNearbyPlaces) {
Location userLocation = mOrientation.getLocation();
double latitude1 = userLocation.getLatitude();
double longitude1 = userLocation.getLongitude();
mAllBounds.clear();
// Loop over the list of nearby places (those within 10 km of the user's current
// location), and compute the relative bearing from the user's location to the
// place's location. This determines the position on the compass view where the
// pin will be drawn.
for (Place place : mNearbyPlaces) {
double latitude2 = place.getLatitude();
double longitude2 = place.getLongitude();
float bearing = MathUtils.getBearing(latitude1, longitude1, latitude2,
longitude2);
String name = place.getName();
double distanceKm = MathUtils.getDistance(latitude1, longitude1, latitude2,
longitude2);
String text = getContext().getResources().getString(
R.string.place_text_format, name, mDistanceFormat.format(distanceKm));
// Measure the text and offset the text bounds to the location where the text
// will finally be drawn.
Rect textBounds = new Rect();
mPlacePaint.getTextBounds(text, 0, text.length(), textBounds);
textBounds.offsetTo((int) (offset + bearing * pixelsPerDegree
+ PLACE_PIN_WIDTH / 2 + PLACE_TEXT_MARGIN), canvas.getHeight() / 2
- (int) PLACE_TEXT_HEIGHT);
// Extend the bounds rectangle to include the pin icon and a small margin
// to the right of the text, for the overlap calculations below.
textBounds.left -= PLACE_PIN_WIDTH + PLACE_TEXT_MARGIN;
textBounds.right += PLACE_TEXT_MARGIN;
// This loop attempts to find the best vertical position for the string by
// starting at the bottom of the display and checking to see if it overlaps
// with any other labels that were already drawn. If there is an overlap, we
// move up and check again, repeating this process until we find a vertical
// position where there is no overlap, or when we reach the limit on
// overlapping place names.
boolean intersects;
int numberOfTries = 0;
do {
intersects = false;
numberOfTries++;
textBounds.offset(0, (int) -(PLACE_TEXT_HEIGHT + PLACE_TEXT_LEADING));
for (Rect existing : mAllBounds) {
if (Rect.intersects(existing, textBounds)) {
intersects = true;
break;
}
}
} while (intersects && numberOfTries <= MAX_OVERLAPPING_PLACE_NAMES);
// Only draw the string if it would not go high enough to overlap the compass
// directions. This means some places may not be drawn, even if they're nearby.
if (numberOfTries <= MAX_OVERLAPPING_PLACE_NAMES) {
mAllBounds.add(textBounds);
canvas.drawBitmap(mPlaceBitmap, offset + bearing * pixelsPerDegree
- PLACE_PIN_WIDTH / 2, textBounds.top + 2, mPaint);
canvas.drawText(text,
offset + bearing * pixelsPerDegree + PLACE_PIN_WIDTH / 2
+ PLACE_TEXT_MARGIN, textBounds.top + PLACE_TEXT_HEIGHT,
mPlacePaint);
}
}
}
}
}