3D rotations on Views

Guides By 4 years ago

If you’ve ever used Carbon for Twitter you’ve probably noticed that it incorporates a few interesting 3D effects on lists throughout the app. It’s very similar to the effects used in the app drawer on Honeycomb and above when you try to scroll past the first and last page.

As complex as this effect looks it’s really very simple to implement. All the hard lifting is done by the Graphics Camera class, not to be confused with the Camera class that controls the hardware Camera.

The example I’m going to run you through is a simple static 3D rotation on a ListView, which by itself is not overly useful but by linking the rotation variable to an onTouch or onFling event and you can start to get some really funky effects.

The step is to get access to the onDraw procedure for the view we want to apply the 3D rotation to. For this example we’ll create a class that inherits from the ListView. There are also a few pre-create objects included. It’s bad practise to allocate memory in onDraw.

import android.content.Context;
import android.graphics.Camera;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ListView;

public class TiltListView extends ListView {

	private Camera mCamera;
	private Matrix mMatrix;

        public TiltListView(Context context, AttributeSet attrs) {
	 	super(context, attrs);
                mCamera = new Camera();
		mMatrix = new Matrix();

The basic idea behind the guts of the code is very simple. The Camera object is used to create a matrix with a 20 degree rotation along the x-Axis. The resulting matrix is then concatenated to the current canvas to apply this effect to the whole view.

	protected void onDraw(Canvas canvas) {
		mCamera.rotate(20, 0, 0);
		mMatrix.preTranslate(-getWidth()/2, -getHeight()/2);
		mMatrix.postTranslate(getWidth()/2, getHeight()/2);

One thing to note is that the position of the Camera effect is always at the top left hand corner (0, 0). In order to perform the rotation in the center of the list we need to move the middle of the canvas to 0, 0. We do this by using preTranslate directly on the matrix. Using postTranslate to move the canvas back to the correct spot.