通常,拍照预览页面的照片拉伸主要与下面两个因素有关:

1.     Surfaceview的大小

2.     Camera中的Preview的大小

如下图:

    图中preview显示的是手机支持的预览尺寸,picture显示的是手机支持设置图片尺寸,screen显示的是屏幕尺寸,surface显示的是surfaceview尺寸,default pre:手机缺省情况下的预览尺寸,default pic:手机缺省请款下的图片尺寸。reqPreview:手机设置的预览尺寸,reqPicSize:手机设置的图片尺寸。
 

如图,该手机surfaceview大小为1280*720(横屏,比例为:16:9)预览尺寸大小为960*720(横屏,比例为4:3)。从上面的二维码可以看到产生了明显的拉伸。正因为surfaceview的宽高比例跟camera preview的宽高比例不一样才会产生这样的效果。

如果surfaceview尺寸比例跟预览尺寸比例相同,那便不会产生变形,如下图:

设置surfaceview大小为 1280*720(横屏,比例为:4:3)预览尺寸大小为2048*1152(横屏,比例为4:3)便不会拉伸变形。

上面只是针对一种屏幕进行设置,而且每台手机所支持的预览尺寸是不一样的,所以这样子固定死的话很可能会产生程序崩溃,而崩溃的原因是因为该手机不支持你所支持的尺寸。

那么问题就来了,怎么样才能够达到适配多台手机,界面不产生拉伸变形,而且程序又不崩溃?

思路如下:

1.     先将获取手机支持预览的尺寸列表通过方法parmeters.getSupportedPreviewSizes()来得到返回类型为List<Size>的值,

2.     先进行屏幕方向的一个判断,因为预览列表里面的尺寸都是w>h(即横屏),如果屏幕是竖屏则需要先将宽高进行调换,这样方便接下来的比较。

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;
}
}
 

Android Camera多屏幕适配解决预览照片拉伸的更多相关文章

  1. android下在屏幕适配小总结

    为什么要屏幕适配?为此我就不说了,网上处理方法要么让你用几套不同分辨率的图片,要么写几套布局文件,要么就是在xml中写dip(这个还是可以的),前面两种感觉过程工作量太大了,由加载大图片的优化思想 同 ...

  2. Android camera调用出现错误解决方法

    开发时,先是使用三星的手机测试,发现一切正常: 但是到了小米的手机的时候,发现图片很模糊,发现是设置camera.setParameters(parameters);报错导致用的是默认的最小的分辨率, ...

  3. Android下的屏幕适配

    1080 100dp 300px720 100dp 200px 300px 1080px 比例是300/1080=0.277200px 720px

  4. Android 多分辨率多屏幕适配

    请参见文章:http://blog.csdn.net/jiangxinyu/article/details/8598046 文章描述非常清晰.

  5. Android开发——自动生成Android屏幕适配的dimens.xml文件

    使用dimens.xml解决屏幕适配问题是Android官方解决方案,本文主要讲述了如何自动生成Android屏幕适配的dimens.xml,减少了工作量,在维护dimens.xml文件时更加省时省力 ...

  6. Android 多屏幕适配 dp和px的关系 最好用dp

    Android 多屏幕适配 dp和px的关系 一直以来别人经常问我,android的多屏幕适配到底是怎么弄,我也不知道如何讲解清楚,或许自己也是挺迷糊. 以下得出的结论主要是结合官方文档进行分析的ht ...

  7. Android 多屏幕适配 dp和px的关系

    一直以来别人经常问我,android的多屏幕适配到底是怎么弄,我也不知道如何讲解清楚,或许自己也是挺迷糊. 以下得出的结论主要是结合官方文档进行分析的https://developer.android ...

  8. Android屏幕适配笔记

    1.限定符 为了适配不同屏幕大小的android手机或android平板,有时候就需要利用限定符来为不同的屏幕设定不同的布局文件,在一般情况下我们都是在layout文件夹下为某个活动准备一个默认的布局 ...

  9. Android屏幕适配与切图_汇总

    首先和最后,还是先看好官方文档:http://developer.android.com/guide/practices/screens_support.html 对应的翻译blog有牛人做了:And ...

随机推荐

  1. ssm中需要注意的问题

    1.在controller中需要加注解 @Controller @RequestMapping("url") @Autowired private CardService card ...

  2. [原创]python高可用程序设计方法

    有时候程序上的bug会导致程序引发诸如段错误的情况而导致程序异常退出,这时用crond服务来检测,就会有一段时间程序处于不可用的情况,为了增强程序的可用性,我们可以让子进程处理业务,而让主进程检测子进 ...

  3. Java设计模式(6)——创建型模式之原型模式(Prototype)

    一.概述 概念 // 引用自<Java与模式> UML图 第二种:登记式 二.实践 先导知识 对象的拷贝: 直接赋值:此时只是相当于a1,a2指向同一个对象,无论哪一个操作的都是同一个对象 ...

  4. python字符串的方法介绍

    博文取自鱼C论坛文章: http://bbs.fishc.com/forum.php?mod=viewthread&tid=38992&extra=page%3D1%26filter% ...

  5. CC3200使用MQTT的SSL加密证书可用日期修改

    1. 在使用CC3200进行SSL加密的时候,需要证书,但是证书有一个截止日期,如果当前CC3200没有设置这个日期,那么证书通信会失败,需要添加代码 int setDeviceTime() { Sl ...

  6. R语言使用过程中出现的问题--读取EXCEL文件

    方法一: 按照R导论中的方法,使用RODBC包, library(RODBC) channel<-odbcConnectExcel("file.xlsx") da2<- ...

  7. libevent学习二(Working with an event loop)

    Runing the loop #define EVLOOP_ONCE             0x01 #define EVLOOP_NONBLOCK         0x02 #define EV ...

  8. nested class 例子

    #include<iostream> using namespace std; /* start of Enclosing class declaration */ class Enclo ...

  9. 165. Merge Two Sorted Lists【LintCode by java】

    Description Merge two sorted (ascending) linked lists and return it as a new sorted list. The new so ...

  10. [HNOI2018]转盘

    [HNOI2018]转盘 给你一个 \(n\) 元环, 你可以在 \(0\) 时刻从任意一个位置出发, 每一秒可以选择往后或者留在原地每个点有个参数 \(T_i\) , 当你走到 \(i\) 的时间 ...