114 lines
5.3 KiB
Plaintext
114 lines
5.3 KiB
Plaintext
page.title=WikiNotes: Linkify your Text!
|
|
@jd:body
|
|
|
|
<img style="margin-left: 1.5em; margin-bottom:1.5em; float: right;"
|
|
src="images/WikiNotes.png" alt="Linkify example" border="0">
|
|
|
|
<p>This article introduces <a
|
|
href="http://android-developers.blogspot.com/2008/03/announcing-apps-for-android
|
|
.html">WikiNotes for Android</a>, part of the <a
|
|
href="http://code.google.com/p/apps-for-android/">Apps for Android</a>
|
|
project. It covers the use of Linkify to turn ordinary text views
|
|
into richer, link-oriented content that causes Android intents to fire
|
|
when a link is selected.</p>
|
|
|
|
<p><strong>Linkify</strong>: The {@link android.text.util.Linkify} class in the
|
|
framework is perfect for creating a wiki note pad. It lets you specify a <a
|
|
title="regular expression"
|
|
href="http://en.wikipedia.org/wiki/Regular_expression">regular expression
|
|
»</a>
|
|
to match, and a scheme to prepend. The scheme is a string that, when
|
|
the matched text is added, forms a Content URI to allow the correct
|
|
data to be looked up.</p>
|
|
|
|
<p>For example, in our case we want to look for a regular expression match for a
|
|
WikiWord (that is, a word with <a title="word with camel case"
|
|
href="http://en.wikipedia.org/wiki/CamelCase">camel case »</a> and no
|
|
spaces). Linkify can then turn this into a Content URI — something like
|
|
<code>content://com.google.android.wikinotes.db.wikinotes/wikinotes/WikiWord</code>,
|
|
which can then be used to locate the correct wiki page from a
|
|
{@link android.content.ContentProvider}.</p>
|
|
|
|
<p>As a bonus, the Linkify class also defines several default matches,
|
|
in particular it is able to turn web URLs, email addresses and
|
|
telephone numbers into active links which fire Android intents
|
|
automatically.</p>
|
|
|
|
<p>Linkify can be passed any TextView in your application, and will
|
|
take care of creating the links and enabling their "clickability" for
|
|
you.</p>
|
|
|
|
<p><strong>Default Linkify</strong>: Using the set of default active
|
|
link options is very straightforward. Simply pass it a handle to a
|
|
TextView with content in it, and the <code>Linkify.ALL</code> flag:</p>
|
|
|
|
<pre>TextView noteView = (TextView) findViewById(R.id.noteview);
|
|
noteView.setText(someContent);
|
|
Linkify.addLinks(noteView, Linkify.ALL);</pre>
|
|
|
|
<p>and that's it. The <code>Linkify.ALL</code> flag applies all of the predefined
|
|
link actions, and the TextView will be immediately updated with a set
|
|
of active links which, if you select them, fire default intents for the
|
|
actions (e.g. a web URL will start the browser with that URL, a
|
|
telephone number will bring up the phone dialer with that number ready
|
|
to call, etc.).</p>
|
|
|
|
<p><strong>Custom Linkify</strong>: So what about our WikiWord? There is no
|
|
pre-defined action for that, so it needs to be defined and associated with a
|
|
scheme.</p>
|
|
|
|
<p>The first task is to define a regular expression that matches the kind of
|
|
WikiWords we want to find. The regex in this case is:</p>
|
|
|
|
<pre>\b[A-Z]+[a-z0-9]+[A-Z][A-Za-z0-9]+\b</pre>
|
|
|
|
<p>Obvious, no? Well actually this is equivalent to the following
|
|
description: "Starting with a word boundary (the \b) find at least one
|
|
upper case letter, followed by at least one lower case letter or a
|
|
numeric digit, followed by another upper case letter, and then any mix
|
|
of upper case, lower case or numeric until the next word boundary (the
|
|
final \b)". Regular expressions are not very pretty, but they are an
|
|
extremely concise and accurate way of specifying a search pattern.</p>
|
|
|
|
<p>We also need to tell Linkify what to do with a match to the
|
|
WikiWord. Linkify will automatically append whatever is matched to a
|
|
scheme that is supplied to it, so for the sake of argument let's assume
|
|
we have a {@link android.content.ContentProvider} that matches the
|
|
following content URI:</p>
|
|
|
|
<pre>content://com.google.android.wikinotes.db.wikinotes/wikinotes/WikiWord</pre>
|
|
|
|
<p>The WikiWord part will be appended by Linkify when it finds a match, so we
|
|
just need the part before that as our scheme.</p>
|
|
|
|
<p>Now that we have these two things, we use Linkify to connect them up:</p>
|
|
|
|
<pre>Pattern wikiWordMatcher = Pattern.compile("\\b[A-Z]+[a-z0-9]+[A-Z][A-Za-z0-9]+\\b");
|
|
String wikiViewURL = "content://com.google.android.wikinotes.db.wikinotes/wikinotes/";
|
|
Linkify.addLinks(noteView, wikiWordMatcher, wikiViewURL);</pre>
|
|
|
|
<p>Note that the \b's had to be escaped with double backslashes for the Java
|
|
Pattern.compile line.</p>
|
|
|
|
<p>Linkify can be used multiple times on the same view to add more
|
|
links, so using this after the Default Linkify call means that the
|
|
existing active links will be maintained and the new WikiWords will be
|
|
added. You could define more Linkify actions and keep applying them to
|
|
the same TextView if you wanted to.</p>
|
|
|
|
<p>Now, if we have a WikiWord in the TextView, let's say
|
|
<code>MyToDoList</code>, Linkify will turn it into an active link with the
|
|
content URI:</p>
|
|
|
|
<pre>content://com.google.android.wikinotes.db.wikinotes/wikinotes/MyToDoList</pre>
|
|
|
|
<p>and if you click on it, Android will fire the default intent for that content
|
|
URI.</p>
|
|
|
|
<p>For this to all work, you will need a ContentProvider that
|
|
understands that Content URI, and you will need a default activity
|
|
capable of doing something with the resulting data. I plan to cover
|
|
these in future blog entries (and soon). In fact, the whole Wiki Note
|
|
Pad application is currently undergoing some clean up and review, and
|
|
will then hopefully be released as a sample application.</p>
|