diff options
| -rw-r--r-- | core/java/android/app/ActivityView.java | 42 | ||||
| -rw-r--r-- | core/java/android/view/SurfaceView.java | 60 |
2 files changed, 101 insertions, 1 deletions
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java index e8918285777b..b56c00e44d3f 100644 --- a/core/java/android/app/ActivityView.java +++ b/core/java/android/app/ActivityView.java @@ -29,6 +29,7 @@ import android.content.Context; import android.content.Intent; import android.graphics.Insets; import android.graphics.Matrix; +import android.graphics.Rect; import android.graphics.Region; import android.hardware.display.DisplayManager; import android.hardware.display.VirtualDisplay; @@ -101,6 +102,8 @@ public class ActivityView extends ViewGroup { private Insets mForwardedInsets; + private float mCornerRadius; + public ActivityView(Context context) { this(context, null /* attrs */); } @@ -204,6 +207,45 @@ public class ActivityView extends ViewGroup { } /** + * @hide + */ + public float getCornerRadius() { + return mSurfaceView.getCornerRadius(); + } + + /** + * Control whether the surface is clipped to the same bounds as the View. If true, then + * the bounds set by {@link #setSurfaceClipBounds(Rect)} are applied to the surface as + * window-crop. + * + * @param clippingEnabled whether to enable surface clipping + * @hide + */ + public void setSurfaceClippingEnabled(boolean clippingEnabled) { + mSurfaceView.setEnableSurfaceClipping(clippingEnabled); + } + + /** + * Sets an area on the contained surface to which it will be clipped + * when it is drawn. Setting the value to null will remove the clip bounds + * and the surface will draw normally, using its full bounds. + * + * @param clipBounds The rectangular area, in the local coordinates of + * this view, to which future drawing operations will be clipped. + * @hide + */ + public void setSurfaceClipBounds(Rect clipBounds) { + mSurfaceView.setClipBounds(clipBounds); + } + + /** + * @hide + */ + public boolean getSurfaceClipBounds(Rect outRect) { + return mSurfaceView.getClipBounds(outRect); + } + + /** * Launch a new activity into this container. * <p>Activity resolved by the provided {@link Intent} must have * {@link android.R.attr#resizeableActivity} attribute set to {@code true} in order to be diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 06ff568202d5..a85830009f58 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -167,6 +167,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall boolean mUseAlpha = false; float mSurfaceAlpha = 1f; + boolean mClipSurfaceToBounds; @UnsupportedAppUsage boolean mHaveFrame = false; @@ -555,9 +556,52 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall super.dispatchDraw(canvas); } + /** + * Control whether the surface is clipped to the same bounds as the View. If true, then + * the bounds set by {@link #setClipBounds(Rect)} are applied to the surface as window-crop. + * + * @param enabled whether to enable surface clipping + * @hide + */ + public void setEnableSurfaceClipping(boolean enabled) { + mClipSurfaceToBounds = enabled; + invalidate(); + } + + @Override + public void setClipBounds(Rect clipBounds) { + super.setClipBounds(clipBounds); + + if (!mClipSurfaceToBounds) { + return; + } + + // When cornerRadius is non-zero, a draw() is required to update + // the viewport (rounding the corners of the clipBounds). + if (mCornerRadius > 0f && !isAboveParent()) { + invalidate(); + } + + if (mSurfaceControl != null) { + if (mClipBounds != null) { + mTmpRect.set(mClipBounds); + } else { + mTmpRect.set(0, 0, mSurfaceWidth, mSurfaceHeight); + } + SyncRtSurfaceTransactionApplier applier = new SyncRtSurfaceTransactionApplier(this); + applier.scheduleApply( + new SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(mSurfaceControl) + .withWindowCrop(mTmpRect) + .build()); + } + } + private void clearSurfaceViewPort(Canvas canvas) { if (mCornerRadius > 0f) { canvas.getClipBounds(mTmpRect); + if (mClipSurfaceToBounds && mClipBounds != null) { + mTmpRect.intersect(mClipBounds); + } canvas.drawRoundRect(mTmpRect.left, mTmpRect.top, mTmpRect.right, mTmpRect.bottom, mCornerRadius, mCornerRadius, mRoundedViewportPaint); } else { @@ -583,6 +627,16 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall } /** + * Returns the corner radius for the SurfaceView. + + * @return the radius of the corners in pixels + * @hide + */ + public float getCornerRadius() { + return mCornerRadius; + } + + /** * Control whether the surface view's surface is placed on top of another * regular surface view in the window (but still behind the window itself). * This is typically used to place overlays on top of an underlying media @@ -840,7 +894,11 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall // crop the buffer to the surface size since the buffer producer may // use SCALING_MODE_SCALE and submit a larger size than the surface // size. - mSurfaceControl.setWindowCrop(mSurfaceWidth, mSurfaceHeight); + if (mClipSurfaceToBounds && mClipBounds != null) { + mSurfaceControl.setWindowCrop(mClipBounds); + } else { + mSurfaceControl.setWindowCrop(mSurfaceWidth, mSurfaceHeight); + } } mSurfaceControl.setCornerRadius(mCornerRadius); if (sizeChanged && !creating) { |