Android初级第九讲之适配和调试



 本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处!

Android适配需要考虑方方面面,主要是图片字体大小和API,但也要考虑其他场景下的一些问题。

先熟悉一下Android设备的dpi,设计上叫ppi,即1inch中有多少个像素

1、考虑横竖屏幕,注意屏幕布局资源的替换和页面数据的保存和重加载,配合onSaveInstance和onRestoreInstance使用

以及适配的屏幕尺寸,通过在主配置文件的Application处,设计supports-screen,normal、large、xlarge等

以下摘抄自Google官方:https://developer.android.com/guide/practices/screens_support.html

屏幕尺寸
按屏幕对角测量的实际物理尺寸。

为简便起见,Android 将所有实际屏幕尺寸分组为四种通用尺寸:小、 正常、大和超大。

屏幕密度
屏幕物理区域中的像素量;通常称为 dpi(每英寸 点数)。例如, 与“正常”或“高”密度屏幕相比,“低”密度屏幕在给定物理区域的像素较少。

为简便起见,Android 将所有屏幕密度分组为六种通用密度: 低、中、高、超高、超超高和超超超高。

方向
从用户视角看屏幕的方向,即横屏还是 竖屏,分别表示屏幕的纵横比是宽还是高。请注意, 不仅不同的设备默认以不同的方向操作,而且 方向在运行时可随着用户旋转设备而改变。
分辨率
屏幕上物理像素的总数。添加对多种屏幕的支持时, 应用不会直接使用分辨率;而只应关注通用尺寸和密度组指定的屏幕 尺寸及密度。
密度无关像素 (dp)
在定义 UI 布局时应使用的虚拟像素单位,用于以密度无关方式表示布局维度 或位置。

密度无关像素等于 160 dpi 屏幕上的一个物理像素,这是 系统为“中”密度屏幕假设的基线密度。在运行时,系统 根据使用中屏幕的实际密度按需要以透明方式处理 dp 单位的任何缩放 。dp 单位转换为屏幕像素很简单:  px = dp * (dpi / 160) 。 例如,在 240 dpi 屏幕上,1 dp 等于 1.5 物理像素。在定义应用的 UI 时应始终使用 dp 单位 ,以确保在不同密度的屏幕上正常显示 UI。

支持的屏幕范围

从 Android 1.6(API 级别 4)开始,Android 支持多种屏幕尺寸和密度,反映设备可能具有的多种不同屏幕配置。 您可以使用 Android 系统的功能优化应用在各种屏幕配置下的用户界面 ,确保应用不仅正常渲染,而且在每个屏幕上提供 最佳的用户体验。

为简化您为多种屏幕设计用户界面的方式,Android 将实际屏幕尺寸和密度的范围 分为:

  • 四种通用 尺寸正常、   和 超大

    :从 Android 3.2(API 级别 13)开始,这些尺寸组 已弃用,而采用根据可用屏幕宽度管理屏幕尺寸的 新技术。如果为 Android 3.2 和更高版本开发,请参阅声明适用于 Android 3.2 的平板电脑布局以了解更多信息。

  • 六种通用的 密度
    • ldpi(低)~120dpi ~density=0.75
    • mdpi(中)~160dpi ~density=1
    • hdpi(高)~240dpi ~density=1.5
    • xhdpi(超高)~320dpi ~density=2
    • xxhdpi(超超高)~480dpi ~density=3
    • xxxhdpi(超超超高)~640dpi ~density=4

以上是对屏幕密度的描述,希望大家明白一点:分辨率越高的手机,指的是密度越高,即单位区域内像素越多。


从 Android 3.2(API 级别 13)开始,以上尺寸组已弃用,您 应改为使用 sw<N>dp 配置限定符来定义布局资源 可用的最小宽度。例如,如果多窗格平板电脑布局 需要至少 600dp 的屏幕宽度,应将其放在 layout-sw600dp/ 中。声明适用于 Android 3.2 的平板电脑布局一节将进一步讨论如何使用新技术声明布局资源。

如果未配置到相应尺寸,则高分辨率的会向高配置的资源扩展,低分辨率的会向低配置的资源扩展。举个栗子:只有hdpi、xhdpi三种资源,则mdpi的手机默认使用hdpi,而xxhdpi使用xhdpi,以实现屏幕的最佳显示效果。


关于图片、布局和密度,根据上述参数可以做如下配置


上面是对大体的尺寸做适配,而安卓的厂商不要太多,各家规范又不太一致,因此可以对具体的尺寸做适配。


以上即对图片、布局,甚至具体尺寸做的适配。

适配的部分代码

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;



2、字体、布局大小

字体尽量用sp,间距和尺寸尽量用dp,理解density就可以明白,这样字体、间距和尺寸就会随着屏幕密度而自动改变为px


3、不同系统API不同-如setBackground,碎片化问题

举个栗子:不同系统对从webView本地拿图片方法不一样

        public void openFileChooser(ValueCallback<Uri> uploadMsg) {
            listener.showConfirmDialog(uploadMsg);
 }

        // For Android 3.0+
        public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
            listener.showConfirmDialog(uploadMsg);
        }

        // For Android 4.1
            listener.showConfirmDialog(uploadMsg);
        }



更多详见:http://blog.csdn.net/reboot123/article/details/52461897


4、Cpu不同-如arm、mips、x86

一般不同手机,会适配不同硬件,而选择合适的cpu是驱动不同硬件达到完美状态的关键,arm是主流。厂商会根据不同功能如拍照美颜、视频流畅度选择不同cpu,有的比较放松如Nexus,有的比较严格如Oppo;严格的结果就是,如果你没有适配它的so包,则相关功能就不可用,银联3.2.5版本即是如此。

一般情况下只适配arm-v7a即可,x86会自动转译,mips几乎可以忽略

更多关于cpu的介绍:http://blog.csdn.net/reboot123/article/details/51601368

5、状态栏、导航栏、菜单栏的长度

比如:http://blog.csdn.net/u010156024/article/details/48321485

6、横竖屏切换,且各生命周期不再重新调用

1)Activity设置  android:configChanges="keyboard|screenSize|orientation|layoutDirection"

2)在Activity中实现onConfigurationChanged方法,重新布局和初始化数据(注意全局变量数据依然存在)

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        mScreenChanged.set(true);//记录横竖屏发生过变化
        if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
            //land
            setContentView(R.layout.activity_land);
            initLand();//初始化横屏数据
        } else if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
            //port
            setContentView(R.layout.activity_port);
            initPort();//初始化竖屏数据
        }
    }

3)在点击事件,强制执行横竖屏操作                                                                             

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.iv_close:
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//强制为竖屏
                break;
            case R.id.iv_stretch:
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);//强制为横屏
                break;
        }
    }

7、图片等比例缩放,需要maxWidth、maxHeight和adjustViewBounds设置为true同时进行才可以
注意,maxWidth和maxHeight不能直接设为屏幕宽高,否则等比例缩放会失败,因为某一方达到最大值,则另一方也会执行同样操作
photo = new ImageView(mContext);
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
photo.setLayoutParams(lp);
photo.setMaxWidth((int) (screenWidth * 0.99));
photo.setMaxHeight((int) (screenHeight * 0.99));
photo.setScaleType(ImageView.ScaleType.FIT_CENTER);
photo.setAdjustViewBounds(true);
如果需要左右滑动、拉伸缩放,做图片预览,那么可以用下面的资源:
http://download.csdn.net/detail/liuxian13183/9846522
ImageView的绘画,先后执行顺序为:
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }




    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
    }
    @Override
    public void onGlobalLayout() {




    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }
前三个可能执行多次,最后一个仅执行一次。

8、H5调试方案:https://segmentfault.com/a/1190000009240637


更多技巧:http://blog.csdn.net/reboot123/article/details/46127797



你可能感兴趣的:(Android初级第九讲之适配和调试)