Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android View outline - using a custom Path

Tags:

android

When I set View's outline as follows it works just fine:

view.setClipToOutline(true);
view.setOutlineProvider(new ViewOutlineProvider() {
  @Override
  public void getOutline(View view, Outline outline) {
    outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), 16);
  }
});

enter image description here

However, using a Path has no effect. Replace setRoundRect with:

Path path = new Path();
path.addRoundRect(
  0, 0, view.getWidth(), view.getHeight(), 16, 16, Path.Direction.CW);
outline.setConvexPath(path);

enter image description here

How to make the view clip to the Path provided?

like image 366
Martin Konicek Avatar asked Apr 21 '17 16:04

Martin Konicek


2 Answers

I know it is not helping in clipping but still, we can take the advantage of outline.setConvexPath(path); in elevation shadow since it's working fine as an outline for the elevation shadow around the path.

I attached an image to make it even more clear in which:

First image: ImageView with [Image with shadow]

android:outlineProvider="bounds"  
android:elevation="4dp"

Second image: CustomImageView with canvas.clipPath(getShapePath()) in onDraw() method [we will get the clipped image but shadow still show as a rectangle bound]

android:outlineProvider="bounds"  
android:elevation="4dp"

Third image: CustomImageView with canvas.clipPath(getShapePath()) in onDraw() method and outline?.setConvexPath(getShapePath()) in ViewOutlineProvider. [we will get the clipped image and shadow will be aligned with the clipped image]

android:outlineProvider="bounds" // this will have no effect since it will be override by setConvexPath  
android:elevation="4dp"

Valid XHTML

Download Source Code

like image 170
Gauraw Negi Avatar answered Nov 16 '22 07:11

Gauraw Negi


It seems that a View can only be clipped to a rectangle, a rounded rectangle, or an oval Outline. Rather, a View can only be clipped to an Outline that is defined specifically with a setRect(), setRoundRect(), or setOval() method. An Outline set with a Path will not work, even though the Path itself may be one of the aforementioned shapes.

This is documented in several places, though not particularly well, in my opinion.

View#setClipToOutline():

Note that this flag will only be respected if the View's Outline returns true from canClip().

Outline#canClip():

Currently, only Outlines that can be represented as a rectangle, circle, or round rect support clipping.

Defining Shadows and Clipping Views - Clip Views:

Only rectangle, circle, and round rectangle outlines support clipping, as determined by the Outline.canClip() method.

At first look, this didn't seem consistent with Outline's own inner workings, as a convex Path is, in fact, used internally for non-circular ovals. However, it does make sense to simply disallow all externally defined Paths, rather than expend the resources necessary to determine if an arbitrary Path is valid.

like image 8
Mike M. Avatar answered Nov 16 '22 06:11

Mike M.