- Splash Screen
- Loading Indication
- Complex TextViews
- Autoloading ListViews
- Summary
Loading Indication
Immediate feedback is one of the most important parts of a good UI. If a button does not have a touch state and the resulting action takes some time, the user will feel like the app is unresponsive. Unfortunately, whether the app needs to run complex image analysis algorithms or just access web resources, there are times when it will not be able to immediately show the users what they want to see. In these instances, you use a loading indicator to give the user a sense that something is happening. Ideally, you use a loading indicator that can show progress such as when downloading a file, but sometimes you have to fall back on the indeterminate loading indicator, which just tells the user, “Hey, something is happening, but who knows how long it will take.”
Dialogs versus Inline
Using dialogs to indicate loading is the go-to solution for a lot of developers. In fact, Android’s ProgressDialog class makes this extremely easy. Just create an instance using one of the static show() methods and then update it if possible. When your task is done, you just dismiss() the dialog. Simple enough, right?
The problem is that these dialogs are modal. That means the user can do nothing else in your app while looking at one of these dialogs, so they don’t make sense unless there really is nothing else the user can do (for example, the previously explained splash screen). You may have allowed the user to back out of the dialog, but that just results in the user being confused as to whether the task actually stopped or not (and further confused when the UI suddenly changes when it does complete). Instead, consider using inline loading indicators.
An inline loading indicator is basically a loading indicator that is a part of your regular view hierarchy. It goes where the content that is loading will go and serves as a placeholder as well as a visual indication of activity. Not only is this significantly less disruptive than a dialog, it lets the user interact with other content immediately. If you go to Google Play to search for a particular app, you don’t want to wait while the front page loads before you can actually search. An additional advantage of inline indicators is that they allow you to load different sections of a screen and display them independently. You might go to someone’s profile page in an app and see the basic info. At the same time, one section is loading that displays recent content posted by that person and another section loads people who are similar to that person. Neither of these pieces is dependent on the other.
Using an Inline Loading Indicator
Using inline loading indicators in your app is actually extremely easy. The simplest way is to just include a ProgressBar in your layout somewhere and then hide or remove it when the loading is complete and add the new views. There are several ways to make this easier to manage. If the extra content is almost always available (for example, you might go from a list of articles to a detailed article page, and you just need to fetch the body text), then an easy approach is to use a ViewSwitcher. A ViewSwitcher is a ViewGroup that contains two child Views and can animate between them. In this case, you use it to display a loading indicator and then switch to the other View when it is ready.
First, define a couple of animations in XML. These go in res/anim. Listing 10.6 defines a simple fade-in animation, and Listing 10.7 defines a fade-out animation.
Listing 10.6. A Simple Fade-in Animation Saved as fade_in.xml
<?xml
version
="1.0"
encoding
="utf-8"
?>
<alpha
xmlns:android
="http://schemas.android.com/apk/res/android"
android:duration
="300"
android:fromAlpha
="0.0"
android:interpolator
="@android:anim/decelerate_interpolator"
android:toAlpha
="1.0"
/>
Listing 10.7. A Simple Fade-out Animation Saved as fade_out.xml
<?xml
version
="1.0"
encoding
="utf-8"
?>
<alpha
xmlns:android
="http://schemas.android.com/apk/res/android"
android:duration
="300"
android:fromAlpha
="1.0"
android:interpolator
="@android:anim/accelerate_interpolator"
android:toAlpha
="0.0"
/>
With those animations defined, all you need now is a ViewSwitcher that is displaying a loading indication and a second child View that is the content you have finished loading. You set the animations and then simply call showNext(), as shown in Listing 10.8.
Listing 10.8. Using a ViewSwitcher to Animate Between Views
ViewSwitcher viewSwitcher = (ViewSwitcher) findViewById (R.id.view_switcher
); viewSwitcher.setInAnimation(this
, R.anim.fade_in
); viewSwitcher.setOutAnimation(this
, R.anim.fade_out
); viewSwitcher.showNext();
Sometimes you’ll have some chunk of content that is frequently not there or that has a complex view hierarchy. In these cases, it’s a good idea to make use of ViewStubs. A ViewStub is an extremely simple implementation of View that essentially acts as a placeholder for other content. It takes up no space and draws nothing, so it has minimal impact on your layout complexity. Think of it like an include tag that does not actually include another layout until you say to do so.
Listing 10.9 shows what a ViewStub will look like in your XML layout. The regular ID is used for finding the ViewStub, but it can also specify an inflatedID for finding the layout after it has been inflated. The layout that will be inflated is specified by the layout property the same as it is in an include tag.
Listing 10.9. An XML ViewStub
<ViewStub
android:id
="@+id/view_stub"
android:layout_width
="match_parent"
android:layout_height
="wrap_content"
android:inflatedId
="@+id/dynamic_content"
android:layout
="@layout/other_layout"
/>
All that is left to do is to find a reference to your ViewStub, inflate it, and do whatever you need to with the resulting layout. See Listing 10.10 for the basic code involved.
Listing 10.10. Inflating a ViewStub in Java
ViewStub stub = (ViewStub) findViewById(R.id.view_stub
); View otherLayout = stub.inflate();// Do something with otherLayout
...