首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Android P测试版中的Xfermode

Android P测试版中的Xfermode
EN

Stack Overflow用户
提问于 2018-07-26 20:05:28
回答 2查看 987关注 0票数 3

左边是Android P beta上的截图,右边是Android 26上的截图。

Xfermode在Android P beta上的工作方式似乎存在不一致之处。

下面是相应的代码。

代码语言:javascript
复制
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);
        }
    }
}

以下是运行安卓示例中的Apidemos时的屏幕截图

Android P

Android 27

EN

回答 2

Stack Overflow用户

发布于 2018-08-08 16:28:43

根据谷歌给出的答案,这是有意为之的行为。

https://issuetracker.google.com/issues/111819103

他们给出了3个选项

着色器使用android.view.ViewOutlineProvider (根据这里的示例,使用着色器绘制ImageView ),它是快速的(每个像素都绘制一次),而且更便携,因为BitmapShader级别1支持BitmapShader。Paint paint = 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(着色器);路径角点=新路径();corners.addRoundRect(边界,半径,Path.Direction.CW);canvas.drawPath(角点,绘制);

  1. 使用SRC_OVER在ImageView上绘制反向路径。如果背景是纯色且速度较慢,则此方法有效,因为某些像素会绘制两次。

其中第一个不能用于渲染凸形复杂路径,正如https://issuetracker.google.com/issues/37064491中所回答的那样

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

票数 2
EN

Stack Overflow用户

发布于 2018-08-24 13:57:30

是的,我也遇到过同样的问题。

也许安卓派似乎不支持drawPath上的drawerDuff.Mode……

但是,你仍然可以使用drawBitmap来裁剪图层。

例如:

代码语言:javascript
复制
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    if (clipPathBitmap != null) {
        canvas.drawBitmap(clipPathBitmap, 0, 0, paint);
    }
}

private void makeClipPathBitmap() {
    clipPathBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
    Canvas c = new Canvas(mShapeBitmap);
    Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
    p.setColor(Color.BLACK);
    clipPath.draw(c, p);
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51538443

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档