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
1,43 MB
Nội dung
CHAPTER 12 ■ FONTS 127 <TextView android:id="@+id/custom" android:text="Hello, world!" android:textSize="20sp" /> </TableRow> </TableLayout> This layout builds a table showing short samples of four fonts. Notice how the first three have the android:typeface attribute, whose value is one of the three built-in font faces (e.g., “sans”). The three built-in fonts are very nice. However, it may be that a designer, or a manager, or a customer wants a different font than one of those three. Or perhaps you want to use a font for specialized purposes, such as a “dingbats” font instead of a series of PNG graphics. The easiest way to accomplish this is to package the desired font(s) with your application. To do this, simply create an assets/ folder in the project root, and put your TrueType (TTF) fonts in the assets. You might, for example, create assets/fonts/ and put your TTF files in there. Then, you need to tell your widgets to use that font. Unfortunately, you can no longer use layout XML for this, since the XML does not know about any fonts you may have tucked away as an application asset. Instead, you need to make the change in Java code: public class FontSampler extends Activity { @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.main); TextView tv=(TextView)findViewById(R.id.custom); Typeface face=Typeface.createFromAsset(getAssets(), "fonts/HandmadeTypewriter.ttf"); tv.setTypeface(face); } } Here we grab the TextView for our “custom” sample, then create a Typeface object via the static createFromAsset() builder method. This takes the application’s AssetManager (from getAssets()) and a path within your assets/ directory to the font you want. Then, it is just a matter of telling the TextView to setTypeface(), providing the Typeface you just created. In this case, we are using the Handmade Typewriter 2 font (see Figure 12-1). 2. http://moorstation.org/typoasis/designers/klein07/text01/handmade.htm Murphy_2419-8C12.fm Page 127 Friday, April 10, 2009 3:34 PM 128 CHAPTER 12 ■ FONTS Figure 12-1. The FontSampler application Note that Android does not seem to like all TrueType fonts. When Android dislikes a custom font, rather than raise an Exception, it seems to substitute Droid Sans (“sans”) quietly. So, if you try to use a different font and it does not seem to be working, it may be that the font in question is incompatible with Android, for whatever reason. Also, you are probably best served by changing the case of your font filenames to be all lowercase, to match the naming convention used in the rest of your resources. Also note that TrueType fonts can be rather pudgy, particularly if they support an exten- sive subset of the available Unicode characters. The Handmade Typewriter font used here runs over 70KB; the DejaVu free fonts can run upwards of 500KB apiece. Even compressed, these add bulk to your application, so be careful not to go overboard with custom fonts, or your application could take up too much room on your users’ phones. Murphy_2419-8C12.fm Page 128 Friday, April 10, 2009 3:34 PM 129 ■ ■ ■ CHAPTER 13 Embedding the WebKit Browser Other GUI toolkits let you use HTML for presenting information, from limited HTML renderers (e.g., Java/Swing, wxWidgets) to embedding Internet Explorer into .NET applications. Android is much the same, in that you can embed the built-in Web browser as a widget in your own activities, for displaying HTML or full-fledged browsing. The Android browser is based on WebKit, the same engine that powers Apple’s Safari Web browser. The Android browser is sufficiently complex that it gets its own Java package (android.webkit), though using the WebView widget itself can be simple or powerful, based upon your requirements. A Browser, Writ Small For simple stuff, WebView is not significantly different than any other widget in Android—pop it into a layout, tell it what URL to navigate to via Java code, and you’re done. For example, WebKit/Browser1 is a simple layout with a WebView. You can find WebKit/ Browser1 along with all the code samples for this chapter in the Source Code area at http:// apress.com. <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <WebView android:id="@+id/webkit" android:layout_width="fill_parent" android:layout_height="fill_parent" /> </LinearLayout> Murphy_2419-8C13.fm Page 129 Friday, April 10, 2009 3:37 PM 130 CHAPTER 13 ■ EMBEDDING THE WEBKIT BROWSER As with any other widget, you need to tell it how it should fill up the space in the layout (in this case, it fills all remaining space). The Java code is equally simple: package com.commonsware.android.webkit; import android.app.Activity; import android.os.Bundle; import android.webkit.WebView; public class BrowserDemo1 extends Activity { WebView browser; @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.main); browser=(WebView)findViewById(R.id.webkit); browser.loadUrl("http://commonsware.com"); } } The only unusual bit with this edition of onCreate() is that we invoke loadUrl() on the WebView widget, to tell it to load a Web page (in this case, the home page of some random firm). However, we also have to make one change to AndroidManifest.xml, requesting permission to access the Internet: <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.commonsware.android.webkit"> <uses-permission android:name="android.permission.INTERNET" /> <application> <activity android:name=".BrowserDemo1" android:label="BrowserDemo1"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> If we fail to add this permission, the browser will refuse to load pages. The resulting activity looks like a Web browser, just with hidden scrollbars (see Figure 13-1). Murphy_2419-8C13.fm Page 130 Friday, April 10, 2009 3:37 PM CHAPTER 13 ■ EMBEDDING THE WEBKIT BROWSER 131 Figure 13-1. The Browser1 sample application As with the regular Android browser, you can pan around the page by dragging it, while the directional pad moves you around all the focusable elements on the page. What is missing is all the extra accouterments that make up a Web browser, such as a navi- gational toolbar. Now, you may be tempted to replace the URL in that source code with something else, such as Google’s home page or another page that relies upon Javascript. By default Javascript is turned off in WebView widgets. If you want to enable Javascript, call getSettings(). setJavaScriptEnabled(true); on the WebView instance. Loading It Up There are two main ways to get content into the WebView. One, shown earlier, is to provide the browser with a URL and have the browser display that page via loadUrl(). The browser will access the Internet through whatever means are available to that specific device at the present time (WiFi, cellular network, Bluetooth-tethered phone, well-trained tiny carrier pigeons, etc.). The alternative is to use loadData(). Here, you supply the HTML for the browser to view. You might use this to • display a manual that was installed as a file with your application package • display snippets of HTML you retrieved as part of other processing, such as the descrip- tion of an entry in an Atom feed • generate a whole user interface using HTML, instead of using the Android widget set Murphy_2419-8C13.fm Page 131 Friday, April 10, 2009 3:37 PM 132 CHAPTER 13 ■ EMBEDDING THE WEBKIT BROWSER There are two flavors of loadData(). The simpler one allows you to provide the content, the MIME type, and the encoding, all as strings. Typically, your MIME type will be text/html and your encoding will be UTF-8 for ordinary HTML. For instance, if you replace the loadUrl() invocation in the previous example with the following code, you get the result shown in Figure 13-2. browser.loadData("<html><body>Hello, world!</body></html>", "text/html", "UTF-8"); Figure 13-2. The Browser2 sample application This is also available as a fully-buildable sample, as WebKit/Browser2. Navigating the Waters As previously mentioned, there is no navigation toolbar with the WebView widget. This allows you to use it in places where such a toolbar would be pointless and a waste of screen real estate. That being said, if you want to offer navigational capabilities, you can, but you have to supply the UI. WebView offers ways to perform garden-variety browser navigation, including the following: • reload() to refresh the currently-viewed Web page • goBack() to go back one step in the browser history, and canGoBack() to determine if there is any history to go back to • goForward() to go forward one step in the browser history, and canGoForward() to deter- mine if there is any history to go forward to Murphy_2419-8C13.fm Page 132 Friday, April 10, 2009 3:37 PM CHAPTER 13 ■ EMBEDDING THE WEBKIT BROWSER 133 • goBackOrForward() to go backward or forward in the browser history, where a negative number as an argument represents a count of steps to go backward, and a positive number represents how many steps to go forward • canGoBackOrForward() to see if the browser can go backward or forward the stated number of steps (following the same positive/negative convention as goBackOrForward()) • clearCache() to clear the browser resource cache and clearHistory() to clear the browsing history Entertaining the Client If you are going to use the WebView as a local user interface (vs. browsing the Web), you will want to be able to get control at key times, particularly when users click on links. You will want to make sure those links are handled properly, either by loading your own content back into the WebView, by submitting an Intent to Android to open the URL in a full browser, or by some other means (see Chapter 25). Your hook into the WebView activity is via setWebViewClient(), which takes an instance of a WebViewClient implementation as a parameter. The supplied callback object will be notified of a wide range of activities, ranging from when parts of a page have been retrieved (onPageStarted(), etc.) to when you, as the host application, need to handle certain user- or circumstance-initiated events, such as onTooManyRedirects() and onReceivedHttpAuthRequest(), etc. A common hook will be shouldOverrideUrlLoading(), where your callback is passed a URL (plus the WebView itself) and you return true if you will handle the request or false if you want default handling (e.g., actually fetch the Web page referenced by the URL). In the case of a feed reader application, for example, you will probably not have a full browser with navigation built into your reader, so if the user clicks a URL, you probably want to use an Intent to ask Android to load that page in a full browser. But, if you have inserted a “fake” URL into the HTML, repre- senting a link to some activity-provided content, you can update the WebView yourself. For example, let’s amend the first browser example to be a browser-based equivalent of our original example: an application that, upon a click, shows the current time. From WebKit/Browser3, here is the revised Java: public class BrowserDemo3 extends Activity { WebView browser; @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.main); browser=(WebView)findViewById(R.id.webkit); browser.setWebViewClient(new Callback()); loadTime(); } Murphy_2419-8C13.fm Page 133 Friday, April 10, 2009 3:37 PM 134 CHAPTER 13 ■ EMBEDDING THE WEBKIT BROWSER void loadTime() { String page="<html><body><a href=\"clock\">" +new Date().toString() +"</a></body></html>"; browser.loadDataWithBaseURL("x-data://base", page, "text/html", "UTF-8", null); } private class Callback extends WebViewClient { public boolean shouldOverrideUrlLoading(WebView view, String url) { loadTime(); return(true); } } } Here, we load a simple Web page into the browser (loadTime()) that consists of the current time, made into a hyperlink to the /clock URL. We also attach an instance of a WebViewClient subclass, providing our implementation of shouldOverrideUrlLoading(). In this case, no matter what the URL, we want to just reload the WebView via loadTime(). Running this activity gives the result shown in Figure 13-3. Figure 13-3. The Browser3 sample application Murphy_2419-8C13.fm Page 134 Friday, April 10, 2009 3:37 PM CHAPTER 13 ■ EMBEDDING THE WEBKIT BROWSER 135 Selecting the link and clicking the D-pad center button will “click” the link, causing us to rebuild the page with the new time. Settings, Preferences, and Options (Oh, My!) With your favorite desktop Web browser, you have some sort of “settings” or “preferences” or “options” window. Between that and the toolbar controls, you can tweak and twiddle the behavior of your browser, from preferred fonts to the behavior of Javascript. Similarly, you can adjust the settings of your WebView widget as you see fit, via the WebSettings instance returned from calling the widget’s getSettings() method. There are lots of options on WebSettings to play with. Most appear fairly esoteric (e.g., setFantasyFontFamily()). However, here are some that you may find more useful: • Control the font sizing via setDefaultFontSize() (to use a point size) or setTextSize() (to use constants indicating relative sizes like LARGER and SMALLEST) • Control Javascript via setJavaScriptEnabled() (to disable it outright) and setJavaScriptCanOpenWindowsAutomatically() (to merely stop it from opening pop-up windows) • Control Web site rendering via setUserAgent() – 0 means the WebView gives the Web site a user-agent string that indicates it is a mobile browser, while 1 results in a user-agent string that suggests it is a desktop browser The settings you change are not persistent, so you should store them somewhere (such as via the Android preferences engine) if you are allowing your users to determine the settings, versus hard-wiring the settings in your application. Murphy_2419-8C13.fm Page 135 Friday, April 10, 2009 3:37 PM Murphy_2419-8C13.fm Page 136 Friday, April 10, 2009 3:37 PM [...]... xmlns :android= "http://schemas .android. com/apk/res /android" android: orientation="vertical" android: layout_width="fill_parent" android: layout_height="fill_parent" > ... your AndroidManifest.xml file: ... http://apress.com The... xmlns :android= "http://schemas .android. com/apk/res /android" > The root of... . encoding="utf-8"?> <LinearLayout xmlns :android= "http://schemas .android. com/apk/res /android& quot; android: orientation="vertical" android: layout_width="fill_parent" android: layout_height="fill_parent" . encoding="utf-8"?> <LinearLayout xmlns :android= "http://schemas .android. com/apk/res /android& quot; android: orientation="vertical" android: layout_width="fill_parent" android: layout_height="fill_parent". encoding="utf-8"?> <LinearLayout xmlns :android= "http://schemas .android. com/apk/res /android& quot; android: orientation="vertical" android: layout_width="fill_parent" android: layout_height="fill_parent"