UI效果(9): 屏幕相关操作

android中有很多未知的“路”,只有走好每一步,才有可能找到捷径!!!


1. 获取 android 设备屏幕大小


在说具体的操作方法之前,我们先了解一下几个知识点,下面都是都是自己的语言描述,与专业术语有差异。


a. 像素与分辨率


像素,指的是一定区域类(矩形区域)横向、纵向上点的乘积的结果,单位是 pixel.


分辨率,指的是一定区域类(矩形区域)横向、纵向上点的乘积如 1280×800.


b. 密度


在android中,密度叫做 density其单位是 dpi(dot per inch),意思是每英寸上面的点数。


关于 dpi 的分类,可以参考:


 

官方推荐是,像素统一使用 dip,字体统一使用 sp 。

 

dip 与 px 之间的换算关系是:


                pixs =dips * (densityDpi/160),也就是说当 densityDpi=160 时,1dip=1px

 

关于单位换算源码位于:

\frameworks\base\core\java\android\util\TypedValue.java

public static float applyDimension(int unit, float value,
                                       DisplayMetrics metrics)
    {
        switch (unit) {
        case COMPLEX_UNIT_PX:
            return value;
        case COMPLEX_UNIT_DIP:
            return value * metrics.density;
        case COMPLEX_UNIT_SP:
            return value * metrics.scaledDensity;
        case COMPLEX_UNIT_PT:
            return value * metrics.xdpi * (1.0f/72);
        case COMPLEX_UNIT_IN:
            return value * metrics.xdpi;
        case COMPLEX_UNIT_MM:
            return value * metrics.xdpi * (1.0f/25.4f);
        }
        return 0;
    }


c. 屏幕的大小与设备分辨率计算


这里说的“屏幕的大小”,指的是设备实在的物理尺寸。

首先区别,设备的 物理尺寸 和 分辨率,

比如 5寸 手机分辨率可以是 480*320,那么 7寸 手机分辨率也可以是 480*320,

但是 5寸 设备显示效果肯定比 7寸 设备要好要清晰。


(1). 计算物理尺寸

 DisplayMetrics dm = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(dm);
        
        int width= dm.widthPixels;
        int height= dm.heightPixels;
        
        Log.d("mark", "screen's width * height =  " +  width + "*" +  height);

打印结果:

screen's width * height =  240*320


下面再说一种网上流传的计算设备屏幕大小的方式:

WindowManager windowManager = getWindowManager();
        Display display = windowManager.getDefaultDisplay();
        int width = display.getWidth();
        int height = display.getHeight();
        
        Log.d("mark", "screen's width * height =  " +  width + "*" +  height);


我的手机测试,实际情况符合!


但是分辨率不可能这么高的。


上面的两种方式当且仅当屏幕密度为 1 的时候,

可以计算分辨率或者物理尺寸,否则只可以计算物理尺寸,抓狂切记敲打

往下看。。。


(2).计算分辨率


最好,你在 manifest.xml 里面加入类似下面的配置:

<uses-sdk
        android:minSdkVersion="6"
        android:targetSdkVersion="10" />


<supports-screens
        android:anyDensity="true"
        android:largeScreens="true"
        android:normalScreens="true"
        android:resizeable="true"
        android:smallScreens="true" />


设备分为高密度、中密度以及低密度的类型,其计算方法是:

屏幕宽(screenWidth) = 横向像素点数 × 密度

屏幕高(screenHeight) = 纵向像素点数 × 密度


DisplayMetrics dm = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(dm);
        
        int widthPixels= dm.widthPixels;
        int heightPixels= dm.heightPixels;
        
        float density = dm.density;
        int dpi = dm.densityDpi;
        Log.d("mark", "other info about device is density = " + density + ", and the dpi is " + dpi);
        
        int screenWidth = (int) (widthPixels * density);
        int screenHeight =(int) (heightPixels * density) ;
        Log.d("mark", "screen's width * height =  " +  screenWidth + "*" +  screenHeight + " and the density = " + density);
        


打印信息:

other info about device is density = 0.75, and the dpi is 120
screen's width * height =  180*240 and the density = 0.75

打印结果就是我手机的分辨率大小。


从打印信息上面可以看出我的手机是低密度的(ldpi),其密度值是 0.75。


关于 density 的值一般是1.0、0.5、0.75、1.5等。


ok,详细信息参看:SDK/docs/guide/practices/screens_support.html



2. layout-320x240 到底指什么


在 android 中,layout-320x240,还有 drawable-320x240 到底指的是什么?


测试还是以我自己的手机为例,下面是测试工程的 res 文件内容




分别建立 drawable-ldpi-320x240、layout-320x240、values-320x240 文件夹。


在 drawable-ldpi-320x240 里面放置一个 app_icon,该图片不同于 drawable 等其它文件夹图标。


在 layout-320x240 放置与 layout 里面相同的布局文件。

这个布局文件是 activity 启动加载的,本质就是加载一个textview。


在 values-320x240 放置与 values 里面相同的 string.xml 文件,只是修改了 textview 显示的字符串。


<string name="java">java or android ?</string>


而 values 里面是 <string name="java">Hello World</string>


我使用如下代码


        DisplayMetrics dm = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(dm);
        int sw = dm.widthPixels;
        int sh = dm.heightPixels;
        System.out.println("sw * sh = " + sw + " * " + sh);


获取手机屏幕大小是 320x240,所以上面文件夹后缀都是 320x240.


运行程序之后,发现调用资源文件都是后缀 320x240 文件夹的东西。


这就说明,320x240 表示的是手机屏幕物理尺寸大小

不是分辨率大小,我手机的分辨率是 180 * 240。


3.  改变 android 设备屏幕方向


android手机在改变屏幕方向(横屏与竖屏互相切换)的时候,会多次调用onCreate()方法,以及onPause()、onStop()、onDestroy()方法,然后重新调用onCreate()、onStart()、onResume()方法使该activity重新展现在我们面前。

利用这种特性可以实现某些特殊的效果,但是在大多数情况下,我们还是想让它只调用一次onCreate()方法。因为onCreate()方法一般用来做一些初始化的工作,毕竟没有多少人希望初始化工作会一次又一次的进行着。特别是你的app有多个activity,如果在改变屏幕方向(横屏与竖屏互相切换)的时候onCreate()方法总是在调用,那么这可能就是一场噩梦!!下面介绍改变这中现状的方法。主要两个步骤!!

<1>修改manifest.xml文件

添加如下代码,即可

 

完整示例如下:

 

这样,切换屏幕时就不会多次调用onCreate()方法,从而不会影响activity生命周期。那么,既然不会多次调用onCreate()方法,系统又是调用哪个方法呢?接着看.....

<2>覆写Activity的onConfigurationChanged()方法

如果你想在屏幕方向改变时,做一些操作必须覆写onConfigurationChanged()方法。在该方法中我们可以添加自己的代码,主要有两中写法,如下:

 

或者:

 

这两种方式,打印结果:

 

但是这是在模拟器上面测试的结果,在真机上测试结果不一样。

还有一点需要注意:super.onConfigurationChanged(newConfig);必须写,否则报异常!
异常信息:

 

说明要调用父类Activity的onConfigurationChanged()方法。


看一下ActivityonConfigurationChanged()方法源码

 

可以看出,调用了抽象类Window的onConfigurationChanged()方法。看源码如下:

 

4. 固定屏幕方向


从上面我们知道,当改变设备或者模拟器的屏幕方向时,相应的显示模式也将根据变化匹配现有的情况,这样,Activity

根据不同的模式(Portrait和Landscape)重新调整视图的显示方式。如果你想让你的视图一直处于某一个固定方向,可以

在Manifest里为相应的Activity添加Android:screenOrientation属性,并赋予”portrait”或”Landscape”属性。


5. 跟 Camera 有关


使用过 android 的照相机的 api 的朋友知道,如果不做处理,画面是不会随着手机的方向变化而变化。

其实改变这种现状也很简单,一句代码的事:

 

记住

这种方法不会禁止应用程序多次调用onCreate()方法,所以你需要按照上面的方法去禁止这种现象发生,如果你需要的话。

对应的 getRequestedOrientation( )方法返回屏幕方向的数据如果没有指定屏幕方向的话调用 getRequestedOrientation( )

方法会返回 -1SCREEN_ORIENTATION_UNSPECIFIED表示没有指定。

如果你在 manifest.xml 或者代码中使用 setRequestedOrientation(方法设置了屏幕方向的话,会返回对应数据。


具体参数可以查看ActivityInfo类的常量。





 

 

©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页