当初Android
系统的诞生之日,这个市场还是诺基亚的天下。也许连当年“安卓之父”安迪·鲁宾先生都不会预料到现在的Android
会是多么的辉煌。据悉,当年Android
的开发团队开发了一段时间Android
后,也许大部分原因是由于市场的原因他们并不对Android
抱有希望。他们在2005年找到了当时韩国的通讯巨头Samsung
,打算将Android
卖掉Samsung
。Samsung
并不看好Android
团队,甚至说道“你和所谓的队伍打算创造这样的东西?你们只有6个人,你喝高了吗?”,在嘲笑声中结束了这次收购,只能说Samsung
与Android
失之交臂。两周后Google
收购了与Samsung
谈崩的Android
团队。
对于Android
,Google
表现出与Samsung
截然不同的反应。Google CEO
拉里·佩奇先是同意与罗宾见一面,在听完罗宾对Android
的描述后,他就直接收购Android
。其实,Google
早就在寻找类似的产品,只能说Google
非常幸运。时至今日,联想到多年前Samsung
为了另谋Android
外的出路,埋头苦心研发Tizen
系统,但奈何于Android
系统的开源政策以及市场的占有率,Tizen
系统一直赶超不过Android
,Samsung
的旗舰机一直用的都是Android
系统,不禁令人感叹万分。
碎片化:通俗的讲是整个安卓平台的差异化非常大。安卓平台的诞生加速了手机智能化的普及,但它最大的缺点也越来越凸显,那就是碎片化严重:设备繁多,品牌众多,版本各异,分辨率不统一等等。这些都逐渐成为安卓系统发展的障碍,造成了安卓系统混乱,也导致了安卓应用隐形开发成本的增多。
我们为了让我们在软件在不同的分辨率以及手机厂家下合理的分配每一个控件的大小,我们需要合理的适配 。
1.获取屏幕的状态 。
2.获取设备屏幕的分辨率 。
3.获取相机支持的分辨率 。
4.计算得出相机最适分辨率。
5.动态获取相机屏幕最适宽高 。
6.动态代码取代硬代码 。
屏幕方向:Android的屏幕方向一共分为两种。第一种是设备是横屏还是竖屏放置。第二种是屏幕切换角度值,也就是我们将设备垂直放置,设备旋转了多少角度。下面我将用代码和图片一一介绍我们的这两种方式 。
/**
* 判断Android横竖屏
**/
Configuration mConfiguration = this.getResources().getConfiguration(); //获取设置的配置信息
int orientation = mConfiguration.orientation ; //获取屏幕方向
if (orientation == Configuration.ORIENTATION_PORTRAIT) {
//竖屏
} else if (orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
//横屏
}
判断Android横竖屏我们可以用肉眼一看就分辨出来,但是程序不行,因此我们需要用代码来实现。
2. 屏幕切换角度值的求取:
/**
* 求取屏幕切换角度值
**/
int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0: degrees = 0; break;
case Surface.ROTATION_90: degrees = 90; break;
case Surface.ROTATION_180: degrees = 180; break;
case Surface.ROTATION_270: degrees = 270; break;
}
代码中switch里面的case分别与下图的屏幕切换角度值一一对应。
摄像头方向:图像传感器的取景方向与手机正常方向成90度夹角。
按常理来说,当我们以正常的手机方向来打开相机时,看到的预览图像应该是横向的。但是,当我们打开系统相机后,看到的预览图像却是正常的,即预览图像与手机方向一致。这是因为系统自带的相机在Android系统底层根据当前手机屏幕的方向对图像传感器采集到的数据进行了旋转,所以无论我们怎么旋转手机屏幕,看到的相机预览图片始终是“正常”的 。
activity
的生命周期 。onCreate()
方法中进行的。 /**
* 展示在界面上
**/
publisher.setPreviewResolution(640, 480);
这类代码我们是将相机展示在界面上的宽度和高度写死了,不利于开发,还影响界面的美观。我们需要做的是根据设备的相机支持的分辨率计算出最合适的分辨率。
1.获取屏幕的状态 。
2.获取设备屏幕的分辨率 。
3.获取相机支持的分辨率 。
4.计算得出相机最适分辨率
5.动态获取相机屏幕最适宽高 。
6.动态代码取代硬代码 。
CameraFragment.screenAngle = (getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay.rotation
/**
* 若此时状态为竖屏
**/
if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
getWindowsSize() //获取屏幕分辨率
CameraUtils.getCameraResolution_PORTRAIT() //获取相机分辨率(竖屏)
CameraUtils.adaptiveCalculate_PORTRAIT () //适配的设置
}
我们需要在软件打开执行onCreate()
方法时,立即获取屏幕的状态,确保屏幕为竖屏方向。
/**
* 获取screen大小
**/
private fun getWindowsSize() {
val screenSize = this.getSystemService(Context.WINDOW_SERVICE) as WindowManager
CameraFragment.screen_width = screenSize.defaultDisplay.width.toFloat()
CameraFragment.screen_height = screenSize.defaultDisplay.height.toFloat()
CameraFragment.screenRate = CameraFragment.screen_width / CameraFragment.screen_height//主屏幕分辨率宽和长的比例,用于下面的适配
}
我们在获取设备屏幕分辨率时,是不是智能手机有着很大的因素。如果是智能手机,那么它就配备方向传感器,宽和高就是我们肉眼所看到的。如果是开发机不带有方向传感器,那我们还需要一些特定的方法适配,但是这种情况我们遇到的几率很少,这里我就不讨论了。
/**
* 获取相机和拍照分辨率(采用相机,竖屏设置)这个方法是选取主屏幕分辨率宽和高的比例和相机支持分辨率宽和高的比例的最小值
**/
fun getCameraResolution_PORTRAIT(){
var camera : Camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT)
var previewSizes = camera.parameters.supportedPreviewSizes
for (i in previewSizes.indices) {
var preSize = previewSizes[i]
Log.i(TAG,"SupportWidth : "+previewSizes[i].width.toFloat() +", SupportHeight : "+previewSizes[i].height.toFloat() )
}
camera.setPreviewCallback(null)
camera.release()
}
我们首先实例化相机调用相机的参数,由此获取到相机支持的宽度和高度 。相机可能会支持多种分辨率,我们将它遍历打印在控制台中查看。
/**
* 获取相机和拍照分辨率(采用相机,竖屏设置)这个方法是选取主屏幕分辨率宽和高的比例和相机支持分辨率宽和高的比例的最小值
**/
fun getCameraResolution_PORTRAIT(){
var camera : Camera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT)
var previewSizes = camera.parameters.supportedPreviewSizes
var screenDiffer:Float = 100F;
for (i in previewSizes.indices) {
var preSize = previewSizes[i]
var screenDivide = previewSizes[i].height.toFloat() / previewSizes[i].width.toFloat()
/**
* 分别选取最合适的相机支持分辨率作为适配
**/
if (CameraFragment.screenRate < 1){
if(screenDivide < 1){
if(Math.abs(screenDivide - CameraFragment.screenRate) < screenDiffer){
CameraFragment.screenPreRate = screenDivide
screenDiffer = Math.abs(screenDivide - CameraFragment.screenRate)
}
}else{
if(Math.abs(screenDivide - CameraFragment.screenRate) < screenDiffer){
CameraFragment.screenPreRate = screenDivide
screenDiffer = Math.abs(screenDivide - CameraFragment.screenRate)
}
}
} else{
if(screenDivide > 1){
if(Math.abs(screenDivide - CameraFragment.screenRate) < screenDiffer){
CameraFragment.screenPreRate = screenDivide
screenDiffer = Math.abs(screenDivide - CameraFragment.screenRate)
}
}else{
if(Math.abs(screenDivide - CameraFragment.screenRate) < screenDiffer){
CameraFragment.screenPreRate = screenDivide
screenDiffer = Math.abs(screenDivide - CameraFragment.screenRate)
}
}
}
}
camera.setPreviewCallback(null)
camera.release()
}
我们将相机支持的分辨率在每一次遍历的for循环中,分别计算它们的长宽比。我们将它和屏幕的长宽比做计较。在每一次for循环中,我们都会选取最接近屏幕的长宽比将它存储在变量中。最后我们计算出和屏幕长宽比最接近的一组相机分辨率,选用这种比例作为屏幕的适配。
/**
* 适配的设置(竖屏设置)
**/
fun adaptiveCalculate_PORTRAIT(){
CameraFragment.preview_width = CameraFragment.screen_width.toInt()
CameraFragment.preview_height = (CameraFragment.screen_width / CameraFragment.screenPreRate).toInt()
}
这是由于我们在第二步获取了设备屏幕的分辨率和第四步计算出了相机最适分辨率的比例。我们根据作差的方式计算出我们的Camera屏幕在设备中的宽度和高度 。
由于设备是竖屏放置,我们设置了Camera屏幕的宽度铺满设备的宽度,然后Camera屏幕的高度通过计算得出。
/**
* 展示在界面上
**/
publisher.setPreviewResolution(preview_height, preview_width);
我们将在setPreviewResolution
方法中填入preview_height
和preview_width
,这就是将我们的预览界面的显示大小设置为动态获取,从而取代文章之前的硬代码。
以上就是我对屏幕适配的理解,第一次写技术博客,有些不足之处希望大家批评指正!