Android SurfaceView與TextureView使用方法詳細(xì)講解
Surface
官方對(duì)Surface的解釋是:由屏幕合成器管理的原始緩沖區(qū)上的句柄,所謂原生緩沖器,是用于保存當(dāng)前窗口的像素?cái)?shù)據(jù)的,也就是說(shuō),通過(guò)Surface可以獲取原生緩沖器以及其中的內(nèi)容。Surface對(duì)應(yīng)一塊屏幕緩沖區(qū),每個(gè)Window對(duì)應(yīng)一個(gè)Surface,任何View都畫(huà)在Surface上,Surface中的Canvas,是用于提供畫(huà)圖的地方。
SurfaceView
SurfaceView與普通的View不同,它擁有自己的Surface,它的工作方式是創(chuàng)建一個(gè)區(qū)別于應(yīng)用窗口的新窗口,與宿主窗口分離,可以在單獨(dú)線(xiàn)程中處理業(yè)務(wù),不受View的屬性控制,無(wú)法進(jìn)行平移縮放等轉(zhuǎn)換,它是通過(guò)“雙緩沖”機(jī)制來(lái)達(dá)到高效的界面刷新效果。
雙緩沖技術(shù)是把要處理的圖片在內(nèi)存中處理好之后,再將其顯示在屏幕上。雙緩沖主要是為了解決反復(fù)局部刷屏帶來(lái)的閃爍。把要畫(huà)的東西先畫(huà)到一個(gè)內(nèi)存區(qū)域里,然后整體的一次性畫(huà)出來(lái)。
下面通過(guò)一個(gè)相機(jī)預(yù)覽的功能,來(lái)看一下SurfaceView的具體使用
private lateinit var surfaceHolder: SurfaceHolder
獲取攝像機(jī)管理類(lèi),打開(kāi)某個(gè)具體的攝像機(jī),在打開(kāi)成功的回調(diào)里面,創(chuàng)建預(yù)覽請(qǐng)求
val cameraManager = getSystemService(Context.CAMERA_SERVICE) as CameraManager
val surfaceView = findViewById<SurfaceView>(R.id.surfaceView)
surfaceHolder = surfaceView.holder
surfaceHolder.setKeepScreenOn(true)
surfaceHolder.addCallback(object : SurfaceHolder.Callback {
override fun surfaceCreated(p0: SurfaceHolder) {
if (ActivityCompat.checkSelfPermission(
this@SurfaceActivity,
Manifest.permission.CAMERA
) != PackageManager.PERMISSION_GRANTED
) {
//無(wú)相機(jī)權(quán)限
return
}
try {
//獲取可用相機(jī)設(shè)備列表
val cameraIdList = cameraManager.cameraIdList
//打開(kāi)相機(jī)
cameraManager.openCamera(
cameraIdList[0],
//攝像頭創(chuàng)建監(jiān)聽(tīng)
object : CameraDevice.StateCallback() {
override fun onOpened(p0: CameraDevice) { //打開(kāi)攝像頭
try {
startPreview(p0)
} catch (e: CameraAccessException) {
e.printStackTrace()
}
}
override fun onDisconnected(p0: CameraDevice) { //關(guān)閉攝像頭
p0.close()
}
override fun onError(p0: CameraDevice, p1: Int) {
Log.i(tag, "CameraDevice.StateCallback onError")
}
},
null
)
} catch (e: CameraAccessException) {
e.printStackTrace()
}
}
override fun surfaceChanged(p0: SurfaceHolder, p1: Int, p2: Int, p3: Int) {
Log.i(tag, "surfaceChanged")
}
override fun surfaceDestroyed(p0: SurfaceHolder) {
Log.i(tag, "surfaceDestroyed")
}
})開(kāi)始預(yù)覽
private fun startPreview(cameraDevice: CameraDevice) {
val captureRequest = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)
captureRequest.addTarget(surfaceHolder.surface)
cameraDevice.createCaptureSession(
listOf(surfaceHolder.surface),
//會(huì)話(huà)狀態(tài)回調(diào)
object : CameraCaptureSession.StateCallback() {
override fun onConfigured(p0: CameraCaptureSession) {
try {
// 創(chuàng)建預(yù)覽需要的CaptureRequest.Builder
val previewRequestBuilder =
cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)
previewRequestBuilder.addTarget(surfaceHolder.surface)
val previewRequest = previewRequestBuilder.build()
p0.setRepeatingRequest(previewRequest, null, null)
} catch (e: CameraAccessException) {
e.printStackTrace()
}
}
override fun onConfigureFailed(p0: CameraCaptureSession) {
Log.i(tag, "onConfigureFailed")
}
}, null
)
}這樣,簡(jiǎn)易的相機(jī)預(yù)覽功能就出來(lái)啦,當(dāng)然,我們還需要申請(qǐng)CAMERA權(quán)限,這里略去。
TextureView
TextureView可以說(shuō)是一個(gè)結(jié)合了View和SurfaceTexture的View對(duì)象,一個(gè)可以把內(nèi)容流作為外部紋理輸出在上面的 View,它只能用于開(kāi)啟了硬件加速的窗口,TextureView不會(huì)創(chuàng)建一個(gè)獨(dú)立的窗口,而是像普通的View一樣,可以進(jìn)行平移、旋轉(zhuǎn)等動(dòng)畫(huà),TextureView在Andriod 4.0之后的 API 中才能使用,不過(guò)現(xiàn)在的安卓設(shè)備基本不存在Andriod 4.0之前的版本了,所以這點(diǎn)不必在意。
TextureView的使用也比較簡(jiǎn)單,需要獲取到它的SurfaceTexture,然后就可以以此來(lái)渲染了,下面通過(guò)一個(gè)簡(jiǎn)易的視頻播放的示例,來(lái)瞧瞧它是怎么使用的。
val textureView = findViewById<TextureView>(R.id.textureView)
val mediaPlayer = MediaPlayer()
textureView.surfaceTextureListener = object : TextureView.SurfaceTextureListener {
override fun onSurfaceTextureAvailable(p0: SurfaceTexture, p1: Int, p2: Int) {
with(mediaPlayer) {
setDataSource(GlobalData.videoUrl)
setSurface(Surface(p0))
prepare()
start()
Log.i(tag, "setOnPreparedListener")
setOnPreparedListener {
it.start()
}
}
}
override fun onSurfaceTextureSizeChanged(p0: SurfaceTexture, p1: Int, p2: Int) {
}
override fun onSurfaceTextureDestroyed(p0: SurfaceTexture): Boolean {
mediaPlayer.stop()
mediaPlayer.release()
return true
}
override fun onSurfaceTextureUpdated(p0: SurfaceTexture) {
}
}SurfaceTexture
SurfaceTexture是Surface和OpenGL ES紋理的組合,用于提供輸出到OpenGL ES紋理的Surface,和SurfaceView不同的是,它對(duì)圖像流的處理并不直接顯示,而是轉(zhuǎn)為GL外部紋理,因此可用于圖像流數(shù)據(jù)的二次處理,如Camera濾鏡,桌面特效等,但是這樣會(huì)有若干幀的延遲。同時(shí),由于它本身管理BufferQueue,因此內(nèi)存消耗也會(huì)稍微大一些。比如Camera的預(yù)覽數(shù)據(jù),變成紋理后就可以通過(guò)SurfaceTexture交給TextureView作為View層級(jí)中的一個(gè)硬件加速層來(lái)顯示。
SurfaceView和TextureView的區(qū)別
- SurfaceView是直接輸出的,擁有自己獨(dú)立Surface,它的渲染可以放在單獨(dú)線(xiàn)程,其缺點(diǎn)是不能做變形和動(dòng)畫(huà)。
- TextureView是一個(gè)可以把內(nèi)容流作為外部紋理輸出的,本身必須是一個(gè)硬件加速層,顯示畫(huà)面更新時(shí)有1~3幀的延遲。
- TextureView本身也包含了SurfaceTexture,它與SurfaceView+SurfaceTexture組合相比,也可以把內(nèi)容流上的圖像轉(zhuǎn)成紋理輸出,區(qū)別在于TextureView是在View層級(jí)中繪制的,而SurfaceView+SurfaceTexture在單獨(dú)的Surface上做繪制的。
| SurfaceView | TextureView |
|---|---|
| 占用內(nèi)存低 | 占用內(nèi)存高 |
| 耗電低 | 耗電高 |
| 繪制及時(shí) | 1-3幀延時(shí) |
| 不支持動(dòng)畫(huà)截圖 | 支持動(dòng)畫(huà)截圖 |
個(gè)人覺(jué)得,對(duì)于需要不斷更新畫(huà)布的游戲來(lái)說(shuō),SurfaceView是最好的選擇,對(duì)于視頻播放器或相機(jī)應(yīng)用的開(kāi)發(fā),則TextureView更加適合。
到此這篇關(guān)于Android SurfaceView與TextureView使用方法詳細(xì)講解的文章就介紹到這了,更多相關(guān)Android SurfaceView與TextureView內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android 高德地圖之poi搜索功能的實(shí)現(xiàn)代碼
這篇文章主要介紹了android 高德地圖之poi搜索功能的實(shí)現(xiàn)代碼,在實(shí)現(xiàn)此功能時(shí)遇到很多問(wèn)題,在文章都給大家提到,需要的朋友可以參考下2017-08-08
Android開(kāi)發(fā)中的文件操作工具類(lèi)FileUtil完整實(shí)例
這篇文章主要介紹了Android開(kāi)發(fā)中的文件操作工具類(lèi)FileUtil,結(jié)合完整實(shí)例形式分析了Android文件操作的常用技巧,包括文件的獲取、遍歷、搜索、復(fù)制、刪除、判斷等功能,需要的朋友可以參考下2017-11-11
Android使用setCustomTitle()方法自定義對(duì)話(huà)框標(biāo)題
Android有自帶的對(duì)話(huà)框標(biāo)題,但是不太美觀(guān),如果要給彈出的對(duì)話(huà)框設(shè)置一個(gè)自定義的標(biāo)題,使用AlertDialog.Builder的setCustomTitle()方法非常方便,接下來(lái)通過(guò)本文給大家介紹Android使用setCustomTitle()方法自定義對(duì)話(huà)框標(biāo)題,感興趣的朋友一起學(xué)習(xí)吧2016-02-02
Jetpack?Compose實(shí)現(xiàn)點(diǎn)擊事件click的多種方法
這篇文章主要介紹了Jetpack?Compose實(shí)現(xiàn)點(diǎn)擊事件的多種方法,Jetpack?Compose是一款基于Kotlin的聲明式UI工具包,可以方便地創(chuàng)建漂亮的用戶(hù)界面,下面我們就來(lái)看看Jetpack?Compose添加點(diǎn)擊事件都可以怎么實(shí)現(xiàn)2024-02-02
基于Android實(shí)現(xiàn)3D翻頁(yè)效果
這篇文章主要為大家詳細(xì)介紹了基于Android實(shí)現(xiàn)3D翻頁(yè)效果的具體代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-06-06
Android編程實(shí)現(xiàn)微信分享信息的方法
這篇文章主要介紹了Android編程實(shí)現(xiàn)微信分享信息的方法,實(shí)例分析了Android官方demo示例,講述了Android微信分享功能的具體實(shí)現(xiàn)技巧,需要的朋友可以參考下2015-10-10
Android UI自定義ListView實(shí)現(xiàn)下拉刷新和加載更多效果
這篇文章主要介紹了Android UI自定義ListView實(shí)現(xiàn)下拉刷新和加載更多效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11
Android編程創(chuàng)建桌面快捷方式的常用方法小結(jié)【2種方法】
這篇文章主要介紹了Android編程創(chuàng)建桌面快捷方式的常用方法,結(jié)合實(shí)例形式總結(jié)分析了2種常見(jiàn)的實(shí)現(xiàn)方法與相關(guān)操作技巧,需要的朋友可以參考下2017-02-02
淺談android獲取設(shè)備唯一標(biāo)識(shí)完美解決方案
本篇文章主要介紹了淺談android獲取設(shè)備唯一標(biāo)識(shí)完美解決方案,具有一定的參考價(jià)值,有興趣的可以了解一下2017-08-08

