Android屏幕适配基础(2)

原创 2017年10月20日 09:21:10

上节课我们留一个问题,项目中的dpi和屏幕dpi如何对应的呢?

这里写图片描述

一般新建一个项目只有drawable文件夹,并没有这些后缀为“mdpi,nodpi,xhdpi,xxhdpi”的文件夹,如何新建这些文件夹呢?

这里写图片描述

假如你要适配的屏幕比较特殊,你也可以直接定义自己的屏幕密度文件夹

这里写图片描述

1 同一张图片,放在不同dpi文件夹下会有什么结果?

我找了一张child.jpg图片,原始为533*300像素,手机屏幕密度为420

imageView.post(new Runnable() {
            @Override
            public void run() {
                Resources res=getResources();
                Bitmap bmp= BitmapFactory.decodeResource(res, R.drawable.child);
                int w = bmp.getWidth();
                int h = bmp.getHeight();
                Log.i("TAG", "宽和高: " + w + "*" + h );
            }
        });

结果如图:

这里写图片描述

mdpi=160dpi,xxhdpi=480dpi,420dpi对应533,那么160dpi对应多少?

我们本能认为是533/(420/160),尺寸应该是207;但是却是533*(420/160)的结果才是1399,这个结果和我们预期的不一样,这是为什么?

因为无论图片放在哪个分辨率的文件夹下,像素总数是不变的。

根据公式 px=dpi*inch,当图片放在低分辨率文件夹中,尺寸就会变大。

沿着这个思路,我们就明白屏幕上显示的尺寸其实要参考三个参数:项目中文件夹的dpi,手机屏幕的dpi,图片原始尺寸,根据这三个参数求出实际屏幕显示的尺寸,而确实Android也是这么处理的。

2 项目中文件夹的dpi(inDensity )

这里需要介绍一个类:TypedValue

这个类的作用是用来存储资源文件的值,可以简单理解为记录当前资源文件夹的屏幕密度

/**
 * Container for a dynamically typed data value.  Primarily used with
 * {@link android.content.res.Resources} for holding resource values.
 */

这里写图片描述

opts.inDensity = density 表示的是当前drawable dpi的值也就是项目中文件夹的dpi(density)

3 屏幕的dpi(inTargetDensity)

上图530行代码:

 opts.inTargetDensity = res.getDisplayMetrics().densityDpi;

这句话的目的是获取屏幕的密度,具体如何实现可以看下DisplayMetrics类的getDeviceDensity方法

 private static int getDeviceDensity() {
        // qemu.sf.lcd_density can be used to override ro.sf.lcd_density
        // when running in the emulator, allowing for dynamic configurations.
        // The reason for this is that ro.sf.lcd_density is write-once and is
        // set by the init process when it parses build.prop before anything else.
        return SystemProperties.getInt("qemu.sf.lcd_density",
                SystemProperties.getInt("ro.sf.lcd_density", DENSITY_DEFAULT));
    }

这是一个系统方法,当App运行的时候会在手机中创建一个build.prop文件用于记录手机的硬件信息,如果root系统可以查看此文件,然后调用此方法获取手机屏幕的密度。

4 inDensity和inTargetDensity如何使用?

追踪java源码到这里:

 private static native Bitmap nativeDecodeStream(...);

点击此链接查看C源码

最终定位到doDecode方法

float scale = 1.0f;   
...
if (env->GetBooleanField(options, gOptions_scaledFieldID)) {
            const int density = env->GetIntField(options, gOptions_densityFieldID);
            const int targetDensity = env->GetIntField(options, gOptions_targetDensityFieldID);
            if (density != 0 && targetDensity != 0 && density != screenDensity) {
                scale = (float) targetDensity / density;
            }
        }
...
 if (scale != 1.0f) {
        willScale = true;
        scaledWidth = static_cast<int>(scaledWidth * scale + 0.5f);
        scaledHeight = static_cast<int>(scaledHeight * scale + 0.5f);
    }
...

> 第一段代码定义一个scale系数,默认是1不需要缩放
> 第二段代码是原理,用手机屏幕密度除以资源文件密度得到缩放系数,这样就能解释为什么资源放在drawable-420dpi到drawable-xxhdpi,图片是在缩小了
> 第三段是计算缩放后的实际图片宽和高,画布也会随之缩小和放大。

版权声明:本文为博主原创文章,未经博主允许不得转载。

Android最便捷的屏幕适配,堪称屏幕适配终结者

效果图 最大幅度解决适配问题,并且最大化方便开发者。 so,看下用法: 你没有看错,拿到设计稿,在布局文件里面直接填写对应的px即可,px:这里的px并非是Google不建议使用的px,...
  • qq_23477421
  • qq_23477421
  • 2016年07月04日 10:34
  • 2840

Android屏幕适配之支持各种屏幕密度(三)

我们之前了解过屏幕的像素密度 dpi,我们身边有很多种类的手机,它们的dpi各不相同,我们如何去适配这些不同的屏幕呢?单位务必使用dp或者sp;dp 是一种非密度制约像素,其尺寸与 160 dpi 像...
  • litengit
  • litengit
  • 2016年07月23日 17:25
  • 788

Android屏幕适配方案(上)

Android开发中,屏幕适配始终是第一个要解决的问题,这一点在实际写的时候其实我们都会注意,然而现在我觉得整理一下屏幕适配方面的知识以便记录,博客写的太少,始终得多记录一下 首先关于屏幕,主流的...
  • YANGDAHUAN
  • YANGDAHUAN
  • 2017年03月03日 20:20
  • 3529

Android 屏幕适配方案

转载请标明出处: http://blog.csdn.net/lmj623565791/article/details/45460089; 本文出自:【张鸿洋的博客】 1、概述大家在Andr...
  • lmj623565791
  • lmj623565791
  • 2015年05月04日 13:08
  • 314505

Android开发:最全面、最易懂的Android屏幕适配解决方案

前言 Android的屏幕适配一直以来都在折磨着我们Android开发者,本文将结合: Google的官方权威适配文档郭霖: Android官方提供的支持不同屏幕大小的全部方法Stormzhang...
  • wangwangli6
  • wangwangli6
  • 2017年03月18日 16:37
  • 7603

最清晰的Android多屏幕适配方案

当您的Android应用即将发布的时候,如果你想让更多的用户去使用你的应用,摆在工程师面前的一个重要问题就是如何让你的应用能在各种各样的终端上运行,这里的各种各样首当其冲的就是不同的屏幕分辨率和尺...
  • shimiso
  • shimiso
  • 2016年07月29日 09:22
  • 6505

android gridView屏幕适配,以及GridView的各种属性

** * 获取屏幕宽度 */ public static int getScreenWidth(Context context) { WindowManager manager = (Wi...
  • ITzhongzi
  • ITzhongzi
  • 2016年07月05日 11:50
  • 1142

最新 Android屏幕适配全攻略(官方权威适配方案)

目录(?)[-] Android屏幕适配出现的原因重要概念 屏幕尺寸屏幕分辨率屏幕像素密度dpdipdpisppxmdpihdpixdpixxdpi 解决方案 支持各种屏幕尺寸 ...
  • MLQ8087
  • MLQ8087
  • 2016年07月21日 11:01
  • 1313

安卓采用AutoLayout开源框架屏幕适配方案

一、概述 相信Android的开发者对于设配问题都比较苦恼,Google官方虽然给出了一系列的建议,但是想要单纯使用这些建议将设备很轻松的做好,还是相当困难的。个人也比较关注适配的问题,之前也发...
  • Me_Dong
  • Me_Dong
  • 2016年12月13日 13:12
  • 1434

Android屏幕适配全攻略(最权威的官方适配指导)

Android的屏幕适配一直以来都在折磨着我们这些开发者,本篇文章以Google的官方文档为基础,全面而深入的讲解了Android屏幕适配的原因、重要概念、解决方案及最佳实践,我相信如果你能认真的学习...
  • bz419927089
  • bz419927089
  • 2015年05月19日 11:34
  • 109203
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android屏幕适配基础(2)
举报原因:
原因补充:

(最多只允许输入30个字)