原文地址請點擊 原創文章,轉載請聯繫做者java
一夢覺來三十載,休休。空爲梅花白了頭android
Camera2
是目前Android相機開發最新的API,舊版本的Camera
已經被廢棄了。
通常狀況下,Camera2
的使用是將圖像發送到SurfaceView
或者TextureView【經過SurfaceTexture】
來預覽。使用JPEG或者Raw sensor格式的ImageReader來捕獲JPEG圖像或RAW緩衝區。【注1】
今天主要是記錄一下, 在使用Camera2
API開發Android相機過程當中,解決預覽畫面變形的問題。
另,本文所記錄的狀況,都是豎屏狀況的設備。
題主參考Google方法給出的Demo,自定義了TextureView
,能夠自動適配寬高,支持全屏展現。代碼地址AutoFitTextureViewgit
如下的畫面基本上處於同一角度拍攝所得github
變形的畫面
bash
正常的小畫面,以寬爲基準計算高度。ide
正常全屏畫面,高度鋪滿屏幕,畫面被拉近。函數
++在解決方案上,主要參考了Google官方給出的Demo。Camera2VideoFragment++。
在Camera2
的使用上,我使用了TextureView
做爲預覽畫面的承載。爲何不使用SurfaceView
呢?由於SurfaceView
是基於Window層面的View,有不少View的屬性都用不了,使用起來比較麻煩。
Camera2
API會返回一系列能夠用於輸出到SurfaceTexture
的Size集合。--++TextureView顯示原理便是使用SurfaceTexture構建的Surface++ post
如圖:
以題主手上的Oppo r15爲例,總共會返回13個能夠用做輸出的size
須要注意的是,若是以豎屏爲例,這裏的寬高是反過來的
在獲得可用的size集合後,根據實際開發狀況選擇合適的PreviewSize便可ui
選定了一個合適的PreviewSize以後,只須要適配TextureView
的寬高便可。小畫面以寬爲基準,須要根據屏幕寬度來計算相應的高度便可。這一部分的代碼,在官方Demo裏已經至關詳細。其實很簡單,就是自電影AutoFitTextureView裏的onMeasure
函數裏,從新設定寬高。google
override fun onMeasure(....){
if (width < ((height * ratioWidth) / ratioHeight)) {
// 控件自己的寬小於根據比例計算來得寬,則使用控件自己的寬
setMeasuredDimension(width, (width * ratioHeight) / ratioWidth)
} else {
setMeasuredDimension((height * ratioWidth) / ratioHeight, height)
}
}
複製代碼
其中ratioWidth、ratioHeight便是PreviewSize
全屏展現預覽畫面,則須要使用TextureView
的另外一個函數——setTransform
。這個函數是給Textureview
設置一個Transform,用於改變TextureView
的畫面。By,雙指縮放時可使用這個函數。
全屏展現時,TextureView
的寬高鋪滿整個屏幕,相應的咱們只須要改變一下Transform
便可,此時高度不變,可是要將畫面的寬度放大。放大的倍數即爲屏幕的高度除以小畫面時計算得來的高度比例便可。
仍是在onMeasure
函數內:
override fun onmeasure(...){
val w = resources.displayMetrics.widthPixels
val h = resources.displayMetrics.heightPixels
setMeasuredDimension(w, h)
fullScreenTransform.reset()
fullScreenTransform.set(defTransform)
// 寬拉伸,高不變
fullScreenTransform.postScale(h.toFloat() /ratioHeight,
1f, w * 0.5f, h * 0.5f)
setTransform(fullScreenTransform)
}
複製代碼
其中fullScreenTransform即爲TextureView最初始的Transform
題主將AutoFitTextureView
從新封裝了一下,對外提供了全屏展現的開關函數。地址在這裏AutoFitTextureView,感興趣的童鞋能夠去看一下。
以上