Los botones personalizados en Android se crean mediante un fichero XML de tipo selector que define diferentes imágenes según el estado del botón (normal, pulsado, con foco), generando así una sensación visual de movimiento al pulsarlo.
Imágenes de estados
Se necesitan tres imágenes que se colocan en res/drawable/:
botonnormal.png— estado por defectobotonpulsado.png— cuando el botón está siendo pulsadobotonconfoco.png— cuando el botón tiene el foco (seleccionado con teclado/D-pad)

Crear el selector (boton.xml)
Se crea el fichero res/drawable/boton.xml con la siguiente estructura:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@drawable/botonpulsado" />
<item android:state_focused="true" android:drawable="@drawable/botonconfoco" />
<item android:drawable="@drawable/botonnormal" />
</selector>
El orden importa: Android evalúa los estados de arriba hacia abajo y usa el primero que coincide. El último item sin condición es el estado por defecto.

Configurar el layout
En el layout se coloca un RelativeLayout con fondo blanco (#FFFFFF) y un Button:
- Propiedad
background:@drawable/boton - Propiedad
text: vacía (la imagen ya actúa como texto visual) - Propiedad
onClick: nombre del método Java que se ejecutará al pulsar

Configurar el onClick
En el panel de propiedades del botón se asigna el nombre del método al atributo onClick. Este método debe declararse en la actividad con firma public void nombreMetodo(View v).

Código Java
public void sePulsa(View v) {
Toast.makeText(getApplicationContext(), "¡Botón pulsado!", Toast.LENGTH_SHORT).show();
}