基础知识

屏幕尺寸、屏幕分辨率、屏幕像素密度

1、屏幕尺寸是指屏幕对角线的长度。单位是英寸,1英寸=2.54厘米。
2、屏幕分辨率是指在横纵向上的像素点数,单位是px,1px=1像素点,一般是纵向像素横向像素,如1280×720。
3、屏幕像素密度是指每英寸上的像素点数,单位是dpi(dot per inch),像素密度和屏幕尺寸和屏幕分辨率有关。

dip、dp、sp、dpi、px、in、pt

1、dip或dp(device independent pixels,设备独立像素):以160dpi为基准,1dp=1px。
2、sp(scaled pixels):可以根据文字大小首选项自动进行缩放。
3、dpi(dots per inch,密度):屏幕像素密度的单位,屏幕每英寸所包含的像素数。
4、px(pixels,像素):物理上的绝对单位。
5、in(inch,英寸):一英寸=2.54cm。
6、pt(磅):一磅=1/72英寸。

mdpi、hdpi、xdpi、xxdpi、xxxdpi
密度分类 密度值范围 代表分辨率 图标尺寸 图片比例
mdpi 120~160dpi 320x480px 48x48px 1
hdpi 160~240dpi 480x800px 72x72px 1.5
xhdpi 240~320dpi 720x1280px 96x96px 2
xxhdpi 320~480dpi 1080x1920px 144x144px 3
xxxhdpi 480~640dpi 1440x2560px 192x192px 4
实战

获取屏幕的数据

// 获取DisplayMetrics实例
DisplayMetrics dm = context.getResources().getDisplayMetrics();// 屏幕高的像素个数
int heightPixels = dm.heightPixels;
// 屏幕宽的像素个数
int widthPixels = dm.widthPixels;// 屏幕密度:每英寸所含的像素的个数
int densityDpi = dm.densityDpi;
// 屏幕密度:densityDpi/160
float density = dm.density;

dp与px相互转换

/*** 转换工具类*/
public class ConvertUtil {/*** dp转换成px** @param context 上下文* @param value   多少dp* @return 返回转换后等于多少px*/public static int dp2px(Context context, float value) {// 获取屏幕的密度:density = densityDpi/160final float scale = context.getResources().getDisplayMetrics().density;// dp转换成px,value*density// + 0.5f是为了四舍五入转换成int类型return (int) (value * scale + 0.5f);}public static int px2dp(Context context, float value) {final float scale = context.getResources().getDisplayMetrics().density;// px转换成dp,value/densityreturn (int) (value / scale + 0.5f);}
}

注意:因为分辨率不一样,所以不能用px;因为屏幕宽度不一样,所以要小心的用dp。

解决方案

一、支持各种屏幕尺寸

1、使用wrap_content、math_parent、weight

wrap_content:根据控件的内容设置控件的尺寸
math_parent:根据父控件的尺寸大小设置控件的尺寸
weight:权重,在线性布局中可以使用weight属性设置控件所占的比例

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView        android:layout_width="80dp"        android:layout_height="80dp"        android:layout_weight="0"        android:background="#028330"/>
<TextView        android:layout_width="wrap_content"        android:layout_height="80dp"        android:text="new reader"        android:textSize="22sp"        android:layout_weight="1"/>
<TextView        android:layout_width="160dp"        android:layout_height="80dp"       android:text="Politics"        android:textSize="18sp"        android:layout_weight="0"        android:background="#028330"/>
</LinearLayout>

实现下图所显示的效果:当屏幕尺寸改变时,new reader控件两边的控件大小不变,new reader控件会占完剩余的空间。

android:layout_weight
公式:所占宽度=原来宽度+剩余空间所占百分比的宽度

2、使用相对布局,禁用绝对布局

简单的布局一般都使用线性布局,而略微复杂点的布局,我们使用相对布局,大多数时候,我们都是使用这两种布局的嵌套。我们使用相对布局的原因是,相对布局能在各种尺寸的屏幕上保持控件间的相对位置。

3、使用限定符
一、使用尺寸限定符

当我们要在大屏幕上显示不同的布局,就要使用large限定符。例如,在宽的屏幕左边显示列表右边显示列表项的详细信息,在一般宽度的屏幕只显示列表,不显示列表项的详细信息,我们就可以使用large限定符。
单面板:res/layout/activity_qualifier.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><fragmentandroid:id="@+id/news_title_fragment"android:name="com.jun.androidexample.qualifier.NewsTitleFragment"android:layout_width="match_parent"android:layout_height="match_parent"/>
</FrameLayout>

双面板:res/layout-large/activity_qualifier.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><fragmentandroid:id="@+id/news_title_fragment"android:name="com.jun.androidexample.qualifier.NewsTitleFragment"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"/><FrameLayoutandroid:id="@+id/news_content_layout"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="3"><fragmentandroid:id="@+id/news_content_fragment"android:name="com.jun.androidexample.qualifier.NewsContentFragment"android:layout_width="match_parent"android:layout_height="match_parent"/></FrameLayout>
</LinearLayout>

如果这个程序运行在屏幕尺寸大于7inch的设备上,系统就会加载res/layout-large/main.xml 而不是res/layout/main.xml,在小于7inch的设备上就会加载res/layout/main.xml。

注意:这种通过large限定符分辨屏幕尺寸的方法,只适用于android3.2之前。在android3.2之后,为了更精确地分辨屏幕尺寸大小,Google推出了最小宽度限定符。

二、使用最小宽度限定符

最小宽度限定符的使用和large基本一致,只是使用了具体的宽度限定。
单面板:res/layout/activity_qualifier.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><fragmentandroid:id="@+id/news_title_fragment"android:name="com.jun.androidexample.qualifier.NewsTitleFragment"android:layout_width="match_parent"android:layout_height="match_parent"/>
</FrameLayout>

双面板:res/layout-sw600dp/activity_qualifier.xml,Small Width最小宽度

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><fragmentandroid:id="@+id/news_title_fragment"android:name="com.jun.androidexample.qualifier.NewsTitleFragment"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"/><FrameLayoutandroid:id="@+id/news_content_layout"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="3"><fragmentandroid:id="@+id/news_content_fragment"android:name="com.jun.androidexample.qualifier.NewsContentFragment"android:layout_width="match_parent"android:layout_height="match_parent"/></FrameLayout>
</LinearLayout>

这就要求我们维护两个相同功能的文件,为了避免繁琐操作,我们就要使用布局别名。

三、使用布局别名

单面板:res/layout/activity_qualifier.xml
双面板:res/layout-large/activity_qualifier.xml
双面板:res/layout-sw600dp/activity_qualifier.xml

因为双面板的布局一样,所以为了方便管理使用以下2个文件代替上面的3个文件。
单面板:res/layout/activity_qualifier_onepane.xml
双面板:res/layout/activity_qualifier_twopanes.xml

然后创建如下3个文件
默认布局,单面板:res/values/layout.xml

<resources><item name="activity_qualifier" type="layout">@layout/activity_qualifier_onepane</item>
</resources>

Android3.2之前的大屏布局,双面板:res/values-large/layout.xml

<resources><item name="activity_qualifier" type="layout">@layout/activity_qualifier_twopanes</item>
</resources>

Android3.2之后的大于600dp屏布局,双面板:res/values-sw600dp/layout.xml

<resources><item name="activity_qualifier" type="layout">@layout/activity_qualifier_twopanes</item>
</resources>

这样无论是哪一种名字都叫activity_qualifier。

记得将之前创建的res/layout-large和res/layout-sw600dp
双面板:res/layout-large/activity_qualifier.xml
双面板:res/layout-sw600dp/activity_qualifier.xml,Small Width最小宽度
都删掉,因为已经不需要了。

四、使用屏幕方向限定符

res/values-port/layout.xml,纵向,单面板

<resources><item name="activity_qualifier" type="layout">@layout/activity_qualifier_onepane</item>
</resources>

res/values-land/layout.xml,横向,双面板

<resources><item name="activity_qualifier" type="layout">@layout/activity_qualifier_twopanes</item>
</resources>
4、使用自动拉伸位图

.9.png格式图片

二、支持各种屏幕密度

1、统一划分

统一划分解决分辨率不一致,宽高不一致的问题。把需要适配的手机屏幕的宽度像素均分为320份,高度像素均分为480份。使用我们写好的程序自动生成资源values-×文件夹,里面包含lay_x.xml和lay_y.xml,分别对应宽度和高度的像素。

在Eclipse中运行如下代码自动生成需要的文件

/*** 将所有不同分辨率的屏幕都分成480x320*/
public class MakeXml {// 生成文件存放的地址是C:\layoutRootprivate final static String rootPath = "C:\\layoutRoot\\values-{0}x{1}\\";// 分成480x320private 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) {setResolution();}// 设置需要适配的不同屏幕的分辨率public static void setResolution(){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;}
}

将C:\layoutRoot目录下的文件拷贝到Android Studio中app/src/main/res/目录下

使用示例:

<Buttonandroid:background="#abd123"android:layout_width="@dimen/x160"android:layout_height="@dimen/y240"/>

宽和高都是屏幕的一半

2、提供备用位图

针对不同分辨率的屏幕提供不同分辨率的位图
res/drawable-mdpi
res/drawable-hdpi
res/drawable-xhdpi
res/drawable-xxhdpi
res/drawable-xxxhdpi

如果只提供一张位图就应该放置在应对分辨率的文件夹中

三、实施自适应用户界面流程

1、确定当前布局
boolean isTwoPane;
// 能找到news_content_layout就是双页否则就是单页
View view = getActivity().findViewById(R.id.news_content_layout);
if (view != null && view.getVisibility() == View.VISIBLE) {isTwoPane = true;
} else {isTwoPane = false;
}
2、根据当前布局做出响应

在单面板模式下,用户点击了新闻标题,我们要打开一个新的Activity来显示新闻详细信息;在双面板模式下,用户点击了新闻标题,我们要在右边面板上显示详细信息。


Percent Support Library(百分比布局库)

添加依赖

compile 'com.android.support:percent:23.3.0'

总结Android屏幕适配(源自简书:李俊的博客)相关推荐

  1. 2021年最详细的Android屏幕适配方案汇总

    1 Android屏幕适配的度量单位和相关概念 建议在阅读本文章之前,可以先阅读快乐李同学写的文章<Android屏幕适配的度量单位和相关概念>,这篇文章包含了阅读本文的一些基础知识,推荐 ...

  2. Android 系统(186)---最易懂的Android屏幕适配解决方案--总结版

    最易懂的Android屏幕适配解决方案--总结版 本文参考自: Google的官方权威适配文档 郭霖:Android官方提供的支持不同屏幕大小的全部方法 Stormzhang:Android 屏幕适配 ...

  3. Android 屏幕适配神器ScreenMatch

    Android屏幕适配 一.smallestWidth限定符 适配(推荐) 1.smallestWidth 限定符适配原理 2.为什么选择 smallestWidth 限定符适配? 3.使用步骤(重点 ...

  4. Android屏幕适配-必备知识

    Android屏幕适配专题 Android屏幕适配-必备知识 Android屏幕适配-终结者 你是否被屏幕的各种参数(dpi.ppi等)搞的头晕眼花? 屏幕的密度到底是怎么回事? 应该如何来进行屏幕适 ...

  5. SmallestWidth一种非常好用的Android屏幕适配

    更新:由于该适配方案越来越多人使用,也有很多人遇到不太理解的问题.所以为了大家更好的使用,我将文章很多内容更新了,老用户可以重新看下整篇文章.主要更新的内容是使用方法跟以前不同了,以前是不改变最小宽度 ...

  6. 一种非常好用的Android屏幕适配

    https://www.jianshu.com/p/1302ad5a4b04 更新:由于该适配方案越来越多人使用,也有很多人遇到不太理解的问题.所以为了大家更好的使用,我将文章很多内容更新了,老用户可 ...

  7. Android 屏幕适配总结

    本文主要涉及以下几篇文章 Android 屏幕适配总结 Android ConstraintLayout 使用与适配(使用篇) Android ConstraintLayout 使用与适配(适配篇) ...

  8. 鸿洋android屏幕适配四部曲-传送门

    鸿洋android屏幕适配四部曲-传送门 两分钟理解Android中PX.DP.SP的区别 https://blog.csdn.net/donkor_/article/details/77680042 ...

  9. Android 屏幕适配

    一.适配方式之dp 名词解释 分辨率:480*800,1280*720.表示物理屏幕区域内像素点的总和.(切记:跟屏幕适配没有任何关系) 因为我们既可以把1280*720 的分辨率做到4.0 的手机上 ...

  10. android屏幕适配详解

    android屏幕适配详解 官方地址:http://developer.android.com/guide/practices/screens_support.html 一.关于布局适配建议 1.不要 ...

最新文章

  1. input输入框的各种事件
  2. C# 程序执行时间差
  3. return 与 exit()的区别--return退出本函数,exit()退出整个程序
  4. python装饰器详解-python装饰器详解
  5. 标志位操作指令七条CLC,STC,CLD,STD,CLI,STI,CMC
  6. xcode 4 with subversion SVN server–Tips
  7. 手机游戏源码下载的网站
  8. steam++加速问题:出现显示443端口被 vmware-hostd(9860)占用的错误。
  9. 流量计算机标准,-流量计执行标准
  10. 基于Gamebuino设计的算盘小游戏
  11. 未实施内容安全策略 (CSP)
  12. 【爬坑记录】记录搭建fabric 遇到的问题-network e2ecli_default not found
  13. php聊天室发送表情,聊天室之表情发送
  14. Thrift 小试牛刀
  15. java 数据库排序_Java如何排序数据库表的数据内容?
  16. java声明是否是质数,java判断是否为素数(质数)的方法
  17. UVA 12563 Jin Ge Jin Qu hao(多阶段决策问题,DP)
  18. 黑马全套Java教程(十一)
  19. Vaa3D并行程序测试-OPENMP-VS2010-加速程序
  20. 国内可用的ntp服务器地址

热门文章

  1. DS18B20高精度温度传感器,使用介绍【400字】【原创】
  2. 2022-03-22 西安 python 爬虫(6)
  3. 最新百亿量化私募名单
  4. 男人的眼泪是血 很容易就会流完
  5. Java经典实验_猴子的经典实验(转载)
  6. 开启hadoop报错:localhost: Permission denied(publickey,gssapi-keyex,gssapi-with-mic,password).
  7. C++图书馆管理系统 详细代码
  8. mysql导入指定数据库_mysql命令行导入sql文件到指定数据库的方法
  9. 真假博士后事件 万万没想到这些明星是学霸
  10. java默认修饰符_java默认方法的修饰符是什么