android屏幕适配的全攻略2--支持手机各种屏幕密度dpi
如何为不同密度的屏幕提供不同的资源和使用密度独立的单位。
1 使用密度无关像素
坚决杜绝在布局文件中使用绝对像素来定位和设置大小。因为不同的屏幕有不同的像素密度,所以使用像素来设置控件大小是有问题的,在不同的设备上同样的像素可能代表不同的物理屏幕尺寸,所以当使用尺寸的时候,总是使用dp或者sp,dp是相对于160dpi屏幕的密度独立的像素单位,而sp是同样的,只不过会相对于用户设定的文字大小去缩放,因此在定义文字大小的时候要用sp而不要在定义布局的时候使用sp。
例如当你设置两个按钮的间隔的时候使用dp 而不是 px:
<Buttonandroid:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/clickme"
android:layout_marginTop="20dp"/>
当定义文字大小的时候,总是使用 sp:
<TextViewandroid:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"/>
2 不同的屏幕密度使用不同的图片
由于Android设备的屏幕密度是各种各样的,您应该为不同密度的屏幕提供不同的图片资源,这样在各种像素密度的屏幕上都能获得最好的图形质量和性能。
在原有矢量图的基础上按照如下的缩放比例来分别生成不同屏幕密度的图片资源:
xhdpi: 2.0
hdpi: 1.5
mdpi: 1.0 (baseline)
ldpi: 0.75
这意味着对于xhdpi 的设备需要使用200×200的图片;对于hdpi的设备只需要 150×150 的图片;而对于mdpi的设备需要 100×100 的图片; 对于ldpi 的设备只需要75×75 的图片。
把这些图片放到位于res/目录下对于的图片目录中:
MyProject/
res/
drawable-xhdpi/
awesomeimage.png
drawable-hdpi/
awesomeimage.png
drawable-mdpi/
awesomeimage.png
drawable-ldpi/
awesomeimage.png
然后,当您使用@drawable/awesomeimage的时候, 系统会根据当前设备的屏幕密度为您选择最优的图片。
小插曲:
如果我们只提供一个图片来适配不同屏幕密度的设备的话,就要考虑放在哪个文件夹下了。
我们以Nexus5为例,如果我们把图片放在drawable-xxhdpi
下,占用的内存最小(凯子哥的例子是11.65M),如果放在drawable
或drawable-mdpi
下,占用的内存将会非常大(凯子哥的例子是74.95M)。如果放在drawable-hdpi
下占用的为35.38M(同一张图片),所以,我们要提供不同尺寸的图片来适配不同的屏幕密度,否则可能会很大程度上浪费内存。
虽然是以了dp这种屏幕密度无关单位,但还是存在下面的问题,看下面的一个列子
Nexu5手机,对应的宽度是360dp
我们现在在一个布局文件中,放置两个按钮,一个按钮在最左边宽度是150dp,另外一个按钮放置布局的最右边宽度是200dp,中间还剩余了10dp,我们来看下布局的显示
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#a79"
tools:context=".MainActivity"> <Button
android:layout_width="150dp"
android:layout_height="fill_parent"
android:layout_alignParentLeft="true"
android:background="#779"
android:text="左边按钮"
/> <Button
android:layout_width="200dp"
android:layout_height="fill_parent"
android:layout_alignParentRight="true"
android:background="#179"
android:text="右边按钮"
/>
</RelativeLayout>
但是该布局在其他手机上的显示效果
即使我们使用了dp和sp,还是会存在上面的同一种布局文件在不同的手机上显示出不一样的效果,因为不同手机的宽度的大小对应的dp是不一样的。
解决上面问题的办法:
1、尽量不要直接写150dp这种固定值,可以使用weight、wrapcontent 相对布局来解决上面的问题,除了这种方法之外,还有没有其他的方式了
思路:把任何设备的手机宽度像素均分为320份,高度像素均分为480份,使用我们写好的程序自动生成资源values-***×***
文件夹,里面包含lay_x.xml
和lay_y.xml
,分别对应宽度和高度的像素。
MakeXml类:
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter; /**
* Created by wei.yuan on 2016/5/10.
*/
public class MakeXml {
private final static String rootPath = "F:\\layoutroot\\values-{0}x{1}\\"; private final static float dw = 320f;
private final static float dh = 480f; private final static String WTemplate = "<dimen name=\"x{0}\">{1}px</dimen>\n";
private final static String HTemplate = "<dimen name=\"y{0}\">{1}px</dimen>\n"; public static void main(String[] args) {
makeString(320, 480);
makeString(480, 800);
makeString(480, 854);
makeString(540, 960);
makeString(600, 1024);
makeString(720, 1184);
makeString(720, 1196);
makeString(720, 1280);
makeString(768, 1024);
makeString(800, 1280);
makeString(1080, 1812);
makeString(1080, 1920);
makeString(1440, 2560);
} public static void makeString(int w, int h) { StringBuffer sb = new StringBuffer();
sb.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
sb.append("<resources>");
float cellw = w / dw;
for (int i = 1; i < 320; i++) {
sb.append(WTemplate.replace("{0}", i + "").replace("{1}",
change(cellw * i) + ""));
}
sb.append(WTemplate.replace("{0}", "320").replace("{1}", w + ""));
sb.append("</resources>"); StringBuffer sb2 = new StringBuffer();
sb2.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
sb2.append("<resources>");
float cellh = h / dh;
for (int i = 1; i < 480; i++) {
sb2.append(HTemplate.replace("{0}", i + "").replace("{1}",
change(cellh * i) + ""));
}
sb2.append(HTemplate.replace("{0}", "480").replace("{1}", h + ""));
sb2.append("</resources>"); String path = rootPath.replace("{0}", h + "").replace("{1}", w + "");
File rootFile = new File(path);
if (!rootFile.exists()) {
rootFile.mkdirs();
}
File layxFile = new File(path + "lay_x.xml");
File layyFile = new File(path + "lay_y.xml");
try {
PrintWriter pw = new PrintWriter(new FileOutputStream(layxFile));
pw.print(sb.toString());
pw.close();
pw = new PrintWriter(new FileOutputStream(layyFile));
pw.print(sb2.toString());
pw.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} } public static float change(float a) {
int temp = (int) (a * 100);
return temp / 100f;
} }
执行上面程序,
private final static String rootPath = "F:\\layoutroot\\values-{0}x{1}\\";知道生成文件的路径
会在f盘盘的layoutroot目录下生成下面这些文件夹和文件
F:\layoutroot\values-480x320\lay_x.xml
<?xml version="1.0" encoding="utf-8"?>
<resources><dimen name="x1">1.0px</dimen>
<dimen name="x2">2.0px</dimen>
<dimen name="x3">3.0px</dimen>
<dimen name="x4">4.0px</dimen>
<dimen name="x5">5.0px</dimen>
...省略...
<dimen name="x316">316.0px</dimen>
<dimen name="x317">317.0px</dimen>
<dimen name="x318">318.0px</dimen>
<dimen name="x319">319.0px</dimen>
<dimen name="x320">320px</dimen>
</resources>
F:\layoutroot\values-480x320\lay_y.xml
<?xml version="1.0" encoding="utf-8"?>
<resources><dimen name="y1">1.0px</dimen>
<dimen name="y2">2.0px</dimen>
<dimen name="y3">3.0px</dimen>
<dimen name="y4">4.0px</dimen>
<dimen name="y5">5.0px</dimen>
...省略...
<dimen name="y476">476.0px</dimen>
<dimen name="y477">477.0px</dimen>
<dimen name="y478">478.0px</dimen>
<dimen name="y479">479.0px</dimen>
<dimen name="y480">480px</dimen>
</resources>
在480×320的设备上,x2就代表2.0px,y2就代表3.0px。
在800×480的设备上,x2就代表3.0px,y2就代表3.33px。依次类推。
我们需要把上面生成的value文件夹拷贝到对应的工程目录下
如何使用:
<Button
android:background="#abd123"
android:layout_width="@dimen/x160"
android:layout_height="@dimen/y240"
android:text="Button" />
这样设置,在各种屏幕宽度的设备上,此Button的宽度和高度就都占屏幕的一半。
效果如下:
我们看到这种方式可以支持大部分屏幕宽度的设备,但是我们也看到了一些设备,如Nexus9、Nexus10上并没有显示出Button,这是因为我们生成的尺寸资源文件里没有对应分辨率的xml文件。
android屏幕适配的全攻略2--支持手机各种屏幕密度dpi的更多相关文章
- android屏幕适配的全攻略3-动态获取手机屏幕宽高及动态设置控件宽高
1.获取手机屏幕宽高: DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetr ...
- android屏幕适配的全攻略--支持不同的屏幕尺寸适配平板和手机
一. 核心概念与单位详解 1. 什么是屏幕尺寸.屏幕分辨率.屏幕像素密度? 屏幕分辨率越大,手机越清晰 dpi就是dot per inch dot意思是点,就是每英寸上面的像素点数 android原始 ...
- 打造一个高逼格的android开源项目——小白全攻略 (转)
转自:打造一个高逼格的android开源项目 小引子 在平时的开发过程中,我们经常会查阅很多的资料,最常参考的是 github 的开源项目.通常在项目的主页面能看到项目的简介和基本使用,并且时不时能看 ...
- Android Preference 设置偏好全攻略
Android 设置是每个App必不可小的东西,看似很简单,但是初学不熟悉的很花时间去研究,特别样式兼容方面,以及有自定义设置的需求,下面是对用法做一个总结 Preference结构 界面结构看下图 ...
- Android屏幕适配全攻略 (转载)
http://blog.csdn.net/jdsjlzx/article/details/45891551 https://github.com/hongyangAndroid/AndroidAuto ...
- Android屏幕适配全攻略(最权威的官方适配指导)屏幕尺寸 屏幕分辨率 屏幕像素密度 dpdipdpisppx mdpihdpixdpixxdpi
Android屏幕适配全攻略(最权威的官方适配指导)原创赵凯强 发布于2015-05-19 11:34:17 阅读数 153734 收藏展开 转载请注明出处:http://blog.csdn.net/ ...
- 【收藏】Android屏幕适配全攻略(最权威的Google官方适配指导)
来源:http://blog.csdn.net/zhaokaiqiang1992 更多:Android AutoLayout全新的适配方式, 堪称适配终结者 Android的屏幕适配一直以来都在折磨着 ...
- Android屏幕适配全攻略(最权威的官方适配指导)(转),共大家分享。
Android的屏幕适配一直以来都在折磨着我们这些开发者,本篇文章以Google的官方文档为基础,全面而深入的讲解了Android屏幕适配的原因.重要概念.解决方案及最佳实践,我相信如果你能认真的学习 ...
- Android屏幕适配全攻略(最权威的官方适配指导) (转)
招聘信息: Cocos2d-X 前端主程 [新浪微博]手机客户端iOS研发工程师 20k-40k iOS 开发工程师 iOS高级开发工程师(中国排名第一的企业级移动互联网云计算公司 和创科技 红圈营销 ...
随机推荐
- ms-setting是什么
ms-settings 遇到了两个问题,记录一下 1)windows桌面右键菜单-->显示设置或者个性化-->报错:ms-settings:personalization-backgrou ...
- OI 做题的常见错误
会引起 Compile Error 的错误 由于这类错误过于简单,相信是个正常人都会修,故略写. int main() 写为 int mian() . 写完 struct 或 class 忘记写分号. ...
- Rocket - tilelink - AsyncCrossing
https://mp.weixin.qq.com/s/v8plWCBD8vZkxykjJe4TCg 介绍AsyncCrossing的实现,主要介绍如何实现diplomacy Node和LazyMo ...
- Chisel3 - Tutorial - ByteSelector
https://mp.weixin.qq.com/s/RQg2ca1rwfVHx_QG-IOV-w 字节选择器. 参考链接: https://github.com/ucb-bar/chisel ...
- Java实现 LeetCode 448 找到所有数组中消失的数字
448. 找到所有数组中消失的数字 给定一个范围在 1 ≤ a[i] ≤ n ( n = 数组大小 ) 的 整型数组,数组中的元素一些出现了两次,另一些只出现一次. 找到所有在 [1, n] 范围之间 ...
- 不可不知的JSON处理库(cJSON)
ANSI C中的超轻量级JSON解析器 JSON(JavaScript对象表示法)是一种轻量级的数据交换格式.人类易于阅读和书写.机器很容易解析和生成.它基于JavaScript编程语言标准ECMA- ...
- Java基础(八)
一.Java集合框架 Java集合类库也将接口与实现分离. 队列接口指出可以在队列的尾部添加元素,在队列的头部删除元素,并且可以查找队列中元素的个数. 队列通常有两种实现方式:一种是使用循环数组:另一 ...
- CentOS8.1中搭建Gitlab服务器
依旧是写在前面的话♠:很多IT人从业N年也许都还没有亲自搭过一次Gitlab服务器,是不是?有木有?!通常都是背着自己的笔记电脑到一家公司入职,或入职后领到公司分配的电脑,然后分配了Git账号,拿了将 ...
- k8s学习-集群调度
4.7.集群调度 4.7.1.说明 简介 Scheduler 是 kubernetes 的调度器,主要的任务是把定义的 pod 分配到集群的节点上.听起来非常简单,但有很多要考虑的问题: 公平:如何保 ...
- jQuery - Ajax ajax方法详解
$.ajax()方法详解 jquery中的ajax方法参数总是记不住,这里记录一下. 1.url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. 2.type: 要求为Strin ...