原文链接:http://android.eoe.cn/topic/ui
当你应用程序运行在电视机时,你应当考虑用户是坐在距离电视屏幕10英尺的地方.当然用户环境被称为10-foot UI.为了给你的用户提供一个可用和愉快的体验,你相应地应该奠定你自己的UI风格...
这个要点向你展示如何针对TV来优化你自己的布局,通过:
- * 为景观模式提供适当的布局源文件.
- * 确保文本和相应的控制在一定距离上是足够大以便看见的.
- * 为高清电视提供高分辨率的位图和图标.
设计景观布局
电视屏幕通常都是取决于景观.针对电视屏幕按照这些技巧来优化你的景观布局:
- * 把屏幕上的导航控制菜单放在屏幕的左边或者右边,并且将菜单内容以垂直的方式显示.
- * 创建那些分段的UI时,通过使用Fragments和使用像用GridView来替代ListView更能充分使用水平空间的视图组控件.
- * 使用视图组例如RelativeLayout和LinearLayout来排版视图.以上这些允许android系统能够针对大小,对齐,纵横比,以及屏幕的像素密度来匹配视图的位置
- * 在视图控制之间提供足够的余地来避免一个杂乱的用户界面.
例如接下来的布局就是针对TV优化的:
在这个布局中,控制是位于左边界.这个UI界面里面显示了一个GridView控件,这个GridView是非常适合景观方向的UI.在这个布局中GridView和Fragment
都是动态设置宽和高,以便能自适应屏幕的分辨率.在运行时控制视图被添加到了左边片段编程.这UI布局文件位res/layoutlandlarge/photogrid_tv.xml下.(这个布局文件放置在layout-land-large,因为电视在景观方向上有大的屏幕.详细请参考Supporting Multiple Screens.)
例如如下一个res/layout-land-large/photogrid_tv.xml:
1 2 3 4 5 6 7 8 9 10 11 12 |
<RelativeLayout android:layout_width="fill_parent"
android:layout_height="fill_parent">
<fragment
android:id="@+id/leftsidecontrols"
android:layout_width="0dip"
android:layout_marginLeft="5dip"
android:layout_height="match_parent" />
<GridView
android:id="@+id/gridview"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
|
为了在屏幕的左边设立操作条选项,你可以在你的应用程序中通过导入Left navigation bar library来实现它,以替代创建一个定制的片段来添加控制视图:
1 |
LeftNavBar bar = (LeftNavBarService.instance()).getLeftNavBar(this);
|
当你有一个内容垂直滚动的活动时,总是使用一个左边导航条;反之,你的用户不得不拖动到内容的顶部来在内容视图和操作条之间进行切换.参考Left navigation bar sample app来看看它是如何简单的在你的应用程序中导入左边导航条的.
使文字和控制容易看到
在一个电视的应用程序的UI里,文字和控制应当是容易看见并且在一定距离内可以导航的.例如这些技巧能让它们在一定距离内更加容易看见:
- * 把文本插入用户能够快速地扫描到的小块中.
- * 在一个黑暗的背景中使用明亮的文本.这个风格在一台电视中更方便读.
- * 避免轻量级的字体以及那些要么非常窄要么非常宽的笔画字体.使用简单的无衬线字体和使用抗混叠来提高可读性.
- * 使用系统的标准的字体大小:
1 2 3 4 5 6 7 |
<TextView
android:id="@+id/atext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceMedium"/>
|
- * 确保那时你的所有视图小工具足够的大以便距离屏幕10英尺的人能清晰可见.要实现它的最好方式是采用相对布局大小而不是绝对布局大小,并且采用密度无关的像素单元而不是绝对的像素单元.例如,设置容器的宽,使用实际的大小来替代像素尺寸,并且设置与父组件的距离,使用dip像素单元替代px像素单元.
针对高分辨率大屏幕设计
普遍的高清电视显示分辨率是720p,1080i,和1080p.把你的UI设置为1080p,并且允许系统在必要的时候将你的UI分辨率下调到720p.通常下调并不意味着是缩小你的UI界面(注意反之则不然,你应该避免倍增,因为它会降低UI质量).
为了获得最佳的图片显示,如果可能的话以9-patch image元素来展示.在你的布局中如果提供低质量或者小图片的话,它们将会出现像素化,模糊,或呈颗粒状.对用户来说这不是一个好的用户体验.取而代之的是采用高质量的图片.
在大屏幕上针对优化应用的更多信息请参考Designing for multiple screens.
设计处理大的位图
android系统有一个内存限制量,所以在你的应用程序中下载和保存一个高分辨率的图片经常会导致内存溢出的错误.为了避免这些,使用如下这些技巧:
- * 仅当它们被显示在屏幕上的时候进行加载.例如,当在GridView和Gallery中显示多组图片时,当在视图的Adapter中调用android.view.View, android.view.ViewGroup) getView()方法时加载图片.
- * 在不在需要的bitmap视图中调用recycle())方法.
- * 在内存回收器重采用WeakReference来存储涉及到的位图对象.
- * 如果你从网络下载图片,使用AsyncTask来下载它们并且将它们保存在sdcard方便快速访问.在应用程序的UI线程中永远也不要处理网络交互.
- * 当你下载它们时按比例缩小原来大的图片到一个更适合它的大小;否则下载图片本身可能会导致内存溢出异常.这里有一个在执行下载的时候按比例缩小图片的范例代码:
范例代码:
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 |
// Get the source image's dimensions
BitmapFactory.Options options = new BitmapFactory.Options();
// This does not download the actual image, just downloads headers.
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(IMAGE_FILE_URL, options);
// The actual width of the image.
int srcWidth = options.outWidth;
// The actual height of the image.
int srcHeight = options.outHeight;
// Only scale if the source is bigger than the width of the destination view.
if(desiredWidth > srcWidth)
desiredWidth = srcWidth;
// Calculate the correct inSampleSize/scale value. This helps reduce memory use. It should be a power of 2.
int inSampleSize = 1;
while(srcWidth / 2 > desiredWidth){
srcWidth /= 2;
srcHeight /= 2;
inSampleSize * = 2;
}
float desiredScale = (float) desiredWidth / srcWidth;
// Decode with inSampleSize
options.inJustDecodeBounds = false;
options.inDither = false;
options.inSampleSize = inSampleSize;
options.inScaled = false;
// Ensures the image stays as a 32-bit ARGB_8888 image.
// This preserves image quality.
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap sampledSrcBitmap = BitmapFactory.decodeFile(IMAGE_FILE_URL, options);
// Resize
Matrix matrix = new Matrix();
matrix.postScale(desiredScale, desiredScale);
Bitmap scaledBitmap = Bitmap.createBitmap(sampledSrcBitmap, 0, 0,
sampledSrcBitmap.getWidth(), sampledSrcBitmap.getHeight(), matrix, true);
sampledSrcBitmap = null;
// Save
FileOutputStream out = new FileOutputStream(LOCAL_PATH_TO_STORE_IMAGE);
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
scaledBitmap = null;
|