Android截屏SurfaceView黑屏問題解決辦法


最近項目中有截屏的需求,普通的view截屏方法網上一搜一大把,但是SurfaceView截屏黑屏問題很多文章說的並不清楚,自己參考了一些別的博客,再加上自己的思考,算是找到了一種解決方案。

1、首先看我們一般是怎么用SurfaceView的

public class SuperSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
    SurfaceHolder surfaceHolder;

    public SuperSurfaceView(Context context) {
        super(context);
        surfaceHolder = this.getHolder();
        surfaceHolder.addCallback(this);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
                               int height) {

    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        new Thread(new MyThread()).start();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {

    }

    class MyThread implements Runnable {
        @Override
        public void run() {
            Canvas canvas = surfaceHolder.lockCanvas(null);//獲取畫布
            Paint mPaint = new Paint();
            mPaint.setColor(Color.BLUE);
            canvas.drawRect(new RectF(100, 100, 1000, 550), mPaint);
            surfaceHolder.unlockCanvasAndPost(canvas);//解鎖畫布,提交畫好的圖像

        }
    }
}

  從以上代碼中,可以看到在MyThread的run方法中創建了一塊畫布,進行SurfaceView的繪制,但是我們知道SurfaceView是雙緩沖機制,這個Canvas上的內容我們拿不到,所以截屏出來是黑屏。所以,要拿到這個畫布上的內容,就自己創建一個畫布,將這些內容畫到自己的Canvas上,就可以了。

2、拿到SurfaceView畫布上的bitmap,看修改過后的代碼

public abstract class SuperSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
    SurfaceHolder surfaceHolder;

    public SuperSurfaceView(Context context) {
        super(context);
        surfaceHolder = this.getHolder();
        surfaceHolder.addCallback(this);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
                               int height) {

    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        new Thread(new MyThread()).start();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {

    }

    class MyThread implements Runnable {
        @Override
        public void run() {
            Canvas canvas = surfaceHolder.lockCanvas(null);//獲取畫布
            doDraw(canvas);
            surfaceHolder.unlockCanvasAndPost(canvas);//解鎖畫布,提交畫好的圖像

        }
    }

    //將繪制圖案的方法抽象出來,讓子類實現,調用getBitmap方法時就會調用此方法
    protected abstract void doDraw(Canvas canvas);

    //調用該方法將doDraw繪制的圖案繪制在自己的canvas上
    public Bitmap getBitmap() {
        Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        doDraw(canvas);
        return bitmap;
    }
}

3、下面看MainActivity中如何使用

        Button bt = (Button) findViewById(R.id.bt);
        FrameLayout fl = (FrameLayout) findViewById(R.id.fl);
        //用到surfaceview需繼承SuperSurfaceView才能截到屏,否則截出來是黑屏
        SuperSurfaceView surfaceView = new SuperSurfaceView(this) {
            @Override
            protected void doDraw(Canvas canvas) {
                Paint mPaint = new Paint();
                mPaint.setColor(Color.BLUE);
                canvas.drawRect(new RectF(100, 100, 1000, 550), mPaint);
            }
        };
        fl.addView(surfaceView);

        bt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //調用該方法即可得到surfaceview上繪制的圖案
                Bitmap bitmap = surfaceView.getBitmap();
            }
        });

 補充:如果界面上還有其他控件需要一起截屏,可以將截到的surfaceview的bitmap和用普通辦法截到的不含surfaceview的bitmap拼接起來就OK了,至於兩個bitmap合為一個bitmap的方法,百度一下有很多,不再贅述。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM