Android截屏SurfaceView黑屏问题的解决办法

发布时间 - 2026-01-11 01:21:03    点击率:

最近项目中有截屏的需求,普通的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的方法,百度一下有很多,不再赘述。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


# Android  # 截屏  # SurfaceView  # 黑屏  # android surfaceView实现播放视频功能  # android使用surfaceview+MediaPlayer播放视频  # Android SurfaceView预览变形完美解决方法  # Android使用SurfaceView实现飘赞动画  # Android Surfaceview的绘制与应用  # Android SurfaceView拍照录像实现方法  # Android系统view与SurfaceView的基本使用及区别分析  # 自己的  # 解锁  # 画好  # 子类  # 有很多  # 是怎么  # 中有  # 再加上  # 看我  # 可以看到  # 不含  # 时就  # 如何使用  # 创建一个  # 大家多多  # 就可以  # 要拿  # 一搜  # 找到了 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 大连网站制作费用,大连新青年网站,五年四班里的视频怎样下载啊?  jQuery 常见小例汇总  如何快速搭建高效服务器建站系统?  Laravel如何操作JSON类型的数据库字段?(Eloquent示例)  如何登录建站主机?访问步骤全解析  C++时间戳转换成日期时间的步骤和示例代码  laravel怎么用DB facade执行原生SQL查询_laravel DB facade原生SQL执行方法  php结合redis实现高并发下的抢购、秒杀功能的实例  JS碰撞运动实现方法详解  SQL查询语句优化的实用方法总结  微博html5版本怎么弄发超话_超话进入入口及发帖格式要求【教程】  高防服务器如何保障网站安全无虞?  如何确保FTP站点访问权限与数据传输安全?  高端智能建站公司优选:品牌定制与SEO优化一站式服务  Laravel如何处理文件上传_Laravel Storage门面实现文件存储与管理  三星网站视频制作教程下载,三星w23网页如何全屏?  Laravel与Inertia.js怎么结合_使用Laravel和Inertia构建现代单页应用  如何快速搭建高效WAP手机网站吸引移动用户?  ChatGPT 4.0官网入口地址 ChatGPT在线体验官网  个人网站制作流程图片大全,个人网站如何注销?  edge浏览器无法安装扩展 edge浏览器插件安装失败【解决方法】  手机钓鱼网站怎么制作视频,怎样拦截钓鱼网站。怎么办?  laravel怎么为API路由添加签名中间件保护_laravel API路由签名中间件保护方法  Laravel怎么使用Session存储数据_Laravel会话管理与自定义驱动配置【详解】  网站制作怎么样才能赚钱,用自己的电脑做服务器架设网站有什么利弊,能赚钱吗?  微信小程序 HTTPS报错整理常见问题及解决方案  java获取注册ip实例  香港服务器网站推广:SEO优化与外贸独立站搭建策略  EditPlus中的正则表达式实战(5)  如何在IIS服务器上快速部署高效网站?  Win11怎么设置默认图片查看器_Windows11照片应用关联设置  如何用狗爹虚拟主机快速搭建网站?  Win11怎样安装网易有道词典_Win11安装词典教程【步骤】  Firefox Developer Edition开发者版本入口  如何续费美橙建站之星域名及服务?  javascript中的try catch异常捕获机制用法分析  在centOS 7安装mysql 5.7的详细教程  如何快速上传建站程序避免常见错误?  Laravel如何为API生成Swagger或OpenAPI文档  如何快速打造个性化非模板自助建站?  Laravel如何使用Gate和Policy进行授权?(权限控制)  微信推文制作网站有哪些,怎么做微信推文,急?  香港服务器选型指南:免备案配置与高效建站方案解析  Laravel用户认证怎么做_Laravel Breeze脚手架快速实现登录注册功能  如何确保西部建站助手FTP传输的安全性?  如何在局域网内绑定自建网站域名?  如何快速搭建FTP站点实现文件共享?  北京网页设计制作网站有哪些,继续教育自动播放怎么设置?  Laravel如何使用Scope本地作用域_Laravel模型常用查询逻辑封装技巧【手册】  html文件怎么打开证书错误_https协议的html打开提示不安全【指南】