Android学习笔记041之屏幕适配

1、屏幕适配原因

  我们都知道Android系统是开发源代码的,任何用户、开发者、OEM厂商、运营商都可以对Android进行定制,修改成他们喜欢的样子。这样就导致Android碎片化非常严重,具体严重到什么程度呢?我们来看一张图

这里的每一个矩形都对应一种Android设备,根据统计,截止到2014年,支持Android的设备共有18796种,具体的统计数据请猛戳这里

  随着搭载Android系统的设备不断增多,设备碎片化、品牌碎片化、系统碎片化、传感器碎片化和屏幕碎片化的程度在不断地加深,今天我们需要学习的就是对我们开发影响非常大的—屏幕碎片化。Android设备的屏幕尺寸很多,为了让我们开发的程序能够美观地显示在不同分辨率、不同尺寸、不同像素密度的设备上,我们在开发过程中需要进行屏幕适配。当然,我们不可能适配全部的屏幕尺寸和分辨率,我们只需要保证我们的程序在主流的屏幕尺寸和分辨率中运行就可以了。

学习屏幕适配之前,我们需要了解一些重要的概念。

2、重要概念

屏幕尺寸

屏幕尺寸是指屏幕对角线的长度,单位是英寸,1英寸=2.54厘米

屏幕分辨率

屏幕分辨率是指屏幕横向和纵向上的像素点数,单位是px,1px=1像素,一般格式是纵向X横向,例如1920X1080

屏幕像素密度

屏幕像素密度是指每英寸上的像素点数,单位是dpi,即“dot per inch”的缩写,像素密度和屏幕尺寸和屏幕分辨率有关。计算公式是:

dip、dp、dpi、sp、px
  • dip:Density Independent Pixels(密度无关像素)的缩写。以160dpi为基准,1dp=1px

  • dp:与dip相同

  • dpi:屏幕像素密度的单位,“dot per inch”的缩写

  • sp:Scale-Independent Pixels的缩写,可以根据文字大小首选项自动进行缩放。Google推荐我们使用12sp以上的大小,通常可以使用12sp,14sp,18sp,22sp,最好不要使用奇数和小数。

  • px:像素,物理上的绝对单位

mdpi、hdpi、xdpi、xxdpi、xxxdpi

mdpi、hdpi、xdpi、xxdpi、xxxdpi的划分我们来看一张表:

在Google官方开发文档中,说明了 mdpi:hdpi:xhdpi:xxhdpi:xxxhdpi=2:3:4:6:8 的尺寸比例进行缩放。例如,一个图标的大小为48×48dp,表示在mdpi上,实际大小为48×48px,在hdpi像素密度上,实际尺寸为mdpi上的1.5倍,即72×72px,以此类推。

3、通过支持各种屏幕尺寸解决

1、使用wrap_content、math_parent、weight

  • wrap_content:根据控件的内容设置控件的尺寸

  • math_parent:根据父控件的尺寸大小设置控件的尺寸

  • weight:权重,在线性布局中可以使用weight属性设置控件所占的比例,计算公式是:所占宽度=原来宽度+剩余空间所占百分比的宽度

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

在实际开发中,我们简单一点的布局使用LinearLayout布局,复杂一点可以使用RelativeLayout,相对布局可以在各种尺寸的屏幕上保持控件之间的相对位置,还会使用这两种布局的嵌套。

3、使用限定符

可以使用尺寸限定符、最小宽度限定符,使用布局别名和使用屏幕方向限定符等。

4、使用.9patch图片

.9.png图片是Android系统下特有的,这个可以保持图片在拉伸之后还能保持一定的效果,比如,图片的重要像素不会被拉伸,使内容区域不受到拉伸影响等。使用.9.png,必须要创建.9.png图片,AndroidSDK给我们提供了工具中就包含了.9.png图片的创建和修改工具,当然也可以直接在Android studio中使用。

通过支持各种屏幕密度解决

把任何设备的手机宽度像素均分为320份,高度像素均分为480份,使用我们写好的程序自动生成资源values-×文件夹,里面包含lay_x.xml和lay_y.xml,分别对应宽度和高度的像素。

程序代码如下:

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;
}

}

运行上面的代码会生成:

在480×320的设备上,x2就代表2.0px,y2就代表3.0px。

在800×480的设备上,x2就代表3.0px,y2就代表3.33px。依次类推。

使用:

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

效果如下:

这样也可以实现屏幕适配。

通过设定百分比解决

  在Web页面设计中,从来没有听说过需要适配的,这是为什么呢?因为浏览器支持百分比设计,这样就可以适配不同的分辨率和尺寸,那么我们Android开发也是不是可以支持百分比设计,那么这样,我们的屏幕适配就没有那么头疼了。以Web页面的设计引出一种适配方案,通过百分比控制控件的大小,达到适配的目的。

  在这里推荐使用Google推出的一个支持百分比设计的库android-percent-support,但是这个库只有两种布局供我们使用,分别是PercentRelativeLayout、PercentFrameLayout,通过名字就可以看出,这是继承自FrameLayout和RelativeLayout两个容器类。

这两个布局支持的属性有:

  • layout_widthPercent

  • layout_heightPercent

  • layout_marginPercent

  • layout_marginLeftPercent

  • layout_marginTopPercent

  • layout_marginRightPercent

  • layout_marginBottomPercent

  • layout_marginStartPercent

  • layout_marginEndPercent

可以看到,支持的有宽高和margin,使用的时候直接用PercentRelativeLayout、PercentFrameLayout替换FrameLayout、RelativeLayout即可。

But没有LinearLayout的扩展,这是非常不好的,因为LinearLayout也是我们常用的布局之一啊,虽然LinearLayout有weight属性,但是weight只支持一个方向的。不用急,鸿洋大神早就已经给我们提供了自定义的一个PercentLinearLayout,具体请猛戳这里:Android 百分比布局库(percent-support-lib) 解析与扩展,里面做了使用的介绍和详细分析了源码,就不在做很多的介绍了。

下面是鸿洋大神提供的android-percent-support扩展,猛戳进入:android-percent-support-extend

Android屏幕适配就简单介绍到这里了,推荐几篇大神的文章:

鸿洋大神的:Android 屏幕适配方案

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. Android 的基本概念 Android 是一个开源的操作系统,主要用于移动设备,如智能手机、平板电脑等。它基于 Linux 内核,提供了丰富的应用程序框架和 API,支持多种开发语言,如 Java、C/C++、Kotlin 等。 Android 应用程序由多个组件组成,包括活动(Activity)、服务(Service)、广播接收器(Broadcast Receiver)和内容提供器(Content Provider)等。这些组件可以组合在一起,形成复杂的应用程序。 2. Android 应用程序开发 Android 应用程序开发主要使用 Java 编程语言和 Android SDK。开发工具包括 Android Studio、Eclipse 等。 Android 应用程序的结构包括布局文件、资源文件、Java 代码和清单文件等。布局文件用于定义应用程序的用户界面,资源文件包括图像、声音、样式、主题等,Java 代码实现应用程序的逻辑,清单文件描述应用程序的组件和权限等信息。 3. Android 应用程序的调试和测试 Android 应用程序的调试和测试可以使用 Android Studio 提供的调试工具,包括断点调试、日志记录等。还可以使用模拟器或真实设备进行测试。 4. Android 应用程序的发布 发布 Android 应用程序需要进行签名和打包操作,签名用于验证应用程序的身和完整性,打包将应用程序打包成 APK 文件,可以上传到应用商店进行发布。 5. Android 应用程序的优 Android 应用程序的优包括优布局、资源、代码和网络等方面,以提高应用程序的性能和用户体验。其中,布局优包括使用布局最优算法、使用自定义视图等;资源优包括压缩资源、使用向量图形等;代码优包括使用异步任务、使用缓存等;网络优包括使用数据压缩、使用本地存储等。 6. Android 开发的挑战 Android 开发面临的挑战包括设备碎片、安全问题、性能问题等。设备碎片指的是不同设备屏幕尺寸、分辨率、操作系统版本等不同,需要对应用程序进行适配;安全问题指的是应用程序需要保证用户数据的安全和隐私;性能问题指的是应用程序需要保证快速响应和流畅运行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值