15

I Have a CustomView working on pre-Lollipop, now I tried to apply android:elevation and android:translateZ on Lollipop devices but doesn't seems to work.

<com.example.CustomView
    android:id="@+id/myview"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:elevation="10dp">
</com.example.CustomView>

What i missing?

rnrneverdies
  • 15,243
  • 9
  • 65
  • 95

1 Answers1

36

As mentioned in Defining Shadows and Clipping Views

You should implement ViewOutlineProvider abstract class by which a View builds its Outline, used for shadow casting and clipping

Rectangular CustomView

public class CustomView extends View {

    // ..

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
       /// ..
       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            setOutlineProvider(new CustomOutline(w, h));
       }
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private class CustomOutline extends ViewOutlineProvider {

        int width; 
        int height;

        CustomOutline(int width, int height) {
            this.width = width;
            this.height = height;
        }

        @Override
        public void getOutline(View view, Outline outline) {
            outline.setRect(0, 0, width, height);
        }
    }

    //...
}

note: This feature is only supported by API21, pre API21 should use 9-patch.

Community
  • 1
  • 1
rnrneverdies
  • 15,243
  • 9
  • 65
  • 95
  • 1
    I don't understand very well why we should do this. I've done it because is the only way I found to show a shadow on my custom view, but I don't understand why. In the editor preview shows the shadow for my custom view just setting the elevation but when I run it it doesn't show the shadow. I don't want a custom shadow just the standard shadow on my custom view. Any further reads or explanations? – Sotti Apr 27 '15 at 12:14
  • 2
    I'm not sure why is not the bounding box by default. The framework code responsible for generating the ambient/spot shadows uses getOutline to determine the view's shape. Your View could be square or a circle or hexagonal, and have no other way to know. So you must provide a Outline. – rnrneverdies Apr 27 '15 at 22:16
  • If you're using a custom Drawable on your custom view, you can alternatively implement `getOutline` on your drawable instead of this approach. – James May 18 '15 at 07:28
  • Just to clarify, by 'custom Drawable your custom view' I am talking about using a custom Drawable subclass as the *background* of your view. – James May 18 '15 at 10:52
  • I am trying to use this but the width and height keep coming out to zero :( – Taylor May 13 '19 at 15:44
  • 1
    If you change the bounds of your view (expand animation or whatever) you can call `invalidateOutline()'. May be helpful to someone – pauminku May 20 '20 at 13:13