[31→100]Android界面开发精要1:尺寸

界面依附于具体的运行设备,更准确说是一块有一块的屏幕,所以我们首先要弄清屏幕有哪些特性。


Android设备通用型号一栏表

这里面有2个核心概念:

  1. 屏幕的物理尺寸,也即是通常说的屏幕大小(Screen Size),用屏幕对角线长度来表示,单位是英寸("),比如图中3.7"、4.0"、3.2"等

  2. 屏幕分辨率(Resolution),表示屏幕有多精细,单位是像素(px),比如图中480*800、1280*720等。

  3. 这两个值相除,产生了一个新的概念屏幕密度(Screen Density),即单位长度像素点数,单位是 像素/英寸(dpi)。

以小米4为例,屏幕size = 4.6英寸(2.25英寸*4英寸),1080*1920像素。
所以,屏幕密度为 480 = 1080/2.25 = 1920/4。

由于Android的开放性,运行它的设备大小和分辨率并不一样,如果采用px作为基础的计算单位,在不同设备上的视觉效果是不一致的。比如,同样一个300px*100px的矩形,在480*800的手机上很显眼,而在1920*1080上可能就只是一点点了。所以我们面临了界面开发的经典问题——适配

怎么适配——使用DP

为了方便开发人员适配,Android提出了一个新的概念独立像素单位dp(Density-independent pixel),代替原来的像素单位px。dp与屏幕密度挂钩。Android规定:

在一个屏幕密度为160的设备上,1dp=1px。

此后,随着屏幕密度的变化,dp保持等比缩放。即

1dp = (当前设备的屏幕密度/160) px
1px = (160/当前设备的屏幕密度)dp

由dp这个概念,Android规定了一系列的标准屏幕尺寸:

  • ldpi:屏幕密度为120。
  • mdpi:屏幕密度为160。
  • hdpi:屏幕密度为240。
  • xhdpi:屏幕密度为320。
  • xxhdpi:屏幕密度为480。
  • xxxhdpi:屏幕密度为640。
  • tvdpi:屏幕密度为213。

除了这些标准尺寸外,也可自定义其它屏幕密度,包括Google Nexus系列都采用了一些非标准尺寸,比如420dpi、560dpi。


Android常用设备dpi列表

在Android代码DisplayMetrics类中,也为这些常用dpi做了定义:

public static final int DENSITY_280 = 280;
public static final int DENSITY_360 = 360;
public static final int DENSITY_400 = 400;
public static final int DENSITY_420 = 420;
public static final int DENSITY_560 = 560;
public static final int DENSITY_DEFAULT = 160;
public static final int DENSITY_HIGH = 240;
public static final int DENSITY_LOW = 120;
public static final int DENSITY_MEDIUM = 160;
public static final int DENSITY_TV = 213;
public static final int DENSITY_XHIGH = 320;
public static final int DENSITY_XXHIGH = 480;
public static final int DENSITY_XXXHIGH = 640;

DP是一个好的解决方案吗?

在实际开发,设计人员提供的视觉设计图,视觉工具从图上直接取到的像素px,直接采用dp机制,意味着开发人员需要不断地将px转成dp,这工作量大、繁琐、重复。所以对于开发人员而言,更好的机制是利用dimension机制,将dp映射为设计图的px值。如下:

    <!-- 宽度 -->
    <dimen name="width_720_1280_1">0.50dp</dimen>
    <dimen name="width_720_1280_2">1.00dp</dimen>
    <dimen name="width_720_1280_3">1.50dp</dimen>
    <dimen name="width_720_1280_4">2.00dp</dimen>
    ……
    <dimen name="width_720_1280_716">358.00dp</dimen>
    <dimen name="width_720_1280_717">358.50dp</dimen>
    <dimen name="width_720_1280_718">359.00dp</dimen>
    <dimen name="width_720_1280_719">359.50dp</dimen>
    <dimen name="width_720_1280_720">360.00dp</dimen>
    <!-- 高度 -->
    <dimen name="height_720_1280_1">0.50dp</dimen>
    <dimen name="height_720_1280_2">1.00dp</dimen>
    <dimen name="height_720_1280_3">1.50dp</dimen>
    <dimen name="height_720_1280_4">2.00dp</dimen>
    ……
    <dimen name="height_720_1280_1277">638.50dp</dimen>
    <dimen name="height_720_1280_1278">639.00dp</dimen>
    <dimen name="height_720_1280_1279">639.50dp</dimen>
    <dimen name="height_720_1280_1280">640.00dp</dimen>
    <!-- 文字 -->
    <dimen name="text_size_720_1280_1">0.50sp</dimen>
    <dimen name="text_size_720_1280_2">1.00sp</dimen>
    <dimen name="text_size_720_1280_3">1.50sp</dimen>
    <dimen name="text_size_720_1280_4">2.00sp</dimen>
    ……
    <dimen name="text_size_720_1280_87">43.50sp</dimen>
    <dimen name="text_size_720_1280_88">44.00sp</dimen>
    <dimen name="text_size_720_1280_89">44.50sp</dimen>
    <dimen name="text_size_720_1280_90">45.00sp</dimen>

这样,对界面绘制人员而言,只需要将图片上的px直接写在就可以了,节省了很多重复计算的时间。

怎么制作这样px映射表呢?

  1. 确定UI设计基于什么样的分辨率?比如640*1136(这是iPhone5的分辨率);
  2. 确定目标适配的Android尺寸?比如720*1289;
  3. 确定dimens的dpi,常用dpi如下:

ldpi:屏幕密度为120。
mdpi:屏幕密度为160。
hdpi:屏幕密度为240。
xhdpi:屏幕密度为320。
xxhdpi:屏幕密度为480。
xxxhdpi:屏幕密度为640。
tvdpi:屏幕密度为213。

  1. 执行Python代码:
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import csv
import os
import re
import sys
import zipfile
import xml.etree.ElementTree as ElementTree

'''自动生成相应的dimens.xml文件'''
if __name__ == '__main__':
    # print "srcipt:", sys.argv[0]
    # for i in range(1, len(sys.argv)):
    #     print "argv[", i , "] = ", sys.argv[i]

    # 原型界面提供的尺寸
    uiWidth = 640;
    uiHeight = 1136;

    # 目标设备尺寸,即目标机型界面
    desWidth = 720
    desHeight = 1280

    # 目标屏幕密度
        # ldpi:屏幕密度为120。
        # mdpi:屏幕密度为160。
        # hdpi:屏幕密度为240。
        # xhdpi:屏幕密度为320。
        # xxhdpi:屏幕密度为480。
        # xxxhdpi:屏幕密度为640。
        # tvdpi:屏幕密度为213。
    density = 320

    print "<!-- "
    print "\t\tUI提供宽高: %d*%d" % (uiWidth, uiHeight)
    print "\t\t适配屏幕宽高: %d*%d" % (desWidth, desHeight)
    print "\t\t适配屏幕密度: %ddpi" % (density)
    print "--> "

    ratio = 1.0*desWidth/uiWidth
    # 输出合理的dimens.xml文件
    for i in range(uiWidth):
        j = i + 1
        # print "<dimen name=\"ws_%d_%d_%s\">%.2fdp</dimen>" % (desWidth, desHeight, j, 1.0 * j * density)
        print "<dimen name=\"ws%s\">%.2fdp</dimen>" % (j, 1.0 * j * ratio * 160/density)

    for i in range(uiHeight):
        j = i + 1
        # print "<dimen name=\"hs_%d_%d_%s\">%.2fdp</dimen>" % (desWidth, desHeight, j, 1.0 * j * density)
        print "<dimen name=\"hs%s\">%.2fdp</dimen>" % (j, 1.0 * j * ratio * 160/density)

    for i in range(90):
        j = i + 1
        # print "<dimen name=\"ts_%d_%d_%s\">%.2fsp</dimen>" % (desWidth, desHeight, j, 1.0 * j * density)
        print "<dimen name=\"ts%s\">%.2fsp</dimen>" % (j, 1.0 * j * ratio * 160/density)

Panda
2016-05-26

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,423评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,147评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,019评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,443评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,535评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,798评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,941评论 3 407
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,704评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,152评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,494评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,629评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,295评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,901评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,742评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,978评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,333评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,499评论 2 348

推荐阅读更多精彩内容