参考:
http://developer.android.com/guide/practices/screens_support.html
px/dp = dpi/160
res/drawable-ldpi 大约120dpi。(注意 大约很重要~。~)
res/drawable-mdpi 大约160dpi。
res/drawable-tvdpi API Level 13引入,大约213dpi。 为电视设备的APP准备。
res/drawable-hdpi 大约240dpi。
res/drawable-xhdpi 大约320dpi。
res/drawable-nodpi 无视dpi。
创建可扩展的布局
避免定义绝对的布局元素。
当定义UI元素的时候,比如Button和TextView,避免使用精确的大小。代替之的是使用wrap_content,match_parent。
1
2
3
4
5
6
|
<
Button
android:id=”@+id/button”
android:layout_width=”match_parent”
android:layout_height=”wrap_content”
android:text=”@string/buttonText”
/>
|
Android 4.0(API 14)引入Grid Layout,一个高灵活度的布局方式,减少内嵌和简化合适和动态的布局。
为了为不同的尺寸(注意这里讨论的是尺寸,不是什么dpi)提供合适的布局,你应该考虑创建多布局定义。
比如3inch 的QVGA和高分辨率 10.1inch的平板,一个适合横屏的布局,不一定适合竖屏。
安卓设备类别很模糊,通常设计要基于可用的空间大小,而不是设备类型。
使用long和notlong修饰符,对应着正常大小的设备和宽屏设备。
port和land修饰符来区分是否是横竖屏模式。
res/layout-long-land/ // Layouts for long screens in landscape mode.
res/layout-notlong-port/ // Layouts for not-long screens in portrait mode.
除了前面2种,android 3.2(API 13)给出了另外几个修饰符,基于当前屏幕的宽/高,或者最小的屏幕宽(宽高较小值):
res/layout-w600dp
res/layout-h720dp
res/layout-sw320dp
在早些版本的如何做呢?
答:
res/layout-small
res/layout-normal
res/layout-large
res/layout-xlarge
这是相对于normal HVGA (HVGA(320x480) 3.2inch 180dpi mdpi)智能手机。small小于HVGA,large大于HVGA,xlarge更大于HVGA(比如平板)。
创建一个res/values/layout.xml文件,使用别名去选择单面板布局。
1
2
3
4
|
<?
xml
version=”1.0” encoding=”utf-8”?>
<
resources
>
<
item
name=”main” type=”layout”>@layout/main_singlepanel</
item
>
</
resources
>
|
为每个应该使用多面板布局的,创建一致的values文件夹:
res/values-large-land
res/values-xlarge
然后,创建并增加一个新的layout.xml资源
1
2
3
4
|
<?
xml
version=”1.0” encoding=”utf-8”?>
<
resources
>
<
item
name=”main” type=”layout”>@layout/main_multipanel</
item
>
</
resources
>
|
在代码中,简单的引用R.layout.main所指向的资源,让系统自己决定选哪个。
某些APP你可能无法做到你的UI适应于所有屏幕尺寸的设备,你可以使用support-screens mainfest的元素,来指定什么样的屏幕是你能接受的。
1
2
3
4
|
<
supports-screens
android:smallScreens=”false”
android:normalScreens=”true”
android:largeScreens=”true”
android:xlargeScreens=”true”/>
|
Android 3.2(API 13)引入 requiresSmallestWidthDp,compatibleWidthLimitDp,largestWidthLimitDp属性:
1
2
3
|
<
supports-screens
android:requiresSmallestWidthDp=”480”
android:compatibleWidthLimitDp=”600”
android:largestWidthLimitDp=”720”/>
|
Android包含了一些简单的Drawable资源类型,可以用XML定义。 其中有:ColorDrawable、ShapeDrawable和GradientDrawable类,这些资源存储在res/drawable文件夹中。
上面提到过,使用dpi分隔符运行时可以做到平稳的适配。 但是呢,像矢量图这种图形它自身可以随意缩放而不失真。但是,GradientDrawable位图是例外,需要用像素定义它的渐变半径。
在res/drawable中:
1.Corlor Drawable
1
2
3
|
<
color
xmlns:android=”http://schemas.android.com/apk/res/android”
android:color=”#FF0000”
/>
|
2.Shape Drawable(对属性若有疑问,自己测试)
这种资源可以定义简单的原始形状图形。shape的属性有:
1.line 水平线,它的宽和风格由stroke来描述。
2.oval 简单的椭圆图形
3.rectangle 简单的矩形。也支持corners子节点属性,使用radius属性去创建一个有圆弧角的矩形。
4.ring 支持innerRadius和thickness属性,分别表示ring形状的内角半斤比率和厚度比率,作为其宽的一部分。(比如1/4的内部半径,可以用值:4)。
5.stroke 这个属性用来指定图形的轮廓的宽和颜色。
6.padding 一会看例子
7.solid 可以用来指定背景色,color属性可用。
下面这个例子:圆角,10dp的轮廓宽,10dp的padding(绿色那部分):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<?
xml
version=”1.0” encoding=”utf-8”?>
<
shape
xmlns:android=”http://schemas.android.com/apk/res/android”
android:shape=”rectangle”>
<
solid
android:color=”#f0600000”/>
<
stroke
android:width=”10dp”
android:color=”#00FF00”/>
<
corners
android:radius=”15dp” />
<
padding
android:left=”10dp”
android:top=”10dp”
android:right=”10dp”
android:bottom=”10dp”
/>
</
shape
>
|
接着我们介绍GradientDrawable类以及如何为Shape Drawable图形去指定填充的样子。
Gradient Drawable能让你设计复杂的渐变填充。每个渐变定义了一个平缓的过渡在2-3种颜色,分别在线性、放射状、或者扫描模式。
每个Gradient Drawable使用gradient标签定义,作为Shape Drawable定义的子节点(就像之前讨论的那些)。
每个Gradient Drawable至少需要startColor和endColor属性和可选择的middleColor。
还有type属性,你可以定义以下几个:
1.linear 默认的渐变类型,画一个直接的颜色渐变,从startColor到endColor,以一个角度(angle属性 可填写0-180)呈现。
2.radial 画一个圆形的渐变,从startColor到endColor,从外边界到中心渐变。这个需要一个gradientRadius属性去指定渐变转化的半径(px)。还有2个可选参数,centerX和centerY属性去设置渐变的中心点。因为渐变半径是以像素PX来定义的,所以它不能动态适应不同dpi的设备。
3.sweep 扫描状的渐变,从startColor到endColor,环绕着外边界,典型的ring(耳环样子)。
下面例子,代表着res/drawable中的3个文件,一个以线性变化的矩形,一个放射状的椭圆,一个扫描状的ring:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
<!-- Rectangle with linear gradient -->
<?
xml
version=”1.0” encoding=”utf-8”?>
<
shape
xmlns:android=”http://schemas.android.com/apk/res/android”
android:shape=”rectangle”
android:useLevel=”false”>
<
gradient
android:startColor=”#ffffff”
android:endColor=”#ffffff”
android:centerColor=”#000000”
android:useLevel=”false”
android:type=”linear”
android:angle=”45”
/>
</
shape
>
<!-- Oval with radial gradient -->
<?
xml
version=”1.0” encoding=”utf-8”?>
<
shape
xmlns:android=”http://schemas.android.com/apk/res/android”
android:shape=”oval”
android:useLevel=”false”>
<
gradient
android:type=”radial”
android:startColor=”#ffffff”
android:endColor=”#ffffff”
android:centerColor=”#000000”
android:useLevel=”false”
android:gradientRadius=”300”
/>
</
shape
>
<!-- Ring with sweep gradient -->
<?
xml
version=”1.0” encoding=”utf-8”?>
<
shape
xmlns:android=”http://schemas.android.com/apk/res/android”
android:shape=”ring”
android:useLevel=”false”
android:innerRadiusRatio=”3”
android:thicknessRatio=”8”>
<
gradient
android:startColor=”#ffffff”
android:endColor=”#ffffff”
android:centerColor=”#000000”
android:useLevel=”false”
android:type=”sweep”
/>
</
shape
>
|
可变化的Drawables
ScaleDrawable scaleHeight,scaleWidth表示缩放的百分比,scaleGravity设置锚点。
1
2
3
4
5
6
7
8
|
<?
xml
version=”1.0” encoding=”utf-8”?>
<
scale
xmlns:android=”http://schemas.android.com/apk/res/android”
android:drawable=”@drawable/icon”
android:scaleHeight=”100%”
android:scaleWidth=”100%”
android:scaleGravity=”center_vertical|center_horizontal”
/>
|
RotateDrawable 下面这个意思就是,从0度到90的旋转,中心点分别是X,Y上的50%。
1
2
3
4
5
6
7
8
|
<?
xml
version=”1.0” encoding=”utf-8”?>
<
rotate
xmlns:android=”http://schemas.android.com/apk/res/android”
android:drawable=”@drawable/icon”
android:fromDegrees=”0”
android:toDegrees=”90”
android:pivotX=”50%”
android:pivotY=”50%”
/>
|
运行时如何运用缩放和旋转呢?
答:使用setImageLevel方法在View对象,变换图片在0-10,000之间,对应着0-100%,默认是0.
1
2
3
4
5
6
7
8
9
10
|
ImageView rotatingImage
= (ImageView)findViewById(R.id.RotatingImageView);
ImageView scalingImage
= (ImageView)findViewById(R.id.ScalingImageView);
// Rotate the image 50% of the way to its final orientation.
rotatingImage.setImageLevel(
5000
);
// Scale the image to 50% of its final size.
scalingImage.setImageLevel(
5000
);
|
Layer Drawables(不介绍了)
1
2
3
4
5
6
7
|
<?
xml
version=”1.0” encoding=”utf-8”?>
<
layer-list
xmlns:android=”http://schemas.android.com/apk/res/android”>
<
item
android:drawable=”@drawable/bottomimage”/>
<
item
android:drawable=”@drawable/image2”/>
<
item
android:drawable=”@drawable/image3”/>
<
item
android:drawable=”@drawable/topimage”/>
</
layer-list
>
|
最上面的条目放在最底层。
State List Drawables(不介绍了)
1
2
3
4
5
6
7
8
9
|
<
selector
xmlns:android=”http://schemas.android.com/apk/res/android”>
<
item
android:state_pressed=”true”
android:drawable=”@drawable/widget_bg_pressed”/>
<
item
android:state_focused=”true”
android:drawable=”@drawable/widget_bg_selected”/>
<
item
android:state_window_focused=”false”
android:drawable=”@drawable/widget_bg_normal”/>
<
item
android:drawable=”@drawable/widget_bg_normal”/>
</
selector
>
|
android:state_pressed—是否被按下
android:state_focused— 是否获得焦点
android:state_hovered— API 11引入,判断鼠标是不是盘旋在视图上。
android:state_selected— 是否被选中。
android:state_checkable— 是否可被选中。
android:state_checked— 是否被选中。
android:state_enabled— 是否可用
android:state_activated— 是否在激活状态。
android:state_window_focused— 父窗口是否获得焦点。
使用Level List Drawable你可以创建一个Drawable资源数组,为每层设定一个整形的索引值。使用level-list节点去创建一个新的Level List Drawable,使用item子节点去定义每层,附上android: drawable/android:maxLevel属性。
1
2
3
4
5
6
7
8
9
|
<
level-list
xmlns:android=”http://schemas.android.com/apk/res/android”>
<
item
android:maxLevel=”0” android:drawable=”@drawable/earthquake_0”/>
<
item
android:maxLevel=”1” android:drawable=”@drawable/earthquake_1”/>
<
item
android:maxLevel=”2” android:drawable=”@drawable/earthquake_2”/>
<
item
android:maxLevel=”4” android:drawable=”@drawable/earthquake_4”/>
<
item
android:maxLevel=”6” android:drawable=”@drawable/earthquake_6”/>
<
item
android:maxLevel=”8” android:drawable=”@drawable/earthquake_8”/>
<
item
android:maxLevel=”10” android:drawable=”@drawable/earthquake_10”/>
</
level-list
>
|
1
|
imageView.setImageLevel(
5
);
|
View会显示与指定的索引值一致或者大于这个指定的索引值的一张图片。