Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 50 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
50
Dung lượng
2,08 MB
Nội dung
Resolution and Density Independence ❘ 117 LISTING 4-23: Level List Drawable resource <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> To select which image to display in code call setImageLevel on the View displaying the Level List Drawable resource, passing in the index of the Drawable you wish to display. imageView.setImageLevel(5); The View will display the image corresponding to the index with an equal or greater value to the one specified. Level List Drawables are particularly useful when creating Widget layouts. NinePatch Drawable NinePatch (or stretchable) images are PNG files that mark the parts of an image that can be stretched. NinePatch images must be properly defined PNG files that end in .9.png . The resource identifier for NinePatches is the file name without the trailing .9.png . A NinePatch is a variation of a PNG image that uses a one-pixel border to define the area of the image that can be stretched if the image is enlarged. To create a NinePatch, draw single-pixel black lines that represent stretchable areas along the left and top borders of your image. The unmarked sections won’t be resized, and the relative size of each of the marked sections will remain the same as the image size changes. NinePatches are a powerful tool for creating images for the backgrounds of Views or Activities that may have a variable size. For example, Android uses NinePatches to create button borders. RESOLUTION AND DENSITY INDEPENDENCE With the first four Android handsets all featuring 3.2’’ HVGA screens, it was easy for developers to become complacent when designing their user interfaces. For almost a year after the release of the first Android handset, there was only one screen size and pixel density to design for. The end of 2009 and start of 2010 heralded an explosion in the number of devices running Android, and with a larger variety of handsets came variation in screen sizes and pixel densities. It’s important to create your UIs knowing that your apps will be running on a broad variety of screen resolutions (including HVGA, QVGA, and two flavors of WVGA — 800x480 and 854x480). Similarly, 118 ❘ CHAPTER 4 CREATING USER INTERFACES the physical screen sizes have begun to vary beyond 3.2 inches to include the 3.7-inch Nexus One and Motorola Droid, and the 4-inch Sony Ericsson Xperia X10. With the floodgates now open, you should expect your applications to be running on an even greater variety of hardware — potentially including tablets, netbooks, and consumer electronics. The following sections will begin by describing the range of screens you need to consider, and how to support them, before summarizing some of the best practices for ensuring your applications are resolution- and density-independent. Finally, you’ll learn how to test your applications against a variety of screen hardware without spending a fortune on phones. The Resource Framework and Resolution Independence The Android framework provides a number of techniques to enable you to optimize your UI for a variety of screen sizes and pixel densities. This section describes the resource directory qualifiers you can use to store alternative assets and layouts for different screen configurations, and the manifest elements you can use to limit the screen sizes your application supports. Resource Qualifiers for Screen Size and Pixel Density In Chapter 3 you were introduced to the Android resource framework. Using this framework you can create a parallel directory structure to store external resources for different host hardware configurations. This section summarizes the folder-name qualifiers you can use to include alternative resources for different screen sizes, pixel densities, and aspect ratios. ➤ Screen size The size of the screen relative to a ‘‘standard’’ smartphone (such as the G1 or Droid). ➤ small A screen smaller than the standard 3.2’’ ➤ medium Typical smartphone screen size ➤ large A screen significantly larger than that of a typical smartphone, such as the screen of a tablet or netbook ➤ Pixel density Refers to the density of pixels on the display. Typically measured in dots per inch (dpi), this is calculated as a function of the physical screen size and resolution. ➤ ldpi Used to store low-density resources for screens with pixel density in the range of 100 to 140dpi ➤ mdpi Used for medium-density screens with 140 to 180dpi ➤ hdpi Used for high-density screens featuring 190 to 250dpi ➤ nodpi Used for resources that must not be scaled regardless of the host screen’s density ➤ Aspect ratio The screen’s aspect ratio is the ratio of its height to its width. Resolution and Density Independence ❘ 119 ➤ long Used for screens that are significantly wider in landscape mode than those of standard smartphones (such as the G1) ➤ notlong Used for screens with a typical smartphone aspect ratio Each of these qualifiers is independent and can be used independently, or in combination with each other, as shown in Listing 4-24. Note that these qualifiers can also be used with the other resource folder qualifiers described in Chapter 3. LISTING 4-24: Sample screen-based resource directory qualifiers res/layout-small-long/ // Layouts for small, long screens. res/layout-large/ // Layouts for large screens. res/drawable-hdpi/ // Drawables for high density screens. Specifying Supported Screen Sizes For some applications it may not be possible to optimize your UI to support all possible screen sizes. You can use the <supports-screens> manifest element to specify which screens your application can be run on, as shown in Listing 4-25. LISTING 4-25: Manifest element supporting normal and large screen sizes <supports-screens android:smallScreens="false" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true" /> In this context a small screen is any display with resolution smaller than HVGA. A large screen is significantly larger than a smartphone (such as a tablet), while normal screens encompass the majority of smartphone handsets. The anyDensity attribute controls how your application will be scaled when displayed on devices of varying pixel density. If you have taken varying pixel density into account in your UI (and you should have) set this to true . A false value will force Android to use compatibility scaling to attempt to scale your application UI correctly. This will generally result in a UI with degraded image assets that show scaling artifacts. Applications built with an SDK of API level 4 or higher will default all of these values to true . Best Practices for Resolution Independence The variety of Android hardware available provides both an exciting opportunity and a potential hazard for application developers. 120 ❘ CHAPTER 4 CREATING USER INTERFACES This section summarizes some of the most common techniques for creating applications that will run effectively on any screen platform. The most important thing to remember is never make assumptions regarding the screen your applica- tion will be running on. Create your layouts and assets for classes of screens (small, normal, and large size with low, medium, and high density) rather than particular screen dimensions or resolutions. By assuming your application will need to be scaled slightly on every device, you can ensure that when it is scaled the UI does not suffer. The Android Developer site includes some excellent tips for supporting multiple screen types. The section on ‘‘Strategies for Legacy Apps’’ is particularly useful for developers with existing applications looking to support new screen sizes and resolutions. You can find this documentation here: http://developer.android .com/guide/practices/screens_support.html#strategies Relative Layouts and Density-Independent Pixels Wherever possible you should avoid using hard-coded pixel values. This applies to layouts, Drawables and font sizes. In particular you should avoid the Absolute Layout class, which depends on the specification of pixel- based coordinates for each child View. Instead, use an alternative Layout manager that describes the child Views relative to each other or the screen edges. For most complex UIs the Relative Layout is likely to be the best solution. Within your layouts you should also avoid specifying View, Drawable, and font sizes using pixel values. Instead, define the height and width of Views using wrap_content or fill_parent where appropriate, and density-independent pixels (dp) or scale-independent pixels (sp) as required for View and font sizes, respectively. Density- and scale-independent pixels are means of specifying screen dimensions that will scale to appear the same on hardware using different pixel densities. One density-independent pixel (dp) is equivalent to one pixel on a 160dpi screen. A line specified as 2dp wide will appear as 3 pixels on a display with 240dpi. Using Scalable Graphics Assets Earlier in this chapter you were introduced to a number of Drawable resources, most of which can be defined in XML and all of which can be scaled smoothly by the run time, regardless of the screen size or pixel density. Where possible, use the following Drawable resources rather than fixed bitmap assets: ➤ NinePatches ➤ Shape Drawables ➤ Gradient Drawables Resolution and Density Independence ❘ 121 ➤ Composite and transformative Drawables such as: ➤ Rotate and Scale Drawables ➤ LevelListDrawables ➤ StateListDrawables Remember when defining these assets to use density-independent pixels (dp). Using scalable assets has the advantage of generic support for arbitrary screen sizes and resolutions, with the framework dynamically scaling your assets to produce the best possible image quality. Provide Optimized Resources for Different Screens When using Drawable resources that cannot be dynamically scaled well, you should create and include image assets optimized for each pixel density category (low, medium, and high). Application icons are an excellent example of a resource that should be optimized for different pixel densities. Using the resource framework described earlier in the chapter (and in Chapter 3), you can create anno- tated Drawable directories to store image assets for each supported density, as shown in the following list: ➤ res/drawable-ldpi ➤ res/drawable-mdpi ➤ res/drawable-hdpi By creating assets optimized for the pixel density of the host platform you ensure that your UI will be crisp and clear and devoid of artifacts like aliasing and lost pixels — typical side effects of scaling. Similarly, you should consider creating alternative layout definitions for different screen sizes. A layout optimized for a typical smartphone screen may crop important information on a small device, or appear too sparse when displayed on a large device such as a tablet. Use the resource framework to annotate the layout resource folder to create specialized layouts for small, normal, and large screens, as shown in the following list: ➤ res/layout-small ➤ res/layout-normal ➤ res/layout-large Testing, Testing, Testing With dozens of Android devices of varying screen sizes and pixel densities now available, it’s impracti- cal (and in some cases impossible) to physically test your application on every device. Android Virtual Devices are ideal platforms for testing your application with a number of different screen configurations. Virtual devices also have the advantage of letting you configure alternative plat- form releases (1.6, 2.0, 2.1, etc.) and hardware configurations (such as keyboards or trackballs). You learned how to create and use Android Virtual Devices in Chapter 2, so this section will focus on how best to create virtual devices that are representative of different screens. 122 ❘ CHAPTER 4 CREATING USER INTERFACES Emulator Skins The simplest way to test your application UI is to use the built-in skins. Each skin emulates a known device configuration with a resolution, pixel density, and physical screen size. As of Android 2.1, the following built-in skins were available for testing: ➤ QVGA 320×240, 120dpi, 3.3 ➤ WQVGA432 432×240, 120dpi, 3.9 ➤ HVGA 480×320, 160dpi, 3.6 ➤ WVGA800 800×480, 240dpi, 3.9 ➤ WVGA854 854×480, 240dpi, 4.1 Testing for Custom Resolutions and Screen Sizes One of the advantages of using an AVD to evaluate devices is the ability to define arbitrary screen resolutions and pixel densities. Figure 4-5 shows a new AVD for a 1024×768 device with a pixel density of 240dpi. FIGURE 4-5 Creating and Using Menus ❘ 123 FIGURE 4-6 When you start a new AVD you will be presented with the Launch Options dialog shown in Figure 4-6. If you check the ‘‘Scale dis- play to real size’’ checkbox and specify a screen size for your virtual device, as well as the dpi of your development monitor, the emula- tor will scale to approximate the physical size and pixel density you specified. This lets you evaluate your UI against a variety of screen sizes and pixel densities as well as resolutions and skins. This is an ideal way to see how your application will appear on a small, high-resolution phone or a large, low resolution tablet. CREATING AND USING MENUS Menus offer a way to expose application functions without sacrificing valuable screen space. Each Activity can specify its own menu that’s displayed when the device’s menu button is pressed. Android also supports context menus that can be assigned to any View. Context menus are normally triggered when a user holds the middle D-pad button, depresses the trackball, or long-presses the touch- screen for around three seconds when the View has focus. Activity and context menus support submenus, checkboxes, radio buttons, shortcut keys, and icons. Introducing the Android Menu System If you’ve ever tried to navigate a mobile phone menu system using a stylus or trackball, you know that traditional menu systems are awkward to use on mobile devices. To improve the usability of application menus, Android features a three-stage menu system optimized for small screens: FIGURE 4-7 . ➤ The icon menu This compact menu (shown in Figure 4-7) appears along the bottom of the screen when the menu button is pressed. It displays the icons and text for a limited number of Menu Items (typically six). By convention, menu icons are grayscale images in an embossed style, though this may vary on different devices. . This icon menu does not display checkboxes, radio buttons, or the shortcut keys for Menu Items, so it’s generally good practice not to depend on checkboxes or radio buttons in icon Menu Items, as they will not be visible. If the Activity menu contains more than the maximum number of visible Menu Items, a More Menu Item is displayed. When selected, it displays the expanded menu. Pressing the back but- ton closes the icon menu. 124 ❘ CHAPTER 4 CREATING USER INTERFACES FIGURE 4-8 . ➤ The expanded menu The expanded menu is triggered when a user selects the More Menu Item from the icon menu. The expanded menu (shown in Figure 4-8) displays a scrollable list of only the Menu Items that weren’t visible in the icon menu. This menu displays full text, shortcut keys, and checkboxes/radio buttons. It does not, however, display icons. Pressing back from the expanded menu returns you to the icon menu. You cannot force Android to display the expanded menu instead of the icon menu. As a result, special care must be taken with Menu Items that feature checkboxes or radio buttons. The maximum number of icon Menu Items can vary by device, so it’s good practice to ensure that their state information is also indicated by an icon or a change in text. FIGURE 4-9 . ➤ Submenus The traditional expanding hierarchi- cal tree can be awkward to navigate using a mouse, so it’s no surprise that this metaphor is particularly ill-suited for use on mobile devices. The Android alternative is to display each submenu in a floating window. For example, when a user selects a submenu such as the creatively labeled Submenu shown in Figure 4-8, its items are displayed in a floating menu dialog box, as shown in Figure 4-9. Note that the name of the submenu is shown in the header bar and that each Menu Item is displayed with its full text, checkbox (if any), and shortcut key. Since Android does not support nested submenus, you can’t add a submenu to a submenu (trying will result in an exception). As with the extended menu, icons are not displayed in the submenu, so it’s good practice to avoid assign- ing icons to submenu items. Pressing the back button closes the floating win- dow without your having to navigate back to the extended or icon menus. Defining an Activity Menu To define a menu for an Activity, override its onCreateOptionsMenu handler. This method is triggered the first time an Activity’s menu is displayed. Creating and Using Menus ❘ 125 The onCreateOptionsMenu receives a Menu object as a parameter. You can store a reference to, and continue to use, the Menu reference elsewhere in your code until the next time onCreateOptionsMenu is called. You should always call through to the superclass implementation, as it automatically includes addi- tional system menu options where appropriate. Use the add method on the Menu object to populate your menu. For each new Menu Item, you must specify the following: ➤ A group value to separate Menu Items for batch processing and ordering. ➤ A unique identifier for each Menu Item. For efficiency reasons, Menu Item selections are generally handled by the onOptionsItemSelected event handler, so this unique identifier is important for determining which Menu Item was pressed. It is convention to declare each menu ID as a private static variable within the Activity class. You can use the Menu.FIRST static constant and simply increment that value for each subsequent item. ➤ An order value that defines the order in which the Menu Items are displayed. ➤ The Menu Item display text, either as a character string or as a string resource. When you have finished populating the Menu return true . Listing 4-26 shows how to add a single Menu Item to an Activity Menu. LISTING 4-26: Adding a Menu Item static final private int MENU_ITEM = Menu.FIRST; @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); // Group ID int groupId = 0; // Unique menu item identifier. Used for event handling. int menuItemId = MENU_ITEM; // The order position of the item int menuItemOrder = Menu.NONE; // Text to be displayed for this menu item. int menuItemText = R.string.menu_item; // Create the menu item and keep a reference to it. MenuItem menuItem = menu.add(groupId, menuItemId, menuItemOrder, menuItemText); return true; } Like the Menu object, each MenuItem returned by add is valid until the next call to onCreateOptionsMenu . Rather than maintaining a reference to each item, you can find a particular Menu Item by passing its ID in to the Menu’s findItem method. 126 ❘ CHAPTER 4 CREATING USER INTERFACES Menu Item Options Android supports most of the traditional Menu Item options you’re probably familiar with, including icons, shortcuts, checkboxes, and radio buttons, as listed here: ➤ Checkboxes and radio buttons Checkboxes and radio buttons on Menu Items are visible in expanded menus and submenus, as shown in Figure 4-9. To set a Menu Item as a checkbox, use the setCheckable method. The state of that checkbox is controlled via setChecked . A radio button group is a group of items displaying circular buttons, in which only one item can be selected at any given time. Checking one of these items will automatically uncheck any checked item in the same group. To create a radio button group, assign the same group identifier to each item and then call Menu.setGroupCheckable , passing in that group identifier and setting the exclusive parameter to true . Checkboxes are not visible in the icon menu, so Menu Items that feature checkboxes should be reserved for submenus and items that appear only in the expanded menu. The following code snippet shows how to add a checkbox and a group of three radio buttons. // Create a new check box item. menu.add(0, CHECKBOX_ITEM, Menu.NONE, "CheckBox").setCheckable(true); // Create a radio button group. menu.add(RB_GROUP, RADIOBUTTON_1, Menu.NONE, "Radiobutton 1"); menu.add(RB_GROUP, RADIOBUTTON_2, Menu.NONE, "Radiobutton 2"); menu.add(RB_GROUP, RADIOBUTTON_3, Menu.NONE, "Radiobutton 3").setChecked(true); menu.setGroupCheckable(RB_GROUP, true, true); ➤ Shortcut keys You can specify a keyboard shortcut for a Menu Item using the setShortcut method. Each call to setShortcut requires two shortcut keys, one for use with the numeric keypad and a second to support a full keyboard. Neither key is case-sensitive. // Add a shortcut to this menu item, ‘0’ if using the numeric keypad // or ‘b’ if using the full keyboard. menuItem.setShortcut(’0’, ‘b’); ➤ Condensed titles The icon menu does not display shortcuts or checkboxes, so it’s often nec- essary to modify its display text to indicate its state. The setTitleCondensed method lets you specify text to be displayed only in the icon menu. menuItem.setTitleCondensed("Short Title"); ➤ Icons The icon property is a Drawable resource identifier for an icon to be used in the Menu Item. Icons are displayed only in the icon menu; they are not visible in the extended menu or submenus. You can specify any Drawable resource as a menu icon, though by convention menu icons are generally grayscale and use an embossed style. menuItem.setIcon(R.drawable.menu_item_icon); ➤ Menu item click listener An event handler that will execute when the Menu Item is selected. For efficiency, the use of such an event handler is discouraged; instead, Menu Item selections should be handled by the onOptionsItemSelected handler, as shown later in this section. [...]... xmlns :android= "http://schemas .android. com/apk/res /android" android: name="Context Menu"> . resource <level-list xmlns :android= "http://schemas .android. com/apk/res /android& quot;> <item android: maxLevel="0" android: drawable="@drawable/earthquake_0"/> <item android: maxLevel="1". xmlns :android= "http://schemas .android. com/apk/res /android& quot; android: name="Context Menu"> <item android: id="@+id/item01" Creating and Using Menus ❘ 131 android: icon="@drawable/menu_item" android: title="Item. Menus ❘ 131 android: icon="@drawable/menu_item" android: title="Item 1"> </item> <item android: id="@+id/item02" android: checkable="true" android: title="Item 2"> </item> <item android: id="@+id/item03" android: numericShortcut="3" android: alphabeticShortcut="3" android: title="Item