2023年7月13日发(作者:)
Android Camera做全屏预览之最简单方法
M厂开发五部:刘 博
一、全屏预览与非全屏预览的区别
对于大多数人来说,我们看电影、玩游戏等都喜欢全屏,我们之所以喜欢全屏的一个主要原因就是全屏的感觉比非全屏看起来的感觉爽,因为画面看起来变大了,有些微小的东西也能够看清楚了。即使有时候不能够去全屏欣赏,我们也会尽量去把画面调到最大化去享受。
20世纪80年代到20世纪末,绝大部分人的生活质量都不怎么好,他们看电视都使用的是屏幕25寸以下的黑白电视机或画面不怎么好的彩色电视机,甚至有的家庭都没有电视机。但是随着社会的发展,科技的进步,人们为了追求好的生活质量,我们可以看到当今社会大部分家庭所使用的电视机都是超大屏幕的,屏幕尺寸大到50寸以上,并且流行的电视机都是超大屏幕。因为消费者意识到屏幕大可以带给他们宽阔美好的视觉感。那么我们手机的Camera做全屏预览是否也是因为上述的原因呢?
今天,智能手机深受广大消费者的喜爱,尤其是对于年轻的消费者。Camera是智能手机的亮点之一, Camera做成全屏预览就能够给手机增加亮点。所谓Camera的全屏预览就是Camera的预览界面占据手机的整个屏幕,否则,就是非全屏预览。首先看一下下面两张图片所示的效果: 图1:非全屏预览界面
图2:全屏预览界面
图1和图2分别是非全屏预览Camera和全屏预览Camera去预览同一个界面所显示的不同效果,它们的不同点就在于非全屏预览比全屏预览显示的预览界面小。具体体现在图1和图2的最右侧,非全屏预览图片最右侧看不到Camera的预览界面,而全屏预览图片整个屏幕都可以看得到Camera的预览界面。那么Camera用非全屏预览和全屏预览拍摄出来的照片有区别吗?答案是肯定的,继续使用图1和图2中的预览界面,用非全屏预览和全屏预览拍摄出来的照片如下:
图3:非全屏预览拍摄的照片
图4:全屏预览拍摄的照片 图3和图4分别展示的是用Camera非全屏预览和全屏预览拍摄出来的照片,我们明显可以看出非全屏预览拍摄的照片比全屏预览拍摄的照片短一点。同一个取景画面,同一个手机,唯一不同的就是手机的Camera一个是非全屏预览,一个是全屏预览,这也就是为什么两张照片大小不一样的原因之所在。
二、全屏预览与非全屏预览的本质差异解析
以我们OPPO的11071手机为例,手机的屏幕大小是:480x320。如果我们要去做全屏预览,那么我们至少要保证预览界面的长度大于等于480px,宽度大于等于320px;如果我们不做全屏预览,那么预览界面的长度或者宽度至少有一个是小于手机的对应长度或宽度,我们手机的预览界面实际上是有一部分没有去预览,默认为黑色显示。
480px480px320px预览界面
图5:全屏预览数据图 图6:非全屏预览数据图
预览界面320px图5表示的效果是一个Camera全屏预览的预览数据图,手机的整个屏幕都会显示预览数据。也就是说,假如手机屏幕上没有任何图标的话,用户可以看到整个手机屏幕都显示的是预览的界面,可以参考图4,它的预览是占满整个手机屏幕的,本质上Camera的预览效果就是图4那样,所以它拍摄出来的照片才会像图4那样。 然而图6则显示的是一个Camera非全屏预览的预览数据图,手机屏幕的左侧大部分会显示预览数据,但手机屏幕右侧的小部分显示的是黑色。为什么会这样呢?因为那些黑色的部分是没有预览数据的,所以才会显示黑色。
图7非全屏预览数据显示效果
图7显示的就是一个屏幕480x320的Camera非全屏预览图,图的右侧显示的黑色。但是可能一个最大的疑问是我们在使用Camera的时候,为什么我们没有看到它显示出来黑色?和图1作对比,如果我们把图1上面的所有按钮UI效果去掉,那么图1的显示效果就和图7一模一样了。可能还有一个疑问是我们既然预览的时候屏幕上有一部分显示的是黑色,为什么我们拍摄出来的照片不显示那些黑色的部分,而是像图3那样?原因很简单,那是因为生成照片是按照预览的数据来生成的,而不是按照手机屏幕的大小去生成照片,因为有预览数据的只是图7中非黑色部分,黑色的那部分没有预览数据,所以生成的照片就不会有黑色那部分。
三、如何去做全屏预览?
如何去做全屏预览呢?很多人可能就说我们把中的SurfaceView的android:layout_width属性和android:layout_height属性设置成“match_parent”不就可以了吗?的部分代码如下:
xmlns:android="/apk/res/android" xmlns:camera="/apk/res/" android:id="@+id/camera" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> android:id="@+id/camera_preview" android:layout_width="match_parent" android:layout_height="match_parent" android:clickable="false" android:focusable="false"/> android:id="@+id/frame_container" android:layout_width="45px" android:layout_height="match_parent" android:layout_marginLeft="10px" android:layout_marginTop="100px" android:layout_marginBottom="40px"/>
是的,我们这样做确实可以看到预览界面变成全屏。但是如果手机屏幕长宽比例不是4:3的话就会出现一个问题,我们看到的预览界面有失真现象,预览的界面和实物相比有变形现象。这又是为什么呢?
由于sensor在任何情况下的比例都是4:3。而我们现在使用的Android智能手机屏幕尺寸大小有480x320、800x480、960x540等大小,我们预览使用的SurfaceView设置的android:layout_width属性和android:layout_height属性为“match_parent”,即480和320、800和480等大小,它们的长宽比基本上都不是4:3,这样就造成的预览界面失真现象。既然我们要做全屏预览,那就要保证预览界面不但要全屏,而且要保证预览界面不能出现失真现象,现在全屏预览可以解决,那么我们如何去解决预览界面失真现象呢?
1、全屏预览的传统做法 我们传统做全屏预览的方法如下:
第一、中SurfaceView的android:layout_width属性和android:layout_height属性都设置成“match_parent”,保持和手机屏幕大小一致;
第二、pictureSize的长宽比例要保证为4:3,比如:mParameters
.setPictureSize(2560, 1920);
第三、previewSize的长宽比例要保持和手机屏幕尺寸长宽比例一样,比如设置成viewSize(480, 320);
第四、要我们去对预览数据做裁剪保证长宽比例为4:3,这个裁剪工作Camera底层驱动可以去裁剪,上层应用也可以去做裁剪,但是底层驱动裁剪比上层应用裁剪起来稍微容易点,经过对数据的裁剪之后就能保证我们全屏预览的界面不会有失真现象。
但是这种做法比较麻烦,上层应用和底层驱动都要去做修改,并且不同项目中的手机屏幕尺寸大小可能都不一样,导致每个项目的上层应用和底层驱动都要去做沟通和修改,尤其是底层驱动的修改比较麻烦。所以介绍一个本人自认为最简单的Camera做全屏预览方法。
2、全屏预览的简单做法
这个全屏预览的简单做法全部由上层应用来解决,底层驱动为此不需要做任何事情。这个做法的主要亮点还是在于去对做一些修改,当然pictureSize和previewSize也要做成4:3的比例,而不是上述描述的把previewSize设置成和屏幕尺寸一样。具体做法如下:
第一、修改。把SurfaceView放在一个AbsoluteLayout绝对布局里面,给绝对布局AbsoluteLayout设置android:layout_width属性和android:layout_height属性分别为480px和360px(这里手机屏幕是480x320,如果手机屏幕是800x480,就设置成800px和600px),我们必须保持AbsoluteLayout的这个长宽属性比例为4:3,并且要保证设置的长宽均大于等于手机屏幕尺寸的大小。反之,对于屏幕大小为480x320的手机,如果我们设置绝对布局AbsoluteLayout的长宽属性分别为427px和320px(屏幕大小为800x480的手机,则设置为640px和480px),这样虽然设置成了4:3,但是我们没有达到全屏的效果,所以我们必须要保证给AbsoluteLayout设置的长度均要大于等于手机屏幕尺寸的大小,但是最好保持某一个对应属性和手机屏幕的尺寸一样大,根据目前市面上的手机尺寸来看,我们都要设置AbsoluteLayout的android:layout_width属性和手机的长一样,比如:都设置为480px。
AbsoluteLayout的属性设置完毕之后,我们需要对SurfaceView做修改,把SurfaceView的android:layout_x属性设置为0px;把SurfaceView的android:layout_y属性设置为-20px,这个是根据我们AbsoluteLayout设置的宽度和手机屏幕的宽度算出来的,比如我们71手机的屏幕宽为320px,我们给AbsoluteLayout设置的android:layout_height为360px,他们相差40px,然后这40px给上下各分担20px,因为上面需要多出20px,再加上手机屏幕最上面的坐标layout_y是0px,所以我们就要把SurfaceView的android:layout_y设置为-20px,给SurfaceView设置android:layout_y大小的公式为:-(AbsoluteLayout的height属性-手机屏幕的宽)/ 2;除此之外,还要把SurfaceView的android:layout_width属性和android:layout_height属性设置成和AbsoluteLayout的一样。这样我们就完成了的修改。说了这么多,可能有点繁琐,但是看一下下面的就觉得非常简单了。
xmlns:android="/apk/res/android" xmlns:camera="/apk/res/" android:id="@+id/camera" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> android:layout_width="480px" android:layout_height="360px"> android:layout_x="0px" android:layout_y="-20px" android:layout_width="480px" android:layout_height="360px" android:clickable="false" android:focusable="false" /> android:layout_width="45px" android:layout_height="match_parent" android:layout_marginLeft="10px" android:layout_marginTop="100px" android:layout_marginBottom="40px"
第二、pictureSize的长宽比例要保证为4:3,比如:mParameters
.setPictureSize(2560, 1920);
第三、previewSize的长宽比例要保证为4:3,比如mParameters
.setPreviewSize(480, 320);
这就是我们全屏预览的简单做法,最简单的地方那就是我们不需要去对它做数据的裁剪工作。
3、使用中存在问题的解决办法
我们71手机有切换前后摄像头动画,但是我们用上述的方法实现了全屏预览之后,这个切换摄像头动画就会出现一个问题:那就是切换摄像头的时候取的最后一帧数据会上下同时往中甲挤压一下做动画。这个问题的原因也很简单,因为我们预览的pictureSize做成了480x360,而我们的切换摄像头的动画是一个ImageView,定义在里面,而给它设置的长宽为480px和320px,相差40px,这样在做动画的时候要把360转换为320之后才去做动画,所以才会往中间挤压一下从360px变成320px。问题的解法也很简单,给ImageView添加android:layout_marginTop属性和android:layout_marginBottom属性,都设置为-21px,可能会有一个疑问,为什么不去设置成-20px,却要设置成-21px?由于这个ImageView的边框占有1px,所以我们才去设置成-21px,而不是-20px。
这个就是本人觉得Android Camera做全屏预览的最简单方法,主要的做法还是在于修改。下面列出的整个代码,方便需要的同事对比参考,当然这个只是71Camera的普通相机。
xmlns:android="/apk/res/android" xmlns:camera="/apk/res/" android:id="@+id/camera" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> android:layout_width="480px" android:layout_height="360px"> android:layout_x="0px" android:layout_y="-20px" android:layout_width="480px" android:layout_height="360px" android:clickable="false" android:focusable="false" /> android:layout_width="45px" android:layout_height="match_parent" android:layout_marginLeft="10px" android:layout_marginTop="100px" android:layout_marginBottom="40px" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="15px" android:layout_marginLeft="50px" android:layout_gravity="left" android:clickable="false" android:focusable="false" android:visibility="gone"> android:layout_width="wrap_content" android:layout_height="wrap_content" android:clickable="false" android:focusable="false" android:src="@drawable/zoom_icon" /> android:layout_marginTop="5px" android:layout_width="45px" android:layout_height="30px" android:layout_toRightOf="@+id/zoom_img" android:textSize="20px" android:textStyle="bold" android:shadowColor="#FF000000" android:shadowDx="1" android:shadowDy="1" android:shadowRadius="1" /> android:id="@+id/focus_rectangle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:clickable="false" android:focusable="false" android:visibility="invisible" /> android:layout_width="match_parent" android:layout_height="match_parent" android:background="#FF000000" android:scaleType="fitXY" android:visibility="gone" android:layout_marginTop="-21px" android:layout_marginBottom="-21px"/> android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="fitXY" android:visibility="gone" android:layout_marginTop="-21px" android:layout_marginBottom="-21px"/> android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="fitXY" android:visibility="gone" android:layout_marginTop="-21px" android:layout_marginBottom="-21px"/> android:id="@+id/camera_switcher" android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_marginLeft="10px" android:layout_marginTop="20px" android:clickable="true" android:focusable="false" android:src= "@drawable/btn_camera_switch_normal" android:background= "@drawable/btn_camera_switch_bg">
发布者:admin,转转请注明出处:http://www.yc00.com/news/1689217170a222426.html
评论列表(0条)