Android APP多屏幕适配

来源:互联网 发布:文泰刻绘2002端口设置 编辑:程序博客网 时间:2024/06/03 23:05

 

现在的Android手机屏幕越来越多,工作面试的时候很多同学都不是很清楚屏幕适配的问题, 网上其实有很多类似的说明,其实大同小异都是翻译google 官方贵的说明,希望大家有时间多学习官方api,这里我也做一下笔记:

1、基本概念

1.1 屏幕大小(screen size)

屏幕的实际大小,用屏幕对角线长度来衡量(比如3.4寸,3.8寸,4.3寸,5寸,7寸等)。

android把屏幕分为以下4种:small,normal,large,extra large等。

1.2 屏幕密度(Screen Density)

一块实际的屏幕区域有多少个像素,一般用dpi衡量(每英寸有多少个点)。

android把屏幕密度分为4种:low,medium,high,extra high。
手机可以有相同的分辨率,但屏幕尺寸可以不相同, 
Diagonal pixel表示对角线的像素值(=),DPI=933/3.7=252 
android将实际的屏幕密度分为四个通用尺寸(low,medium,high,and extra high) 
一般情况下的普通屏幕:ldpi是120dpi,mdpi是160dpi,hdpi是240dpi,xhdpi是320dpi 
对于屏幕来说,dpi越大,屏幕的精细度越高,屏幕看起来就越清楚 。

1.3 屏幕方向(orientation)

屏幕方向分为landscape(横屏)和portrait(竖屏)。

1.4 分辨率(Resolution)

屏幕上的总实际像素数。对屏幕进行适配时,一般不关注它的分辨率,只关注它的屏幕大小和密度。与密度无关的像素(Density-independent pixel,dp或dip) -  为了保证你的UI适合不同的屏幕密度,建议你采用dp来定义程序UI。它的计算方法为:px = dp * (dpi / 160)。

sp(scale-independent pixel)

如何分辨一个屏幕是ldpi、mdpi、hdpi的方法:

 

2、怎样适配多种屏幕

2.1 支持屏幕类型

manifest里定义你的程序支持的屏幕类型,相应代码如下:

<supports-screens android:resizeable=["true"| "false"]
android:smallScreens=["true" | "false"]   //是否支持小屏
android:normalScreens=["true" | "false"]  //是否支持中屏
android:largeScreens=["true" | "false"]   //是否支持大屏
android:xlargeScreens=["true" | "false"]  //是否支持超大屏
android:anyDensity=["true" | "false"]    //是否支持多种不同密度的屏幕
android:requiresSmallestWidthDp=”integer”
android:compatibleWidthLimitDp=”integer”
android:largestWidthLimitDp=”integer”/>

a. 是否支持多种不同密度的屏幕

android:anyDensity=["true" | "false"]

如果android:anyDensity="true"

指应用程序支持不同密度,会根据屏幕的分辨率自动去匹配。

如果android:anyDensity="false"

应用程序支持不同密度,系统自动缩放图片尺寸和这个图片的坐标。具体解释一下系统是如何自动缩放资源的。

例如我们在hdpi,mdpi,ldpi文件夹下拥有同一种资源,那么应用也不会自动地去相应文件夹下寻找资源,这种情况都是出现在高密度,以及低密度的手机上,比如说一部240×320像素的手机,

如果设置android:anyDensity="false",Android系统会将240 x 320(低密度)转换为 320×480(中密度),这样的话,应用就会在小密度手机上加载mdpi文件中的资源。

b. 是否支持大屏幕

android:largeScreens=["true" | "false"]

如果在声明不支持的大屏幕,而这个屏幕尺寸是larger的话,系统使用尺寸为("normal")和密度为("medium)显示, 不过会出现一层黑色的背景。

c. 是否支持小屏幕

android:smallScreens=["true" | "false"]

如果在声明不支持的小屏幕,而当前屏幕尺寸是smaller的话,系统也使用尺寸为("normal")和密度为("medium)显示 .

如果应用程序能在小屏幕上正确缩放(最低是small尺寸或最小宽度320dp),那就不需要用到本属性。否则,就应该为最小屏幕宽度标识符设置本属性

来匹配应用程序所需的最小尺寸。

2.2 对不同大小的屏幕提供不同的layout。

比如,如果需要对大小为large的屏幕提供支持,需要在res目录下新建一个文件夹layout-large/并提供layout。当然,也可以在res目录下建立layout-port和layout-land两个目录,里面分别放置竖屏和横屏两种布局文件,以适应对横屏竖屏自动切换。

res/layout

res/layout-small
res/layout-normal
res/layout-large
res/layout-xlarge

 

android  新版本支持:
res/layout-mdpi
res/layout-hdpi
res/layout-xhdpi

 

Android 4.0版本 之后支持layout-mdpi、layout-hdpi 这种写法。

2.3 对不同密度的屏幕提供不同的图片。

1) 应尽量使用点9格式的图片,使用draw9图片则不需要适配,会自动进行拉伸。

2) 使用位图则需要针对不同的屏幕放置合适大小的图,在res目录下建立对应的包,Android有个自动匹配机制去选择对应的布局和图片资源

3) Android平台中支持一系列你所提供的指定大小(size-specific),指定密度(density-specific)的合适资源。指定大小(size-specific)的合适资源是指small, normal, large, and xlarge。指定密度(density-specific)的合适资源,是指ldpi (low), mdpi (medium), hdpi (high), and xhdpi (extra high).

drawable
drawable-ldpi
drawable-mdpi
drawable-hdpi
drawable-xhdpi
drawable-nodpi
drawable-nodpi-1024×600
drawable-nodpi-1280×800
drawable-nodpi-800×480

4) 图片大小的确定:low:medium:high:extra high比例为3:4:6:8。举例来说,对于中等密度(medium)的屏幕你的图片像素大小为48×48,那么低密度(low)屏幕的图片大小应为36×36,高(high)的为72×72,extra high为96×96。

 

通常情况下从开发角度讲,应用程序会根据3类Android手机屏幕提供3套UI布局文件,但是相应界面图标也需要提供3套

Icon Type

Standard Asset Sizes (in Pixels), for Generalized Screen Densities

 

App

ldpi

mdpi

hdpi

xhdpi

Launcher

36 x 36 px

48 x 48 px

72 x 72 px

96 x96 px

Menu

36 x 36 px

48 x 48 px

72 x 72 px

96 x96 px

Status Bar

24 x 24 px

32x32 px

48 x 48 px

72 x 72 px

Tab

24 x 24 px

32x32 px

48 x 48 px

72 x 72 px

Dialog

24 x 24 px

32x32 px

48 x 48 px

72 x 72 px

List View

24 x 24 px

32x32 px

48 x 48 px

72 x 72 px

 

3、多屏幕适配的黄金原则

3.1 布局文件配置属性

layout文件中设置控件尺寸时应采用wrap_content,fill_parent,match_parent和dp。

为了使文字大小更好的适应屏幕应该使用sp来定义文字大小。

layout_weight属性尽量不要嵌套使用。如父节点已经使用了weight属性,则子节点尽量避免使用。

3.2配置文件定义具体值

为了使代码简单,android内部使用pix为单位表示控件的尺寸,但这是基于当前屏幕基础上的。为了适应多种屏幕,android建议开发者不要使用具体的像素来表示控件尺寸。

布局文件中的所有文字大小以及控件大小都必须申明在xml配置文件中,values/dimens.xml,不同的屏幕定义不同的大小,可以很好的适配。

values
values-ldpi
values-mdpi
values-hdpi
values-xhdpi
values-nodpi
values-nodpi-1024×600
values-nodpi-1280×800
values-nodpi-800×480

3.3 布局文件

1)不要使用AbsoluteLayout(android1.5已废弃) 。

2)尽量使用RelativeLayout,如果必须使用权重则可以考虑RelativeLayout和LinearLayout混合使用。

3)需要根据物理尺寸的大小准备多套布局:

layout(放一些通用布局xml文件,比如界面中顶部和底部的布局,不会随着屏幕大小变化。

layout-mdpi (屏幕尺寸小于3.5英寸左右的布局)

layout-hdpi (屏幕尺寸小于4英寸左右)

layout-xhdpi(4.5英寸-7英寸之间)

3.4 对不同的屏幕提供合适大小的图片。见2.3部分。

3.5 根据屏幕大小计算

如果有些时候需要自定义控件,空间大小特别严格的话,可以考虑获取当前屏幕大小进行计算分割。

DisplayMetrics metric = new DisplayMetrics(); 
getWindowManager().getDefaultDisplay().getMetrics(metric); 
int width = metric.widthPixels;  // 屏幕宽度(像素) 
int height = metric.heightPixels;  // 屏幕高度(像素) 
float density = metric.density;  // 屏幕密度(0.75 / 1.0 / 1.5) 
int densityDpi = metric.densityDpi;  // 屏幕密度DPI(120 / 160 / 240) 

4、横竖屏切换

4.1 禁止切换横屏或竖屏

可以在配置Activity的地方进行如下的配置

 

        android:screenOrientation="portrait"

 

        android:screenOrientation="landscape"

 

或者 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

 

       setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

 

这样就可以保证是竖屏总是竖屏了,或者横屏总是横屏。

4.2 可以切换横屏或竖屏

 

若要软件在横竖屏之间切换,由于横竖屏的高宽会发生转换,有可能会要求不同的布局。可以通过以下方法来切换布局:

 

1layout-landlayout-port

      res目录下建立layout-land(横屏的layout)layout-port(竖屏的layout)目录,相应的layout文件不变,比如main.xml。其他的不用管,模拟器会自动寻找。

 

2onCreate()中判断横竖屏

 

     通过this.getResources().getConfiguration().orientation判断当前是横屏还是竖屏,然后加载相应的xml布局文件。因为当屏幕变为横屏的时候,系统会重新呼叫当前ActivityOnCreate方法,你可以把以下方法放在你的OnCreate中来检查当前的方向,然后可以让你的SetContentView来载入不同的Layout xml.

if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {

Log.i("info", "landscape");

}

else if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {

Log.i("info", "portrait");

 

}

4.3 横竖屏切换用onConfigurationChanged

   这种方法缺点是动态适应差。比如横竖屏切换时需要你自己写代码来使用不同的layoutresource,语言设置的动态改变等.

首先要在配置Activity的时候进行如下的配置:

 

<activity android:name=".MyActivity"

          android:configChanges="orientation|keyboardHidden|screenSize"

          android:label="@string/app_name">

 

另外需要重写ActivityonConfigurationChanged方法。实现方式如下,不需要做太多的内容:

 

@Override

public void onConfigurationChanged(Configuration newConfig) {

    super.onConfigurationChanged(newConfig);

 

    // Checks the orientation of the screen

    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {

        Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();

 

   } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){

        Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();

    }

}

关于android应用开发 性能优化的一些建议

1.httpgzip压缩,设置连接超时时间和响应超时时间

http请求按照业务需求,分为是否可以缓存和不可缓存,那么在无网络的环境中,仍然通过缓存的httpresponse浏览部分数据,实现离线阅读。

 

2.listview 性能优化

1).复用convertView

getItemView中,判断convertView是否为空,如果不为空,可复用。如果couvertview中的view需要添加listerner,代码一定要在if(convertView==null){}之外。

2).异步加载图片

item中如果包含有webimage,那么最好异步加载

3).快速滑动时不显示图片

当快速滑动列表时(SCROLL_STATE_FLING),item中的图片或获取需要消耗资源的view,可以不显示出来;而处于其他两种状态(SCROLL_STATE_IDLESCROLL_STATE_TOUCH_SCROLL),则将那些view显示出来

 

3.使用线程池,分为核心线程池和普通线程池,下载图片等耗时任务放置在普通线程池,避免耗时任务阻塞线程池后,导致所有异步任务都必须等待

 

4.异步任务,分为核心任务和普通任务,只有核心任务中出现的系统级错误才会报错,异步任务的ui操作需要判断原activity是否处于激活状态

 

5.尽量避免static成员变量引用资源耗费过多的实例,比如Context

 

6.使用WeakReference代替强引用,弱引用可以让您保持对对象的引用,同时允许GC在必要时释放对象,回收内存。对于那些创建便宜但耗费大量内存的对象,即希望保持该对象,又要在应用程序需要时使用,同时希望GC必要时回收时,可以考虑使用弱引用。

 

7.超级大胖子Bitmap

及时的销毁(ActivityonDestroy时,将bitmap回收)

设置一定的采样率

巧妙的运用软引用

drawable对应resid的资源,bitmap对应其他资源

 

8.保证Cursor占用的内存被及时的释放掉,而不是等待GC来处理。并且Android明显是倾向于编 程者手动的将Cursor close

 

9.线程也是造成内存泄露的一个重要的源头。线程产生内存泄露的主要原因在于线程 生命周期的不可控

 

10.如果ImageView的图片是来自网络,进行异步加载

 

11.应用开发中自定义View的时候,交互部分,千万不要写成线程不断刷新界面显示,而是根据TouchListener事件主动触发界面的更新

0 0