您的位置:首页 > 移动开发 > Android开发

Android中的屏幕适配

2016-07-20 16:13 615 查看
一、屏幕适配的个人理解

                跌跌撞撞也好,摸爬滚打也罢。在Android编程圈子中也徘徊一年有余。对于较多基础概念并不十分清楚,现在是时候回到更贴近底层的地方去的时候了。

            Android系统的硬件覆盖电子产品的方方面面,这也是硬件屏幕多样化,形成Android碎片化重要原因。碎片化是一个难题,但并不表示,Android程序开发就不必做兼容考虑。所以,屏幕适配成为其中很重要的环节。

           在市面上依旧没有一劳永逸,一次适配所有的绝佳方案。但是,我们可以应用现有的技术手段能够将我们App适用对象优化到更好,逐渐靠近百分百。通过不断地创新与优化,找到最后的解决途径。以下,将来聊聊实际中的适配处理。

1,适配中的核心关键词

           dpi:像素密度比,是指在固定的物理长度下的像素数量。【dot per inch】

           dp[dip]:屏幕无关像素,不是物理长度,也不是像素点。只有在具体的像素密度比下,可以转换为像素。dp*dpi = px;一款手机已经定制成功,像素密度比确定,dp也确定。

           屏幕分辨率:屏幕高和宽的像素数。分辨率类型大致有:1920*1080(xxh);1280*720(xh);960*540,800*400,854*480(h);480*320(m);240*320(l);

          low:medium:high:extra-high:extra-extra-high=3:4:6:8:12,即是:ldpi:mdpi:hdpi:xhdpi:xxhdpi=3:4:6:8:12。



不同像素密度下合理展示图标大小:



2,适配的理解

         适配的理解就是在程序运行的时候,程序在不同硬件上能够展示如设计那样的效果。

        不适配的情形有:带文字的控件宽度不够,文字展示不全;图标,Bar,按钮过小或者过大。

个人理解,需要做好Android系统硬件的适配,需要分为两个方面:

        (1)同一分辨率下,不同屏幕大小【手机 -- IPad -- 电视】;

        (2)同一屏幕尺寸下,不同屏幕分辨率。

         对于第一种情形,处理的更多方式是直接另起一个APP,其内置展示页面以及业务逻辑,因为屏幕之间巨大的差异,已经发生了质的变化,甚至可以说是不同的APP。

         手机本身也存在多种尺寸,但因为其相差不是很大,屏幕长宽的比例依旧保持相差不大。也归纳到同一屏幕尺寸下,不同分辨率的适配。

         当然,在同一APP中,也能够实现屏幕尺寸发生巨大差异的处理。其维护及实现复杂度相比于再开启一个APP的代价似乎更大。有这个方面的兴趣,可以更多研究。Android屏幕适配经验谈
值得你拥有。&_& &_& &_& 当然,这个Android屏幕适配全攻略
也匹配的上更多的深研。

         以下,将实现以“同一”硬件尺寸下的Android系统硬件适配。

二、屏幕适配的方法

1,布局方面

          多使用LinearLayout,RelativeLayout,不使用绝对布局(现在已经过时);

2,控件属性

          多使用match_parent/wrap_content;可使用dp/sp,不使用px(Android Studio中已经有提醒);

3,权重

          在长度/宽度为0dp时,使用layout_weight,垂直/水平根据权重分割父控件的对应高度/宽度。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/desc_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="布局适配"
android:textSize="26sp" />
<!--布局适配-->
<EditText
android:id="@+id/body_et"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/desc_1" />

<Button
android:id="@+id/body_ensure"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_below="@+id/body_et"
android:text="确认"
android:textSize="26sp" />

<Button
android:id="@+id/body_search"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/body_et"
android:layout_toLeftOf="@+id/body_ensure"
android:text="搜索"
android:textSize="26sp" />

<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_below="@+id/body_search"
android:background="@color/red" />

<!--单位适配-->
<TextView
android:id="@+id/desc_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/divider"
android:text="单位适配"
android:textSize="26sp" />

<Button
android:id="@+id/bt1"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_below="@+id/desc_2"
android:text="dp"
android:textSize="26sp" />

<Button
android:layout_width="200px"
android:layout_height="wrap_content"
android:layout_below="@+id/desc_2"
android:layout_toRightOf="@+id/bt1"
android:text="px"
android:textSize="26sp" />

<!--权重适配-->
<View
android:id="@+id/divider2"
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_below="@+id/bt1"
android:background="@color/red" />

<TextView
android:id="@+id/desc_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/divider2"
android:text="权重适配"
android:textSize="26sp" />

<LinearLayout
android:id="@+id/ll_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/desc_3"
android:orientation="horizontal">

<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="横向权重: 1 "
android:textSize="26sp" />

<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="横向权重: 1"
android:textSize="26sp" />
</LinearLayout>
<!--权重适配-->
<View
android:id="@+id/divider3"
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_below="@+id/ll_1"
android:background="@color/red" />

<LinearLayout
android:id="@+id/ll_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/divider3"
android:orientation="vertical">

<Button
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:text="纵向权重: 1"
android:textSize="26sp" />

<Button
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:text="纵向权重: 1"
android:textSize="26sp" />
</LinearLayout>

<View
android:id="@+id/divider4"
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_below="@+id/ll_2"
android:background="@color/red" />

</RelativeLayout>          适配效果:
布局适配:



整体适配效果:



单位适配:



4,使用硬件单位化

         将手机屏幕虚拟的的划分成为固定的份数,以320*480为例,生成对应分辨率资源文件。

public class MakeXml {
private final static String rootPath = "C:\\Users\\Administrator\\Desktop\\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(768, 1280);//nexus 4
makeString(800, 1280);
makeString(1080, 1812);
makeString(1080, 1920);
makeString(1440, 2560);
makeString(1536, 2048);//nexus 9
makeString(2560, 1600);//nexus 10
}

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;
}              java生成文件放置在res/目录下。



使用:

<Button
android:layout_width="@dimen/x160"
android:layout_height="@dimen/x240" />效果:



弊端:当没生成对应分辨率的文件时,展示效果为空白,如Nexus 7所示。并且生成文件一直在APP中,相对较耗存储空间。

5,图片适配

            依据不同分辨率,切出对应分辨率的图片,可实现背景、按钮、图片、TabBar、Icon等的屏幕适配。

切图比例如图所示:



为了缩小App的体积,且多套图是不太建议的。可以采用切大图及市场占有率最高的两套来适配所有。

图片适配遍历的流程:



           图片适配还可以采用.9图片来实现。在.9图片的制作中,请注意每边都留上2px,即是不让边框线完全没有。同时也注意缩放范围。保持最核心图标的合理变形,整体符合视觉效果的合理缩放。

           Android SDK中提供了编辑9-Patch图片的工具,在tools目录下draw9patch.bat,能够立刻看到编辑后的拉伸效果。

6,百分比屏幕适配

            浏览器中,Web程序展示的屏幕变化并不会少于手机样式,但是很少出现适配问题。是多采用比例布局的缘故。在Android5.0中,新增百分比布局。

<?xml version="1.0" encoding="utf-8"?>
<android.support.percent.PercentRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.percent.PercentRelativeLayout
android:id="@+id/rl1"
android:layout_width="match_parent"
android:layout_height="50dp">

<Button
android:id="@+id/bt1"
android:layout_width="200dp"
android:layout_height="match_parent"
android:text="百分布局的固定宽度"
android:textSize="18sp" />

<Button
android:id="@+id/bt2"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_toRightOf="@+id/bt1"
android:background="@color/blue"
android:text="比例:50%"
android:textSize="20sp"
app:layout_widthPercent="50%" />

<Button
android:id="@+id/bt3"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_toRightOf="@+id/bt2"
android:background="@color/red"
android:text="比例:50%"
android:textSize="20sp"
app:layout_widthPercent="50%" />

</android.support.percent.PercentRelativeLayout>

<android.support.percent.PercentRelativeLayout
android:id="@+id/rl2"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_below="@+id/rl1">

<Button
android:id="@+id/bt4"
android:layout_width="0dp"
android:layout_height="match_parent"
android:background="@color/green"
android:text="比例:30%"
android:textSize="20sp"
app:layout_widthPercent="30%" />

<Button
android:id="@+id/bt5"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_toRightOf="@+id/bt4"
android:background="@color/purple"
android:text="比例:40%"
android:textSize="20sp"
app:layout_widthPercent="40%" />

<Button
android:id="@+id/bt6"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_toRightOf="@+id/bt5"
android:background="@color/gold"
android:text="比例:30%"
android:textSize="20sp"
app:layout_widthPercent="30%" />

</android.support.percent.PercentRelativeLayout>

<Button
android:id="@+id/bt7"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_below="@+id/rl2"
android:text="纵向百分布局:20%"
app:layout_heightPercent="20%" />

<Button
android:id="@+id/bt8"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_below="@+id/bt7"
android:background="@color/navy"
android:text="纵向百分布局:20%"
app:layout_heightPercent="20%" />

</android.support.percent.PercentRelativeLayout>布局展示效果:



百分布局中,控件是相对与父控件的对应属性。所以,在指定过某些控件的固定长度后,依旧不能完全适配。如视图第一行所示。在完全分割父控件对应属性100%的情形下,百分布局的适配性很好。

三、个人感慨

             编程路上因为有很多兴趣相似、相同的人共同前行而变得更有意义。若你看到这篇文章,有什么建议、优化记得分享一下哦~_~

             一个普通男孩,充实着自己的脑袋,也把这个作为一个标注。愿大家前行更美好~~

戳这里,有源码~_~

专注下来!!!!【  让一件事的发生成为必然   】

                                                                                                每篇一句鼓励,愿你我前行更美好~~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息