Using Android’s ViewPager PageTransformer

A recent addition I made to the Reader in WordPress for Android is the ability to swipe through articles, which is a pretty standard thing on Android thanks to the ViewPager.

But after using it a while, I decided I wasn’t happy with the default swipe animation, so I created a custom PageTransformer to provide a different one.

I then added the ability to swipe through photos in an article, and again I wasn’t happy with the default animation. Rather than create another PageTransformer, I changed the one I’d already coded so it could provide a number of different animations.

Here’s a video demo:

The source code for this custom PageTransformer, which is part of the open source WordPress for Android app, is below.

[code language=”java” collapse=”false”]
package org.wordpress.android.ui.reader;

import android.support.v4.view.ViewPager;
import android.view.View;

/*
* ViewPager transformation animation invoked when a visible/attached page is scrolled – before
* changing this, first see https://code.google.com/p/android/issues/detail?id=58918#c5
* tl;dr make sure to remove X translation when a page is no longer fully visible
*
* Usage: viewPager.setPageTransformer(false, new ReaderViewPagerTransformer(TransformType.FLOW));
*/
class ReaderViewPagerTransformer implements ViewPager.PageTransformer {
static enum TransformType {
FLOW,
DEPTH,
ZOOM,
SLIDE_OVER
}
private final TransformType mTransformType;

ReaderViewPagerTransformer(TransformType transformType) {
mTransformType = transformType;
}

private static final float MIN_SCALE_DEPTH = 0.75f;
private static final float MIN_SCALE_ZOOM = 0.85f;
private static final float MIN_ALPHA_ZOOM = 0.5f;
private static final float SCALE_FACTOR_SLIDE = 0.85f;
private static final float MIN_ALPHA_SLIDE = 0.35f;

public void transformPage(View page, float position) {
final float alpha;
final float scale;
final float translationX;

switch (mTransformType) {
case FLOW:
page.setRotationY(position * -30f);
return;

case SLIDE_OVER:
if (position < 0 && position > -1) {
// this is the page to the left
scale = Math.abs(Math.abs(position) – 1) * (1.0f – SCALE_FACTOR_SLIDE) + SCALE_FACTOR_SLIDE;
alpha = Math.max(MIN_ALPHA_SLIDE, 1 – Math.abs(position));
int pageWidth = page.getWidth();
float translateValue = position * -pageWidth;
if (translateValue > -pageWidth) {
translationX = translateValue;
} else {
translationX = 0;
}
} else {
alpha = 1;
scale = 1;
translationX = 0;
}
break;

case DEPTH:
if (position > 0 && position < 1) {
// moving to the right
alpha = (1 – position);
scale = MIN_SCALE_DEPTH + (1 – MIN_SCALE_DEPTH) * (1 – Math.abs(position));
translationX = (page.getWidth() * -position);
} else {
// use default for all other cases
alpha = 1;
scale = 1;
translationX = 0;
}
break;

case ZOOM:
if (position >= -1 && position <= 1) {
scale = Math.max(MIN_SCALE_ZOOM, 1 – Math.abs(position));
alpha = MIN_ALPHA_ZOOM +
(scale – MIN_SCALE_ZOOM) / (1 – MIN_SCALE_ZOOM) * (1 – MIN_ALPHA_ZOOM);
float vMargin = page.getHeight() * (1 – scale) / 2;
float hMargin = page.getWidth() * (1 – scale) / 2;
if (position < 0) {
translationX = (hMargin – vMargin / 2);
} else {
translationX = (-hMargin + vMargin / 2);
}
} else {
alpha = 1;
scale = 1;
translationX = 0;
}
break;

default:
return;
}

page.setAlpha(alpha);
page.setTranslationX(translationX);
page.setScaleX(scale);
page.setScaleY(scale);
}
}
[/code]

Tech as the Teen Common Ground

I was born in England in 1967. Two years later my family moved to the USA. Since then, many of my relatives have scattered across the globe.

When a cousin visits me in the USA – which happens maybe once every five years – we seek some common ground, and invariably it turns out to be music or some other form of entertainment. We start talking about the music and movies we like, and from there we find other things to talk about.

By when their kids interact with my kids, the common ground is tech.

My cousin from Germany visited us last week, and we wondered if our sons – who had never met – would have much to talk about. But it turned out they’re both avid users of Instagram and Snapchat, and they both run Minecraft servers and have YouTube channels where they talk about their gaming addiction.

Their common ground in tech was the starting point for their relationship, and that relationship continues even after we said our goodbyes thanks to the tech they use to communicate.

Why I Left Indie Development

indiana-jones

In what feels like a different life now, I used to be a fairly well-known indie developer. I spoke at events like SXSW, and my blog had a large audience of people who liked hearing about my work on HomeSite, TopStyle and FeedDemon.

I parted ways with that life several years ago, in part because it’s extremely difficult to be a one-man show and still have time to be a husband and father. I was also burned out from years of doing my own support. I had lovely customers, of course, but I spent so much time supporting them that I wasn’t able to spend as much time feeding my code addiction. Almost everything I do professionally is so I can enjoy the bliss of getting lost in writing software.

But I also gave up pursuing the indie life because I wanted to make the switch to mobile development, and I didn’t see much future for indie mobile developers. The economics of the various app stores coupled with the plethora of free software didn’t paint a rosy picture for one-person companies building consumer apps. In fact, I didn’t make the leap to mobile until I was offered a full-time job as an Android dev.

So it’s been interesting reading the latest round of blog posts about the state of indie mobile development. While there are success stories, there certainly aren’t many of them. Making a decent living as an indie developer writing mobile apps is ridiculously hard – and I don’t see it getting better anytime soon.

A lot of mobile developers have left the indie ship and done as I have and joined a larger company, many of which look at mobile apps as a free (or nearly free) complement to their other offerings.1 There’s plenty of opportunity here for mobile developers, and I think that opportunity will continue to grow for a while.


  1. As an aside, I’m not convinced the “mobile as a complement” strategy is the right one long term. Mobile is becoming the primary way people access their information, to the point that web and desktop software are turning into the complement.

Goodbye Blue Sky

goodbye-blue-sky
My parents grew up in England during World War II. They used to tell me about the air raid sirens that sounded at night alerting them to seek shelter, quickly.

I often asked them about this, thinking they must still be haunted by the thought of bombs dropping on them as they slept.

But they said it was normal to them. It was all they ever knew.

That has always stuck with me.

It makes me wonder how many things we accept simply because we’ve never known any different.

Abolishing the Gingerbread Tax

A few weeks ago I said this:

Every Android developer I know will dance in the streets the day they can drop support for pre-ICS versions of Android

Well, it looks like it’s time for me to hit the streets because WordPress for Android – the app I work on – is dropping Gingerbread support in new versions.

Strangely, though, I was a bit nervous when we first talked about doing this. Leaving any users stranded really bothered me.

But then I thought about how much extra work we put into maintaining backwards compatibility for a dwindling number of people, and I considered how much better the app could be for the large majority of our users if we spent that time improving it for newer devices.

When I looked at it that way, I wondered whether we should’ve dropped Gingerbread support even sooner. And I wondered how many other Android developers are continuing to make the majority of their users pay this Gingerbread Tax.

If you’re one of them, perhaps it’s time your app stops supporting pre-ICS devices, too.

 

Settling on a Name

red-rose

I remember during the LA riots of 1992 the media struggled with how to refer to Rodney King. Then someone decided to call him a “black motorist” and next thing you know every reporter was calling him a black motorist. Yes, they collectively decided, he drove a motor vehicle and he’s black, so he’s a black motorist. Problem solved.

During the war with Iraq, there was some confusion about what to call those who were fighting back. Were they terrorists, or freedom fighters, or what? Then the word “insurgents” was floated and it stuck. From then on, the media coalesced around calling them insurgents, even though nobody seemed to know what it meant.

We see it all the time even if we’re not aware of it. Climate change, financial crisis, bailout, and other phrases that try not to assign blame unless it’s in our country’s interests. We hear what these things are called and our mood is altered, our opinion on what’s being reported is changed.

I like to pay attention to how things are named because it affects how we deal with them, and it informs me about the opinions of those in power. Our media tends to favor those in power, and I tend not to, so when a name is settled upon I try to look behind the scenes and ask myself why those in power have chosen that name.

 

My Trusty FeedDemon Bag

feeddemon-bagYears ago, when FeedDemon was thriving, I had a canvas FeedDemon bag created for me by CafePress.

I figured it was a novelty, like having a t-shirt made from a picture of your kids when they’re young that you stop wearing once they outgrow the diaper stage.

But instead this bag has remained my trusty companion and shows no signs of getting old. It has outlived FeedDemon itself.

I’ve taken it everywhere, but I don’t think I’ve ever been asked about it. Probably for good reason: who wants to ask an obvious geek about their bag when it has a demonic logo on it?

It has been on every vacation with me, carrying sunscreen, towels, and books to the beach. I’ve taken it on business trips to hold my electronics. It has come with me to the grocery store to carry home ice cream, veggies, and beer. Now it goes to the gym with me to hold my headphones, towel, water, and post-workout snack.

It has survived storms, car wrecks, and even plane crashes. This is the Samuel L. Jackson of bags, and I wouldn’t be surprised if it lasts longer than I do.