Android P Beta中的Xfermode

时间:2018-07-26 12:05:28

标签: android beta xfermode

左边是在Android P beta上截取的屏幕截图,右边是在Android 26上截取的屏幕截图。 Curve differences Xfermode在Android P beta上的工作方式似乎不一致。

下面是相应的代码。

public class CropView extends View {

    private Paint paint;
    private Path clipPath;
    private int arcHeight;

    public CropView(Context context) {
        super(context);
        init();
    }

    public CropView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public CropView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
        arcHeight = getResources().getDimensionPixelOffset(R.dimen.row_size);
        setLayerType();
    }

    private void setLayerType() {
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
            // looks like this is happening in some devices with lollipop and kitkat
            // trying to fix https://github.com/lifesum/bugs/issues/7040
            setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        } else {
            setLayerType(LAYER_TYPE_HARDWARE, null);
        }
    }

    private Path createClipPath(int height, int width) {
        final Path path = new Path();

        path.moveTo(0, 0);
        path.lineTo(0, height);
        path.quadTo(width / 2, height + arcHeight, width, height - arcHeight);

        path.lineTo(width, 0);
        path.close();

        return path;
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        if (changed) {
            int height = getMeasuredHeight();
            int width = getMeasuredWidth();
            clipPath = createClipPath(height, width);
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (clipPath != null) {
            canvas.drawPath(clipPath, paint);
        }
    }
}

下面是运行来自Android示例的Apidemos时的屏幕截图

Android P Android P Android 27 Android 27

2 个答案:

答案 0 :(得分:1)

按照Google给出的答案,这是预期的行为。
https://issuetracker.google.com/issues/111819103

他们给了3个选择

  1. 使用android.view.ViewOutlineProvider(如此处的示例https://github.com/googlesamples/android-ClippingBasic)。
  2. 用BitmapShader替换ImageView,因为它在API级别1中支持BitmapShader,所以它速度快(每个像素绘制一次)并且更便于携带。 Paint paint = new Paint(); paint.setColor(Color.BLACK); paint.setStyle(Paint.Style.FILL); 位图bm = BitmapFactory.decodeResource(getResources(),R.drawable.spiderman); 着色器着色器=新的BitmapShader(bm,Shader.TileMode.CLAMP,Shader.TileMode.CLAMP); paint.setShader(shader); 路径角=新的Path(); corners.addRoundRect(bounds,radii,Path.Direction.CW); canvas.drawPath(corners,paint);
  3. 在ImageView的顶部绘制一条带有SRC_OVER的反向路径。如果背景是纯色且速度较慢,则此方法有效,因为某些像素被绘制了两次。

其中第一个不能用于渲染凸复杂路径,如https://issuetracker.google.com/issues/37064491

尝试其他两个选项,然后在此处发布结果。

答案 1 :(得分:0)

是的,我遇到了同样的问题。

也许Android-Pie似乎不支持drawPath上的dragderDuff.Mode ...

但是,您仍然可以使用drawBitmap剪切图层。

例如:

if (ModelState.IsValid)
{
    // your logic

    return new HttpResponseMessage(HttpStatusCode.OK);
}
else
{
    return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}