自定义视图截图以编程方式在android中不起作用

时间:2015-10-03 11:19:24

标签: android screenshot android-custom-view android-screen

我有这样的自定义视图,

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 个答案:

答案 0 :(得分:1)

我遇到了类似的问题(对于Drawable),问题主要在于canvas.getHeight()canvas.getWidth()方法在制作{{1}时的位置和大小打电话。在实际绘制视图时,这些方法返回与视图尺寸相同的值,一切都很顺利。在绘制屏幕截图时,这些将返回整个屏幕截图的高度和宽度,而不是视图的尺寸。

解决方案是将变量drawCirclecanvasHeight计算为 如下:

  • 对于drawable:canvasWidth
  • 查看:canvasWidth = getBounds().width();

答案 1 :(得分:0)

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

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);
  //...
}