Pushing the ActionBar to the Next Level
原文地址:http://cyrilmottier.com/2013/05/24/pushing-the-actionbar-to-the-next-level/
sampleAPK下载地址:http://cyrilmottier.com/2013/05/24/pushing-the-actionbar-to-the-next-level/media/2013/05/pushing-the-actionbar-to-the-next-level/TranslucentActionBar.apk
Back in November 2012, I wrote a blog post entitled ”ActionBar on the Move”. This article was mainly dealing with a technique to nicely and uniquely animate your ActionBar
. Although I mentioned some of the effect’s possible applications, I never had time to effectively add an ActionBar
animation to one of my own apps nor saw an application on the Play Store taking advantage of it.
While being at Google I/O last week, I finally found an application using the ActionBar
animation technique. Let’s be honest, it literally blew my mind the first time I saw it. I felt in love with the nice, subtle and yet extremely useful animated effect probably more than the entire app itself! I am pretty sure you know the application I am talking about as it has been presented during the Google I/O keynote. You have also probably recently received an update of it: Play Music!
The latest update of Play Music (v5.0) has been completely redesign and features a brand new artist/album detail screen. If you open such a detail screen, you’ll notice the ActionBar
is initially invisible and overlaps a large image describing the artist/album. Once you start scrolling down (if possible), the ActionBar
fades in gradually. The ActionBar
turns completely opaque when the large image has been scrolled out of the screen.
Here are two main advantages of this ActionBar
animation:
- Polish the UI: animations synchronized on an element you’re interacting with are generally appreciated by users because it makes them feel the UI is natural and reacts to their actions. The fading animation is a direct consequence of the per-pixel scrolling state and not a launched-once animation.
- Take advantage of the screen real estate: while still preserving the UX of the platform, this pattern let the user primarily focus on the content rather than the controls. Used in addition to a nicely designed screen, it can be a game changer for your app’s interface.
In this article, I will deep dive into the details of implementing the technique described in ”ActionBar on the Move” to create an effect similar to the one used in the Play Music app.
In order to better understand the goal we are targeting, you can have a look at the screenshots below or alternatively download the sample application.
Download the sample APK
Application theming/styling
As you can easily notice, in order to reproduce such an effect, the ActionBar
must overlap the content of the screen. This can be easily done using the android:windowActionBarOverlay
XML attributes. The code below describes the definition of the themes we’ll use:
values/themes.xml
| |
Pretty logically, the style of the ActionBar
is defined in values/styles.xml
as follows:
values/styles.xml
| |
Finally, we can use these themes in order to style our Activity
.
AndroidManifest.xml
| |
Note that by using themes/styles we remove all potential flickering issues at startup (see Android App Launching Made Gorgeous for more information).
Getting the content ready
As explained previously, the ActionBar
fading is synchronized on the per-pixel state scrolling of the scrolling container. In this example, we’ll simply use a ScrollView
as a scrolling container. One of the major drawback of this container is you can’t register a listener in order to be notified when the scroll has changed. This can be easily done be creating a NotifyingScrollView
extending the original ScrollView
:
NotifyingScrollView.java
| |
Then, we can use this new scrolling container in an XML layout:
layout/activity_home.xml
| |
Fading in/out the ActionBar
Now most of the boilerplate is ready, we can plug all of these components together. The ActionBar
algorithm is rather simple and only consists on computing the alpha depending on the current per-pixel scrolling state of the NotifyingScrollView
. Note that the effective scrolled distance must be clamped to [0, image_height - actionbar_height] in order to avoid weird values that may occur mainly because of the default over scroll behavior of scrolling containers on Android:
HomeActivity.java
| |
As described in ”ActionBar on the Move”, this snippet of code above doesn’t work for pre-JELLY_BEAN_MR1 devices. Indeed, the ActionBar
isn’t invalidating itself when required because it isn’t registering itself as the Drawable
’s callback. You can workaround this issue simply be attaching the following Callback
in the onCreate(Bundle)
method:
HomeActivity.java
| |
HomeActivity.java
| |
You can already run the code “as it”. Although the result looks alike the animation used in Play Music we can still continue to tweak it to make it better.
A final brush stroke
Enforcing ActionBar contrast
Having an transparent ActionBar
may lead to design issues because you generally don’t know about the background you’ll be displayed on top of. For instance you may end up with a transparent ActionBar
displaying a white text on top of a white description image. No need to say it makes theActionBar
invisible and useless.
The easiest way to avoid such a problem consists on modifying the image to make it a little bit darker at the top. Thus, in a worse case scenario (i.e. white image) we would have a grey area on top of the image making the ActionBar
content (title, icons, buttons, etc.) visible.
A simple way to do that is to overlay a translucent dark to transparent gradient on top of the image. This can be done in XML only with the Drawable
described below:
drawable/gradient.xml
| |
The gradient is overlaid using a wrapping FrameLayout
:
layout/activity_home.xml
| |
Avoid over-scroll
In Gingerbread (API 9), Android introduced a brand new way to notify the user a scrollable container is being scrolled beyond the content bounds. First it introduced the notion of EdgeEffect
(available in the API starting API 14) and enabled over-scroll. While this is not a problem in general, it can be pretty annoying when one of the edge of your scrollable content is different from the background color.
You can reproduce it be simply flinging the ScrollView
rapidly to the top and you’ll notice some white color (the background color) appears on top of the screen because the image is scrolling beyond the bounds. I personally consider this a a UI glitch and usually prefer disabling it in this rare cases.
One could imagine the best way to avoid over-scroll is to use View#setOverScrollMode(int)
to change the mode to View#OVER_SCROLL_NEVER
. Although it works, it also remove the edge effect which can be visually disturbing1. A simple way to do that is to modify the NotifyingScrollView
to force the maximum over scroll values to zero when necessary:
NotifyingScrollView.java
| |
Conclusion
I seriously don’t know if the team behind the Play Music application decided to implement the behavior based on my article. But it appears they brilliantly used the technique to both polish and emphasize the UI. It is clearly an awesome pattern to use whenever you need to design a screen which content is self-explanatory and is more important than the ActionBar
content itself.
- Do not ask me why the naming of the constants/method is so ambiguous…
还没有评论,来说两句吧...