android 多屏幕适配解决方案
2014-06-16 16:42
399 查看
现在的Android手机屏幕越来越多,工作面试的时候很多同学都不是很清楚屏幕适配的问题,网上其实有很多类似的说明,其实大同小异都是翻译google 官方贵的说明,希望大家有时间多学习官方api,这里我也做一下笔记:
android把屏幕分为以下4种:small,normal,large,extra large等。
android把屏幕密度分为4种:low,medium,high,extrahigh。
手机可以有相同的分辨率,但屏幕尺寸可以不相同,
Diagonal pixel表示对角线的像素值(=),DPI=933/3.7=252
android将实际的屏幕密度分为四个通用尺寸(low,medium,high,and extra high)
一般情况下的普通屏幕:ldpi是120dpi,mdpi是160dpi,hdpi是240dpi,xhdpi是320dpi
对于屏幕来说,dpi越大,屏幕的精细度越高,屏幕看起来就越清楚 。
sp(scale-independent pixel)
如何分辨一个屏幕是ldpi、mdpi、hdpi的方法:
<supports-screensandroid: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”/>
如果android:anyDensity="true"
指应用程序支持不同密度,会根据屏幕的分辨率自动去匹配。
如果android:anyDensity="false"
应用程序支持不同密度,系统自动缩放图片尺寸和这个图片的坐标。具体解释一下系统是如何自动缩放资源的。
例如我们在hdpi,mdpi,ldpi文件夹下拥有同一种资源,那么应用也不会自动地去相应文件夹下寻找资源,这种情况都是出现在高密度,以及低密度的手机上,比如说一部240×320像素的手机,
如果设置android:anyDensity="false",Android系统会将240 x 320(低密度)转换为 320×480(中密度),这样的话,应用就会在小密度手机上加载mdpi文件中的资源。
如果在声明不支持的大屏幕,而这个屏幕尺寸是larger的话,系统使用尺寸为("normal")和密度为("medium)显示,不过会出现一层黑色的背景。
如果在声明不支持的小屏幕,而当前屏幕尺寸是smaller的话,系统也使用尺寸为("normal")和密度为("medium)显示.
如果应用程序能在小屏幕上正确缩放(最低是small尺寸或最小宽度320dp),那就不需要用到本属性。否则,就应该为最小屏幕宽度标识符设置本属性
来匹配应用程序所需的最小尺寸。
Android 4.0版本 之后支持layout-mdpi、layout-hdpi这种写法。
res/layout
res/layout-small
res/layout-normal
res/layout-large
res/layout-xlarge
android 新版本支持:
res/layout-mdpi
res/layout-hdpi
res/layout-xhdpi
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:extrahigh比例为3:4:6:8。举例来说,对于中等密度(medium)的屏幕你的图片像素大小为48×48,那么低密度(low)屏幕的图片大小应为36×36,高(high)的为72×72,extra high为96×96。
通常情况下从开发角度讲,应用程序会根据3类Android手机屏幕提供3套UI布局文件,但是相应界面图标也需要提供3套:
为了使文字大小更好的适应屏幕应该使用sp来定义文字大小。
layout_weight属性尽量不要嵌套使用。如父节点已经使用了weight属性,则子节点尽量避免使用。
布局文件中的所有文字大小以及控件大小都必须申明在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
2)尽量使用RelativeLayout,如果必须使用权重则可以考虑RelativeLayout和LinearLayout混合使用。
3)需要根据物理尺寸的大小准备多套布局:
layout(放一些通用布局xml文件,比如界面中顶部和底部的布局,不会随着屏幕大小变化。
layout-mdpi (屏幕尺寸小于3.5英寸左右的布局)
layout-hdpi (屏幕尺寸小于4英寸左右)
layout-xhdpi(4.5英寸-7英寸之间)
如果有些时候需要自定义控件,空间大小特别严格的话,可以考虑获取当前屏幕大小进行计算分割。
DisplayMetricsmetric = 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)
附图1-横竖屏切换无差别布局, 附图2-横竖屏切换布局改变。
android:screenOrientation="portrait"
android:screenOrientation="landscape"
或者setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
这样就可以保证是竖屏总是竖屏了,或者横屏总是横屏。
若要软件在横竖屏之间切换,由于横竖屏的高宽会发生转换,有可能会要求不同的布局。可以通过以下方法来切换布局:
1)layout-land和layout-port
在res目录下建立layout-land(横屏的layout)和layout-port(竖屏的layout)目录,相应的layout文件不变,比如main.xml。其他的不用管,模拟器会自动寻找。
2)onCreate()中判断横竖屏
通过this.getResources().getConfiguration().orientation判断当前是横屏还是竖屏,然后加载相应的xml布局文件。因为当屏幕变为横屏的时候,系统会重新呼叫当前Activity的OnCreate方法,你可以把以下方法放在你的 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");
}
首先要在配置Activity的时候进行如下的配置:
<activityandroid:name=".MyActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:label="@string/app_name">
另外需要重写Activity的onConfigurationChanged方法。实现方式如下,不需要做太多的内容:
@Override
public voidonConfigurationChanged(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();
}
}
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,extrahigh。
手机可以有相同的分辨率,但屏幕尺寸可以不相同,
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-screensandroid: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两个目录,里面分别放置竖屏和横屏两种布局文件,以适应对横屏竖屏自动切换。Android 4.0版本 之后支持layout-mdpi、layout-hdpi这种写法。
res/layout
res/layout-small
res/layout-normal
res/layout-large
res/layout-xlarge
android 新版本支持:
res/layout-mdpi
res/layout-hdpi
res/layout-xhdpi
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:extrahigh比例为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 x 96 px |
Menu | 36 x 36 px | 48 x 48 px | 72 x 72 px | 96 x 96 px |
Status Bar | 24 x 24 px | 32x 32 px | 48 x 48 px | 72 x 72 px |
Tab | 24 x 24 px | 32x 32 px | 48 x 48 px | 72 x 72 px |
Dialog | 24 x 24 px | 32x 32 px | 48 x 48 px | 72 x 72 px |
List View | 24 x 24 px | 32x 32 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 根据屏幕大小计算如果有些时候需要自定义控件,空间大小特别严格的话,可以考虑获取当前屏幕大小进行计算分割。
DisplayMetricsmetric = 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、横竖屏切换
实际工作过程中,很多时候需要横竖屏切换,而且横竖屏需要对应不同的布局模式。这个时候需要控制横竖屏的布局,可以通过系统自适应机制来处理,也可以通过代码控制.附图1-横竖屏切换无差别布局, 附图2-横竖屏切换布局改变。
4.1 禁止切换横屏或竖屏
可以在配置Activity的地方进行如下的配置android:screenOrientation="portrait"
android:screenOrientation="landscape"
或者setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
这样就可以保证是竖屏总是竖屏了,或者横屏总是横屏。
4.2 可以切换横屏或竖屏
若要软件在横竖屏之间切换,由于横竖屏的高宽会发生转换,有可能会要求不同的布局。可以通过以下方法来切换布局:
1)layout-land和layout-port
在res目录下建立layout-land(横屏的layout)和layout-port(竖屏的layout)目录,相应的layout文件不变,比如main.xml。其他的不用管,模拟器会自动寻找。
2)onCreate()中判断横竖屏
通过this.getResources().getConfiguration().orientation判断当前是横屏还是竖屏,然后加载相应的xml布局文件。因为当屏幕变为横屏的时候,系统会重新呼叫当前Activity的OnCreate方法,你可以把以下方法放在你的 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
这种方法缺点是动态适应差。比如横竖屏切换时需要你自己写代码来使用不同的layout等resource,语言设置的动态改变等.首先要在配置Activity的时候进行如下的配置:
<activityandroid:name=".MyActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:label="@string/app_name">
另外需要重写Activity的onConfigurationChanged方法。实现方式如下,不需要做太多的内容:
@Override
public voidonConfigurationChanged(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屏幕适配 - 超级解决方案percent-support-lib
- Android屏幕适配方案:产品级的解决方案
- 最易懂的Android屏幕适配解决方案--总结版
- Android开发:最全面、最易懂的Android屏幕适配解决方案
- Android屏幕适配解决方案
- Android屏幕适配解决方案
- Android开发中屏幕适配解决方案
- 关于android屏幕适配的解决方案
- Android开发:最全面、最易懂的Android屏幕适配解决方案
- Android开发:最全面、最易懂的Android屏幕适配解决方案
- Android屏幕适配方案:产品级的解决方案
- Android开发:最全面、最易懂的Android屏幕适配解决方案
- Android开发:最全面、最易懂的Android屏幕适配解决方案
- Android开发:最全面、最易懂的Android屏幕适配解决方案
- Android 屏幕适配相关解决方案
- Android屏幕适配方案:产品级的解决方案
- Android开发:全面、易懂的Android屏幕适配解决方案
- [置顶] Android屏幕适配 超级解决方案percent-support-lib
- Android开发:最全面、最易懂的Android屏幕适配解决方案
- Android屏幕适配解决方案