1. Surfaceview的大小android
2. Camera中的Preview的大小ide
如圖,該手機surfaceview大小爲1280*720(橫屏,比例爲:16:9)預覽尺寸大小爲960*720(橫屏,比例爲4:3)。從上面的二維碼能夠看到產生了明顯的拉伸。正由於surfaceview的寬高比例跟camera preview的寬高比例不同纔會產生這樣的效果。post
若是surfaceview尺寸比例跟預覽尺寸比例相同,那便不會產生變形,以下圖:this
設置surfaceview大小爲 1280*720(橫屏,比例爲:4:3)預覽尺寸大小爲2048*1152(橫屏,比例爲4:3)便不會拉伸變形。spa
上面只是針對一種屏幕進行設置,並且每臺手機所支持的預覽尺寸是不同的,因此這樣子固定死的話極可能會產生程序崩潰,而崩潰的緣由是由於該手機不支持你所支持的尺寸。.net
思路以下:code
1. 先將獲取手機支持預覽的尺寸列表經過方法parmeters.getSupportedPreviewSizes()來獲得返回類型爲List<Size>的值,orm
2. 先進行屏幕方向的一個判斷,由於預覽列表裏面的尺寸都是w>h(即橫屏),若是屏幕是豎屏則須要先將寬高進行調換,這樣方便接下來的比較。blog
3. 先用for循環將預覽尺寸列表每一個元素寬高與surfaceview的寬高進行比較,若是存在寬高尺寸都與surfaceview寬高尺寸相同的size則將該寬高設置爲預覽尺寸。圖片
4. 若是步驟2找不到相同尺寸就得進行該步驟,將尺寸列表的寬高比例和surfaceview的比例做比較,找到一個相同或相近的。(通常來講,只要surfaceview的尺寸和屏幕尺寸相同,就能夠找到相同的比例)而後將該尺寸的size設置爲預覽尺寸。
接下來是上代碼
/** * 經過對比獲得與寬高比最接近的尺寸(若是有相同尺寸,優先選擇) * * @param surfaceWidth * 須要被進行對比的原寬 * @param surfaceHeight * 須要被進行對比的原高 * @param preSizeList * 須要對比的預覽尺寸列表 * @return 獲得與原寬高比例最接近的尺寸 */ protected Camera.Size getCloselyPreSize(int surfaceWidth, int surfaceHeight, List<Size> preSizeList) { int ReqTmpWidth; int ReqTmpHeight; // 當屏幕爲垂直的時候須要把寬高值進行調換,保證寬大於高 if (mIsPortrait) { ReqTmpWidth = surfaceHeight; ReqTmpHeight = surfaceWidth; } else { ReqTmpWidth = surfaceWidth; ReqTmpHeight = surfaceHeight; } //先查找preview中是否存在與surfaceview相同寬高的尺寸 for(Camera.Size size : preSizeList){ if((size.width == ReqTmpWidth) && (size.height == ReqTmpHeight)){ return size; } } // 獲得與傳入的寬高比最接近的size float reqRatio = ((float) ReqTmpWidth) / ReqTmpHeight; float curRatio, deltaRatio; float deltaRatioMin = Float.MAX_VALUE; Camera.Size retSize = null; for (Camera.Size size : preSizeList) { curRatio = ((float) size.width) / size.height; deltaRatio = Math.abs(reqRatio - curRatio); if (deltaRatio < deltaRatioMin) { deltaRatioMin = deltaRatio; retSize = size; } } return retSize; }
其中 參數 width 和height 是 SurfaceView 的寬和高,能夠在surfaceChanged方法中找到:
package com.yfqsdie.tower.preview; import com.yfqsdie.tower.util.CameraUtil; import android.content.Context; import android.graphics.PixelFormat; import android.hardware.Camera; import android.os.Handler; import android.util.AttributeSet; import android.view.SurfaceHolder; import android.view.SurfaceView; /** * Created by renlei * DATE: 15-11-5 * Time: 下午4:52 */ public class MySurfacePreview extends SurfaceView implements SurfaceHolder.Callback { private SurfaceHolder surfaceHolder; private Handler mHandler; public MySurfacePreview(Context context, AttributeSet attrs) { super(context, attrs); surfaceHolder = getHolder(); surfaceHolder.setFormat(PixelFormat.TRANSPARENT);//translucent半�?�明 transparent透明 surfaceHolder.addCallback(this); } @Override public void surfaceCreated(SurfaceHolder holder) { CameraUtil.getInstance().doOpenCamera(Camera.CameraInfo.CAMERA_FACING_BACK); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { System.out.print("width="+width+" height="+height+" format="+format); // CameraUtil.getInstance().doStartPreview(surfaceHolder); CameraUtil.getInstance().doStartPreview(surfaceHolder,width,height); //spire modify 2017-09-27 解決變形問題 if (mHandler != null) { mHandler.postDelayed(new Runnable() { @Override public void run() { mHandler.sendEmptyMessage(CameraUtil.PREVIEW_HAS_STARTED); } }, 1000); } } @Override public void surfaceDestroyed(SurfaceHolder holder) { CameraUtil.getInstance().doStopPreview(); } public void setmHandler(Handler handler) { this.mHandler = handler; } }