In Android 5.0 one of the key concepts from the material design spec is using elevation to promote UI elements in perceived importance. According to the documentation and Google-provided example, as long as the device is running Lollipop or better, all that is required is to set the elevation property, and the framework will handle the shadow effect.

However, in my testing with both Android 5.0 and 5.0.1, the documentation neglects to mention one very important caveat: If your drawable applies an alpha, the elevation property is ignored. To see this behavior, follow the walk-through below, or download and import the entire project directly into Android Studio.

1. Create a new Android project in Android Studio. Target SDK 21 or higher.

2. In the /res/drawable folder, create a new xml shape. (This xml drawable definition was lifted directly from the Google documentation on customizing view shadows.)

square.xml




3. In the /res/layout folder, modify your activity_main.xml file to include: an image view, a couple of buttons, and a text view widget.

activity_main.xml

4. In the /java/MainActivity.java file, wire up a couple of click listeners to raise and lower the elevation property.

MainActivty.java
package com.authorwjf.shadows;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends Activity implements View.OnClickListener {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.raise).setOnClickListener(this);
findViewById(R.id.lower).setOnClickListener(this);
}

@Override
public void onClick(View v) {
int elevation = Integer.parseInt(((TextView) findViewById(R.id.label)).getText().toString());
if (v.getId()==R.id.raise) {
elevation+=5;
} else {
elevation-=5;
}
if (elevation<0) {
elevation=0;
} else if (elevation>100) {
elevation=100;
}
findViewById(R.id.img).setElevation(elevation);
((TextView) findViewById(R.id.label)).setText(Integer.toString(elevation));
}
}

At this point, you’d expect that by raising and lowering the elevation, you would observe the framework rendering a shadow to visually denote the Z axis. You can see from the screenshot below (Figure A), this isn’t the case. The image view still appears to have an elevation of zero, despite the exposed property saying otherwise.

Figure A


What I found after some googling and experimentation is that if the background assigned to your view contains an alpha, the built-in shadow effects don’t work. I’ve taken the liberty of removing the alpha from the above XML drawable.

square.xml




Now the application behaves as expected (Figure B). It’s a subtle difference, but I think that is a big part of what material design is about: subtle differences that make for a more polished user experience (UX).

Figure B