首页 > 代码库 > 屏幕适配经验

屏幕适配经验

横屏和竖屏的切换,以及分辨率大小不同。

一、横竖屏切换:

1、Android应用程序支持横竖屏幕的切换,android中每次屏幕的切换动会重启Activity,所以应该在Activity销毁(执行onPause()方法和onDestroy()方法)前保存当前活动的状态;在Activity再次创建的时候载入配置,那样,进行中的游戏就不会自动重启了!有的程序适合从竖屏切换到横屏,或者反过来,这个时候怎么办呢?可以在配置Activity的地方进行如下的配置android:screenOrientation="portrait"(landscape是横向,portrait是纵向)。这样就可以保证是竖屏总是竖屏了。

2、而有的程序是适合横竖屏切换的。如何处理呢?首先要在配置Activity的时候进行如下的配置:

android:configChanges="keyboardHidden|orientation",

另外需要重写Activity的onConfigurationChanged方法。

实现方式如下:

@Override

publicvoidonConfigurationChanged(ConfigurationnewConfig){

super.onConfigurationChanged(newConfig);

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

//landdonothingisok

}elseif(this.getResources().getConfiguration().orientation==Configuration.ORIENTATION_PORTRAIT){

//portdonothingisok

}

}

 

二、分辨率问题:

对于分辨率问题,官方给的解决办法是创建不同的layout文件夹,这就需要对每种分辨率的手机都要写一个布局文件,虽然看似解决了分辨率的问题,但是如果其中一处或多处有修改了,就要每个布局文件都要做出修改,这样就造成很大的麻烦。那么可以通过以下几种方式解决:

一)使用layout_weight

目前最为推荐的Android多屏幕自适应解决方案。

    该属性的作用是决定控件在其父布局中的显示权重,一般用于线性布局中。其值越小,则对应的layout_width或layout_height的优先级就越高(一般到100作用就不太明显了);一般横向布局中,决定的是layout_width的优先级;纵向布局中,决定的是layout_height的优先级。

    传统的layout_weight使用方法是将当前控件的layout_width和layout_height都设置成fill_parent,这样就可以把控件的显示比例完全交给layout_weight;这样使用的话,就出现了layout_weight越小,显示比例越大的情况(即权重越大,显示所占的效果越小)。不过对于2个控件还好,如果控件过多,且显示比例也不相同的时候,控制起来就比较麻烦了,毕竟反比不是那么好确定的。于是就有了现在最为流行的0px设值法。看似让人难以理解的layout_height=0px的写法,结合layout_weight,却可以使控件成正比例显示,轻松解决了当前Android开发最为头疼的碎片化问题之一。

先看下面的styles(style_layout.xml)

<?xml version="1.0" encoding="utf-8"?>

<resources> 

 

<!-- 全屏幕拉伸-->

  <style name="layout_full"> 

    <item name="android:layout_width">fill_parent</item> 

    <item name="android:layout_height">fill_parent</item> 

  </style>

  

<!-- 固定自身大小-->

  <style name="layout_wrap"> 

    <item name="android:layout_width">wrap_content</item> 

    <item name="android:layout_height">wrap_content</item> 

  </style>

 

<!-- 横向分布-->

  <style name="layout_horizontal" parent="layout_full"> 

    <item name="android:layout_width">0px</item> 

  </style>

   

<!-- 纵向分布-->

  <style name="layout_vertical" parent="layout_full"> 

    <item name="android:layout_height">0px</item> 

  </style>

        

</resources>

可以看到,layout_width和layout_height两个属性被我封装成了4个style, 根据实际布局情况,选用当中的一种,不需要自己设置

二)清单文件配置:【不建议使用这种方式,需要对不同的界面写不同的布局】

需要在AndroidManifest.xml文件的<manifest>元素如下添加子元素

<supports-screensandroid:largeScreens="true"

android:normalScreens="true"

android:anyDensity="true"

android:smallScreens="true"

android:xlargeScreens="true">

</supports-screens>

以上是为我们的屏幕设置多分辨率支持(更准确的说是适配大、中、小三种密度)。

Android:anyDensity="true",这一句对整个的屏幕都起着十分重要的作用,值为true,我们的应用程序当安装在不同密度的手机上时,程序会分别加载hdpi,mdpi,ldpi文件夹中的资源。相反,如果值设置为false,即使我们在hdpi,mdpi,ldpi,xdpi文件夹下拥有同一种资源,那么应用也不会自动地去相应文件夹下寻找资源。而是会在大密度和小密度手机上加载中密度mdpi文件中的资源。

有时候会根据需要在代码中动态地设置某个值,可以在代码中为这几种密度分别设置偏移量,但是这种方法最好不要使用,最好的方式是在xml文件中不同密度的手机进行分别设置。这里地图的偏移量可以在values-xpdi,values-hpdi,values-mdpi,values-ldpi四种文件夹中的dimens.xml文件进行设置。

 

三)、其他:

说明:

       在不同分辨率的手机模拟器下,控件显示的位置会稍有不同

       通过在layout中定义的布局设置的参数,使用dp(dip),会根据不同的屏幕分辨率进行适配

       但是在代码中的各个参数值,都是使用的像素(px)为单位的

技巧:

1、尽量使用线性布局,相对布局,如果屏幕放不下了,可以使用ScrollView(可以上下拖动)

ScrowView使用的注意:

在不同的屏幕上显示内容不同的情况,其实这个问题我们往往是用滚动视图来解决的,也就是ScrowView;需要注意的是ScrowView中使用layout_weight是无效的,既然使用ScrowView了,就把它里面的控件的大小都设成固定的吧。

2、指定宽高的时候,采用dip的单位,dp单位动态匹配

3、由于android代码中写的单位都是像素,所有需要通过工具类进行转化

4、尽量使用9-patch图,可以自动的依据图片上面显示的内容被拉伸和收缩。其中在编辑的时候,灰色区域是被拉伸的,上下两个点控制水平方向的拉伸,左右两点控制垂直方向的拉伸

       工具在adt-bundle-windows-x86-20130522\sdk\tools目录下的draw9patch.bat

 

 

 

三、手机分辨率px和dp的关系:

dp:是dip的简写,指密度无关的像素。

       指一个抽象意义上的像素,程序用它来定义界面元素。一个与密度无关的,在逻辑尺寸上,与一个位于像素密度为160DPI的屏幕上的像素是一致的。要把密度无关像素转换为屏幕像素,可以用这样一个简单的公式:pixels=dips*(density/160)。举个例子,在DPI为240的屏幕上,1个DIP等于1.5个物理像素。

强烈推荐你用DIP来定义你程序的界面布局,因为这样可以保证你的UI在各种分辨率的屏幕上都可以正常显示。

/**

     * 根据手机的分辨率从 px(像素) 的单位 转成为 dp

     */ 

    public static int px2dip(Context context, float pxValue) { 

        final float scale = context.getResources().getDisplayMetrics().density; 

        return (int) (pxValue / scale + 0.5f); 

    } 

 

/**

     * 根据手机的分辨率从 dip 的单位 转成为 px(像素)

     */ 

    public static int dip2px(Context context, float dpValue) { 

        final float scale = context.getResources().getDisplayMetrics().density; 

        return (int) (dpValue * scale + 0.5f); 

    } 

屏幕适配经验