When your application is running on a television set, you should assume that the user is sitting about ten feet away from the screen. This user environment is referred to as the 10-foot UI. To provide your users with a usable and enjoyable experience, you should style and lay out your UI accordingly..
This lesson shows you how to optimize layouts for TV by:
TV screens are always in landscape orientation. Follow these tips to build landscape layouts optimized for TV screens:
TV屏幕一般都是横向的,根据这些提示,我们为我们的TV创建横向的布局;
GridView
instead ofListView
to make better use of the horizontal screen space.RelativeLayout
or LinearLayout
to arrange views. This allows the Android system to adjust the position of the views to the size, alignment, aspect ratio, and pixel density of the TV screen.For example, the following layout is optimized for TV: 示例:
In this layout, the controls are on the lefthand side. The UI is displayed within a GridView
, which is well-suited to landscape orientation. In this layout both GridView and Fragment have the width and height set dynamically, so they can adjust to the screen resolution. Controls are added to the left side Fragment programatically at runtime. The layout file for this UI is res/layout-land-large/photogrid_tv.xml
. (This layout file is placed inlayout-land-large
because TVs have large screens with landscape orientation. For details refer to Supporting Multiple Screens.)
在这个布局中,控制栏在左侧,这个界面的显示是一个GridView,这是很适合横向布局的, 在这个布局中 GridView and Fragment 可以动态的调整宽度和高度, 所以这样可以根据屏幕的分辨率进行调整. 在运行的时候把控制栏添加到相应的Fragment 中. 布局文件是 res/layout-land-large/photogrid_tv.xml
.(这个布局文件方在 layout-land-large文件夹中, 因为TV的屏幕分辨率是横向的, 具体细节请查看Supporting Multiple Screens)
<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>
To set up action bar items on the left side of the screen, you can also include the Left navigation bar library in your application to set up action items on the left side of the screen, instead of creating a custom Fragment to add controls:
添加一个action bar的条目 在屏幕的左侧, 你也可以包含一个Left navigation bar library, 在你的应用程序中 去设置 action bar在屏幕的左侧,而不是去自定义一个Fragment 来添加控件.
LeftNavBar bar = (LeftNavBarService.instance()).getLeftNavBar(this);
When you have an activity in which the content scrolls vertically, always use a left navigation bar; otherwise, your users have to scroll to the top of the content to switch between the content view and the ActionBar. Look at the Left navigation bar sample app to see how to simple it is to include the left navigation bar in your app.
当你有一个activity 的垂直滚动, 总得要使用左侧的导航栏.要不然,你的用户一定要拖动到内容的顶部 才能对导航栏进行操作.参照Left navigation bar sample app 看看如何简单的添加一个左侧导航栏到你的应用中.
The text and controls in a TV application's UI should be easily visible and navigable from a distance. Follow these tips to make them easier to see from a distance :
在一个TV应用的UI里面, 文字和控件是很容易显示和控制 在一定的距离里面.根据这些观点,在一定的空间内,让他们更加容易被发现
<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"/>
The common HDTV display resolutions are 720p, 1080i, and 1080p. Design your UI for 1080p, and then allow the Android system to downscale your UI to 720p if necessary. In general, downscaling (removing pixels) does not degrade the UI (Notice that the converse is not true; you should avoid upscaling because it degrades UI quality).
常见的高清晰度电视显示分辨率为720p,1080i和1080p,把你的UI设置为1080p,并且允许系统在必要的时候将你的UI分辨率下调到720p.通常下调并不意味着是缩小你的UI界面(注意反之则不然,你应该避免倍增,因为它会降低UI质量).
To get the best scaling results for images, provide them as 9-patch image elements if possible. If you provide low quality or small images in your layouts, they will appear pixelated, fuzzy, or grainy. This is not a good experience for the user. Instead, use high-quality images.
得到图像的最佳的缩放效果,提供他们提供他们9-patch image图像元素,如果可能的话图像元素,如果可能的话.如果提供低质量或者小图片的话,它们将会出现像素化,模糊,或呈颗粒状. 这样用户体验很不好, 反之,应该用高质量图片替代.
For more information on optimizing apps for large screens see Designing for multiple screens.
在大屏幕上针对优化应用的更多信息请参考Designing for multiple screens.
The Android system has a limited amount of memory, so downloading and storing high-resolution images can often cause out-of-memory errors in your app. To avoid this, follow these tips:
android系统对内存有一定的限制, 所以在下载或者保存 高像素图片的时候经常会出现 OOM 内存泄露问题, 根据这些问题,去避免出现类似问题:
GridView
or Gallery
, only load an image when getView()
is called on the View's Adapter
.recycle()
on Bitmap
views that are no longer needed.WeakReference
for storing references to Bitmap
objects in an in-memory Collection
.AsyncTask
to fetch them and store them on the SD card for faster access. Never do network transactions on the application's UI thread.// 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;