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高级开发工程师(中国排名第一的企业级移动互联网云计算公司 和创科技 红圈营销 ...
随机推荐
- 【朝夕专刊】RabbitMQ消息的持久化优先级
欢迎大家阅读<朝夕Net社区技术专刊> 我们致力于.NetCore的推广和落地,为更好的帮助大家学习,方便分享干货,特创此刊!很高兴你能成为忠实读者,文末福利不要错过哦! 上篇文章介绍了R ...
- for循环的嵌套 函数方法
1.双层for循环:外层循环控制行,内行循环控制列 for循环嵌套例子 用五角星组成一个矩形 // 99乘法表 // for(var i = 1 ;i <= 9 ; i++){ // f ...
- Java实现 LeetCode 1162 地图分析(可以暴力或者动态规划的BFS)
1162. 地图分析 你现在手里有一份大小为 N x N 的『地图』(网格) grid,上面的每个『区域』(单元格)都用 0 和 1 标记好了.其中 0 代表海洋,1 代表陆地,你知道距离陆地区域最远 ...
- Java中TreeSet的详细用法
第1部分 TreeSet介绍 TreeSet简介 TreeSet 是一个有序的集合,它的作用是提供有序的Set集合.它继承于AbstractSet抽象类,实现了NavigableSet, Clonea ...
- Java实现 LeetCode 26 删除排序数组中的重复项
26. 删除排序数组中的重复项 给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) ...
- java实现 蓝桥杯 算法训练 安慰奶牛
问题描述 Farmer John变得非常懒,他不想再继续维护供奶牛之间供通行的道路.道路被用来连接N个牧场,牧场被连续地编号为1到N.每一个牧场都是一个奶牛的家.FJ计划除去P条道路中尽可能多的道路, ...
- java实现第七届蓝桥杯圆圈舞
圆圈舞 题目描述 春天温暖的阳光照耀着大地,正是草原上的小动物们最快乐的时候.小动物们在草原上开了一个舞会,欢度这美好的时光. 舞会上最重要的一个环节就是跳圆舞曲,n只小动物手拉手围成一大圈,随着音乐 ...
- tcpdump 基于mac地址抓取数据包
1.刚刚接触tcpdump时,常用tcpdump -i eth1 host 192.168.1.1 这个命令基于ip地址抓取数据包信息. tcpdump -i eth1(接口名称) host 192. ...
- Maven发布Release到中心仓库历程记录(无个人域名)
Maven发布Release到中心仓库历程记录(无个人域名) 前言 因为前段时间自己做了一个爬虫项目(地址),自己很希望分享到maven中心仓库上,感觉拥有自己的jar包令我兴奋,便开始了maven发 ...
- Java I/O模型及其底层原理
Java I/O是Java基础之一,在面试中也比较常见,在这里我们尝试通过这篇文章阐述Java I/O的基础概念,帮助大家更好的理解Java I/O. 在刚开始学习Java I/O时,我很迷惑,因为网 ...