Android APP多屏幕适配

    xiaoxiao2021-03-25  101

     

    现在的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事件主动触发界面的更新

    转载请注明原文地址: https://ju.6miu.com/read-39796.html

    最新回复(0)