Search code examples
androidandroid-source

Clip content of ActivityView


i am implementing a custom launcher in Android, displaying 3rd party apps using ActivityViews. I want to clip the content of these ActivityViews to a custom shape (other than Circle, Rectangle, RoundedRectangle, Ring...).

I already tried to call clipPath/drawPath on the dispatchDraw canvas of a parent viewgroup element which works fine for all children except the ActivityView. Even the ActivityView itself and its referenced SurfaceView seem to be clipped according to my given path (if i add a solid color for testing). But the rendered content remains unchanged. Manipulating the SurfaceView canvas (which you receive by calling getHolder().lockCanvas()) doesnt have any effect, too.

I think this has something to do with the virtualdisplay and/or various SurfaceControls which are used by the ActivityView, but i dont have any clue how to set clipping areas/paths for those classes.

Does anyone have an idea how to solve this?

Hint: i cannot paint over the ActivityViews content as i want to display the system wallpaper in the transparent areas.


Solution

  • finally setting up the PorterDuffXfermode correctly solved the issue. Just overwrite the dispatchDraw method of the parent viewgroup and erase the required areas using PorterDuff.

    Sometimes it looks like the direction does matter how the path for drawPath is created (CW or CCW). So maybe try both.

    Unfortunately this approach does not work if the hosted activity uses a SurfaceView on its own.

    protected void dispatchDraw(Canvas canvas) {
        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
        p.setColor(getContext().getColor(android.R.color.white));
        p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
    
        int save = canvas.save();
        super.dispatchDraw(canvas);
        canvas.drawPath(path, p);
        canvas.restoreToCount(save);
    }