当前位置: 首页 > web >正文

Android修行手册 - TextureView和SurfaceView的属性方法以及示例

往期文章分享
  • 点击跳转=>《导航贴》- Unity手册,系统实战学习
  • 点击跳转=>《导航贴》- Android手册,重温移动开发

本文约8.6千字,新手阅读需要11分钟,复习需要4分钟收藏随时查阅不再迷路

👉关于作者

众所周知,人生是一个漫长的流程,不断克服困难,不断反思前进的过程。在这个过程中会产生很多对于人生的质疑和思考,于是我决定将自己的思考,经验和故事全部分享出来,以此寻找共鸣 !!!
专注于Android/Unity和各种游戏开发技巧,以及各种资源分享(网站、工具、素材、源码、游戏等)
有什么需要欢迎私我,交流群让学习不再孤单

在这里插入图片描述

👉前提

这是小空坚持写的Android新手向系列,欢迎品尝。

大佬(√)

新手(√√√)

👉实践过程

😜SurfaceView属性和方法

surfaceCreated(@NonNull SurfaceHolder holder):surface创建时回调

surfaceDestroyed(@NonNull SurfaceHolder holder):surface销毁时回调

surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height):surface发生变化时回调

SurfaceHolder.addCallback(context):添加回调,也就是上面三个方法

lockCanvas():获取Canvas对象并锁定画布,调用Canvas进行绘图,和unlockCanvasAndPost是依次成对出现。

unlockCanvasAndPost():结束锁定画布,并且提交改变。和lockCanvas是依次成对出现。

😜TextureView属性和方法

getSurfaceTexture():此方法返回此视图使用的 SurfaceTexture。

getBitmap(整型宽度,整型高度):此方法返回返回关联表面纹理内容的位图表示形式。

getTransform(Matrix transform):此方法返回与此纹理视图关联的转换。

isOpaque():此方法指示此视图是否不透明。

lockCanvas():此方法开始编辑曲面中的像素。

setOpaque(boolean opaque):此方法指示此纹理视图的内容是否不透明。

setTransform(Matrix transform):此方法将转换设置为与此纹理视图关联。

unlockCanvasAndPost(Canvas canvas):此方法完成对曲面中像素的编辑。

onSurfaceTextureAvailable(SurfaceTexture arg0, int arg1, int arg2):创建的监听,前提开启硬件加速

onSurfaceTextureDestroyed(SurfaceTexture arg0):销毁的监听

onSurfaceTextureSizeChanged(SurfaceTexture arg0, int arg1,int arg2):变化的监听

onSurfaceTextureUpdated(SurfaceTexture arg0):更新的监听

😜TextureView示例

public class MainActivity extends Activity implements SurfaceTextureListener{private Camera mCamera;private TextureView [mTextureView]();protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mTextureView = new TextureView(this);mTextureView.setSurfaceTextureListener(this);setContentView(mTextureView);}public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {mCamera = Camera.open();try {mCamera.setPreviewTexture(surface);mCamera.startPreview();//可以修改透明度和旋转方向mTextureView.setAlpha(1.0f);mTextureView.setRotation(90.0f);} catch (IOException ioe) {// 异常处理}}public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {}public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {mCamera.stopPreview();mCamera.release();return true;}public void onSurfaceTextureUpdated(SurfaceTexture surface) {}
}

😜SurfaceView示例

16.TextureView和SurfaceView-心电图.gif

Java版本自定义

/*** Created by akitaka on 2022-06-20.** @author akitaka* @filename ECGSurfaceView* @describe  绘制心电图案例,注意里面的数字都是测试临时写的,真实的功能一定是适配的动态变量值* @email 960576866@qq.com*/
public class ECGSurfaceViewJava extends SurfaceView implements SurfaceHolder.Callback {//简单模拟一下数据public List<Integer> ecgDatas = new ArrayList<>();//矩阵  画布 画笔 颜色private Rect rect;private Canvas mCanvas;private Paint mPaint;  //画波形的画笔private String line_color = "#01FC00";  //画笔默认是绿色的private int wave_speed = 30;//定义波速:30mm/sprivate int sleepTime = 8;//每次锁屏的时间间距,单位ms 连线的时间长度,,如果大则会卡顿效果private SurfaceHolder surfaceHolder;private boolean isCanRun = true;private int mStartX = 0;private int mStartY = 0;private Runnable drawRunnable = new Runnable() {@Overridepublic void run() {while (isCanRun) {//在这获取改view的宽度  如果mStartX超过则归位 这样实现反复从头画,我这800只是简单表示下效果if (mStartX > 800) {mStartX = 0;}//绘制区域不断向右变化rect.set(mStartX, 0, mStartX + 16, 300);mCanvas = surfaceHolder.lockCanvas(rect);  //提交绘制区域if (mCanvas == null) return;//很重要,如果反复从头绘制,会覆盖上一次的绘制mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);if (ecgDatas.size() > 0) {mCanvas.drawLine(mStartX, mStartY, mStartX + 16, ecgDatas.get(0), mPaint);//这个点的重点是下一个点的起点mStartX = mStartX + 16;mStartY = ecgDatas.get(0);ecgDatas.remove(0);} else {initData();}surfaceHolder.unlockCanvasAndPost(mCanvas);    //这种方式把上次绘制的遮盖了 因此出现了断点}}};public ECGSurfaceViewJava(Context context, AttributeSet attrs) {super(context, attrs);this.surfaceHolder = this.getHolder();//获取holderthis.surfaceHolder.addCallback(this);rect = new Rect();  //绘制矩阵内mPaint = new Paint();mPaint.setColor(Color.parseColor(line_color));   //画笔颜色mPaint.setAntiAlias(true);   //抗锯齿mPaint.setStrokeWidth(2);initData();}private void initData() {ecgDatas.clear();for (int i = 0; i < 200; i++) {ecgDatas.add((int) (Math.random() * 200));}mStartY = ecgDatas.get(0);}@Overridepublic void surfaceCreated(SurfaceHolder holder) {new Thread(drawRunnable).start();}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {isCanRun = false;}
}

Kotlin版本自定义

/*** Created by akitaka on 2022-06-20.* @author akitaka* @filename ECGSurfaceViewKotlin* @describe* @email 960576866@qq.com*/
class ECGSurfaceViewKotlin(context: Context?, attrs: AttributeSet?) : SurfaceView(context, attrs), SurfaceHolder.Callback {//简单模拟一下数据var ecgDatas: MutableList<Int> = ArrayList()//矩阵  画布 画笔 颜色private var rect: Rect? = nullprivate var mCanvas: Canvas? = null//画波形的画笔private var mPaint: Paint? = nullprivate val line_color = "#01FC00" //画笔默认是绿色的private val wave_speed = 30 //定义波速:30mm/sprivate val sleepTime = 8 //每次锁屏的时间间距,单位ms 连线的时间长度,,如果大则会卡顿效果var surfaceHolder: SurfaceHolder? = nullprivate var isCanRun = trueprivate var mStartX = 0private var mStartY = 0private val drawRunnable = Runnable {while (isCanRun) {//在这获取改view的宽度  如果mStartX超过则归位 这样实现反复从头画,我这800只是简单表示下效果if (mStartX > 800) {mStartX = 0}//绘制区域不断向右变化rect!![mStartX, 0, mStartX + 16] = 300mCanvas = surfaceHolder!!.lockCanvas(rect) //提交绘制区域if (mCanvas == null) return@Runnable//很重要,如果反复从头绘制,会覆盖上一次的绘制mCanvas!!.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)if (ecgDatas.size > 0) {mCanvas!!.drawLine(mStartX.toFloat(), mStartY.toFloat(), (mStartX + 16).toFloat(), ecgDatas[0].toFloat(), mPaint)//这个点的重点是下一个点的起点mStartX = mStartX + 16mStartY = ecgDatas[0]ecgDatas.removeAt(0)} else {initData()}surfaceHolder!!.unlockCanvasAndPost(mCanvas!!) //这种方式把上次绘制的遮盖了 因此出现了断点}}init {surfaceHolder = this.holder //获取holdersurfaceHolder!!.addCallback(this)rect = Rect() //绘制矩阵内mPaint = Paint()mPaint!!.setColor(Color.parseColor(line_color)) //画笔颜色mPaint!!.setAntiAlias(true) //抗锯齿mPaint!!.setStrokeWidth(2f)initData()}private fun initData() {ecgDatas.clear()for (i in 0..199) {ecgDatas.add((Math.random() * 200).toInt())}mStartY = ecgDatas[0]}override fun surfaceCreated(holder: SurfaceHolder?) {Thread(drawRunnable).start()}override fun surfaceChanged(holder: SurfaceHolder?, format: Int, width: Int, height: Int) {}override fun surfaceDestroyed(holder: SurfaceHolder?) {isCanRun = false}
}

布局直接使用即可:

<cn.appstudy.customView.ECGSurfaceViewJavaandroid:layout_width="match_parent"android:layout_height="200dp"/><cn.appstudy.customView.ECGSurfaceViewKotlinandroid:layout_width="match_parent"android:layout_height="200dp"android:layout_marginTop="220dp" />

上面小空只是简单写了下示例,如果是画心电图其实还有更多的逻辑,比如多个心电图同步,比如超出屏幕后回到起始位置,比如实时更新心电图数据,再比如心电图速度控制等等。

而且上面心电图示例是从左到右的,还有可能从上到下,从右到左的等等,更多功能就交给大佬们去开发了。

👉其他

📢作者:小空和小芝中的小空
📢转载说明-务必注明来源:https://zhima.blog.csdn.net/
📢这位道友请留步☁️,我观你气度不凡,谈吐间隐隐有王者霸气💚,日后定有一番大作为📝!!!旁边有点赞👍收藏🌟今日传你,点了吧,未来你成功☀️,我分文不取,若不成功⚡️,也好回来找我。

温馨提示点击下方卡片获取更多意想不到的资源。
空名先生

http://www.xdnf.cn/news/10977.html

相关文章:

  • 老板口中的一区二区是什么意思?
  • 列表滚动底部加载下一页
  • EJB进行开发项目
  • 使用 Version Catalogs统一配置版本 (Gradle 7.0+ 特性)
  • 每天总结一个html标签——area与map标签
  • 终极陷阱:Java序列化漏洞的内爆原理与防御体系重建
  • 6.3本日总结
  • Python-nuitka
  • LARWINER拉威兒艺术珠宝携手郭培GUOPEI高定服装 共谱「宝光凝粹,锦绣华裳」
  • 依赖注入-@Resource和@Autowired
  • 多数据库学习之星瑞格[SinoDB]数据库安装部署指南
  • CppCon 2014 学习:CONVERGENT EVOLUTION
  • Modbus转Ethernet IP网关助力罗克韦尔PLC数据交互
  • Ubuntu系统 | 本地部署ollama+deepseek
  • 青少年近视防控的科学抉择:长期佩戴与间断使用的深度解析
  • MicroPython+ESP32 连接接WIFI
  • 【散刷】二叉树基础OJ题(二)
  • 基于VLC的Unity视频播放器(四)
  • 如何写一条高效分页 SQL?
  • RK3568驱动指南|第十二篇 GPIO子系统-第130章 GPIO的调试方法
  • 数据安全管理进阶:81页 2024数据安全典型场景案例集【附全文阅读】
  • MyBatis常用注解全解析:从基础CRUD到高级映射
  • Shell脚本编程入门与实战指南
  • Qwen2.5-VL 视觉编码器的SwiGLU
  • IT运维工具的选择标准有哪些?
  • [蓝桥杯]求解台阶问题
  • PCI DSS培训记录
  • 便携式雷达信号模拟器,定义复杂电磁环境模拟新标准
  • Docker 容器化:核心技术原理与实践
  • 微软PowerBI考试 PL300-Power BI 入门