在安卓系统中,以编程方式截取自定义视图的屏幕截图无法正常工作

3
我有一个自定义视图,像这样:
public class RoundedCornerLayout extends FrameLayout
{
    private final static float CORNER_RADIUS = 100.0f;

    private Bitmap maskBitmap;
    private Paint paint, maskPaint;
    private float cornerRadius;

    public RoundedCornerLayout(Context context)
    {
        super(context);
        init(context, null, 0);
    }

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

    public RoundedCornerLayout(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
        init(context, attrs, defStyle);
    }

    private void init(Context context, AttributeSet attrs, int defStyle)
    {
        p = new Paint();
        p.setFlags(Paint.ANTI_ALIAS_FLAG);
        p.setColor(Color.WHITE);
        p.setStyle(android.graphics.Paint.Style.STROKE);
        p.setStrokeWidth(6);

        pp = new Paint();
        pp.setColor(Color.parseColor("#686868"));

        DisplayMetrics metrics = context.getResources().getDisplayMetrics();
        cornerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, CORNER_RADIUS, metrics);

        paint = new Paint(Paint.ANTI_ALIAS_FLAG);

        maskPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
        maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));

        setWillNotDraw(false);
    }

    Paint p;
    Paint pp;

    @Override
    public void draw(Canvas canvas)
    {

        android.util.Log.e("MAYUR", "draw");

        canvas.drawCircle(canvas.getWidth() / 2, canvas.getHeight() / 2, canvas.getWidth() / 2, pp);

        Bitmap offscreenBitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas offscreenCanvas = new Canvas(offscreenBitmap);

        super.draw(offscreenCanvas);

        if (maskBitmap == null)
        {
            maskBitmap = createMask(canvas.getWidth(), canvas.getHeight());
        }

        offscreenCanvas.drawBitmap(maskBitmap, 0f, 0f, maskPaint);
        canvas.drawBitmap(offscreenBitmap, 0f, 0f, paint);

        canvas.drawCircle(canvas.getWidth() / 2, canvas.getHeight() / 2, (canvas.getWidth() - 6) / 2, p);
    }

    private Bitmap createMask(int width, int height)
    {
        Bitmap mask = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8);
        Canvas canvas = new Canvas(mask);

        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.WHITE);

        canvas.drawRect(0, 0, width, height, paint);

        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        canvas.drawRoundRect(new RectF(0, 0, width, height), cornerRadius, cornerRadius, paint);

        return mask;
    }
}

而我是这样截屏的,
View v1 = ll_contain;
v1.setDrawingCacheEnabled(true);
v1.buildDrawingCache(true);
Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
v1.setDrawingCacheEnabled(false);

保存位图到SD卡,但保存结果与屏幕上显示的不同。为什么?我做错了什么?
请给我解决这个问题的方向,我尝试搜索问题,但没有找到任何人遇到过这种类型的问题。
屏幕上的视图显示如下:

enter image description here

在截屏时,它会像这样保存:

enter image description here

2个回答

1
我遇到了类似的问题(对于Drawable),问题在于在调用drawCircle时使用canvas.getHeight()canvas.getWidth()方法来确定位置和大小。实际绘制视图时,这些方法返回与视图尺寸相同的值,一切正常。但是在绘制截图时,它们将返回整个截图的高度和宽度,而不是视图的尺寸。
解决方法是计算变量canvasHeightcanvasWidth如下:
  • 对于drawable:canvasWidth = getBounds().width();
  • 对于view:canvasWidth = getRight() - getLeft();

0

我测试了您的代码,并且在将绘图缓存保存到sdcard时没有遇到任何问题/瑕疵,如下面的屏幕截图所示:

device screenshot vs drawing cache

你是如何将位图保存到SD卡的?我使用以下方法,在布局准备好时调用:
private void saveScreenShot(){
        View v1 = findViewById(R.id.container);
        v1.setDrawingCacheEnabled(true);
        v1.buildDrawingCache(true);
        Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
        v1.setDrawingCacheEnabled(false);
        FileOutputStream out = null;
        try {
            out = new FileOutputStream("/sdcard/test.png");
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

您可以尝试在init()方法中强制将视图的层类型设置为SOFTWARE,看看是否会有所改变:

private void init(Context context, AttributeSet attrs, int defStyle){
  setLayerType(LAYER_TYPE_SOFTWARE, null);
  //...
}

谢谢您测试我的代码。如果您在xml中使用RoundedCornerLayout时,同时将其高度和宽度设置为200dp并保存,那么一定会出现问题。 - Mayur R. Amipara
@MayurR.Amipara 我已将宽度和高度都设置为200dp,保存时仍然没有问题。 - bonnyz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接