安卓Camera屏幕竖屏适配

安卓Camera屏幕在竖屏上显示适配

  • 1、前言
  • 2、Android 的适配
    • 2.1 什么是适配?
    • 2.2 为什么要适配?
    • 2.3 如何适配?
  • 3、Android 适配前需要了解的内容
    • 3.1 屏幕的方向和摄像头方向
    • 3.2 基础概念的了解
  • 4、Android 适配的历程
    • 4.1 适配前的硬代码
    • 4.2 适配的总体流程
    • 4.3 适配的详细步骤
  • 5、总结
  • 6、参考资料

1、前言

当初Android系统的诞生之日,这个市场还是诺基亚的天下。也许连当年“安卓之父”安迪·鲁宾先生都不会预料到现在的Android会是多么的辉煌。据悉,当年Android的开发团队开发了一段时间Android后,也许大部分原因是由于市场的原因他们并不对Android抱有希望。他们在2005年找到了当时韩国的通讯巨头Samsung,打算将Android卖掉SamsungSamsung并不看好Android团队,甚至说道“你和所谓的队伍打算创造这样的东西?你们只有6个人,你喝高了吗?”,在嘲笑声中结束了这次收购,只能说SamsungAndroid失之交臂。两周后Google收购了与Samsung谈崩的Android团队。
对于AndroidGoogle表现出与Samsung截然不同的反应。Google CEO拉里·佩奇先是同意与罗宾见一面,在听完罗宾对Android的描述后,他就直接收购Android。其实,Google早就在寻找类似的产品,只能说Google非常幸运。时至今日,联想到多年前Samsung为了另谋Android外的出路,埋头苦心研发Tizen系统,但奈何于Android系统的开源政策以及市场的占有率,Tizen系统一直赶超不过AndroidSamsung的旗舰机一直用的都是Android系统,不禁令人感叹万分。

2、Android 的适配

2.1 什么是适配?

2.2 为什么要适配?

碎片化:通俗的讲是整个安卓平台的差异化非常大。安卓平台的诞生加速了手机智能化的普及,但它最大的缺点也越来越凸显,那就是碎片化严重:设备繁多,品牌众多,版本各异,分辨率不统一等等。这些都逐渐成为安卓系统发展的障碍,造成了安卓系统混乱,也导致了安卓应用隐形开发成本的增多。
我们为了让我们在软件在不同的分辨率以及手机厂家下合理的分配每一个控件的大小,我们需要合理的适配 。

2.3 如何适配?

1.获取屏幕的状态 。
2.获取设备屏幕的分辨率 。
3.获取相机支持的分辨率 。
4.计算得出相机最适分辨率。
5.动态获取相机屏幕最适宽高 。
6.动态代码取代硬代码 。

3、Android 适配前需要了解的内容

3.1 屏幕的方向和摄像头方向

屏幕方向:Android的屏幕方向一共分为两种。第一种是设备是横屏还是竖屏放置。第二种是屏幕切换角度值,也就是我们将设备垂直放置,设备旋转了多少角度。下面我将用代码和图片一一介绍我们的这两种方式 。

  1. 屏幕方向的求取:
	/**
     * 判断Android横竖屏
     **/
     Configuration mConfiguration = this.getResources().getConfiguration(); //获取设置的配置信息
	int orientation = mConfiguration.orientation ; //获取屏幕方向
	if (orientation == Configuration.ORIENTATION_PORTRAIT) {
		//竖屏
	} else if (orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
		//横屏
	}

判断Android横竖屏我们可以用肉眼一看就分辨出来,但是程序不行,因此我们需要用代码来实现。
安卓Camera屏幕竖屏适配_第1张图片
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分别与下图的屏幕切换角度值一一对应。
安卓Camera屏幕竖屏适配_第2张图片
摄像头方向:图像传感器的取景方向与手机正常方向成90度夹角。
按常理来说,当我们以正常的手机方向来打开相机时,看到的预览图像应该是横向的。但是,当我们打开系统相机后,看到的预览图像却是正常的,即预览图像与手机方向一致。这是因为系统自带的相机在Android系统底层根据当前手机屏幕的方向对图像传感器采集到的数据进行了旋转,所以无论我们怎么旋转手机屏幕,看到的相机预览图片始终是“正常”的 。

3.2 基础概念的了解

  1. 我们需要了解什么是屏幕尺寸、屏幕分辨率、屏幕像素密度,这里我就不一一展开了。
  2. 我们必须要了解activity的生命周期 。
    生命周期:正常情况下的也就是我们经常了解的一个活动的正常的生命流程。
    我们这次的开发主要在生命周期中的onCreate()方法中进行的。

4、Android 适配的历程

4.1 适配前的硬代码

	/**
     * 展示在界面上
     **/
	publisher.setPreviewResolution(640, 480);

这类代码我们是将相机展示在界面上的宽度和高度写死了,不利于开发,还影响界面的美观。我们需要做的是根据设备的相机支持的分辨率计算出最合适的分辨率。

4.2 适配的总体流程

1.获取屏幕的状态 。
2.获取设备屏幕的分辨率 。
3.获取相机支持的分辨率 。
4.计算得出相机最适分辨率
5.动态获取相机屏幕最适宽高 。
6.动态代码取代硬代码 。

4.3 适配的详细步骤

  1. 获取屏幕的状态 。
	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()方法时,立即获取屏幕的状态,确保屏幕为竖屏方向。

  1. 获取设备屏幕的分辨率 。
	/**
     * 获取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//主屏幕分辨率宽和长的比例,用于下面的适配
    }

我们在获取设备屏幕分辨率时,是不是智能手机有着很大的因素。如果是智能手机,那么它就配备方向传感器,宽和高就是我们肉眼所看到的。如果是开发机不带有方向传感器,那我们还需要一些特定的方法适配,但是这种情况我们遇到的几率很少,这里我就不讨论了。

  1. 获取相机支持的分辨率 。
	/**
     * 获取相机和拍照分辨率(采用相机,竖屏设置)这个方法是选取主屏幕分辨率宽和高的比例和相机支持分辨率宽和高的比例的最小值
     **/
    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()
    }

我们首先实例化相机调用相机的参数,由此获取到相机支持的宽度和高度 。相机可能会支持多种分辨率,我们将它遍历打印在控制台中查看。

  1. 计算得出相机最适分辨率
	/**
     * 获取相机和拍照分辨率(采用相机,竖屏设置)这个方法是选取主屏幕分辨率宽和高的比例和相机支持分辨率宽和高的比例的最小值
     **/
    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循环中,我们都会选取最接近屏幕的长宽比将它存储在变量中。最后我们计算出和屏幕长宽比最接近的一组相机分辨率,选用这种比例作为屏幕的适配。

  1. 动态获取相机屏幕最适宽高 。
	/**
     * 适配的设置(竖屏设置)
     **/
    fun adaptiveCalculate_PORTRAIT(){
        CameraFragment.preview_width = CameraFragment.screen_width.toInt()
        CameraFragment.preview_height = (CameraFragment.screen_width / CameraFragment.screenPreRate).toInt()
    }

这是由于我们在第二步获取了设备屏幕的分辨率和第四步计算出了相机最适分辨率的比例。我们根据作差的方式计算出我们的Camera屏幕在设备中的宽度和高度 。
由于设备是竖屏放置,我们设置了Camera屏幕的宽度铺满设备的宽度,然后Camera屏幕的高度通过计算得出。

  1. 动态代码取代硬代码 。
	/**
     * 展示在界面上
     **/
	publisher.setPreviewResolution(preview_height, preview_width);

我们将在setPreviewResolution方法中填入preview_heightpreview_width,这就是将我们的预览界面的显示大小设置为动态获取,从而取代文章之前的硬代码。

5、总结

以上就是我对屏幕适配的理解,第一次写技术博客,有些不足之处希望大家批评指正!

6、参考资料

  • Camera API | Android Developers
  • Android Debug Bridge | Android中文API
  • GitHub - googlesamples/android-Camera2Basic
  • GitHub - begeekmyfriend/yasea: RTMP live streaming client for Android
  • Camera API官方提供的支持不同屏幕大小的全部方法
  • CSDN博客专家-鸿洋:Android 屏幕适配方案
  • CSDN博客专家-凯子:Android屏幕适配全攻略(最权威的官方适配指导)

你可能感兴趣的:(安卓Camera屏幕竖屏适配)