参考:
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。
<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文件,使用别名去选择单面板布局。
<?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资源
<?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的元素,来指定什么样的屏幕是你能接受的。
<supports-screens android:smallScreens=”false” android:normalScreens=”true” android:largeScreens=”true” android:xlargeScreens=”true”/>
Android 3.2(API 13)引入 requiresSmallestWidthDp,compatibleWidthLimitDp,largestWidthLimitDp属性:
<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
<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(绿色那部分):
<?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:
<!-- 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设置锚点。
<?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%。
<?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.
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(不介绍了)
<?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(不介绍了)
<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属性。
<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>
imageView.setImageLevel(5);
View会显示与指定的索引值一致或者大于这个指定的索引值的一张图片。